authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-15 18:54:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:26-07:00
logf3d0fc7a66fa40e86036e7c626231e7de265cd64
treeaac6243b4e4e5de1f3f941a7bf6e88d9e46ac01b
parenta21e7ab64f66c83c57b2d87b71c19d50d94ed543

backends: port to new `std.io.BufferedWriter` API


129 files changed, 5611 insertions(+), 6719 deletions(-)

lib/compiler/aro/aro/Compilation.zig+1-1
...@@ -546,7 +546,7 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi...@@ -546,7 +546,7 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi
546 }546 }
547547
548 try buf.appendSlice("#define __STDC__ 1\n");548 try buf.appendSlice("#define __STDC__ 1\n");
549 try buf.writer().print("#define __STDC_HOSTED__ {d}\n", .{@intFromBool(comp.target.os.tag != .freestanding)});549 try buf.print("#define __STDC_HOSTED__ {d}\n", .{@intFromBool(comp.target.os.tag != .freestanding)});
550550
551 // standard macros551 // standard macros
552 try buf.appendSlice(552 try buf.appendSlice(
lib/compiler/build_runner.zig+5-2
...@@ -695,7 +695,10 @@ fn runStepNames(...@@ -695,7 +695,10 @@ fn runStepNames(
695695
696 if (run.summary != .none) {696 if (run.summary != .none) {
697 var bw = std.debug.lockStdErr2(&stdio_buffer);697 var bw = std.debug.lockStdErr2(&stdio_buffer);
698 defer std.debug.unlockStdErr();698 defer {
699 bw.flush() catch {};
700 std.debug.unlockStdErr();
701 }
699702
700 const total_count = success_count + failure_count + pending_count + skipped_count;703 const total_count = success_count + failure_count + pending_count + skipped_count;
701 ttyconf.setColor(&bw, .cyan) catch {};704 ttyconf.setColor(&bw, .cyan) catch {};
...@@ -710,7 +713,7 @@ fn runStepNames(...@@ -710,7 +713,7 @@ fn runStepNames(
710 if (test_fail_count > 0) bw.print("; {d} failed", .{test_fail_count}) catch {};713 if (test_fail_count > 0) bw.print("; {d} failed", .{test_fail_count}) catch {};
711 if (test_leak_count > 0) bw.print("; {d} leaked", .{test_leak_count}) catch {};714 if (test_leak_count > 0) bw.print("; {d} leaked", .{test_leak_count}) catch {};
712715
713 bw.writeAll("\n") catch {};716 bw.writeByte('\n') catch {};
714717
715 // Print a fancy tree with build results.718 // Print a fancy tree with build results.
716 var step_stack_copy = try step_stack.clone(gpa);719 var step_stack_copy = try step_stack.clone(gpa);
lib/std/Build/Cache/Path.zig+2-2
...@@ -133,11 +133,11 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {...@@ -133,11 +133,11 @@ pub fn makePath(p: Path, sub_path: []const u8) !void {
133}133}
134134
135pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {135pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 {
136 return std.fmt.allocPrint(allocator, "{}", .{p});136 return std.fmt.allocPrint(allocator, "{f}", .{p});
137}137}
138138
139pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {139pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
140 return std.fmt.allocPrintZ(allocator, "{}", .{p});140 return std.fmt.allocPrintZ(allocator, "{f}", .{p});
141}141}
142142
143pub fn format(143pub fn format(
lib/std/Build/Step.zig+4-4
...@@ -469,7 +469,7 @@ pub fn evalZigProcess(...@@ -469,7 +469,7 @@ pub fn evalZigProcess(
469 // This is intentionally printed for failure on the first build but not for469 // This is intentionally printed for failure on the first build but not for
470 // subsequent rebuilds.470 // subsequent rebuilds.
471 if (s.result_error_bundle.errorMessageCount() > 0) {471 if (s.result_error_bundle.errorMessageCount() > 0) {
472 return s.fail("the following command failed with {d} compilation errors:\n{s}", .{472 return s.fail("the following command failed with {d} compilation errors:\n{s}\n", .{
473 s.result_error_bundle.errorMessageCount(),473 s.result_error_bundle.errorMessageCount(),
474 try allocPrintCmd(arena, null, argv),474 try allocPrintCmd(arena, null, argv),
475 });475 });
...@@ -689,7 +689,7 @@ pub inline fn handleChildProcUnsupported(...@@ -689,7 +689,7 @@ pub inline fn handleChildProcUnsupported(
689) error{ OutOfMemory, MakeFailed }!void {689) error{ OutOfMemory, MakeFailed }!void {
690 if (!std.process.can_spawn) {690 if (!std.process.can_spawn) {
691 return s.fail(691 return s.fail(
692 "unable to execute the following command: host cannot spawn child processes\n{s}",692 "unable to execute the following command: host cannot spawn child processes\n{s}\n",
693 .{try allocPrintCmd(s.owner.allocator, opt_cwd, argv)},693 .{try allocPrintCmd(s.owner.allocator, opt_cwd, argv)},
694 );694 );
695 }695 }
...@@ -706,14 +706,14 @@ pub fn handleChildProcessTerm(...@@ -706,14 +706,14 @@ pub fn handleChildProcessTerm(
706 .Exited => |code| {706 .Exited => |code| {
707 if (code != 0) {707 if (code != 0) {
708 return s.fail(708 return s.fail(
709 "the following command exited with error code {d}:\n{s}",709 "the following command exited with error code {d}:\n{s}\n",
710 .{ code, try allocPrintCmd(arena, opt_cwd, argv) },710 .{ code, try allocPrintCmd(arena, opt_cwd, argv) },
711 );711 );
712 }712 }
713 },713 },
714 .Signal, .Stopped, .Unknown => {714 .Signal, .Stopped, .Unknown => {
715 return s.fail(715 return s.fail(
716 "the following command terminated unexpectedly:\n{s}",716 "the following command terminated unexpectedly:\n{s}\n",
717 .{try allocPrintCmd(arena, opt_cwd, argv)},717 .{try allocPrintCmd(arena, opt_cwd, argv)},
718 );718 );
719 },719 },
lib/std/Build/Step/CheckObject.zig+4-4
...@@ -1523,11 +1523,11 @@ const MachODumper = struct {...@@ -1523,11 +1523,11 @@ const MachODumper = struct {
1523 ) !void {1523 ) !void {
1524 const size = try br.takeLeb128(u64);1524 const size = try br.takeLeb128(u64);
1525 if (size > 0) {1525 if (size > 0) {
1526 const flags = try br.takeLeb128(u64);1526 const flags = try br.takeLeb128(u8);
1527 switch (flags) {1527 switch (flags) {
1528 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {1528 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {
1529 const ord = try br.takeLeb128(u64);1529 const ord = try br.takeLeb128(u64);
1530 const name = try br.takeDelimiterConclusive(0);1530 const name = try br.takeSentinel(0);
1531 try exports.append(.{1531 try exports.append(.{
1532 .name = if (name.len > 0) name else prefix,1532 .name = if (name.len > 0) name else prefix,
1533 .tag = .reexport,1533 .tag = .reexport,
...@@ -1568,8 +1568,8 @@ const MachODumper = struct {...@@ -1568,8 +1568,8 @@ const MachODumper = struct {
15681568
1569 const nedges = try br.takeByte();1569 const nedges = try br.takeByte();
1570 for (0..nedges) |_| {1570 for (0..nedges) |_| {
1571 const label = try br.takeDelimiterConclusive(0);1571 const label = try br.takeSentinel(0);
1572 const off = try br.takeLeb128(u64);1572 const off = try br.takeLeb128(usize);
1573 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });1573 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
1574 const seek = br.seek;1574 const seek = br.seek;
1575 br.seek = off;1575 br.seek = off;
lib/std/Target.zig+7-12
...@@ -301,28 +301,23 @@ pub const Os = struct {...@@ -301,28 +301,23 @@ pub const Os = struct {
301301
302 /// This function is defined to serialize a Zig source code representation of this302 /// This function is defined to serialize a Zig source code representation of this
303 /// type, that, when parsed, will deserialize into the same data.303 /// type, that, when parsed, will deserialize into the same data.
304 pub fn format(304 pub fn format(ver: WindowsVersion, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
305 ver: WindowsVersion,
306 comptime fmt_str: []const u8,
307 _: std.fmt.FormatOptions,
308 writer: *std.io.BufferedWriter,
309 ) anyerror!void {
310 const maybe_name = std.enums.tagName(WindowsVersion, ver);305 const maybe_name = std.enums.tagName(WindowsVersion, ver);
311 if (comptime std.mem.eql(u8, fmt_str, "s")) {306 if (comptime std.mem.eql(u8, fmt_str, "s")) {
312 if (maybe_name) |name|307 if (maybe_name) |name|
313 try writer.print(".{s}", .{name})308 try bw.print(".{s}", .{name})
314 else309 else
315 try writer.print(".{d}", .{@intFromEnum(ver)});310 try bw.print(".{d}", .{@intFromEnum(ver)});
316 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {311 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
317 if (maybe_name) |name|312 if (maybe_name) |name|
318 try writer.print(".{s}", .{name})313 try bw.print(".{s}", .{name})
319 else314 else
320 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});315 try bw.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
321 } else if (fmt_str.len == 0) {316 } else if (fmt_str.len == 0) {
322 if (maybe_name) |name|317 if (maybe_name) |name|
323 try writer.print("WindowsVersion.{s}", .{name})318 try bw.print("WindowsVersion.{s}", .{name})
324 else319 else
325 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});320 try bw.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
326 } else std.fmt.invalidFmtError(fmt_str, ver);321 } else std.fmt.invalidFmtError(fmt_str, ver);
327 }322 }
328 };323 };
lib/std/Uri.zig+13-13
...@@ -236,44 +236,44 @@ pub const WriteToStreamOptions = struct {...@@ -236,44 +236,44 @@ pub const WriteToStreamOptions = struct {
236 port: bool = true,236 port: bool = true,
237};237};
238238
239pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, writer: *std.io.BufferedWriter) anyerror!void {239pub fn writeToStream(uri: Uri, options: WriteToStreamOptions, bw: *std.io.BufferedWriter) anyerror!void {
240 if (options.scheme) {240 if (options.scheme) {
241 try writer.print("{s}:", .{uri.scheme});241 try bw.print("{s}:", .{uri.scheme});
242 if (options.authority and uri.host != null) {242 if (options.authority and uri.host != null) {
243 try writer.writeAll("//");243 try bw.writeAll("//");
244 }244 }
245 }245 }
246 if (options.authority) {246 if (options.authority) {
247 if (options.authentication and uri.host != null) {247 if (options.authentication and uri.host != null) {
248 if (uri.user) |user| {248 if (uri.user) |user| {
249 try writer.print("{fuser}", .{user});249 try bw.print("{fuser}", .{user});
250 if (uri.password) |password| {250 if (uri.password) |password| {
251 try writer.print(":{fpassword}", .{password});251 try bw.print(":{fpassword}", .{password});
252 }252 }
253 try writer.writeByte('@');253 try bw.writeByte('@');
254 }254 }
255 }255 }
256 if (uri.host) |host| {256 if (uri.host) |host| {
257 try writer.print("{fhost}", .{host});257 try bw.print("{fhost}", .{host});
258 if (options.port) {258 if (options.port) {
259 if (uri.port) |port| try writer.print(":{d}", .{port});259 if (uri.port) |port| try bw.print(":{d}", .{port});
260 }260 }
261 }261 }
262 }262 }
263 if (options.path) {263 if (options.path) {
264 try writer.print("{fpath}", .{264 try bw.print("{fpath}", .{
265 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,265 if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path,
266 });266 });
267 if (options.query) {267 if (options.query) {
268 if (uri.query) |query| try writer.print("?{fquery}", .{query});268 if (uri.query) |query| try bw.print("?{fquery}", .{query});
269 }269 }
270 if (options.fragment) {270 if (options.fragment) {
271 if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment});271 if (uri.fragment) |fragment| try bw.print("#{ffragment}", .{fragment});
272 }272 }
273 }273 }
274}274}
275275
276pub fn format(uri: Uri, comptime fmt: []const u8, _: std.fmt.Options, writer: *std.io.BufferedWriter) anyerror!void {276pub fn format(uri: Uri, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
277 const scheme = comptime std.mem.indexOfScalar(u8, fmt, ';') != null or fmt.len == 0;277 const scheme = comptime std.mem.indexOfScalar(u8, fmt, ';') != null or fmt.len == 0;
278 const authentication = comptime std.mem.indexOfScalar(u8, fmt, '@') != null or fmt.len == 0;278 const authentication = comptime std.mem.indexOfScalar(u8, fmt, '@') != null or fmt.len == 0;
279 const authority = comptime std.mem.indexOfScalar(u8, fmt, '+') != null or fmt.len == 0;279 const authority = comptime std.mem.indexOfScalar(u8, fmt, '+') != null or fmt.len == 0;
...@@ -288,7 +288,7 @@ pub fn format(uri: Uri, comptime fmt: []const u8, _: std.fmt.Options, writer: *s...@@ -288,7 +288,7 @@ pub fn format(uri: Uri, comptime fmt: []const u8, _: std.fmt.Options, writer: *s
288 .path = path,288 .path = path,
289 .query = query,289 .query = query,
290 .fragment = fragment,290 .fragment = fragment,
291 }, writer);291 }, bw);
292}292}
293293
294/// Parses the URI or returns an error.294/// Parses the URI or returns an error.
lib/std/fmt.zig+1-5
...@@ -531,11 +531,7 @@ pub fn Formatter(comptime formatFn: anytype) type {...@@ -531,11 +531,7 @@ pub fn Formatter(comptime formatFn: anytype) type {
531 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;531 const Data = @typeInfo(@TypeOf(formatFn)).@"fn".params[0].type.?;
532 return struct {532 return struct {
533 data: Data,533 data: Data,
534 pub fn format(534 pub fn format(self: @This(), writer: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
535 self: @This(),
536 writer: *std.io.BufferedWriter,
537 comptime fmt: []const u8,
538 ) anyerror!void {
539 try formatFn(self.data, writer, fmt);535 try formatFn(self.data, writer, fmt);
540 }536 }
541 };537 };
lib/std/io/BufferedReader.zig+79-51
...@@ -201,8 +201,8 @@ pub fn toss(br: *BufferedReader, n: usize) void {...@@ -201,8 +201,8 @@ pub fn toss(br: *BufferedReader, n: usize) void {
201201
202/// Equivalent to `peek` + `toss`.202/// Equivalent to `peek` + `toss`.
203pub fn take(br: *BufferedReader, n: usize) anyerror![]u8 {203pub fn take(br: *BufferedReader, n: usize) anyerror![]u8 {
204 const result = try peek(br, n);204 const result = try br.peek(n);
205 toss(br, n);205 br.toss(n);
206 return result;206 return result;
207}207}
208208
...@@ -218,7 +218,7 @@ pub fn take(br: *BufferedReader, n: usize) anyerror![]u8 {...@@ -218,7 +218,7 @@ pub fn take(br: *BufferedReader, n: usize) anyerror![]u8 {
218/// See also:218/// See also:
219/// * `take`219/// * `take`
220pub fn takeArray(br: *BufferedReader, comptime n: usize) anyerror!*[n]u8 {220pub fn takeArray(br: *BufferedReader, comptime n: usize) anyerror!*[n]u8 {
221 return (try take(br, n))[0..n];221 return (try br.take(n))[0..n];
222}222}
223223
224/// Skips the next `n` bytes from the stream, advancing the seek position.224/// Skips the next `n` bytes from the stream, advancing the seek position.
...@@ -232,7 +232,7 @@ pub fn takeArray(br: *BufferedReader, comptime n: usize) anyerror!*[n]u8 {...@@ -232,7 +232,7 @@ pub fn takeArray(br: *BufferedReader, comptime n: usize) anyerror!*[n]u8 {
232/// * `discardUntilEnd`232/// * `discardUntilEnd`
233/// * `discardUpTo`233/// * `discardUpTo`
234pub fn discard(br: *BufferedReader, n: usize) anyerror!void {234pub fn discard(br: *BufferedReader, n: usize) anyerror!void {
235 if ((try discardUpTo(br, n)) != n) return error.EndOfStream;235 if ((try br.discardUpTo(n)) != n) return error.EndOfStream;
236}236}
237237
238/// Skips the next `n` bytes from the stream, advancing the seek position.238/// Skips the next `n` bytes from the stream, advancing the seek position.
...@@ -325,6 +325,34 @@ pub fn partialRead(br: *BufferedReader, buffer: []u8) anyerror!usize {...@@ -325,6 +325,34 @@ pub fn partialRead(br: *BufferedReader, buffer: []u8) anyerror!usize {
325 @panic("TODO");325 @panic("TODO");
326}326}
327327
328/// Returns a slice of the next bytes of buffered data from the stream until
329/// `sentinel` is found, advancing the seek position.
330///
331/// Returned slice has a sentinel.
332///
333/// If the stream ends before the sentinel is found, `error.EndOfStream` is
334/// returned.
335///
336/// If the sentinel is not found within a number of bytes matching the
337/// capacity of the `BufferedReader`, `error.StreamTooLong` is returned.
338///
339/// Invalidates previously returned values from `peek`.
340///
341/// See also:
342/// * `peekSentinel`
343/// * `takeDelimiterExclusive`
344/// * `takeDelimiterInclusive`
345pub fn takeSentinel(br: *BufferedReader, comptime sentinel: u8) anyerror![:sentinel]u8 {
346 const result = try br.peekSentinel(sentinel);
347 br.toss(result.len + 1);
348 return result;
349}
350
351pub fn peekSentinel(br: *BufferedReader, comptime sentinel: u8) anyerror![:sentinel]u8 {
352 const result = try br.takeDelimiterInclusive(sentinel);
353 return result[0 .. result.len - 1 :sentinel];
354}
355
328/// Returns a slice of the next bytes of buffered data from the stream until356/// Returns a slice of the next bytes of buffered data from the stream until
329/// `delimiter` is found, advancing the seek position.357/// `delimiter` is found, advancing the seek position.
330///358///
...@@ -339,36 +367,17 @@ pub fn partialRead(br: *BufferedReader, buffer: []u8) anyerror!usize {...@@ -339,36 +367,17 @@ pub fn partialRead(br: *BufferedReader, buffer: []u8) anyerror!usize {
339/// Invalidates previously returned values from `peek`.367/// Invalidates previously returned values from `peek`.
340///368///
341/// See also:369/// See also:
342/// * `takeDelimiterConclusive`370/// * `takeSentinel`
371/// * `takeDelimiterExclusive`
343/// * `peekDelimiterInclusive`372/// * `peekDelimiterInclusive`
344pub fn takeDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {373pub fn takeDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
345 const result = try peekDelimiterInclusive(br, delimiter);374 const result = try br.peekDelimiterInclusive(delimiter);
346 toss(result.len);375 br.toss(result.len);
347 return result;376 return result;
348}377}
349378
350pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {379pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
351 const storage = &br.storage;380 return (try br.peekDelimiterInclusiveUnlessEnd(delimiter)) orelse error.EndOfStream;
352 const buffer = storage.buffer[0..storage.end];
353 const seek = br.seek;
354 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {
355 @branchHint(.likely);
356 return buffer[seek .. end + 1];
357 }
358 const remainder = buffer[seek..];
359 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
360 var i = remainder.len;
361 storage.end = i;
362 br.seek = 0;
363 while (i < storage.buffer.len) {
364 const status = try br.unbuffered_reader.read(storage, .none);
365 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| {
366 return storage.buffer[0 .. end + 1];
367 }
368 if (status.end) return error.EndOfStream;
369 i = storage.end;
370 }
371 return error.StreamTooLong;
372}381}
373382
374/// Returns a slice of the next bytes of buffered data from the stream until383/// Returns a slice of the next bytes of buffered data from the stream until
...@@ -384,21 +393,32 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8...@@ -384,21 +393,32 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
384/// Invalidates previously returned values from `peek`.393/// Invalidates previously returned values from `peek`.
385///394///
386/// See also:395/// See also:
396/// * `takeSentinel`
387/// * `takeDelimiterInclusive`397/// * `takeDelimiterInclusive`
388/// * `peekDelimiterConclusive`398/// * `peekDelimiterExclusive`
389pub fn takeDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {399pub fn takeDelimiterExclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
390 const result = try peekDelimiterConclusive(br, delimiter);400 const result_unless_end = try br.peekDelimiterInclusiveUnlessEnd(delimiter);
401 const result = result_unless_end orelse {
402 br.toss(br.storage.end);
403 return br.storage.buffer[0..br.storage.end];
404 };
391 br.toss(result.len);405 br.toss(result.len);
392 return result;406 return result[0 .. result.len - 1];
407}
408
409pub fn peekDelimiterExclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
410 const result_unless_end = try br.peekDelimiterInclusiveUnlessEnd(delimiter);
411 const result = result_unless_end orelse return br.storage.buffer[0..br.storage.end];
412 return result[0 .. result.len - 1];
393}413}
394414
395pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {415fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) anyerror!?[]u8 {
396 const storage = &br.storage;416 const storage = &br.storage;
397 const buffer = storage.buffer[0..storage.end];417 const buffer = storage.buffer[0..storage.end];
398 const seek = br.seek;418 const seek = br.seek;
399 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {419 if (std.mem.indexOfScalarPos(u8, buffer, seek, delimiter)) |end| {
400 @branchHint(.likely);420 @branchHint(.likely);
401 return buffer[seek..end];421 return buffer[seek .. end + 1];
402 }422 }
403 const remainder = buffer[seek..];423 const remainder = buffer[seek..];
404 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);424 std.mem.copyForwards(u8, buffer[0..remainder.len], remainder);
...@@ -407,10 +427,8 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8...@@ -407,10 +427,8 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
407 br.seek = 0;427 br.seek = 0;
408 while (i < storage.buffer.len) {428 while (i < storage.buffer.len) {
409 const status = try br.unbuffered_reader.read(storage, .unlimited);429 const status = try br.unbuffered_reader.read(storage, .unlimited);
410 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| {430 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| return storage.buffer[0 .. end + 1];
411 return storage.buffer[0 .. end + 1];431 if (status.end) return null;
412 }
413 if (status.end) return storage.buffer[0..storage.end];
414 i = storage.end;432 i = storage.end;
415 }433 }
416 return error.StreamTooLong;434 return error.StreamTooLong;
...@@ -436,7 +454,7 @@ pub fn streamReadDelimiter(br: *BufferedReader, bw: *std.io.BufferedWriter, deli...@@ -436,7 +454,7 @@ pub fn streamReadDelimiter(br: *BufferedReader, bw: *std.io.BufferedWriter, deli
436///454///
437/// Returns number of bytes streamed as well as whether the input reached the end.455/// Returns number of bytes streamed as well as whether the input reached the end.
438/// The end is not signaled to the writer.456/// The end is not signaled to the writer.
439pub fn streamReadDelimiterConclusive(457pub fn streamReadDelimiterExclusive(
440 br: *BufferedReader,458 br: *BufferedReader,
441 bw: *std.io.BufferedWriter,459 bw: *std.io.BufferedWriter,
442 delimiter: u8,460 delimiter: u8,
...@@ -468,7 +486,7 @@ pub fn streamReadDelimiterLimited(...@@ -468,7 +486,7 @@ pub fn streamReadDelimiterLimited(
468/// including the delimiter.486/// including the delimiter.
469///487///
470/// If end of stream is found, this function succeeds.488/// If end of stream is found, this function succeeds.
471pub fn discardDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror!void {489pub fn discardDelimiterExclusive(br: *BufferedReader, delimiter: u8) anyerror!void {
472 _ = br;490 _ = br;
473 _ = delimiter;491 _ = delimiter;
474 @panic("TODO");492 @panic("TODO");
...@@ -517,7 +535,7 @@ pub fn takeByte(br: *BufferedReader) anyerror!u8 {...@@ -517,7 +535,7 @@ pub fn takeByte(br: *BufferedReader) anyerror!u8 {
517 const seek = br.seek;535 const seek = br.seek;
518 if (seek >= buffer.len) {536 if (seek >= buffer.len) {
519 @branchHint(.unlikely);537 @branchHint(.unlikely);
520 try fill(br, 1);538 try br.fill(1);
521 }539 }
522 br.seek = seek + 1;540 br.seek = seek + 1;
523 return buffer[seek];541 return buffer[seek];
...@@ -531,20 +549,20 @@ pub fn takeByteSigned(br: *BufferedReader) anyerror!i8 {...@@ -531,20 +549,20 @@ pub fn takeByteSigned(br: *BufferedReader) anyerror!i8 {
531/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.549/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
532pub inline fn takeInt(br: *BufferedReader, comptime T: type, endian: std.builtin.Endian) anyerror!T {550pub inline fn takeInt(br: *BufferedReader, comptime T: type, endian: std.builtin.Endian) anyerror!T {
533 const n = @divExact(@typeInfo(T).int.bits, 8);551 const n = @divExact(@typeInfo(T).int.bits, 8);
534 return std.mem.readInt(T, try takeArray(br, n), endian);552 return std.mem.readInt(T, try br.takeArray(n), endian);
535}553}
536554
537/// Asserts the buffer was initialized with a capacity at least `n`.555/// Asserts the buffer was initialized with a capacity at least `n`.
538pub fn takeVarInt(br: *BufferedReader, comptime Int: type, endian: std.builtin.Endian, n: usize) anyerror!Int {556pub fn takeVarInt(br: *BufferedReader, comptime Int: type, endian: std.builtin.Endian, n: usize) anyerror!Int {
539 assert(n <= @sizeOf(Int));557 assert(n <= @sizeOf(Int));
540 return std.mem.readVarInt(Int, try take(br, n), endian);558 return std.mem.readVarInt(Int, try br.take(n), endian);
541}559}
542560
543/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.561/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
544pub fn takeStruct(br: *BufferedReader, comptime T: type) anyerror!*align(1) T {562pub fn takeStruct(br: *BufferedReader, comptime T: type) anyerror!*align(1) T {
545 // Only extern and packed structs have defined in-memory layout.563 // Only extern and packed structs have defined in-memory layout.
546 comptime assert(@typeInfo(T).@"struct".layout != .auto);564 comptime assert(@typeInfo(T).@"struct".layout != .auto);
547 return @ptrCast(try takeArray(br, @sizeOf(T)));565 return @ptrCast(try br.takeArray(@sizeOf(T)));
548}566}
549567
550/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.568/// Asserts the buffer was initialized with a capacity at least `@sizeOf(T)`.
...@@ -561,7 +579,7 @@ pub fn takeStructEndian(br: *BufferedReader, comptime T: type, endian: std.built...@@ -561,7 +579,7 @@ pub fn takeStructEndian(br: *BufferedReader, comptime T: type, endian: std.built
561/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.579/// Asserts the buffer was initialized with a capacity at least `@sizeOf(Enum)`.
562pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) anyerror!Enum {580pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.Endian) anyerror!Enum {
563 const Tag = @typeInfo(Enum).@"enum".tag_type;581 const Tag = @typeInfo(Enum).@"enum".tag_type;
564 const int = try takeInt(br, Tag, endian);582 const int = try br.takeInt(Tag, endian);
565 return std.meta.intToEnum(Enum, int);583 return std.meta.intToEnum(Enum, int);
566}584}
567585
...@@ -588,10 +606,12 @@ fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Re...@@ -588,10 +606,12 @@ fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Re
588 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1));606 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1));
589 for (buffer, 1..) |byte, len| {607 for (buffer, 1..) |byte, len| {
590 if (remaining_bits > 0) {608 if (remaining_bits > 0) {
591 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) | if (result_info.bits > 7) @shrExact(result, 7) else 0;609 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) |
610 if (result_info.bits > 7) @shrExact(result, 7) else 0;
592 remaining_bits -= 7;611 remaining_bits -= 7;
593 } else if (fits) fits = switch (result_info.signedness) {612 } else if (fits) fits = switch (result_info.signedness) {
594 .signed => @as(i7, @bitCast(byte.bits)) == @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),613 .signed => @as(i7, @bitCast(byte.bits)) ==
614 @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),
595 .unsigned => byte.bits == 0,615 .unsigned => byte.bits == 0,
596 };616 };
597 if (byte.more) continue;617 if (byte.more) continue;
...@@ -652,6 +672,14 @@ test read {...@@ -652,6 +672,14 @@ test read {
652 return error.Unimplemented;672 return error.Unimplemented;
653}673}
654674
675test takeSentinel {
676 return error.Unimplemented;
677}
678
679test peekSentinel {
680 return error.Unimplemented;
681}
682
655test takeDelimiterInclusive {683test takeDelimiterInclusive {
656 return error.Unimplemented;684 return error.Unimplemented;
657}685}
...@@ -660,11 +688,11 @@ test peekDelimiterInclusive {...@@ -660,11 +688,11 @@ test peekDelimiterInclusive {
660 return error.Unimplemented;688 return error.Unimplemented;
661}689}
662690
663test takeDelimiterConclusive {691test takeDelimiterExclusive {
664 return error.Unimplemented;692 return error.Unimplemented;
665}693}
666694
667test peekDelimiterConclusive {695test peekDelimiterExclusive {
668 return error.Unimplemented;696 return error.Unimplemented;
669}697}
670698
...@@ -672,7 +700,7 @@ test streamReadDelimiter {...@@ -672,7 +700,7 @@ test streamReadDelimiter {
672 return error.Unimplemented;700 return error.Unimplemented;
673}701}
674702
675test streamReadDelimiterConclusive {703test streamReadDelimiterExclusive {
676 return error.Unimplemented;704 return error.Unimplemented;
677}705}
678706
...@@ -680,7 +708,7 @@ test streamReadDelimiterLimited {...@@ -680,7 +708,7 @@ test streamReadDelimiterLimited {
680 return error.Unimplemented;708 return error.Unimplemented;
681}709}
682710
683test discardDelimiterConclusive {711test discardDelimiterExclusive {
684 return error.Unimplemented;712 return error.Unimplemented;
685}713}
686714
lib/std/io/BufferedWriter.zig+127-110
...@@ -92,7 +92,7 @@ pub fn writableSlice(bw: *BufferedWriter, minimum_length: usize) anyerror![]u8 {...@@ -92,7 +92,7 @@ pub fn writableSlice(bw: *BufferedWriter, minimum_length: usize) anyerror![]u8 {
92 return cap_slice;92 return cap_slice;
93 }93 }
94 const buffer = bw.buffer[0..bw.end];94 const buffer = bw.buffer[0..bw.end];
95 const n = try bw.unbuffered_writer.write(buffer);95 const n = try bw.unbuffered_writer.writev(&.{buffer});
96 if (n == buffer.len) {96 if (n == buffer.len) {
97 @branchHint(.likely);97 @branchHint(.likely);
98 bw.end = 0;98 bw.end = 0;
...@@ -306,7 +306,7 @@ pub fn write(bw: *BufferedWriter, bytes: []const u8) anyerror!usize {...@@ -306,7 +306,7 @@ pub fn write(bw: *BufferedWriter, bytes: []const u8) anyerror!usize {
306/// transferred.306/// transferred.
307pub fn writeAll(bw: *BufferedWriter, bytes: []const u8) anyerror!void {307pub fn writeAll(bw: *BufferedWriter, bytes: []const u8) anyerror!void {
308 var index: usize = 0;308 var index: usize = 0;
309 while (index < bytes.len) index += try write(bw, bytes[index..]);309 while (index < bytes.len) index += try bw.write(bytes[index..]);
310}310}
311311
312pub fn print(bw: *BufferedWriter, comptime format: []const u8, args: anytype) anyerror!void {312pub fn print(bw: *BufferedWriter, comptime format: []const u8, args: anytype) anyerror!void {
...@@ -354,7 +354,7 @@ pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void {...@@ -354,7 +354,7 @@ pub fn writeByte(bw: *BufferedWriter, byte: u8) anyerror!void {
354/// many times as necessary.354/// many times as necessary.
355pub fn splatByteAll(bw: *BufferedWriter, byte: u8, n: usize) anyerror!void {355pub fn splatByteAll(bw: *BufferedWriter, byte: u8, n: usize) anyerror!void {
356 var remaining: usize = n;356 var remaining: usize = n;
357 while (remaining > 0) remaining -= try splatByte(bw, byte, remaining);357 while (remaining > 0) remaining -= try bw.splatByte(byte, remaining);
358}358}
359359
360/// Writes the same byte many times, allowing short writes.360/// Writes the same byte many times, allowing short writes.
...@@ -368,11 +368,11 @@ pub fn splatByte(bw: *BufferedWriter, byte: u8, n: usize) anyerror!usize {...@@ -368,11 +368,11 @@ pub fn splatByte(bw: *BufferedWriter, byte: u8, n: usize) anyerror!usize {
368/// many times as necessary.368/// many times as necessary.
369pub fn splatBytesAll(bw: *BufferedWriter, bytes: []const u8, splat: usize) anyerror!void {369pub fn splatBytesAll(bw: *BufferedWriter, bytes: []const u8, splat: usize) anyerror!void {
370 var remaining_bytes: usize = bytes.len * splat;370 var remaining_bytes: usize = bytes.len * splat;
371 remaining_bytes -= try splatBytes(bw, bytes, splat);371 remaining_bytes -= try bw.splatBytes(bytes, splat);
372 while (remaining_bytes > 0) {372 while (remaining_bytes > 0) {
373 const leftover = remaining_bytes % bytes.len;373 const leftover = remaining_bytes % bytes.len;
374 const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };374 const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };
375 remaining_bytes -= try splatBytes(bw, &buffers, splat);375 remaining_bytes -= try bw.splatBytes(&buffers, splat);
376 }376 }
377}377}
378378
...@@ -519,7 +519,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp...@@ -519,7 +519,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp
519 const headers_and_trailers = options.headers_and_trailers;519 const headers_and_trailers = options.headers_and_trailers;
520 const headers = headers_and_trailers[0..options.headers_len];520 const headers = headers_and_trailers[0..options.headers_len];
521 switch (options.limit) {521 switch (options.limit) {
522 .nothing => return writevAll(bw, headers_and_trailers),522 .nothing => return bw.writevAll(headers_and_trailers),
523 .unlimited => {523 .unlimited => {
524 // When reading the whole file, we cannot include the trailers in the524 // When reading the whole file, we cannot include the trailers in the
525 // call that reads from the file handle, because we have no way to525 // call that reads from the file handle, because we have no way to
...@@ -528,7 +528,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp...@@ -528,7 +528,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp
528 var i: usize = 0;528 var i: usize = 0;
529 var offset = options.offset;529 var offset = options.offset;
530 while (true) {530 while (true) {
531 var n = try writeFile(bw, file, offset, .unlimited, headers[i..], headers.len - i);531 var n = try bw.writeFile(file, offset, .unlimited, headers[i..], headers.len - i);
532 while (i < headers.len and n >= headers[i].len) {532 while (i < headers.len and n >= headers[i].len) {
533 n -= headers[i].len;533 n -= headers[i].len;
534 i += 1;534 i += 1;
...@@ -546,7 +546,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp...@@ -546,7 +546,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp
546 var i: usize = 0;546 var i: usize = 0;
547 var offset = options.offset;547 var offset = options.offset;
548 while (true) {548 while (true) {
549 var n = try writeFile(bw, file, offset, .limited(len), headers_and_trailers[i..], headers.len - i);549 var n = try bw.writeFile(file, offset, .limited(len), headers_and_trailers[i..], headers.len - i);
550 while (i < headers.len and n >= headers[i].len) {550 while (i < headers.len and n >= headers[i].len) {
551 n -= headers[i].len;551 n -= headers[i].len;
552 i += 1;552 i += 1;
...@@ -564,7 +564,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp...@@ -564,7 +564,7 @@ pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOp
564 if (i >= headers_and_trailers.len) return;564 if (i >= headers_and_trailers.len) return;
565 }565 }
566 headers_and_trailers[i] = headers_and_trailers[i][n..];566 headers_and_trailers[i] = headers_and_trailers[i][n..];
567 return writevAll(bw, headers_and_trailers[i..]);567 return bw.writevAll(headers_and_trailers[i..]);
568 }568 }
569 offset = offset.advance(n);569 offset = offset.advance(n);
570 len -= n;570 len -= n;
...@@ -605,7 +605,7 @@ pub fn alignBuffer(...@@ -605,7 +605,7 @@ pub fn alignBuffer(
605}605}
606606
607pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.fmt.Options) anyerror!void {607pub fn alignBufferOptions(bw: *BufferedWriter, buffer: []const u8, options: std.fmt.Options) anyerror!void {
608 return alignBuffer(bw, buffer, options.width orelse buffer.len, options.alignment, options.fill);608 return bw.alignBuffer(buffer, options.width orelse buffer.len, options.alignment, options.fill);
609}609}
610610
611pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void {611pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void {
...@@ -614,15 +614,15 @@ pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void {...@@ -614,15 +614,15 @@ pub fn printAddress(bw: *BufferedWriter, value: anytype) anyerror!void {
614 .pointer => |info| {614 .pointer => |info| {
615 try bw.writeAll(@typeName(info.child) ++ "@");615 try bw.writeAll(@typeName(info.child) ++ "@");
616 if (info.size == .slice)616 if (info.size == .slice)
617 try printIntOptions(bw, @intFromPtr(value.ptr), 16, .lower, .{})617 try bw.printIntOptions(@intFromPtr(value.ptr), 16, .lower, .{})
618 else618 else
619 try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});619 try bw.printIntOptions(@intFromPtr(value), 16, .lower, .{});
620 return;620 return;
621 },621 },
622 .optional => |info| {622 .optional => |info| {
623 if (@typeInfo(info.child) == .pointer) {623 if (@typeInfo(info.child) == .pointer) {
624 try bw.writeAll(@typeName(info.child) ++ "@");624 try bw.writeAll(@typeName(info.child) ++ "@");
625 try printIntOptions(bw, @intFromPtr(value), 16, .lower, .{});625 try bw.printIntOptions(@intFromPtr(value), 16, .lower, .{});
626 return;626 return;
627 }627 }
628 },628 },
...@@ -648,7 +648,7 @@ pub fn printValue(...@@ -648,7 +648,7 @@ pub fn printValue(
648 } else fmt;648 } else fmt;
649649
650 if (comptime std.mem.eql(u8, actual_fmt, "*")) {650 if (comptime std.mem.eql(u8, actual_fmt, "*")) {
651 return printAddress(bw, value);651 return bw.printAddress(value);
652 }652 }
653653
654 if (std.meta.hasMethod(T, "format")) {654 if (std.meta.hasMethod(T, "format")) {
...@@ -661,24 +661,24 @@ pub fn printValue(...@@ -661,24 +661,24 @@ pub fn printValue(
661 }661 }
662662
663 switch (@typeInfo(T)) {663 switch (@typeInfo(T)) {
664 .float, .comptime_float => return printFloat(bw, actual_fmt, options, value),664 .float, .comptime_float => return bw.printFloat(actual_fmt, options, value),
665 .int, .comptime_int => return printInt(bw, actual_fmt, options, value),665 .int, .comptime_int => return bw.printInt(actual_fmt, options, value),
666 .bool => {666 .bool => {
667 if (actual_fmt.len != 0) invalidFmtError(fmt, value);667 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
668 return alignBufferOptions(bw, if (value) "true" else "false", options);668 return bw.alignBufferOptions(if (value) "true" else "false", options);
669 },669 },
670 .void => {670 .void => {
671 if (actual_fmt.len != 0) invalidFmtError(fmt, value);671 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
672 return alignBufferOptions(bw, "void", options);672 return bw.alignBufferOptions("void", options);
673 },673 },
674 .optional => {674 .optional => {
675 if (actual_fmt.len == 0 or actual_fmt[0] != '?')675 if (actual_fmt.len == 0 or actual_fmt[0] != '?')
676 @compileError("cannot print optional without a specifier (i.e. {?} or {any})");676 @compileError("cannot print optional without a specifier (i.e. {?} or {any})");
677 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);677 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
678 if (value) |payload| {678 if (value) |payload| {
679 return printValue(bw, remaining_fmt, options, payload, max_depth);679 return bw.printValue(remaining_fmt, options, payload, max_depth);
680 } else {680 } else {
681 return alignBufferOptions(bw, "null", options);681 return bw.alignBufferOptions("null", options);
682 }682 }
683 },683 },
684 .error_union => {684 .error_union => {
...@@ -686,9 +686,9 @@ pub fn printValue(...@@ -686,9 +686,9 @@ pub fn printValue(
686 @compileError("cannot format error union without a specifier (i.e. {!} or {any})");686 @compileError("cannot format error union without a specifier (i.e. {!} or {any})");
687 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);687 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
688 if (value) |payload| {688 if (value) |payload| {
689 return printValue(bw, remaining_fmt, options, payload, max_depth);689 return bw.printValue(remaining_fmt, options, payload, max_depth);
690 } else |err| {690 } else |err| {
691 return printValue(bw, "", options, err, max_depth);691 return bw.printValue("", options, err, max_depth);
692 }692 }
693 },693 },
694 .error_set => {694 .error_set => {
...@@ -721,14 +721,14 @@ pub fn printValue(...@@ -721,14 +721,14 @@ pub fn printValue(
721 }721 }
722722
723 try bw.writeByte('(');723 try bw.writeByte('(');
724 try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth);724 try bw.printValue(actual_fmt, options, @intFromEnum(value), max_depth);
725 try bw.writeByte(')');725 try bw.writeByte(')');
726 },726 },
727 .@"union" => |info| {727 .@"union" => |info| {
728 if (actual_fmt.len != 0) invalidFmtError(fmt, value);728 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
729 try bw.writeAll(@typeName(T));729 try bw.writeAll(@typeName(T));
730 if (max_depth == 0) {730 if (max_depth == 0) {
731 bw.writeAll("{ ... }");731 try bw.writeAll("{ ... }");
732 return;732 return;
733 }733 }
734 if (info.tag_type) |UnionTagType| {734 if (info.tag_type) |UnionTagType| {
...@@ -737,13 +737,13 @@ pub fn printValue(...@@ -737,13 +737,13 @@ pub fn printValue(
737 try bw.writeAll(" = ");737 try bw.writeAll(" = ");
738 inline for (info.fields) |u_field| {738 inline for (info.fields) |u_field| {
739 if (value == @field(UnionTagType, u_field.name)) {739 if (value == @field(UnionTagType, u_field.name)) {
740 try printValue(bw, ANY, options, @field(value, u_field.name), max_depth - 1);740 try bw.printValue(ANY, options, @field(value, u_field.name), max_depth - 1);
741 }741 }
742 }742 }
743 try bw.writeAll(" }");743 try bw.writeAll(" }");
744 } else {744 } else {
745 try bw.writeByte('@');745 try bw.writeByte('@');
746 try bw.printIntOptions(@intFromPtr(&value), 16, .lower);746 try bw.printIntOptions(@intFromPtr(&value), 16, .lower, options);
747 }747 }
748 },748 },
749 .@"struct" => |info| {749 .@"struct" => |info| {
...@@ -761,7 +761,7 @@ pub fn printValue(...@@ -761,7 +761,7 @@ pub fn printValue(
761 } else {761 } else {
762 try bw.writeAll(", ");762 try bw.writeAll(", ");
763 }763 }
764 try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1);764 try bw.printValue(ANY, options, @field(value, f.name), max_depth - 1);
765 }765 }
766 try bw.writeAll(" }");766 try bw.writeAll(" }");
767 return;767 return;
...@@ -780,19 +780,19 @@ pub fn printValue(...@@ -780,19 +780,19 @@ pub fn printValue(
780 }780 }
781 try bw.writeAll(f.name);781 try bw.writeAll(f.name);
782 try bw.writeAll(" = ");782 try bw.writeAll(" = ");
783 try printValue(bw, ANY, options, @field(value, f.name), max_depth - 1);783 try bw.printValue(ANY, options, @field(value, f.name), max_depth - 1);
784 }784 }
785 try bw.writeAll(" }");785 try bw.writeAll(" }");
786 },786 },
787 .pointer => |ptr_info| switch (ptr_info.size) {787 .pointer => |ptr_info| switch (ptr_info.size) {
788 .one => switch (@typeInfo(ptr_info.child)) {788 .one => switch (@typeInfo(ptr_info.child)) {
789 .array, .@"enum", .@"union", .@"struct" => {789 .array, .@"enum", .@"union", .@"struct" => {
790 return printValue(bw, actual_fmt, options, value.*, max_depth);790 return bw.printValue(actual_fmt, options, value.*, max_depth);
791 },791 },
792 else => {792 else => {
793 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };793 var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" };
794 try writevAll(bw, &buffers);794 try bw.writevAll(&buffers);
795 try printIntOptions(bw, @intFromPtr(value), 16, .lower, options);795 try bw.printIntOptions(@intFromPtr(value), 16, .lower, options);
796 return;796 return;
797 },797 },
798 },798 },
...@@ -800,10 +800,10 @@ pub fn printValue(...@@ -800,10 +800,10 @@ pub fn printValue(
800 if (actual_fmt.len == 0)800 if (actual_fmt.len == 0)
801 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");801 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
802 if (ptr_info.sentinel() != null) {802 if (ptr_info.sentinel() != null) {
803 return printValue(bw, actual_fmt, options, std.mem.span(value), max_depth);803 return bw.printValue(actual_fmt, options, std.mem.span(value), max_depth);
804 }804 }
805 if (actual_fmt[0] == 's' and ptr_info.child == u8) {805 if (actual_fmt[0] == 's' and ptr_info.child == u8) {
806 return alignBufferOptions(bw, std.mem.span(value), options);806 return bw.alignBufferOptions(std.mem.span(value), options);
807 }807 }
808 invalidFmtError(fmt, value);808 invalidFmtError(fmt, value);
809 },809 },
...@@ -815,19 +815,19 @@ pub fn printValue(...@@ -815,19 +815,19 @@ pub fn printValue(
815 }815 }
816 if (ptr_info.child == u8) switch (actual_fmt.len) {816 if (ptr_info.child == u8) switch (actual_fmt.len) {
817 1 => switch (actual_fmt[0]) {817 1 => switch (actual_fmt[0]) {
818 's' => return alignBufferOptions(bw, value, options),818 's' => return bw.alignBufferOptions(value, options),
819 'x' => return printHex(bw, value, .lower),819 'x' => return bw.printHex(value, .lower),
820 'X' => return printHex(bw, value, .upper),820 'X' => return bw.printHex(value, .upper),
821 else => {},821 else => {},
822 },822 },
823 3 => if (actual_fmt[0] == 'b' and actual_fmt[1] == '6' and actual_fmt[2] == '4') {823 3 => if (actual_fmt[0] == 'b' and actual_fmt[1] == '6' and actual_fmt[2] == '4') {
824 return printBase64(bw, value);824 return bw.printBase64(value);
825 },825 },
826 else => {},826 else => {},
827 };827 };
828 try bw.writeAll("{ ");828 try bw.writeAll("{ ");
829 for (value, 0..) |elem, i| {829 for (value, 0..) |elem, i| {
830 try printValue(bw, actual_fmt, options, elem, max_depth - 1);830 try bw.printValue(actual_fmt, options, elem, max_depth - 1);
831 if (i != value.len - 1) {831 if (i != value.len - 1) {
832 try bw.writeAll(", ");832 try bw.writeAll(", ");
833 }833 }
...@@ -843,16 +843,16 @@ pub fn printValue(...@@ -843,16 +843,16 @@ pub fn printValue(
843 }843 }
844 if (info.child == u8) {844 if (info.child == u8) {
845 if (actual_fmt[0] == 's') {845 if (actual_fmt[0] == 's') {
846 return alignBufferOptions(bw, &value, options);846 return bw.alignBufferOptions(&value, options);
847 } else if (actual_fmt[0] == 'x') {847 } else if (actual_fmt[0] == 'x') {
848 return printHex(bw, &value, .lower);848 return bw.printHex(&value, .lower);
849 } else if (actual_fmt[0] == 'X') {849 } else if (actual_fmt[0] == 'X') {
850 return printHex(bw, &value, .upper);850 return bw.printHex(&value, .upper);
851 }851 }
852 }852 }
853 try bw.writeAll("{ ");853 try bw.writeAll("{ ");
854 for (value, 0..) |elem, i| {854 for (value, 0..) |elem, i| {
855 try printValue(bw, actual_fmt, options, elem, max_depth - 1);855 try bw.printValue(actual_fmt, options, elem, max_depth - 1);
856 if (i < value.len - 1) {856 if (i < value.len - 1) {
857 try bw.writeAll(", ");857 try bw.writeAll(", ");
858 }858 }
...@@ -866,7 +866,7 @@ pub fn printValue(...@@ -866,7 +866,7 @@ pub fn printValue(
866 try bw.writeAll("{ ");866 try bw.writeAll("{ ");
867 var i: usize = 0;867 var i: usize = 0;
868 while (i < info.len) : (i += 1) {868 while (i < info.len) : (i += 1) {
869 try printValue(bw, actual_fmt, options, value[i], max_depth - 1);869 try bw.printValue(actual_fmt, options, value[i], max_depth - 1);
870 if (i < info.len - 1) {870 if (i < info.len - 1) {
871 try bw.writeAll(", ");871 try bw.writeAll(", ");
872 }872 }
...@@ -876,16 +876,16 @@ pub fn printValue(...@@ -876,16 +876,16 @@ pub fn printValue(
876 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),876 .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"),
877 .type => {877 .type => {
878 if (actual_fmt.len != 0) invalidFmtError(fmt, value);878 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
879 return alignBufferOptions(bw, @typeName(value), options);879 return bw.alignBufferOptions(@typeName(value), options);
880 },880 },
881 .enum_literal => {881 .enum_literal => {
882 if (actual_fmt.len != 0) invalidFmtError(fmt, value);882 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
883 const buffer = [_]u8{'.'} ++ @tagName(value);883 const buffer = [_]u8{'.'} ++ @tagName(value);
884 return alignBufferOptions(bw, buffer, options);884 return bw.alignBufferOptions(buffer, options);
885 },885 },
886 .null => {886 .null => {
887 if (actual_fmt.len != 0) invalidFmtError(fmt, value);887 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
888 return alignBufferOptions(bw, "null", options);888 return bw.alignBufferOptions("null", options);
889 },889 },
890 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),890 else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"),
891 }891 }
...@@ -903,34 +903,34 @@ pub fn printInt(...@@ -903,34 +903,34 @@ pub fn printInt(
903 } else value;903 } else value;
904904
905 switch (fmt.len) {905 switch (fmt.len) {
906 0 => return printIntOptions(bw, int_value, 10, .lower, options),906 0 => return bw.printIntOptions(int_value, 10, .lower, options),
907 1 => switch (fmt[0]) {907 1 => switch (fmt[0]) {
908 'd' => return printIntOptions(bw, int_value, 10, .lower, options),908 'd' => return bw.printIntOptions(int_value, 10, .lower, options),
909 'c' => {909 'c' => {
910 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {910 if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) {
911 return printAsciiChar(bw, @as(u8, int_value), options);911 return bw.printAsciiChar(@as(u8, int_value), options);
912 } else {912 } else {
913 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");913 @compileError("cannot print integer that is larger than 8 bits as an ASCII character");
914 }914 }
915 },915 },
916 'u' => {916 'u' => {
917 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {917 if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) {
918 return printUnicodeCodepoint(bw, @as(u21, int_value), options);918 return bw.printUnicodeCodepoint(@as(u21, int_value), options);
919 } else {919 } else {
920 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");920 @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence");
921 }921 }
922 },922 },
923 'b' => return printIntOptions(bw, int_value, 2, .lower, options),923 'b' => return bw.printIntOptions(int_value, 2, .lower, options),
924 'x' => return printIntOptions(bw, int_value, 16, .lower, options),924 'x' => return bw.printIntOptions(int_value, 16, .lower, options),
925 'X' => return printIntOptions(bw, int_value, 16, .upper, options),925 'X' => return bw.printIntOptions(int_value, 16, .upper, options),
926 'o' => return printIntOptions(bw, int_value, 8, .lower, options),926 'o' => return bw.printIntOptions(int_value, 8, .lower, options),
927 'B' => return printByteSize(bw, int_value, .decimal, options),927 'B' => return bw.printByteSize(int_value, .decimal, options),
928 'D' => return printDuration(bw, int_value, options),928 'D' => return bw.printDuration(int_value, options),
929 else => invalidFmtError(fmt, value),929 else => invalidFmtError(fmt, value),
930 },930 },
931 2 => {931 2 => {
932 if (fmt[0] == 'B' and fmt[1] == 'i') {932 if (fmt[0] == 'B' and fmt[1] == 'i') {
933 return printByteSize(bw, int_value, .binary, options);933 return bw.printByteSize(int_value, .binary, options);
934 } else {934 } else {
935 invalidFmtError(fmt, value);935 invalidFmtError(fmt, value);
936 }936 }
...@@ -941,17 +941,17 @@ pub fn printInt(...@@ -941,17 +941,17 @@ pub fn printInt(
941}941}
942942
943pub fn printAsciiChar(bw: *BufferedWriter, c: u8, options: std.fmt.Options) anyerror!void {943pub fn printAsciiChar(bw: *BufferedWriter, c: u8, options: std.fmt.Options) anyerror!void {
944 return alignBufferOptions(bw, @as(*const [1]u8, &c), options);944 return bw.alignBufferOptions(@as(*const [1]u8, &c), options);
945}945}
946946
947pub fn printAscii(bw: *BufferedWriter, bytes: []const u8, options: std.fmt.Options) anyerror!void {947pub fn printAscii(bw: *BufferedWriter, bytes: []const u8, options: std.fmt.Options) anyerror!void {
948 return alignBufferOptions(bw, bytes, options);948 return bw.alignBufferOptions(bytes, options);
949}949}
950950
951pub fn printUnicodeCodepoint(bw: *BufferedWriter, c: u21, options: std.fmt.Options) anyerror!void {951pub fn printUnicodeCodepoint(bw: *BufferedWriter, c: u21, options: std.fmt.Options) anyerror!void {
952 var buf: [4]u8 = undefined;952 var buf: [4]u8 = undefined;
953 const len = try std.unicode.utf8Encode(c, &buf);953 const len = try std.unicode.utf8Encode(c, &buf);
954 return alignBufferOptions(bw, buf[0..len], options);954 return bw.alignBufferOptions(buf[0..len], options);
955}955}
956956
957pub fn printIntOptions(957pub fn printIntOptions(
...@@ -1019,7 +1019,7 @@ pub fn printIntOptions(...@@ -1019,7 +1019,7 @@ pub fn printIntOptions(
1019 }1019 }
1020 }1020 }
10211021
1022 return alignBufferOptions(bw, buf[index..], options);1022 return bw.alignBufferOptions(buf[index..], options);
1023}1023}
10241024
1025pub fn printFloat(1025pub fn printFloat(
...@@ -1036,19 +1036,19 @@ pub fn printFloat(...@@ -1036,19 +1036,19 @@ pub fn printFloat(
1036 const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {1036 const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) {
1037 error.BufferTooSmall => "(float)",1037 error.BufferTooSmall => "(float)",
1038 };1038 };
1039 return alignBufferOptions(bw, s, options);1039 return bw.alignBufferOptions(s, options);
1040 },1040 },
1041 'd' => {1041 'd' => {
1042 const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {1042 const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) {
1043 error.BufferTooSmall => "(float)",1043 error.BufferTooSmall => "(float)",
1044 };1044 };
1045 return alignBufferOptions(bw, s, options);1045 return bw.alignBufferOptions(s, options);
1046 },1046 },
1047 'x' => {1047 'x' => {
1048 var sub_bw: BufferedWriter = undefined;1048 var sub_bw: BufferedWriter = undefined;
1049 sub_bw.initFixed(&buf);1049 sub_bw.initFixed(&buf);
1050 sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable;1050 sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable;
1051 return alignBufferOptions(bw, sub_bw.getWritten(), options);1051 return bw.alignBufferOptions(sub_bw.getWritten(), options);
1052 },1052 },
1053 else => invalidFmtError(fmt, value),1053 else => invalidFmtError(fmt, value),
1054 }1054 }
...@@ -1150,7 +1150,7 @@ pub fn printFloatHexadecimal(bw: *BufferedWriter, value: anytype, opt_precision:...@@ -1150,7 +1150,7 @@ pub fn printFloatHexadecimal(bw: *BufferedWriter, value: anytype, opt_precision:
1150 try bw.splatByteAll('0', precision - trimmed.len);1150 try bw.splatByteAll('0', precision - trimmed.len);
1151 };1151 };
1152 try bw.writeAll("p");1152 try bw.writeAll("p");
1153 try printIntOptions(bw, exponent - exponent_bias, 10, .lower, .{});1153 try bw.printIntOptions(exponent - exponent_bias, 10, .lower, .{});
1154}1154}
11551155
1156pub const ByteSizeUnits = enum {1156pub const ByteSizeUnits = enum {
...@@ -1169,7 +1169,7 @@ pub fn printByteSize(...@@ -1169,7 +1169,7 @@ pub fn printByteSize(
1169 comptime units: ByteSizeUnits,1169 comptime units: ByteSizeUnits,
1170 options: std.fmt.Options,1170 options: std.fmt.Options,
1171) anyerror!void {1171) anyerror!void {
1172 if (value == 0) return alignBufferOptions(bw, "0B", options);1172 if (value == 0) return bw.alignBufferOptions("0B", options);
1173 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.1173 // The worst case in terms of space needed is 32 bytes + 3 for the suffix.
1174 var buf: [std.fmt.float.min_buffer_size + 3]u8 = undefined;1174 var buf: [std.fmt.float.min_buffer_size + 3]u8 = undefined;
11751175
...@@ -1213,7 +1213,7 @@ pub fn printByteSize(...@@ -1213,7 +1213,7 @@ pub fn printByteSize(
1213 },1213 },
1214 }1214 }
12151215
1216 return alignBufferOptions(bw, buf[0..i], options);1216 return bw.alignBufferOptions(buf[0..i], options);
1217}1217}
12181218
1219// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/79481219// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
...@@ -1250,7 +1250,7 @@ pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn {...@@ -1250,7 +1250,7 @@ pub fn invalidFmtError(comptime fmt: []const u8, value: anytype) noreturn {
12501250
1251pub fn printDurationSigned(bw: *BufferedWriter, ns: i64) anyerror!void {1251pub fn printDurationSigned(bw: *BufferedWriter, ns: i64) anyerror!void {
1252 if (ns < 0) try bw.writeByte('-');1252 if (ns < 0) try bw.writeByte('-');
1253 return printDurationUnsigned(bw, @abs(ns));1253 return bw.printDurationUnsigned(@abs(ns));
1254}1254}
12551255
1256pub fn printDurationUnsigned(bw: *BufferedWriter, ns: u64) anyerror!void {1256pub fn printDurationUnsigned(bw: *BufferedWriter, ns: u64) anyerror!void {
...@@ -1296,7 +1296,7 @@ pub fn printDurationUnsigned(bw: *BufferedWriter, ns: u64) anyerror!void {...@@ -1296,7 +1296,7 @@ pub fn printDurationUnsigned(bw: *BufferedWriter, ns: u64) anyerror!void {
1296 }1296 }
1297 }1297 }
12981298
1299 try printIntOptions(bw, ns_remaining, 10, .lower, .{});1299 try bw.printIntOptions(ns_remaining, 10, .lower, .{});
1300 try bw.writeAll("ns");1300 try bw.writeAll("ns");
1301}1301}
13021302
...@@ -1312,7 +1312,7 @@ pub fn printDuration(bw: *BufferedWriter, nanoseconds: anytype, options: std.fmt...@@ -1312,7 +1312,7 @@ pub fn printDuration(bw: *BufferedWriter, nanoseconds: anytype, options: std.fmt
1312 .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable,1312 .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable,
1313 .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable,1313 .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable,
1314 }1314 }
1315 return alignBufferOptions(bw, sub_bw.getWritten(), options);1315 return bw.alignBufferOptions(sub_bw.getWritten(), options);
1316}1316}
13171317
1318pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anyerror!void {1318pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anyerror!void {
...@@ -1321,8 +1321,8 @@ pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anye...@@ -1321,8 +1321,8 @@ pub fn printHex(bw: *BufferedWriter, bytes: []const u8, case: std.fmt.Case) anye
1321 .lower => "0123456789abcdef",1321 .lower => "0123456789abcdef",
1322 };1322 };
1323 for (bytes) |c| {1323 for (bytes) |c| {
1324 try writeByte(bw, charset[c >> 4]);1324 try bw.writeByte(charset[c >> 4]);
1325 try writeByte(bw, charset[c & 15]);1325 try bw.writeByte(charset[c & 15]);
1326 }1326 }
1327}1327}
13281328
...@@ -1334,50 +1334,67 @@ pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!void {...@@ -1334,50 +1334,67 @@ pub fn printBase64(bw: *BufferedWriter, bytes: []const u8) anyerror!void {
1334 }1334 }
1335}1335}
13361336
1337/// Write a single unsigned integer as unsigned LEB128 to the given writer.1337/// Write a single unsigned integer as LEB128 to the given writer.
1338pub fn writeUleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!void {1338pub fn writeUleb128(bw: *BufferedWriter, value: anytype) anyerror!void {
1339 const Arg = @TypeOf(arg);1339 try bw.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1340 const Int = switch (Arg) {1340 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
1341 comptime_int => std.math.IntFittingRange(arg, arg),1341 .int => |value_info| switch (value_info.signedness) {
1342 else => Arg,1342 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),
1343 };1343 .unsigned => value,
1344 const Value = if (@typeInfo(Int).int.bits < 8) u8 else Int;1344 },
1345 var value: Value = arg;1345 else => comptime unreachable,
1346 });
1347}
13461348
1347 while (true) {1349/// Write a single signed integer as LEB128 to the given writer.
1348 const byte: u8 = @truncate(value & 0x7f);1350pub fn writeSleb128(bw: *BufferedWriter, value: anytype) anyerror!void {
1349 value >>= 7;1351 try bw.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1350 if (value == 0) {1352 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
1351 try bw.writeByte(byte);1353 .int => |value_info| switch (value_info.signedness) {
1352 return;1354 .signed => value,
1353 } else {1355 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),
1354 try bw.writeByte(byte | 0x80);1356 },
1355 }1357 else => comptime unreachable,
1356 }1358 });
1357}1359}
13581360
1359/// Write a single signed integer as signed LEB128 to the given writer.1361/// Write a single integer as LEB128 to the given writer.
1360pub fn writeIleb128(bw: *std.io.BufferedWriter, arg: anytype) anyerror!void {1362pub fn writeLeb128(bw: *BufferedWriter, value: anytype) anyerror!void {
1361 const Arg = @TypeOf(arg);1363 const value_info = @typeInfo(@TypeOf(value)).int;
1362 const Int = switch (Arg) {1364 try bw.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{
1363 comptime_int => std.math.IntFittingRange(-@abs(arg), @abs(arg)),1365 .signedness = value_info.signedness,
1364 else => Arg,1366 .bits = std.mem.alignForwardAnyAlign(u16, value_info.bits, 7),
1365 };1367 } }), value));
1366 const Signed = if (@typeInfo(Int).int.bits < 8) i8 else Int;1368}
1367 const Unsigned = std.meta.Int(.unsigned, @typeInfo(Signed).int.bits);
1368 var value: Signed = arg;
13691369
1370fn writeMultipleOf7Leb128(bw: *BufferedWriter, value: anytype) anyerror!void {
1371 const value_info = @typeInfo(@TypeOf(value)).int;
1372 comptime assert(value_info.bits % 7 == 0);
1373 var remaining = value;
1370 while (true) {1374 while (true) {
1371 const unsigned: Unsigned = @bitCast(value);1375 const buffer: []packed struct(u8) { bits: u7, more: bool } = @ptrCast(try bw.writableSlice(1));
1372 const byte: u8 = @truncate(unsigned);1376 for (buffer, 1..) |*byte, len| {
1373 value >>= 6;1377 const more = switch (value_info.signedness) {
1374 if (value == -1 or value == 0) {1378 .signed => remaining >> 6 != remaining >> (value_info.bits - 1),
1375 try bw.writeByte(byte & 0x7F);1379 .unsigned => remaining > std.math.maxInt(u7),
1376 return;1380 };
1377 } else {1381 byte.* = if (@inComptime()) @typeInfo(@TypeOf(buffer)).pointer.child{
1378 value >>= 1;1382 .bits = @bitCast(@as(@Type(.{ .int = .{
1379 try bw.writeByte(byte | 0x80);1383 .signedness = value_info.signedness,
1384 .bits = 7,
1385 } }), @truncate(remaining))),
1386 .more = more,
1387 } else .{
1388 .bits = @bitCast(@as(@Type(.{ .int = .{
1389 .signedness = value_info.signedness,
1390 .bits = 7,
1391 } }), @truncate(remaining))),
1392 .more = more,
1393 };
1394 if (value_info.bits > 7) remaining >>= 7;
1395 if (!more) return bw.advance(len);
1380 }1396 }
1397 bw.advance(buffer.len);
1381 }1398 }
1382}1399}
13831400
lib/std/leb128.zig+2-2
...@@ -55,10 +55,10 @@ test writeUnsignedFixed {...@@ -55,10 +55,10 @@ test writeUnsignedFixed {
55}55}
5656
57/// This is an "advanced" function. It allows one to use a fixed amount of memory to store an57/// This is an "advanced" function. It allows one to use a fixed amount of memory to store an
58/// ILEB128. This defeats the entire purpose of using this data encoding; it will no longer use58/// SLEB128. This defeats the entire purpose of using this data encoding; it will no longer use
59/// fewer bytes to store smaller numbers. The advantage of using a fixed width is that it makes59/// fewer bytes to store smaller numbers. The advantage of using a fixed width is that it makes
60/// fields have a predictable size and so depending on the use case this tradeoff can be worthwhile.60/// fields have a predictable size and so depending on the use case this tradeoff can be worthwhile.
61/// An example use case of this is in emitting DWARF info where one wants to make a ILEB128 field61/// An example use case of this is in emitting DWARF info where one wants to make a SLEB128 field
62/// "relocatable", meaning that it becomes possible to later go back and patch the number to be a62/// "relocatable", meaning that it becomes possible to later go back and patch the number to be a
63/// different value without shifting all the following code.63/// different value without shifting all the following code.
64pub fn writeSignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.signed, l * 7)) void {64pub fn writeSignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.signed, l * 7)) void {
lib/std/math/big/int.zig+16-20
...@@ -2322,13 +2322,7 @@ pub const Const = struct {...@@ -2322,13 +2322,7 @@ pub const Const = struct {
2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.2322 /// this function will fail to print the string, printing "(BigInt)" instead of a number.
2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.2323 /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory.
2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.2324 /// See `toString` and `toStringAlloc` for a way to print big integers without failure.
2325 pub fn format(2325 pub fn format(self: Const, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
2326 self: Const,
2327 comptime fmt: []const u8,
2328 options: std.fmt.FormatOptions,
2329 out_stream: anytype,
2330 ) !void {
2331 _ = options;
2332 comptime var base = 10;2326 comptime var base = 10;
2333 comptime var case: std.fmt.Case = .lower;2327 comptime var case: std.fmt.Case = .lower;
23342328
...@@ -2348,19 +2342,21 @@ pub const Const = struct {...@@ -2348,19 +2342,21 @@ pub const Const = struct {
2348 std.fmt.invalidFmtError(fmt, self);2342 std.fmt.invalidFmtError(fmt, self);
2349 }2343 }
23502344
2351 const available_len = 64;2345 const max_str_len = self.sizeInBaseUpperBound(base);
2352 if (self.limbs.len > available_len)2346 const limbs_len = calcToStringLimbsBufferLen(self.limbs.len, base);
2353 return out_stream.writeAll("(BigInt)");2347 if (bw.writableSlice(max_str_len + @alignOf(Limb) - 1 + @sizeOf(Limb) * limbs_len)) |buf| {
23542348 const limbs: [*]Limb = @alignCast(@ptrCast(std.mem.alignPointer(buf[max_str_len..].ptr, @alignOf(Limb))));
2355 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;2349 bw.advance(self.toString(buf[0..max_str_len], base, case, limbs[0..limbs_len]));
23562350 return;
2357 const biggest: Const = .{2351 } else |_| if (bw.writableSlice(max_str_len)) |buf| {
2358 .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len),2352 const available_len = 64;
2359 .positive = false,2353 var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined;
2360 };2354 if (limbs.len >= limbs_len) {
2361 var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined;2355 bw.advance(self.toString(buf, base, case, &limbs));
2362 const len = self.toString(&buf, base, case, &limbs);2356 return;
2363 return out_stream.writeAll(buf[0..len]);2357 }
2358 } else |_| {}
2359 try bw.writeAll("(BigInt)");
2364 }2360 }
23652361
2366 /// Converts self to a string in the requested base.2362 /// Converts self to a string in the requested base.
lib/std/net.zig+2-2
...@@ -1358,7 +1358,7 @@ fn linuxLookupNameFromHosts(...@@ -1358,7 +1358,7 @@ fn linuxLookupNameFromHosts(
13581358
1359 var line_buf: [512]u8 = undefined;1359 var line_buf: [512]u8 = undefined;
1360 var br = file.reader().buffered(&line_buf);1360 var br = file.reader().buffered(&line_buf);
1361 while (br.takeDelimiterConclusive('\n')) |line| {1361 while (br.takeSentinel('\n')) |line| {
1362 var split_it = mem.splitScalar(u8, line, '#');1362 var split_it = mem.splitScalar(u8, line, '#');
1363 const no_comment_line = split_it.first();1363 const no_comment_line = split_it.first();
13641364
...@@ -1550,7 +1550,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {...@@ -1550,7 +1550,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
15501550
1551 var line_buf: [512]u8 = undefined;1551 var line_buf: [512]u8 = undefined;
1552 var br = file.reader().buffered(&line_buf);1552 var br = file.reader().buffered(&line_buf);
1553 while (br.takeDelimiterConclusive('\n')) |line_with_comment| {1553 while (br.takeSentinel('\n')) |line_with_comment| {
1554 const line = line: {1554 const line = line: {
1555 var split = mem.splitScalar(u8, line_with_comment, '#');1555 var split = mem.splitScalar(u8, line_with_comment, '#');
1556 break :line split.first();1556 break :line split.first();
lib/std/zig.zig+4-4
...@@ -544,9 +544,9 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u...@@ -544,9 +544,9 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u
544 var buffer: std.ArrayListAlignedUnmanaged(u8, .@"2") = .empty;544 var buffer: std.ArrayListAlignedUnmanaged(u8, .@"2") = .empty;
545 defer buffer.deinit(gpa);545 defer buffer.deinit(gpa);
546546
547 try buffer.ensureUnusedCapacity(size_hint);547 try buffer.ensureUnusedCapacity(gpa, size_hint);
548548
549 input.readIntoArrayList(gpa, .init(max_src_size), .@"2", &buffer) catch |err| switch (err) {549 input.readIntoArrayList(gpa, .limited(max_src_size), .@"2", &buffer) catch |err| switch (err) {
550 error.ConnectionResetByPeer => unreachable,550 error.ConnectionResetByPeer => unreachable,
551 error.ConnectionTimedOut => unreachable,551 error.ConnectionTimedOut => unreachable,
552 error.NotOpenForReading => unreachable,552 error.NotOpenForReading => unreachable,
...@@ -568,7 +568,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u...@@ -568,7 +568,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u
568 // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8568 // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8
569 if (std.mem.startsWith(u8, buffer.items, "\xff\xfe")) {569 if (std.mem.startsWith(u8, buffer.items, "\xff\xfe")) {
570 if (buffer.items.len % 2 != 0) return error.InvalidEncoding;570 if (buffer.items.len % 2 != 0) return error.InvalidEncoding;
571 return std.unicode.utf16LeToUtf8AllocZ(gpa, buffer.items) catch |err| switch (err) {571 return std.unicode.utf16LeToUtf8AllocZ(gpa, @ptrCast(buffer.items)) catch |err| switch (err) {
572 error.DanglingSurrogateHalf => error.UnsupportedEncoding,572 error.DanglingSurrogateHalf => error.UnsupportedEncoding,
573 error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding,573 error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding,
574 error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding,574 error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding,
...@@ -576,7 +576,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u...@@ -576,7 +576,7 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: u
576 };576 };
577 }577 }
578578
579 return buffer.toOwnedSliceSentinel(0);579 return buffer.toOwnedSliceSentinel(gpa, 0);
580}580}
581581
582pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void {582pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void {
lib/std/zig/Ast.zig+1-1
...@@ -562,7 +562,7 @@ pub fn renderError(tree: Ast, parse_error: Error, bw: *std.io.BufferedWriter) an...@@ -562,7 +562,7 @@ pub fn renderError(tree: Ast, parse_error: Error, bw: *std.io.BufferedWriter) an
562562
563 .invalid_byte => {563 .invalid_byte => {
564 const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];564 const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];
565 return bw.print("{s} contains invalid byte: '{'}'", .{565 return bw.print("{s} contains invalid byte: '{f'}'", .{
566 switch (tok_slice[0]) {566 switch (tok_slice[0]) {
567 '\'' => "character literal",567 '\'' => "character literal",
568 '"', '\\' => "string literal",568 '"', '\\' => "string literal",
lib/std/zig/AstGen.zig+7-6
...@@ -11465,7 +11465,7 @@ fn failWithStrLitError(...@@ -11465,7 +11465,7 @@ fn failWithStrLitError(
11465 astgen,11465 astgen,
11466 token,11466 token,
11467 @intCast(offset + err.offset()),11467 @intCast(offset + err.offset()),
11468 "{}",11468 "{f}",
11469 .{err.fmt(raw_string)},11469 .{err.fmt(raw_string)},
11470 );11470 );
11471}11471}
...@@ -13898,8 +13898,9 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {...@@ -13898,8 +13898,9 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {
13898 assert(tree.errors.len > 0);13898 assert(tree.errors.len > 0);
1389913899
13900 var msg: std.io.AllocatingWriter = undefined;13900 var msg: std.io.AllocatingWriter = undefined;
13901 const msg_writer = msg.init(gpa);13901 msg.init(gpa);
13902 defer msg.deinit();13902 defer msg.deinit();
13903 const msg_bw = &msg.buffered_writer;
1390313904
13904 var notes: std.ArrayListUnmanaged(u32) = .empty;13905 var notes: std.ArrayListUnmanaged(u32) = .empty;
13905 defer notes.deinit(gpa);13906 defer notes.deinit(gpa);
...@@ -13933,19 +13934,19 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {...@@ -13933,19 +13934,19 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {
13933 .extra = .{ .offset = bad_off },13934 .extra = .{ .offset = bad_off },
13934 };13935 };
13935 msg.clearRetainingCapacity();13936 msg.clearRetainingCapacity();
13936 tree.renderError(err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)13937 tree.renderError(err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
13937 return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.getWritten()}, notes.items);13938 return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.getWritten()}, notes.items);
13938 }13939 }
1393913940
13940 var cur_err = tree.errors[0];13941 var cur_err = tree.errors[0];
13941 for (tree.errors[1..]) |err| {13942 for (tree.errors[1..]) |err| {
13942 if (err.is_note) {13943 if (err.is_note) {
13943 tree.renderError(err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)13944 tree.renderError(err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
13944 try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.getWritten()}));13945 try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.getWritten()}));
13945 } else {13946 } else {
13946 // Flush error13947 // Flush error
13947 const extra_offset = tree.errorOffset(cur_err);13948 const extra_offset = tree.errorOffset(cur_err);
13948 tree.renderError(cur_err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)13949 tree.renderError(cur_err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
13949 try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);13950 try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
13950 notes.clearRetainingCapacity();13951 notes.clearRetainingCapacity();
13951 cur_err = err;13952 cur_err = err;
...@@ -13959,7 +13960,7 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {...@@ -13959,7 +13960,7 @@ fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {
1395913960
13960 // Flush error13961 // Flush error
13961 const extra_offset = tree.errorOffset(cur_err);13962 const extra_offset = tree.errorOffset(cur_err);
13962 tree.renderError(cur_err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)13963 tree.renderError(cur_err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
13963 try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);13964 try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
13964}13965}
1396513966
lib/std/zig/LibCInstallation.zig+1-1
...@@ -43,7 +43,7 @@ pub fn parse(...@@ -43,7 +43,7 @@ pub fn parse(
43 }43 }
44 }44 }
4545
46 const contents = try std.fs.cwd().readFileAlloc(allocator, libc_file, std.math.maxInt(usize));46 const contents = try std.fs.cwd().readFileAlloc(libc_file, allocator, .unlimited);
47 defer allocator.free(contents);47 defer allocator.free(contents);
4848
49 var it = std.mem.tokenizeScalar(u8, contents, '\n');49 var it = std.mem.tokenizeScalar(u8, contents, '\n');
lib/std/zig/ZonGen.zig+3-2
...@@ -778,7 +778,7 @@ fn lowerStrLitError(...@@ -778,7 +778,7 @@ fn lowerStrLitError(
778 zg,778 zg,
779 token,779 token,
780 @intCast(offset + err.offset()),780 @intCast(offset + err.offset()),
781 "{}",781 "{f}",
782 .{err.fmt(raw_string)},782 .{err.fmt(raw_string)},
783 );783 );
784}784}
...@@ -885,8 +885,9 @@ fn lowerAstErrors(zg: *ZonGen) Allocator.Error!void {...@@ -885,8 +885,9 @@ fn lowerAstErrors(zg: *ZonGen) Allocator.Error!void {
885 assert(tree.errors.len > 0);885 assert(tree.errors.len > 0);
886886
887 var msg: std.io.AllocatingWriter = undefined;887 var msg: std.io.AllocatingWriter = undefined;
888 const msg_bw = msg.init(gpa);888 msg.init(gpa);
889 defer msg.deinit();889 defer msg.deinit();
890 const msg_bw = &msg.buffered_writer;
890891
891 var notes: std.ArrayListUnmanaged(Zoir.CompileError.Note) = .empty;892 var notes: std.ArrayListUnmanaged(Zoir.CompileError.Note) = .empty;
892 defer notes.deinit(gpa);893 defer notes.deinit(gpa);
lib/std/zig/llvm/BitcodeReader.zig+12-12
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1allocator: std.mem.Allocator,1allocator: std.mem.Allocator,
2record_arena: std.heap.ArenaAllocator.State,2record_arena: std.heap.ArenaAllocator.State,
3reader: std.io.AnyReader,3br: *std.io.BufferedReader,
4keep_names: bool,4keep_names: bool,
5bit_buffer: u32,5bit_buffer: u32,
6bit_offset: u5,6bit_offset: u5,
...@@ -93,14 +93,14 @@ pub const Record = struct {...@@ -93,14 +93,14 @@ pub const Record = struct {
93};93};
9494
95pub const InitOptions = struct {95pub const InitOptions = struct {
96 reader: std.io.AnyReader,96 br: *std.io.BufferedReader,
97 keep_names: bool = false,97 keep_names: bool = false,
98};98};
99pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {99pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
100 return .{100 return .{
101 .allocator = allocator,101 .allocator = allocator,
102 .record_arena = .{},102 .record_arena = .{},
103 .reader = options.reader,103 .br = options.br,
104 .keep_names = options.keep_names,104 .keep_names = options.keep_names,
105 .bit_buffer = 0,105 .bit_buffer = 0,
106 .bit_offset = 0,106 .bit_offset = 0,
...@@ -170,9 +170,9 @@ pub fn next(bc: *BitcodeReader) !?Item {...@@ -170,9 +170,9 @@ pub fn next(bc: *BitcodeReader) !?Item {
170 }170 }
171}171}
172172
173pub fn skipBlock(bc: *BitcodeReader, block: Block) !void {173pub fn skipBlock(bc: *BitcodeReader, block: Block) anyerror!void {
174 assert(bc.bit_offset == 0);174 assert(bc.bit_offset == 0);
175 try bc.reader.skipBytes(@as(u34, block.len) * 4, .{});175 try bc.br.discard(4 * @as(u34, block.len));
176 try bc.endBlock();176 try bc.endBlock();
177}177}
178178
...@@ -369,21 +369,21 @@ fn align32Bits(bc: *BitcodeReader) void {...@@ -369,21 +369,21 @@ fn align32Bits(bc: *BitcodeReader) void {
369 bc.bit_offset = 0;369 bc.bit_offset = 0;
370}370}
371371
372fn read32Bits(bc: *BitcodeReader) !u32 {372fn read32Bits(bc: *BitcodeReader) anyerror!u32 {
373 assert(bc.bit_offset == 0);373 assert(bc.bit_offset == 0);
374 return bc.reader.readInt(u32, .little);374 return bc.br.takeInt(u32, .little);
375}375}
376376
377fn readBytes(bc: *BitcodeReader, bytes: []u8) !void {377fn readBytes(bc: *BitcodeReader, bytes: []u8) anyerror!void {
378 assert(bc.bit_offset == 0);378 assert(bc.bit_offset == 0);
379 try bc.reader.readNoEof(bytes);379 try bc.br.read(bytes);
380380
381 const trailing_bytes = bytes.len % 4;381 const trailing_bytes = bytes.len % 4;
382 if (trailing_bytes > 0) {382 if (trailing_bytes > 0) {
383 var bit_buffer = [1]u8{0} ** 4;383 var bit_buffer: [4]u8 = @splat(0);
384 try bc.reader.readNoEof(bit_buffer[trailing_bytes..]);384 try bc.br.read(bit_buffer[trailing_bytes..]);
385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);385 bc.bit_buffer = std.mem.readInt(u32, &bit_buffer, .little);
386 bc.bit_offset = @intCast(trailing_bytes * 8);386 bc.bit_offset = @intCast(8 * trailing_bytes);
387 }387 }
388}388}
389389
lib/std/zig/llvm/Builder.zig+343-508
...@@ -91,26 +91,21 @@ pub const String = enum(u32) {...@@ -91,26 +91,21 @@ pub const String = enum(u32) {
91 string: String,91 string: String,
92 builder: *const Builder,92 builder: *const Builder,
93 };93 };
94 fn format(94 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
95 data: FormatData,
96 comptime fmt_str: []const u8,
97 _: std.fmt.FormatOptions,
98 writer: anytype,
99 ) @TypeOf(writer).Error!void {
100 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|95 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
101 @compileError("invalid format string: '" ++ fmt_str ++ "'");96 @compileError("invalid format string: '" ++ fmt_str ++ "'");
102 assert(data.string != .none);97 assert(data.string != .none);
103 const string_slice = data.string.slice(data.builder) orelse98 const string_slice = data.string.slice(data.builder) orelse
104 return writer.print("{d}", .{@intFromEnum(data.string)});99 return bw.print("{d}", .{@intFromEnum(data.string)});
105 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|100 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
106 return writer.writeAll(string_slice);101 return bw.writeAll(string_slice);
107 try printEscapedString(102 try printEscapedString(
108 string_slice,103 string_slice,
109 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|104 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
110 .always_quote105 .always_quote
111 else106 else
112 .quote_unless_valid_identifier,107 .quote_unless_valid_identifier,
113 writer,108 bw,
114 );109 );
115 }110 }
116 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {111 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
...@@ -228,7 +223,7 @@ pub const Type = enum(u32) {...@@ -228,7 +223,7 @@ pub const Type = enum(u32) {
228 _,223 _,
229224
230 pub const ptr_amdgpu_constant =225 pub const ptr_amdgpu_constant =
231 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));226 @field(Type, std.fmt.comptimePrint("ptr{f }", .{AddrSpace.amdgpu.constant}));
232227
233 pub const Tag = enum(u4) {228 pub const Tag = enum(u4) {
234 simple,229 simple,
...@@ -654,17 +649,12 @@ pub const Type = enum(u32) {...@@ -654,17 +649,12 @@ pub const Type = enum(u32) {
654 type: Type,649 type: Type,
655 builder: *const Builder,650 builder: *const Builder,
656 };651 };
657 fn format(652 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
658 data: FormatData,
659 comptime fmt_str: []const u8,
660 fmt_opts: std.fmt.FormatOptions,
661 writer: anytype,
662 ) @TypeOf(writer).Error!void {
663 assert(data.type != .none);653 assert(data.type != .none);
664 if (comptime std.mem.eql(u8, fmt_str, "m")) {654 if (comptime std.mem.eql(u8, fmt_str, "m")) {
665 const item = data.builder.type_items.items[@intFromEnum(data.type)];655 const item = data.builder.type_items.items[@intFromEnum(data.type)];
666 switch (item.tag) {656 switch (item.tag) {
667 .simple => try writer.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {657 .simple => try bw.writeAll(switch (@as(Simple, @enumFromInt(item.data))) {
668 .void => "isVoid",658 .void => "isVoid",
669 .half => "f16",659 .half => "f16",
670 .bfloat => "bf16",660 .bfloat => "bf16",
...@@ -681,29 +671,29 @@ pub const Type = enum(u32) {...@@ -681,29 +671,29 @@ pub const Type = enum(u32) {
681 .function, .vararg_function => |kind| {671 .function, .vararg_function => |kind| {
682 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);672 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
683 const params = extra.trail.next(extra.data.params_len, Type, data.builder);673 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
684 try writer.print("f_{m}", .{extra.data.ret.fmt(data.builder)});674 try bw.print("f_{fm}", .{extra.data.ret.fmt(data.builder)});
685 for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)});675 for (params) |param| try bw.print("{fm}", .{param.fmt(data.builder)});
686 switch (kind) {676 switch (kind) {
687 .function => {},677 .function => {},
688 .vararg_function => try writer.writeAll("vararg"),678 .vararg_function => try bw.writeAll("vararg"),
689 else => unreachable,679 else => unreachable,
690 }680 }
691 try writer.writeByte('f');681 try bw.writeByte('f');
692 },682 },
693 .integer => try writer.print("i{d}", .{item.data}),683 .integer => try bw.print("i{d}", .{item.data}),
694 .pointer => try writer.print("p{d}", .{item.data}),684 .pointer => try bw.print("p{d}", .{item.data}),
695 .target => {685 .target => {
696 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);686 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
697 const types = extra.trail.next(extra.data.types_len, Type, data.builder);687 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
698 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);688 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
699 try writer.print("t{s}", .{extra.data.name.slice(data.builder).?});689 try bw.print("t{s}", .{extra.data.name.slice(data.builder).?});
700 for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)});690 for (types) |ty| try bw.print("_{fm}", .{ty.fmt(data.builder)});
701 for (ints) |int| try writer.print("_{d}", .{int});691 for (ints) |int| try bw.print("_{d}", .{int});
702 try writer.writeByte('t');692 try bw.writeByte('t');
703 },693 },
704 .vector, .scalable_vector => |kind| {694 .vector, .scalable_vector => |kind| {
705 const extra = data.builder.typeExtraData(Type.Vector, item.data);695 const extra = data.builder.typeExtraData(Type.Vector, item.data);
706 try writer.print("{s}v{d}{m}", .{696 try bw.print("{s}v{d}{fm}", .{
707 switch (kind) {697 switch (kind) {
708 .vector => "",698 .vector => "",
709 .scalable_vector => "nx",699 .scalable_vector => "nx",
...@@ -719,24 +709,24 @@ pub const Type = enum(u32) {...@@ -719,24 +709,24 @@ pub const Type = enum(u32) {
719 .array => Type.Array,709 .array => Type.Array,
720 else => unreachable,710 else => unreachable,
721 }, item.data);711 }, item.data);
722 try writer.print("a{d}{m}", .{ extra.length(), extra.child.fmt(data.builder) });712 try bw.print("a{d}{fm}", .{ extra.length(), extra.child.fmt(data.builder) });
723 },713 },
724 .structure, .packed_structure => {714 .structure, .packed_structure => {
725 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);715 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
726 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);716 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
727 try writer.writeAll("sl_");717 try bw.writeAll("sl_");
728 for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)});718 for (fields) |field| try bw.print("{fm}", .{field.fmt(data.builder)});
729 try writer.writeByte('s');719 try bw.writeByte('s');
730 },720 },
731 .named_structure => {721 .named_structure => {
732 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);722 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
733 try writer.writeAll("s_");723 try bw.writeAll("s_");
734 if (extra.id.slice(data.builder)) |id| try writer.writeAll(id);724 if (extra.id.slice(data.builder)) |id| try bw.writeAll(id);
735 },725 },
736 }726 }
737 return;727 return;
738 }728 }
739 if (std.enums.tagName(Type, data.type)) |name| return writer.writeAll(name);729 if (std.enums.tagName(Type, data.type)) |name| return bw.writeAll(name);
740 const item = data.builder.type_items.items[@intFromEnum(data.type)];730 const item = data.builder.type_items.items[@intFromEnum(data.type)];
741 switch (item.tag) {731 switch (item.tag) {
742 .simple => unreachable,732 .simple => unreachable,
...@@ -744,40 +734,40 @@ pub const Type = enum(u32) {...@@ -744,40 +734,40 @@ pub const Type = enum(u32) {
744 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);734 var extra = data.builder.typeExtraDataTrail(Type.Function, item.data);
745 const params = extra.trail.next(extra.data.params_len, Type, data.builder);735 const params = extra.trail.next(extra.data.params_len, Type, data.builder);
746 if (!comptime std.mem.eql(u8, fmt_str, ">"))736 if (!comptime std.mem.eql(u8, fmt_str, ">"))
747 try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)});737 try bw.print("{f%} ", .{extra.data.ret.fmt(data.builder)});
748 if (!comptime std.mem.eql(u8, fmt_str, "<")) {738 if (!comptime std.mem.eql(u8, fmt_str, "<")) {
749 try writer.writeByte('(');739 try bw.writeByte('(');
750 for (params, 0..) |param, index| {740 for (params, 0..) |param, index| {
751 if (index > 0) try writer.writeAll(", ");741 if (index > 0) try bw.writeAll(", ");
752 try writer.print("{%}", .{param.fmt(data.builder)});742 try bw.print("{f%}", .{param.fmt(data.builder)});
753 }743 }
754 switch (kind) {744 switch (kind) {
755 .function => {},745 .function => {},
756 .vararg_function => {746 .vararg_function => {
757 if (params.len > 0) try writer.writeAll(", ");747 if (params.len > 0) try bw.writeAll(", ");
758 try writer.writeAll("...");748 try bw.writeAll("...");
759 },749 },
760 else => unreachable,750 else => unreachable,
761 }751 }
762 try writer.writeByte(')');752 try bw.writeByte(')');
763 }753 }
764 },754 },
765 .integer => try writer.print("i{d}", .{item.data}),755 .integer => try bw.print("i{d}", .{item.data}),
766 .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}),756 .pointer => try bw.print("ptr{f }", .{@as(AddrSpace, @enumFromInt(item.data))}),
767 .target => {757 .target => {
768 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);758 var extra = data.builder.typeExtraDataTrail(Type.Target, item.data);
769 const types = extra.trail.next(extra.data.types_len, Type, data.builder);759 const types = extra.trail.next(extra.data.types_len, Type, data.builder);
770 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);760 const ints = extra.trail.next(extra.data.ints_len, u32, data.builder);
771 try writer.print(761 try bw.print(
772 \\target({"}762 \\target({f"}
773 , .{extra.data.name.fmt(data.builder)});763 , .{extra.data.name.fmt(data.builder)});
774 for (types) |ty| try writer.print(", {%}", .{ty.fmt(data.builder)});764 for (types) |ty| try bw.print(", {f%}", .{ty.fmt(data.builder)});
775 for (ints) |int| try writer.print(", {d}", .{int});765 for (ints) |int| try bw.print(", {d}", .{int});
776 try writer.writeByte(')');766 try bw.writeByte(')');
777 },767 },
778 .vector, .scalable_vector => |kind| {768 .vector, .scalable_vector => |kind| {
779 const extra = data.builder.typeExtraData(Type.Vector, item.data);769 const extra = data.builder.typeExtraData(Type.Vector, item.data);
780 try writer.print("<{s}{d} x {%}>", .{770 try bw.print("<{s}{d} x {f%}>", .{
781 switch (kind) {771 switch (kind) {
782 .vector => "",772 .vector => "",
783 .scalable_vector => "vscale x ",773 .scalable_vector => "vscale x ",
...@@ -793,38 +783,38 @@ pub const Type = enum(u32) {...@@ -793,38 +783,38 @@ pub const Type = enum(u32) {
793 .array => Type.Array,783 .array => Type.Array,
794 else => unreachable,784 else => unreachable,
795 }, item.data);785 }, item.data);
796 try writer.print("[{d} x {%}]", .{ extra.length(), extra.child.fmt(data.builder) });786 try bw.print("[{d} x {f%}]", .{ extra.length(), extra.child.fmt(data.builder) });
797 },787 },
798 .structure, .packed_structure => |kind| {788 .structure, .packed_structure => |kind| {
799 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);789 var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data);
800 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);790 const fields = extra.trail.next(extra.data.fields_len, Type, data.builder);
801 switch (kind) {791 switch (kind) {
802 .structure => {},792 .structure => {},
803 .packed_structure => try writer.writeByte('<'),793 .packed_structure => try bw.writeByte('<'),
804 else => unreachable,794 else => unreachable,
805 }795 }
806 try writer.writeAll("{ ");796 try bw.writeAll("{ ");
807 for (fields, 0..) |field, index| {797 for (fields, 0..) |field, index| {
808 if (index > 0) try writer.writeAll(", ");798 if (index > 0) try bw.writeAll(", ");
809 try writer.print("{%}", .{field.fmt(data.builder)});799 try bw.print("{f%}", .{field.fmt(data.builder)});
810 }800 }
811 try writer.writeAll(" }");801 try bw.writeAll(" }");
812 switch (kind) {802 switch (kind) {
813 .structure => {},803 .structure => {},
814 .packed_structure => try writer.writeByte('>'),804 .packed_structure => try bw.writeByte('>'),
815 else => unreachable,805 else => unreachable,
816 }806 }
817 },807 },
818 .named_structure => {808 .named_structure => {
819 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);809 const extra = data.builder.typeExtraData(Type.NamedStructure, item.data);
820 if (comptime std.mem.eql(u8, fmt_str, "%")) try writer.print("%{}", .{810 if (comptime std.mem.eql(u8, fmt_str, "%")) try bw.print("%{f}", .{
821 extra.id.fmt(data.builder),811 extra.id.fmt(data.builder),
822 }) else switch (extra.body) {812 }) else switch (extra.body) {
823 .none => try writer.writeAll("opaque"),813 .none => try bw.writeAll("opaque"),
824 else => try format(.{814 else => try format(.{
825 .type = extra.body,815 .type = extra.body,
826 .builder = data.builder,816 .builder = data.builder,
827 }, fmt_str, fmt_opts, writer),817 }, bw, fmt_str),
828 }818 }
829 },819 },
830 }820 }
...@@ -1139,12 +1129,7 @@ pub const Attribute = union(Kind) {...@@ -1139,12 +1129,7 @@ pub const Attribute = union(Kind) {
1139 attribute_index: Index,1129 attribute_index: Index,
1140 builder: *const Builder,1130 builder: *const Builder,
1141 };1131 };
1142 fn format(1132 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
1143 data: FormatData,
1144 comptime fmt_str: []const u8,
1145 _: std.fmt.FormatOptions,
1146 writer: anytype,
1147 ) @TypeOf(writer).Error!void {
1148 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|1133 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|
1149 @compileError("invalid format string: '" ++ fmt_str ++ "'");1134 @compileError("invalid format string: '" ++ fmt_str ++ "'");
1150 const attribute = data.attribute_index.toAttribute(data.builder);1135 const attribute = data.attribute_index.toAttribute(data.builder);
...@@ -1219,37 +1204,37 @@ pub const Attribute = union(Kind) {...@@ -1219,37 +1204,37 @@ pub const Attribute = union(Kind) {
1219 .no_sanitize_address,1204 .no_sanitize_address,
1220 .no_sanitize_hwaddress,1205 .no_sanitize_hwaddress,
1221 .sanitize_address_dyninit,1206 .sanitize_address_dyninit,
1222 => try writer.print(" {s}", .{@tagName(attribute)}),1207 => try bw.print(" {s}", .{@tagName(attribute)}),
1223 .byval,1208 .byval,
1224 .byref,1209 .byref,
1225 .preallocated,1210 .preallocated,
1226 .inalloca,1211 .inalloca,
1227 .sret,1212 .sret,
1228 .elementtype,1213 .elementtype,
1229 => |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),1214 => |ty| try bw.print(" {s}({f%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
1230 .@"align" => |alignment| try writer.print("{ }", .{alignment}),1215 .@"align" => |alignment| try bw.print("{f }", .{alignment}),
1231 .dereferenceable,1216 .dereferenceable,
1232 .dereferenceable_or_null,1217 .dereferenceable_or_null,
1233 => |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),1218 => |size| try bw.print(" {s}({d})", .{ @tagName(attribute), size }),
1234 .nofpclass => |fpclass| {1219 .nofpclass => |fpclass| {
1235 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;1220 const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
1236 try writer.print(" {s}(", .{@tagName(attribute)});1221 try bw.print(" {s}(", .{@tagName(attribute)});
1237 var any = false;1222 var any = false;
1238 var remaining: Int = @bitCast(fpclass);1223 var remaining: Int = @bitCast(fpclass);
1239 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {1224 inline for (@typeInfo(FpClass).@"struct".decls) |decl| {
1240 const pattern: Int = @bitCast(@field(FpClass, decl.name));1225 const pattern: Int = @bitCast(@field(FpClass, decl.name));
1241 if (remaining & pattern == pattern) {1226 if (remaining & pattern == pattern) {
1242 if (!any) {1227 if (!any) {
1243 try writer.writeByte(' ');1228 try bw.writeByte(' ');
1244 any = true;1229 any = true;
1245 }1230 }
1246 try writer.writeAll(decl.name);1231 try bw.writeAll(decl.name);
1247 remaining &= ~pattern;1232 remaining &= ~pattern;
1248 }1233 }
1249 }1234 }
1250 try writer.writeByte(')');1235 try bw.writeByte(')');
1251 },1236 },
1252 .alignstack => |alignment| try writer.print(1237 .alignstack => |alignment| try bw.print(
1253 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)1238 if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
1254 " {s}={d}"1239 " {s}={d}"
1255 else1240 else
...@@ -1257,53 +1242,53 @@ pub const Attribute = union(Kind) {...@@ -1257,53 +1242,53 @@ pub const Attribute = union(Kind) {
1257 .{ @tagName(attribute), alignment.toByteUnits() orelse return },1242 .{ @tagName(attribute), alignment.toByteUnits() orelse return },
1258 ),1243 ),
1259 .allockind => |allockind| {1244 .allockind => |allockind| {
1260 try writer.print(" {s}(\"", .{@tagName(attribute)});1245 try bw.print(" {s}(\"", .{@tagName(attribute)});
1261 var any = false;1246 var any = false;
1262 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {1247 inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
1263 if (comptime std.mem.eql(u8, field.name, "_")) continue;1248 if (comptime std.mem.eql(u8, field.name, "_")) continue;
1264 if (@field(allockind, field.name)) {1249 if (@field(allockind, field.name)) {
1265 if (!any) {1250 if (!any) {
1266 try writer.writeByte(',');1251 try bw.writeByte(',');
1267 any = true;1252 any = true;
1268 }1253 }
1269 try writer.writeAll(field.name);1254 try bw.writeAll(field.name);
1270 }1255 }
1271 }1256 }
1272 try writer.writeAll("\")");1257 try bw.writeAll("\")");
1273 },1258 },
1274 .allocsize => |allocsize| {1259 .allocsize => |allocsize| {
1275 try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });1260 try bw.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
1276 if (allocsize.num_elems != AllocSize.none)1261 if (allocsize.num_elems != AllocSize.none)
1277 try writer.print(",{d}", .{allocsize.num_elems});1262 try bw.print(",{d}", .{allocsize.num_elems});
1278 try writer.writeByte(')');1263 try bw.writeByte(')');
1279 },1264 },
1280 .memory => |memory| {1265 .memory => |memory| {
1281 try writer.print(" {s}(", .{@tagName(attribute)});1266 try bw.print(" {s}(", .{@tagName(attribute)});
1282 var any = memory.other != .none or1267 var any = memory.other != .none or
1283 (memory.argmem == .none and memory.inaccessiblemem == .none);1268 (memory.argmem == .none and memory.inaccessiblemem == .none);
1284 if (any) try writer.writeAll(@tagName(memory.other));1269 if (any) try bw.writeAll(@tagName(memory.other));
1285 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {1270 inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
1286 if (@field(memory, kind) != memory.other) {1271 if (@field(memory, kind) != memory.other) {
1287 if (any) try writer.writeAll(", ");1272 if (any) try bw.writeAll(", ");
1288 try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });1273 try bw.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
1289 any = true;1274 any = true;
1290 }1275 }
1291 }1276 }
1292 try writer.writeByte(')');1277 try bw.writeByte(')');
1293 },1278 },
1294 .uwtable => |uwtable| if (uwtable != .none) {1279 .uwtable => |uwtable| if (uwtable != .none) {
1295 try writer.print(" {s}", .{@tagName(attribute)});1280 try bw.print(" {s}", .{@tagName(attribute)});
1296 if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});1281 if (uwtable != UwTable.default) try bw.print("({s})", .{@tagName(uwtable)});
1297 },1282 },
1298 .vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{1283 .vscale_range => |vscale_range| try bw.print(" {s}({d},{d})", .{
1299 @tagName(attribute),1284 @tagName(attribute),
1300 vscale_range.min.toByteUnits().?,1285 vscale_range.min.toByteUnits().?,
1301 vscale_range.max.toByteUnits() orelse 0,1286 vscale_range.max.toByteUnits() orelse 0,
1302 }),1287 }),
1303 .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {1288 .string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {
1304 try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)});1289 try bw.print(" {f\"}", .{string_attr.kind.fmt(data.builder)});
1305 if (string_attr.value != .empty)1290 if (string_attr.value != .empty)
1306 try writer.print("={\"}", .{string_attr.value.fmt(data.builder)});1291 try bw.print("={f\"}", .{string_attr.value.fmt(data.builder)});
1307 },1292 },
1308 .none => unreachable,1293 .none => unreachable,
1309 }1294 }
...@@ -1583,16 +1568,11 @@ pub const Attributes = enum(u32) {...@@ -1583,16 +1568,11 @@ pub const Attributes = enum(u32) {
1583 attributes: Attributes,1568 attributes: Attributes,
1584 builder: *const Builder,1569 builder: *const Builder,
1585 };1570 };
1586 fn format(1571 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
1587 data: FormatData,
1588 comptime fmt_str: []const u8,
1589 fmt_opts: std.fmt.FormatOptions,
1590 writer: anytype,
1591 ) @TypeOf(writer).Error!void {
1592 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{1572 for (data.attributes.slice(data.builder)) |attribute_index| try Attribute.Index.format(.{
1593 .attribute_index = attribute_index,1573 .attribute_index = attribute_index,
1594 .builder = data.builder,1574 .builder = data.builder,
1595 }, fmt_str, fmt_opts, writer);1575 }, bw, fmt_str);
1596 }1576 }
1597 pub fn fmt(self: Attributes, builder: *const Builder) std.fmt.Formatter(format) {1577 pub fn fmt(self: Attributes, builder: *const Builder) std.fmt.Formatter(format) {
1598 return .{ .data = .{ .attributes = self, .builder = builder } };1578 return .{ .data = .{ .attributes = self, .builder = builder } };
...@@ -1781,22 +1761,12 @@ pub const Linkage = enum(u4) {...@@ -1781,22 +1761,12 @@ pub const Linkage = enum(u4) {
1781 extern_weak = 7,1761 extern_weak = 7,
1782 external = 0,1762 external = 0,
17831763
1784 pub fn format(1764 pub fn format(self: Linkage, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1785 self: Linkage,1765 if (self != .external) try bw.print(" {s}", .{@tagName(self)});
1786 comptime _: []const u8,
1787 _: std.fmt.FormatOptions,
1788 writer: anytype,
1789 ) @TypeOf(writer).Error!void {
1790 if (self != .external) try writer.print(" {s}", .{@tagName(self)});
1791 }1766 }
17921767
1793 fn formatOptional(1768 fn formatOptional(data: ?Linkage, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1794 data: ?Linkage,1769 if (data) |linkage| try bw.print(" {s}", .{@tagName(linkage)});
1795 comptime _: []const u8,
1796 _: std.fmt.FormatOptions,
1797 writer: anytype,
1798 ) @TypeOf(writer).Error!void {
1799 if (data) |linkage| try writer.print(" {s}", .{@tagName(linkage)});
1800 }1770 }
1801 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {1771 pub fn fmtOptional(self: ?Linkage) std.fmt.Formatter(formatOptional) {
1802 return .{ .data = self };1772 return .{ .data = self };
...@@ -1808,13 +1778,8 @@ pub const Preemption = enum {...@@ -1808,13 +1778,8 @@ pub const Preemption = enum {
1808 dso_local,1778 dso_local,
1809 implicit_dso_local,1779 implicit_dso_local,
18101780
1811 pub fn format(1781 pub fn format(self: Preemption, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1812 self: Preemption,1782 if (self == .dso_local) try bw.print(" {s}", .{@tagName(self)});
1813 comptime _: []const u8,
1814 _: std.fmt.FormatOptions,
1815 writer: anytype,
1816 ) @TypeOf(writer).Error!void {
1817 if (self == .dso_local) try writer.print(" {s}", .{@tagName(self)});
1818 }1783 }
1819};1784};
18201785
...@@ -1833,10 +1798,10 @@ pub const Visibility = enum(u2) {...@@ -1833,10 +1798,10 @@ pub const Visibility = enum(u2) {
18331798
1834 pub fn format(1799 pub fn format(
1835 self: Visibility,1800 self: Visibility,
1836 comptime _: []const u8,1801 comptime format_string: []const u8,
1837 _: std.fmt.FormatOptions,
1838 writer: anytype,1802 writer: anytype,
1839 ) @TypeOf(writer).Error!void {1803 ) @TypeOf(writer).Error!void {
1804 comptime assert(format_string.len == 0);
1840 if (self != .default) try writer.print(" {s}", .{@tagName(self)});1805 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1841 }1806 }
1842};1807};
...@@ -1846,13 +1811,8 @@ pub const DllStorageClass = enum(u2) {...@@ -1846,13 +1811,8 @@ pub const DllStorageClass = enum(u2) {
1846 dllimport = 1,1811 dllimport = 1,
1847 dllexport = 2,1812 dllexport = 2,
18481813
1849 pub fn format(1814 pub fn format(self: DllStorageClass, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1850 self: DllStorageClass,1815 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
1851 comptime _: []const u8,
1852 _: std.fmt.FormatOptions,
1853 writer: anytype,
1854 ) @TypeOf(writer).Error!void {
1855 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1856 }1816 }
1857};1817};
18581818
...@@ -1863,15 +1823,10 @@ pub const ThreadLocal = enum(u3) {...@@ -1863,15 +1823,10 @@ pub const ThreadLocal = enum(u3) {
1863 initialexec = 3,1823 initialexec = 3,
1864 localexec = 4,1824 localexec = 4,
18651825
1866 pub fn format(1826 pub fn format(self: ThreadLocal, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
1867 self: ThreadLocal,
1868 comptime prefix: []const u8,
1869 _: std.fmt.FormatOptions,
1870 writer: anytype,
1871 ) @TypeOf(writer).Error!void {
1872 if (self == .default) return;1827 if (self == .default) return;
1873 try writer.print("{s}thread_local", .{prefix});1828 try bw.print("{s}thread_local", .{prefix});
1874 if (self != .generaldynamic) try writer.print("({s})", .{@tagName(self)});1829 if (self != .generaldynamic) try bw.print("({s})", .{@tagName(self)});
1875 }1830 }
1876};1831};
18771832
...@@ -1882,13 +1837,8 @@ pub const UnnamedAddr = enum(u2) {...@@ -1882,13 +1837,8 @@ pub const UnnamedAddr = enum(u2) {
1882 unnamed_addr = 1,1837 unnamed_addr = 1,
1883 local_unnamed_addr = 2,1838 local_unnamed_addr = 2,
18841839
1885 pub fn format(1840 pub fn format(self: UnnamedAddr, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1886 self: UnnamedAddr,1841 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
1887 comptime _: []const u8,
1888 _: std.fmt.FormatOptions,
1889 writer: anytype,
1890 ) @TypeOf(writer).Error!void {
1891 if (self != .default) try writer.print(" {s}", .{@tagName(self)});
1892 }1842 }
1893};1843};
18941844
...@@ -1981,13 +1931,8 @@ pub const AddrSpace = enum(u24) {...@@ -1981,13 +1931,8 @@ pub const AddrSpace = enum(u24) {
1981 pub const funcref: AddrSpace = @enumFromInt(20);1931 pub const funcref: AddrSpace = @enumFromInt(20);
1982 };1932 };
19831933
1984 pub fn format(1934 pub fn format(self: AddrSpace, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
1985 self: AddrSpace,1935 if (self != .default) try bw.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
1986 comptime prefix: []const u8,
1987 _: std.fmt.FormatOptions,
1988 writer: anytype,
1989 ) @TypeOf(writer).Error!void {
1990 if (self != .default) try writer.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) });
1991 }1936 }
1992};1937};
19931938
...@@ -1995,15 +1940,8 @@ pub const ExternallyInitialized = enum {...@@ -1995,15 +1940,8 @@ pub const ExternallyInitialized = enum {
1995 default,1940 default,
1996 externally_initialized,1941 externally_initialized,
19971942
1998 pub fn format(1943 pub fn format(self: ExternallyInitialized, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1999 self: ExternallyInitialized,1944 if (self != .default) try bw.print(" {s}", .{@tagName(self)});
2000 comptime _: []const u8,
2001 _: std.fmt.FormatOptions,
2002 writer: anytype,
2003 ) @TypeOf(writer).Error!void {
2004 if (self == .default) return;
2005 try writer.writeByte(' ');
2006 try writer.writeAll(@tagName(self));
2007 }1945 }
2008};1946};
20091947
...@@ -2026,13 +1964,8 @@ pub const Alignment = enum(u6) {...@@ -2026,13 +1964,8 @@ pub const Alignment = enum(u6) {
2026 return if (self == .default) 0 else (@intFromEnum(self) + 1);1964 return if (self == .default) 0 else (@intFromEnum(self) + 1);
2027 }1965 }
20281966
2029 pub fn format(1967 pub fn format(self: Alignment, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
2030 self: Alignment,1968 try bw.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
2031 comptime prefix: []const u8,
2032 _: std.fmt.FormatOptions,
2033 writer: anytype,
2034 ) @TypeOf(writer).Error!void {
2035 try writer.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return });
2036 }1969 }
2037};1970};
20381971
...@@ -2105,12 +2038,7 @@ pub const CallConv = enum(u10) {...@@ -2105,12 +2038,7 @@ pub const CallConv = enum(u10) {
21052038
2106 pub const default = CallConv.ccc;2039 pub const default = CallConv.ccc;
21072040
2108 pub fn format(2041 pub fn format(self: CallConv, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
2109 self: CallConv,
2110 comptime _: []const u8,
2111 _: std.fmt.FormatOptions,
2112 writer: anytype,
2113 ) @TypeOf(writer).Error!void {
2114 switch (self) {2042 switch (self) {
2115 default => {},2043 default => {},
2116 .fastcc,2044 .fastcc,
...@@ -2164,8 +2092,8 @@ pub const CallConv = enum(u10) {...@@ -2164,8 +2092,8 @@ pub const CallConv = enum(u10) {
2164 .aarch64_sme_preservemost_from_x2,2092 .aarch64_sme_preservemost_from_x2,
2165 .m68k_rtdcc,2093 .m68k_rtdcc,
2166 .riscv_vectorcallcc,2094 .riscv_vectorcallcc,
2167 => try writer.print(" {s}", .{@tagName(self)}),2095 => try bw.print(" {s}", .{@tagName(self)}),
2168 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2096 _ => try bw.print(" cc{d}", .{@intFromEnum(self)}),
2169 }2097 }
2170 }2098 }
2171};2099};
...@@ -2191,26 +2119,21 @@ pub const StrtabString = enum(u32) {...@@ -2191,26 +2119,21 @@ pub const StrtabString = enum(u32) {
2191 string: StrtabString,2119 string: StrtabString,
2192 builder: *const Builder,2120 builder: *const Builder,
2193 };2121 };
2194 fn format(2122 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
2195 data: FormatData,
2196 comptime fmt_str: []const u8,
2197 _: std.fmt.FormatOptions,
2198 writer: anytype,
2199 ) @TypeOf(writer).Error!void {
2200 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|2123 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
2201 @compileError("invalid format string: '" ++ fmt_str ++ "'");2124 @compileError("invalid format string: '" ++ fmt_str ++ "'");
2202 assert(data.string != .none);2125 assert(data.string != .none);
2203 const string_slice = data.string.slice(data.builder) orelse2126 const string_slice = data.string.slice(data.builder) orelse
2204 return writer.print("{d}", .{@intFromEnum(data.string)});2127 return bw.print("{d}", .{@intFromEnum(data.string)});
2205 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|2128 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
2206 return writer.writeAll(string_slice);2129 return bw.writeAll(string_slice);
2207 try printEscapedString(2130 try printEscapedString(
2208 string_slice,2131 string_slice,
2209 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|2132 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
2210 .always_quote2133 .always_quote
2211 else2134 else
2212 .quote_unless_valid_identifier,2135 .quote_unless_valid_identifier,
2213 writer,2136 bw,
2214 );2137 );
2215 }2138 }
2216 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {2139 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {
...@@ -2264,7 +2187,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a...@@ -2264,7 +2187,7 @@ pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: a
2264}2187}
22652188
2266pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {2189pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {
2267 self.strtab_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;2190 self.strtab_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
2268 return self.trailingStrtabStringAssumeCapacity();2191 return self.trailingStrtabStringAssumeCapacity();
2269}2192}
22702193
...@@ -2383,13 +2306,8 @@ pub const Global = struct {...@@ -2383,13 +2306,8 @@ pub const Global = struct {
2383 global: Index,2306 global: Index,
2384 builder: *const Builder,2307 builder: *const Builder,
2385 };2308 };
2386 fn format(2309 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
2387 data: FormatData,2310 try bw.print("@{f}", .{
2388 comptime _: []const u8,
2389 _: std.fmt.FormatOptions,
2390 writer: anytype,
2391 ) @TypeOf(writer).Error!void {
2392 try writer.print("@{}", .{
2393 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),2311 data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
2394 });2312 });
2395 }2313 }
...@@ -4834,28 +4752,23 @@ pub const Function = struct {...@@ -4834,28 +4752,23 @@ pub const Function = struct {
4834 function: Function.Index,4752 function: Function.Index,
4835 builder: *Builder,4753 builder: *Builder,
4836 };4754 };
4837 fn format(4755 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
4838 data: FormatData,
4839 comptime fmt_str: []const u8,
4840 _: std.fmt.FormatOptions,
4841 writer: anytype,
4842 ) @TypeOf(writer).Error!void {
4843 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|4756 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
4844 @compileError("invalid format string: '" ++ fmt_str ++ "'");4757 @compileError("invalid format string: '" ++ fmt_str ++ "'");
4845 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {4758 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
4846 if (data.instruction == .none) return;4759 if (data.instruction == .none) return;
4847 try writer.writeByte(',');4760 try bw.writeByte(',');
4848 }4761 }
4849 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {4762 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {
4850 if (data.instruction == .none) return;4763 if (data.instruction == .none) return;
4851 try writer.writeByte(' ');4764 try bw.writeByte(' ');
4852 }4765 }
4853 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try writer.print(4766 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null) try bw.print(
4854 "{%} ",4767 "{f%} ",
4855 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},4768 .{data.instruction.typeOf(data.function, data.builder).fmt(data.builder)},
4856 );4769 );
4857 assert(data.instruction != .none);4770 assert(data.instruction != .none);
4858 try writer.print("%{}", .{4771 try bw.print("%{f}", .{
4859 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),4772 data.instruction.name(data.function.ptrConst(data.builder)).fmt(data.builder),
4860 });4773 });
4861 }4774 }
...@@ -6361,7 +6274,7 @@ pub const WipFunction = struct {...@@ -6361,7 +6274,7 @@ pub const WipFunction = struct {
63616274
6362 while (true) {6275 while (true) {
6363 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);6276 gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);
6364 const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{6277 const unique_name = try wip_name.builder.fmt("{fr}{s}{fr}", .{
6365 name.fmt(wip_name.builder),6278 name.fmt(wip_name.builder),
6366 sep,6279 sep,
6367 gop.value_ptr.fmt(wip_name.builder),6280 gop.value_ptr.fmt(wip_name.builder),
...@@ -7031,13 +6944,8 @@ pub const MemoryAccessKind = enum(u1) {...@@ -7031,13 +6944,8 @@ pub const MemoryAccessKind = enum(u1) {
7031 normal,6944 normal,
7032 @"volatile",6945 @"volatile",
70336946
7034 pub fn format(6947 pub fn format(self: MemoryAccessKind, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
7035 self: MemoryAccessKind,6948 if (self != .normal) try bw.print("{s}{s}", .{ prefix, @tagName(self) });
7036 comptime prefix: []const u8,
7037 _: std.fmt.FormatOptions,
7038 writer: anytype,
7039 ) @TypeOf(writer).Error!void {
7040 if (self != .normal) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
7041 }6949 }
7042};6950};
70436951
...@@ -7045,13 +6953,8 @@ pub const SyncScope = enum(u1) {...@@ -7045,13 +6953,8 @@ pub const SyncScope = enum(u1) {
7045 singlethread,6953 singlethread,
7046 system,6954 system,
70476955
7048 pub fn format(6956 pub fn format(self: SyncScope, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
7049 self: SyncScope,6957 if (self != .system) try bw.print(
7050 comptime prefix: []const u8,
7051 _: std.fmt.FormatOptions,
7052 writer: anytype,
7053 ) @TypeOf(writer).Error!void {
7054 if (self != .system) try writer.print(
7055 \\{s}syncscope("{s}")6958 \\{s}syncscope("{s}")
7056 , .{ prefix, @tagName(self) });6959 , .{ prefix, @tagName(self) });
7057 }6960 }
...@@ -7066,13 +6969,8 @@ pub const AtomicOrdering = enum(u3) {...@@ -7066,13 +6969,8 @@ pub const AtomicOrdering = enum(u3) {
7066 acq_rel = 5,6969 acq_rel = 5,
7067 seq_cst = 6,6970 seq_cst = 6,
70686971
7069 pub fn format(6972 pub fn format(self: AtomicOrdering, bw: *std.io.BufferedWriter, comptime prefix: []const u8) anyerror!void {
7070 self: AtomicOrdering,6973 if (self != .none) try bw.print("{s}{s}", .{ prefix, @tagName(self) });
7071 comptime prefix: []const u8,
7072 _: std.fmt.FormatOptions,
7073 writer: anytype,
7074 ) @TypeOf(writer).Error!void {
7075 if (self != .none) try writer.print("{s}{s}", .{ prefix, @tagName(self) });
7076 }6974 }
7077};6975};
70786976
...@@ -7487,26 +7385,21 @@ pub const Constant = enum(u32) {...@@ -7487,26 +7385,21 @@ pub const Constant = enum(u32) {
7487 constant: Constant,7385 constant: Constant,
7488 builder: *Builder,7386 builder: *Builder,
7489 };7387 };
7490 fn format(7388 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
7491 data: FormatData,
7492 comptime fmt_str: []const u8,
7493 _: std.fmt.FormatOptions,
7494 writer: anytype,
7495 ) @TypeOf(writer).Error!void {
7496 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|7389 if (comptime std.mem.indexOfNone(u8, fmt_str, ", %")) |_|
7497 @compileError("invalid format string: '" ++ fmt_str ++ "'");7390 @compileError("invalid format string: '" ++ fmt_str ++ "'");
7498 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {7391 if (comptime std.mem.indexOfScalar(u8, fmt_str, ',') != null) {
7499 if (data.constant == .no_init) return;7392 if (data.constant == .no_init) return;
7500 try writer.writeByte(',');7393 try bw.writeByte(',');
7501 }7394 }
7502 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {7395 if (comptime std.mem.indexOfScalar(u8, fmt_str, ' ') != null) {
7503 if (data.constant == .no_init) return;7396 if (data.constant == .no_init) return;
7504 try writer.writeByte(' ');7397 try bw.writeByte(' ');
7505 }7398 }
7506 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null)7399 if (comptime std.mem.indexOfScalar(u8, fmt_str, '%') != null)
7507 try writer.print("{%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});7400 try bw.print("{f%} ", .{data.constant.typeOf(data.builder).fmt(data.builder)});
7508 assert(data.constant != .no_init);7401 assert(data.constant != .no_init);
7509 if (std.enums.tagName(Constant, data.constant)) |name| return writer.writeAll(name);7402 if (std.enums.tagName(Constant, data.constant)) |name| return bw.writeAll(name);
7510 switch (data.constant.unwrap()) {7403 switch (data.constant.unwrap()) {
7511 .constant => |constant| {7404 .constant => |constant| {
7512 const item = data.builder.constant_items.get(constant);7405 const item = data.builder.constant_items.get(constant);
...@@ -7545,11 +7438,11 @@ pub const Constant = enum(u32) {...@@ -7545,11 +7438,11 @@ pub const Constant = enum(u32) {
7545 const allocator = stack.get();7438 const allocator = stack.get();
7546 const str = try bigint.toStringAlloc(allocator, 10, undefined);7439 const str = try bigint.toStringAlloc(allocator, 10, undefined);
7547 defer allocator.free(str);7440 defer allocator.free(str);
7548 try writer.writeAll(str);7441 try bw.writeAll(str);
7549 },7442 },
7550 .half,7443 .half,
7551 .bfloat,7444 .bfloat,
7552 => |tag| try writer.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {7445 => |tag| try bw.print("0x{c}{X:0>4}", .{ @as(u8, switch (tag) {
7553 .half => 'H',7446 .half => 'H',
7554 .bfloat => 'R',7447 .bfloat => 'R',
7555 else => unreachable,7448 else => unreachable,
...@@ -7580,7 +7473,7 @@ pub const Constant = enum(u32) {...@@ -7580,7 +7473,7 @@ pub const Constant = enum(u32) {
7580 ) + 1,7473 ) + 1,
7581 else => 0,7474 else => 0,
7582 };7475 };
7583 try writer.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){7476 try bw.print("0x{X:0>16}", .{@as(u64, @bitCast(Float.Repr(f64){
7584 .mantissa = std.math.shl(7477 .mantissa = std.math.shl(
7585 Mantissa64,7478 Mantissa64,
7586 repr.mantissa,7479 repr.mantissa,
...@@ -7602,13 +7495,13 @@ pub const Constant = enum(u32) {...@@ -7602,13 +7495,13 @@ pub const Constant = enum(u32) {
7602 },7495 },
7603 .double => {7496 .double => {
7604 const extra = data.builder.constantExtraData(Double, item.data);7497 const extra = data.builder.constantExtraData(Double, item.data);
7605 try writer.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });7498 try bw.print("0x{X:0>8}{X:0>8}", .{ extra.hi, extra.lo });
7606 },7499 },
7607 .fp128,7500 .fp128,
7608 .ppc_fp128,7501 .ppc_fp128,
7609 => |tag| {7502 => |tag| {
7610 const extra = data.builder.constantExtraData(Fp128, item.data);7503 const extra = data.builder.constantExtraData(Fp128, item.data);
7611 try writer.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{7504 try bw.print("0x{c}{X:0>8}{X:0>8}{X:0>8}{X:0>8}", .{
7612 @as(u8, switch (tag) {7505 @as(u8, switch (tag) {
7613 .fp128 => 'L',7506 .fp128 => 'L',
7614 .ppc_fp128 => 'M',7507 .ppc_fp128 => 'M',
...@@ -7622,7 +7515,7 @@ pub const Constant = enum(u32) {...@@ -7622,7 +7515,7 @@ pub const Constant = enum(u32) {
7622 },7515 },
7623 .x86_fp80 => {7516 .x86_fp80 => {
7624 const extra = data.builder.constantExtraData(Fp80, item.data);7517 const extra = data.builder.constantExtraData(Fp80, item.data);
7625 try writer.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{7518 try bw.print("0xK{X:0>4}{X:0>8}{X:0>8}", .{
7626 extra.hi, extra.lo_hi, extra.lo_lo,7519 extra.hi, extra.lo_hi, extra.lo_lo,
7627 });7520 });
7628 },7521 },
...@@ -7631,7 +7524,7 @@ pub const Constant = enum(u32) {...@@ -7631,7 +7524,7 @@ pub const Constant = enum(u32) {
7631 .zeroinitializer,7524 .zeroinitializer,
7632 .undef,7525 .undef,
7633 .poison,7526 .poison,
7634 => |tag| try writer.writeAll(@tagName(tag)),7527 => |tag| try bw.writeAll(@tagName(tag)),
7635 .structure,7528 .structure,
7636 .packed_structure,7529 .packed_structure,
7637 .array,7530 .array,
...@@ -7640,7 +7533,7 @@ pub const Constant = enum(u32) {...@@ -7640,7 +7533,7 @@ pub const Constant = enum(u32) {
7640 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);7533 var extra = data.builder.constantExtraDataTrail(Aggregate, item.data);
7641 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));7534 const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder));
7642 const vals = extra.trail.next(len, Constant, data.builder);7535 const vals = extra.trail.next(len, Constant, data.builder);
7643 try writer.writeAll(switch (tag) {7536 try bw.writeAll(switch (tag) {
7644 .structure => "{ ",7537 .structure => "{ ",
7645 .packed_structure => "<{ ",7538 .packed_structure => "<{ ",
7646 .array => "[",7539 .array => "[",
...@@ -7648,10 +7541,10 @@ pub const Constant = enum(u32) {...@@ -7648,10 +7541,10 @@ pub const Constant = enum(u32) {
7648 else => unreachable,7541 else => unreachable,
7649 });7542 });
7650 for (vals, 0..) |val, index| {7543 for (vals, 0..) |val, index| {
7651 if (index > 0) try writer.writeAll(", ");7544 if (index > 0) try bw.writeAll(", ");
7652 try writer.print("{%}", .{val.fmt(data.builder)});7545 try bw.print("{f%}", .{val.fmt(data.builder)});
7653 }7546 }
7654 try writer.writeAll(switch (tag) {7547 try bw.writeAll(switch (tag) {
7655 .structure => " }",7548 .structure => " }",
7656 .packed_structure => " }>",7549 .packed_structure => " }>",
7657 .array => "]",7550 .array => "]",
...@@ -7662,20 +7555,20 @@ pub const Constant = enum(u32) {...@@ -7662,20 +7555,20 @@ pub const Constant = enum(u32) {
7662 .splat => {7555 .splat => {
7663 const extra = data.builder.constantExtraData(Splat, item.data);7556 const extra = data.builder.constantExtraData(Splat, item.data);
7664 const len = extra.type.vectorLen(data.builder);7557 const len = extra.type.vectorLen(data.builder);
7665 try writer.writeByte('<');7558 try bw.writeByte('<');
7666 for (0..len) |index| {7559 for (0..len) |index| {
7667 if (index > 0) try writer.writeAll(", ");7560 if (index > 0) try bw.writeAll(", ");
7668 try writer.print("{%}", .{extra.value.fmt(data.builder)});7561 try bw.print("{f%}", .{extra.value.fmt(data.builder)});
7669 }7562 }
7670 try writer.writeByte('>');7563 try bw.writeByte('>');
7671 },7564 },
7672 .string => try writer.print("c{\"}", .{7565 .string => try bw.print("c{f\"}", .{
7673 @as(String, @enumFromInt(item.data)).fmt(data.builder),7566 @as(String, @enumFromInt(item.data)).fmt(data.builder),
7674 }),7567 }),
7675 .blockaddress => |tag| {7568 .blockaddress => |tag| {
7676 const extra = data.builder.constantExtraData(BlockAddress, item.data);7569 const extra = data.builder.constantExtraData(BlockAddress, item.data);
7677 const function = extra.function.ptrConst(data.builder);7570 const function = extra.function.ptrConst(data.builder);
7678 try writer.print("{s}({}, {})", .{7571 try bw.print("{s}({f}, {f})", .{
7679 @tagName(tag),7572 @tagName(tag),
7680 function.global.fmt(data.builder),7573 function.global.fmt(data.builder),
7681 extra.block.toInst(function).fmt(extra.function, data.builder),7574 extra.block.toInst(function).fmt(extra.function, data.builder),
...@@ -7685,7 +7578,7 @@ pub const Constant = enum(u32) {...@@ -7685,7 +7578,7 @@ pub const Constant = enum(u32) {
7685 .no_cfi,7578 .no_cfi,
7686 => |tag| {7579 => |tag| {
7687 const function: Function.Index = @enumFromInt(item.data);7580 const function: Function.Index = @enumFromInt(item.data);
7688 try writer.print("{s} {}", .{7581 try bw.print("{s} {f}", .{
7689 @tagName(tag),7582 @tagName(tag),
7690 function.ptrConst(data.builder).global.fmt(data.builder),7583 function.ptrConst(data.builder).global.fmt(data.builder),
7691 });7584 });
...@@ -7697,7 +7590,7 @@ pub const Constant = enum(u32) {...@@ -7697,7 +7590,7 @@ pub const Constant = enum(u32) {
7697 .addrspacecast,7590 .addrspacecast,
7698 => |tag| {7591 => |tag| {
7699 const extra = data.builder.constantExtraData(Cast, item.data);7592 const extra = data.builder.constantExtraData(Cast, item.data);
7700 try writer.print("{s} ({%} to {%})", .{7593 try bw.print("{s} ({f%} to {f%})", .{
7701 @tagName(tag),7594 @tagName(tag),
7702 extra.val.fmt(data.builder),7595 extra.val.fmt(data.builder),
7703 extra.type.fmt(data.builder),7596 extra.type.fmt(data.builder),
...@@ -7709,13 +7602,13 @@ pub const Constant = enum(u32) {...@@ -7709,13 +7602,13 @@ pub const Constant = enum(u32) {
7709 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);7602 var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data);
7710 const indices =7603 const indices =
7711 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);7604 extra.trail.next(extra.data.info.indices_len, Constant, data.builder);
7712 try writer.print("{s} ({%}, {%}", .{7605 try bw.print("{s} ({f%}, {f%}", .{
7713 @tagName(tag),7606 @tagName(tag),
7714 extra.data.type.fmt(data.builder),7607 extra.data.type.fmt(data.builder),
7715 extra.data.base.fmt(data.builder),7608 extra.data.base.fmt(data.builder),
7716 });7609 });
7717 for (indices) |index| try writer.print(", {%}", .{index.fmt(data.builder)});7610 for (indices) |index| try bw.print(", {f%}", .{index.fmt(data.builder)});
7718 try writer.writeByte(')');7611 try bw.writeByte(')');
7719 },7612 },
7720 .add,7613 .add,
7721 .@"add nsw",7614 .@"add nsw",
...@@ -7727,7 +7620,7 @@ pub const Constant = enum(u32) {...@@ -7727,7 +7620,7 @@ pub const Constant = enum(u32) {
7727 .xor,7620 .xor,
7728 => |tag| {7621 => |tag| {
7729 const extra = data.builder.constantExtraData(Binary, item.data);7622 const extra = data.builder.constantExtraData(Binary, item.data);
7730 try writer.print("{s} ({%}, {%})", .{7623 try bw.print("{s} ({f%}, {f%})", .{
7731 @tagName(tag),7624 @tagName(tag),
7732 extra.lhs.fmt(data.builder),7625 extra.lhs.fmt(data.builder),
7733 extra.rhs.fmt(data.builder),7626 extra.rhs.fmt(data.builder),
...@@ -7751,7 +7644,7 @@ pub const Constant = enum(u32) {...@@ -7751,7 +7644,7 @@ pub const Constant = enum(u32) {
7751 .@"asm sideeffect alignstack inteldialect unwind",7644 .@"asm sideeffect alignstack inteldialect unwind",
7752 => |tag| {7645 => |tag| {
7753 const extra = data.builder.constantExtraData(Assembly, item.data);7646 const extra = data.builder.constantExtraData(Assembly, item.data);
7754 try writer.print("{s} {\"}, {\"}", .{7647 try bw.print("{s} {f\"}, {f\"}", .{
7755 @tagName(tag),7648 @tagName(tag),
7756 extra.assembly.fmt(data.builder),7649 extra.assembly.fmt(data.builder),
7757 extra.constraints.fmt(data.builder),7650 extra.constraints.fmt(data.builder),
...@@ -7759,7 +7652,7 @@ pub const Constant = enum(u32) {...@@ -7759,7 +7652,7 @@ pub const Constant = enum(u32) {
7759 },7652 },
7760 }7653 }
7761 },7654 },
7762 .global => |global| try writer.print("{}", .{global.fmt(data.builder)}),7655 .global => |global| try bw.print("{f}", .{global.fmt(data.builder)}),
7763 }7656 }
7764 }7657 }
7765 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {7658 pub fn fmt(self: Constant, builder: *Builder) std.fmt.Formatter(format) {
...@@ -7819,22 +7712,17 @@ pub const Value = enum(u32) {...@@ -7819,22 +7712,17 @@ pub const Value = enum(u32) {
7819 function: Function.Index,7712 function: Function.Index,
7820 builder: *Builder,7713 builder: *Builder,
7821 };7714 };
7822 fn format(7715 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
7823 data: FormatData,
7824 comptime fmt_str: []const u8,
7825 fmt_opts: std.fmt.FormatOptions,
7826 writer: anytype,
7827 ) @TypeOf(writer).Error!void {
7828 switch (data.value.unwrap()) {7716 switch (data.value.unwrap()) {
7829 .instruction => |instruction| try Function.Instruction.Index.format(.{7717 .instruction => |instruction| try Function.Instruction.Index.format(.{
7830 .instruction = instruction,7718 .instruction = instruction,
7831 .function = data.function,7719 .function = data.function,
7832 .builder = data.builder,7720 .builder = data.builder,
7833 }, fmt_str, fmt_opts, writer),7721 }, bw, fmt_str),
7834 .constant => |constant| try Constant.format(.{7722 .constant => |constant| try Constant.format(.{
7835 .constant = constant,7723 .constant = constant,
7836 .builder = data.builder,7724 .builder = data.builder,
7837 }, fmt_str, fmt_opts, writer),7725 }, bw, fmt_str),
7838 .metadata => unreachable,7726 .metadata => unreachable,
7839 }7727 }
7840 }7728 }
...@@ -7869,13 +7757,8 @@ pub const MetadataString = enum(u32) {...@@ -7869,13 +7757,8 @@ pub const MetadataString = enum(u32) {
7869 metadata_string: MetadataString,7757 metadata_string: MetadataString,
7870 builder: *const Builder,7758 builder: *const Builder,
7871 };7759 };
7872 fn format(7760 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
7873 data: FormatData,7761 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, bw);
7874 comptime _: []const u8,
7875 _: std.fmt.FormatOptions,
7876 writer: anytype,
7877 ) @TypeOf(writer).Error!void {
7878 try printEscapedString(data.metadata_string.slice(data.builder), .always_quote, writer);
7879 }7762 }
7880 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {7763 fn fmt(self: MetadataString, builder: *const Builder) std.fmt.Formatter(format) {
7881 return .{ .data = .{ .metadata_string = self, .builder = builder } };7764 return .{ .data = .{ .metadata_string = self, .builder = builder } };
...@@ -8039,29 +7922,24 @@ pub const Metadata = enum(u32) {...@@ -8039,29 +7922,24 @@ pub const Metadata = enum(u32) {
8039 AllCallsDescribed: bool = false,7922 AllCallsDescribed: bool = false,
8040 Unused: u2 = 0,7923 Unused: u2 = 0,
80417924
8042 pub fn format(7925 pub fn format(self: DIFlags, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
8043 self: DIFlags,
8044 comptime _: []const u8,
8045 _: std.fmt.FormatOptions,
8046 writer: anytype,
8047 ) @TypeOf(writer).Error!void {
8048 var need_pipe = false;7926 var need_pipe = false;
8049 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {7927 inline for (@typeInfo(DIFlags).@"struct".fields) |field| {
8050 switch (@typeInfo(field.type)) {7928 switch (@typeInfo(field.type)) {
8051 .bool => if (@field(self, field.name)) {7929 .bool => if (@field(self, field.name)) {
8052 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7930 if (need_pipe) try bw.writeAll(" | ") else need_pipe = true;
8053 try writer.print("DIFlag{s}", .{field.name});7931 try bw.print("DIFlag{s}", .{field.name});
8054 },7932 },
8055 .@"enum" => if (@field(self, field.name) != .Zero) {7933 .@"enum" => if (@field(self, field.name) != .Zero) {
8056 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7934 if (need_pipe) try bw.writeAll(" | ") else need_pipe = true;
8057 try writer.print("DIFlag{s}", .{@tagName(@field(self, field.name))});7935 try bw.print("DIFlag{s}", .{@tagName(@field(self, field.name))});
8058 },7936 },
8059 .int => assert(@field(self, field.name) == 0),7937 .int => assert(@field(self, field.name) == 0),
8060 else => @compileError("bad field type: " ++ field.name ++ ": " ++7938 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8061 @typeName(field.type)),7939 @typeName(field.type)),
8062 }7940 }
8063 }7941 }
8064 if (!need_pipe) try writer.writeByte('0');7942 if (!need_pipe) try bw.writeByte('0');
8065 }7943 }
8066 };7944 };
80677945
...@@ -8101,29 +7979,24 @@ pub const Metadata = enum(u32) {...@@ -8101,29 +7979,24 @@ pub const Metadata = enum(u32) {
8101 ObjCDirect: bool = false,7979 ObjCDirect: bool = false,
8102 Unused: u20 = 0,7980 Unused: u20 = 0,
81037981
8104 pub fn format(7982 pub fn format(self: DISPFlags, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
8105 self: DISPFlags,
8106 comptime _: []const u8,
8107 _: std.fmt.FormatOptions,
8108 writer: anytype,
8109 ) @TypeOf(writer).Error!void {
8110 var need_pipe = false;7983 var need_pipe = false;
8111 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {7984 inline for (@typeInfo(DISPFlags).@"struct".fields) |field| {
8112 switch (@typeInfo(field.type)) {7985 switch (@typeInfo(field.type)) {
8113 .bool => if (@field(self, field.name)) {7986 .bool => if (@field(self, field.name)) {
8114 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7987 if (need_pipe) try bw.writeAll(" | ") else need_pipe = true;
8115 try writer.print("DISPFlag{s}", .{field.name});7988 try bw.print("DISPFlag{s}", .{field.name});
8116 },7989 },
8117 .@"enum" => if (@field(self, field.name) != .Zero) {7990 .@"enum" => if (@field(self, field.name) != .Zero) {
8118 if (need_pipe) try writer.writeAll(" | ") else need_pipe = true;7991 if (need_pipe) try bw.writeAll(" | ") else need_pipe = true;
8119 try writer.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});7992 try bw.print("DISPFlag{s}", .{@tagName(@field(self, field.name))});
8120 },7993 },
8121 .int => assert(@field(self, field.name) == 0),7994 .int => assert(@field(self, field.name) == 0),
8122 else => @compileError("bad field type: " ++ field.name ++ ": " ++7995 else => @compileError("bad field type: " ++ field.name ++ ": " ++
8123 @typeName(field.type)),7996 @typeName(field.type)),
8124 }7997 }
8125 }7998 }
8126 if (!need_pipe) try writer.writeByte('0');7999 if (!need_pipe) try bw.writeByte('0');
8127 }8000 }
8128 };8001 };
81298002
...@@ -8323,20 +8196,15 @@ pub const Metadata = enum(u32) {...@@ -8323,20 +8196,15 @@ pub const Metadata = enum(u32) {
8323 };8196 };
8324 };8197 };
8325 };8198 };
8326 fn format(8199 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime fmt_str: []const u8) anyerror!void {
8327 data: FormatData,
8328 comptime fmt_str: []const u8,
8329 fmt_opts: std.fmt.FormatOptions,
8330 writer: anytype,
8331 ) @TypeOf(writer).Error!void {
8332 if (data.node == .none) return;8200 if (data.node == .none) return;
83338201
8334 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';8202 const is_specialized = fmt_str.len > 0 and fmt_str[0] == 'S';
8335 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;8203 const recurse_fmt_str = if (is_specialized) fmt_str[1..] else fmt_str;
83368204
8337 if (data.formatter.need_comma) try writer.writeAll(", ");8205 if (data.formatter.need_comma) try bw.writeAll(", ");
8338 defer data.formatter.need_comma = true;8206 defer data.formatter.need_comma = true;
8339 try writer.writeAll(data.prefix);8207 try bw.writeAll(data.prefix);
83408208
8341 const builder = data.formatter.builder;8209 const builder = data.formatter.builder;
8342 switch (data.node) {8210 switch (data.node) {
...@@ -8351,48 +8219,44 @@ pub const Metadata = enum(u32) {...@@ -8351,48 +8219,44 @@ pub const Metadata = enum(u32) {
8351 .expression => {8219 .expression => {
8352 var extra = builder.metadataExtraDataTrail(Expression, item.data);8220 var extra = builder.metadataExtraDataTrail(Expression, item.data);
8353 const elements = extra.trail.next(extra.data.elements_len, u32, builder);8221 const elements = extra.trail.next(extra.data.elements_len, u32, builder);
8354 try writer.writeAll("!DIExpression(");8222 try bw.writeAll("!DIExpression(");
8355 for (elements) |element| try format(.{8223 for (elements) |element| try format(.{
8356 .formatter = data.formatter,8224 .formatter = data.formatter,
8357 .node = .{ .u64 = element },8225 .node = .{ .u64 = element },
8358 }, "%", fmt_opts, writer);8226 }, bw, "%");
8359 try writer.writeByte(')');8227 try bw.writeByte(')');
8360 },8228 },
8361 .constant => try Constant.format(.{8229 .constant => try Constant.format(.{
8362 .constant = @enumFromInt(item.data),8230 .constant = @enumFromInt(item.data),
8363 .builder = builder,8231 .builder = builder,
8364 }, recurse_fmt_str, fmt_opts, writer),8232 }, bw, recurse_fmt_str),
8365 else => unreachable,8233 else => unreachable,
8366 }8234 }
8367 },8235 },
8368 .index => |node| try writer.print("!{d}", .{node}),8236 .index => |node| try bw.print("!{d}", .{node}),
8369 inline .local_value, .local_metadata => |node, tag| try Value.format(.{8237 inline .local_value, .local_metadata => |node, tag| try Value.format(.{
8370 .value = node.value,8238 .value = node.value,
8371 .function = node.function,8239 .function = node.function,
8372 .builder = builder,8240 .builder = builder,
8373 }, switch (tag) {8241 }, bw, switch (tag) {
8374 .local_value => recurse_fmt_str,8242 .local_value => recurse_fmt_str,
8375 .local_metadata => "%",8243 .local_metadata => "%",
8376 else => unreachable,8244 else => unreachable,
8377 }, fmt_opts, writer),8245 }),
8378 inline .local_inline, .local_index => |node, tag| {8246 inline .local_inline, .local_index => |node, tag| {
8379 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))8247 if (comptime std.mem.eql(u8, recurse_fmt_str, "%"))
8380 try writer.print("{%} ", .{Type.metadata.fmt(builder)});8248 try bw.print("{f%} ", .{Type.metadata.fmt(builder)});
8381 try format(.{8249 try format(.{
8382 .formatter = data.formatter,8250 .formatter = data.formatter,
8383 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),8251 .node = @unionInit(FormatData.Node, @tagName(tag)["local_".len..], node),
8384 }, "%", fmt_opts, writer);8252 }, bw, "%");
8385 },8253 },
8386 .string => |node| try writer.print((if (is_specialized) "" else "!") ++ "{}", .{8254 .string => |node| try bw.print((if (is_specialized) "" else "!") ++ "{f}", .{
8387 node.fmt(builder),8255 node.fmt(builder),
8388 }),8256 }),
8389 inline .bool,8257 inline .bool, .u32, .u64 => |node| try bw.print("{}", .{node}),
8390 .u32,8258 inline .di_flags, .sp_flags => |node| try bw.print("{f}", .{node}),
8391 .u64,8259 .raw => |node| try bw.writeAll(node),
8392 .di_flags,
8393 .sp_flags,
8394 => |node| try writer.print("{}", .{node}),
8395 .raw => |node| try writer.writeAll(node),
8396 }8260 }
8397 }8261 }
8398 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {8262 inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype) switch (@TypeOf(node)) {
...@@ -8506,8 +8370,8 @@ pub const Metadata = enum(u32) {...@@ -8506,8 +8370,8 @@ pub const Metadata = enum(u32) {
8506 DIGlobalVariableExpression,8370 DIGlobalVariableExpression,
8507 },8371 },
8508 nodes: anytype,8372 nodes: anytype,
8509 writer: anytype,8373 bw: *std.io.BufferedWriter,
8510 ) !void {8374 ) anyerror!void {
8511 comptime var fmt_str: []const u8 = "";8375 comptime var fmt_str: []const u8 = "";
8512 const names = comptime std.meta.fieldNames(@TypeOf(nodes));8376 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
8513 comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined;8377 comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined;
...@@ -8523,7 +8387,7 @@ pub const Metadata = enum(u32) {...@@ -8523,7 +8387,7 @@ pub const Metadata = enum(u32) {
8523 }8387 }
8524 fmt_str = fmt_str ++ "(";8388 fmt_str = fmt_str ++ "(";
8525 inline for (fields[2..], names) |*field, name| {8389 inline for (fields[2..], names) |*field, name| {
8526 fmt_str = fmt_str ++ "{[" ++ name ++ "]S}";8390 fmt_str = fmt_str ++ "{[" ++ name ++ "]fS}";
8527 field.* = .{8391 field.* = .{
8528 .name = name,8392 .name = name,
8529 .type = std.fmt.Formatter(format),8393 .type = std.fmt.Formatter(format),
...@@ -8546,7 +8410,7 @@ pub const Metadata = enum(u32) {...@@ -8546,7 +8410,7 @@ pub const Metadata = enum(u32) {
8546 name ++ ": ",8410 name ++ ": ",
8547 @field(nodes, name),8411 @field(nodes, name),
8548 );8412 );
8549 try writer.print(fmt_str, fmt_args);8413 try bw.print(fmt_str, fmt_args);
8550 }8414 }
8551 };8415 };
8552};8416};
...@@ -8636,7 +8500,7 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8636,7 +8500,7 @@ pub fn init(options: Options) Allocator.Error!Builder {
8636 inline for (.{ 0, 4 }) |addr_space_index| {8500 inline for (.{ 0, 4 }) |addr_space_index| {
8637 const addr_space: AddrSpace = @enumFromInt(addr_space_index);8501 const addr_space: AddrSpace = @enumFromInt(addr_space_index);
8638 assert(self.ptrTypeAssumeCapacity(addr_space) ==8502 assert(self.ptrTypeAssumeCapacity(addr_space) ==
8639 @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space})));8503 @field(Type, std.fmt.comptimePrint("ptr{f }", .{addr_space})));
8640 }8504 }
8641 }8505 }
86428506
...@@ -8759,16 +8623,17 @@ pub fn deinit(self: *Builder) void {...@@ -8759,16 +8623,17 @@ pub fn deinit(self: *Builder) void {
8759 self.* = undefined;8623 self.* = undefined;
8760}8624}
87618625
8762pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {8626pub fn setModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *std.io.BufferedWriter {
8763 self.module_asm.clearRetainingCapacity();8627 self.module_asm.clearRetainingCapacity();
8764 return self.appendModuleAsm();8628 return self.appendModuleAsm(aw);
8765}8629}
87668630
8767pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {8631pub fn appendModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) *std.io.BufferedWriter {
8768 return self.module_asm.writer(self.gpa);8632 return aw.fromArrayList(self.gpa, &self.module_asm);
8769}8633}
87708634
8771pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {8635pub fn finishModuleAsm(self: *Builder, aw: *std.io.AllocatingWriter) Allocator.Error!void {
8636 self.module_asm = aw.toArrayList();
8772 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')8637 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
8773 try self.module_asm.append(self.gpa, '\n');8638 try self.module_asm.append(self.gpa, '\n');
8774}8639}
...@@ -8804,7 +8669,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo...@@ -8804,7 +8669,7 @@ pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allo
8804}8669}
88058670
8806pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {8671pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {
8807 self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;8672 self.string_bytes.printAssumeCapacity(fmt_str, fmt_args);
8808 return self.trailingStringAssumeCapacity();8673 return self.trailingStringAssumeCapacity();
8809}8674}
88108675
...@@ -9076,9 +8941,13 @@ pub fn getIntrinsic(...@@ -9076,9 +8941,13 @@ pub fn getIntrinsic(
9076 const allocator = stack.get();8941 const allocator = stack.get();
90778942
9078 const name = name: {8943 const name = name: {
9079 const writer = self.strtab_string_bytes.writer(self.gpa);8944 {
9080 try writer.print("llvm.{s}", .{@tagName(id)});8945 var aw: std.io.AllocatingWriter = undefined;
9081 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});8946 const bw = aw.fromArrayList(self.gpa, &self.strtab_string_bytes);
8947 defer self.strtab_string_bytes = aw.toArrayList();
8948 bw.print("llvm.{s}", .{@tagName(id)}) catch |err| return @errorCast(err);
8949 for (overload) |ty| bw.print(".{fm}", .{ty.fmt(self)}) catch |err| return @errorCast(err);
8950 }
9082 break :name try self.trailingStrtabString();8951 break :name try self.trailingStrtabString();
9083 };8952 };
9084 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;8953 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
...@@ -9494,108 +9363,78 @@ pub fn asmValue(...@@ -9494,108 +9363,78 @@ pub fn asmValue(
94949363
9495pub fn dump(self: *Builder) void {9364pub fn dump(self: *Builder) void {
9496 const stderr: std.fs.File = .stderr();9365 const stderr: std.fs.File = .stderr();
9497 self.print(stderr.writer().unbuffered()) catch {};9366 self.printBuffered(stderr.writer()) catch {};
9498}9367}
94999368
9500pub fn printToFile(self: *Builder, path: []const u8) Allocator.Error!bool {9369pub fn printToFile(self: *Builder, path: []const u8) bool {
9501 var file = std.fs.cwd().createFile(path, .{}) catch |err| {9370 var file = std.fs.cwd().createFile(path, .{}) catch |err| {
9502 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });9371 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9503 return false;9372 return false;
9504 };9373 };
9505 defer file.close();9374 defer file.close();
9506 self.print(file.writer()) catch |err| {9375 self.printBuffered(file.writer()) catch |err| {
9507 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });9376 log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
9508 return false;9377 return false;
9509 };9378 };
9510 return true;9379 return true;
9511}9380}
95129381
9513pub fn print(self: *Builder, writer: *std.io.BufferedWriter) (@TypeOf(writer).Error || Allocator.Error)!void {9382pub fn printBuffered(self: *Builder, writer: std.io.Writer) anyerror!void {
9514 var bw = std.io.bufferedWriter(writer);9383 var buffer: [4096]u8 = undefined;
9515 try self.printUnbuffered(bw.writer());9384 var bw = writer.buffered(&buffer);
9385 try self.print(&bw);
9516 try bw.flush();9386 try bw.flush();
9517}9387}
95189388
9519fn WriterWithErrors(comptime BackingWriter: type, comptime ExtraErrors: type) type {9389pub fn print(self: *Builder, bw: *std.io.BufferedWriter) anyerror!void {
9520 return struct {
9521 backing_writer: BackingWriter,
9522
9523 pub const Error = BackingWriter.Error || ExtraErrors;
9524 pub const Writer = std.io.Writer(*const Self, Error, write);
9525
9526 const Self = @This();
9527
9528 pub fn writer(self: *const Self) Writer {
9529 return .{ .context = self };
9530 }
9531
9532 pub fn write(self: *const Self, bytes: []const u8) Error!usize {
9533 return self.backing_writer.write(bytes);
9534 }
9535 };
9536}
9537fn writerWithErrors(
9538 backing_writer: anytype,
9539 comptime ExtraErrors: type,
9540) WriterWithErrors(@TypeOf(backing_writer), ExtraErrors) {
9541 return .{ .backing_writer = backing_writer };
9542}
9543
9544pub fn printUnbuffered(
9545 self: *Builder,
9546 backing_writer: anytype,
9547) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
9548 const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
9549 const writer = writer_with_errors.writer();
9550
9551 var need_newline = false;9390 var need_newline = false;
9552 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };9391 var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
9553 defer metadata_formatter.map.deinit(self.gpa);9392 defer metadata_formatter.map.deinit(self.gpa);
95549393
9555 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {9394 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
9556 if (need_newline) try writer.writeByte('\n') else need_newline = true;9395 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9557 if (self.source_filename != .none) try writer.print(9396 if (self.source_filename != .none) try bw.print(
9558 \\; ModuleID = '{s}'9397 \\; ModuleID = '{s}'
9559 \\source_filename = {"}9398 \\source_filename = {f"}
9560 \\9399 \\
9561 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });9400 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
9562 if (self.data_layout != .none) try writer.print(9401 if (self.data_layout != .none) try bw.print(
9563 \\target datalayout = {"}9402 \\target datalayout = {f"}
9564 \\9403 \\
9565 , .{self.data_layout.fmt(self)});9404 , .{self.data_layout.fmt(self)});
9566 if (self.target_triple != .none) try writer.print(9405 if (self.target_triple != .none) try bw.print(
9567 \\target triple = {"}9406 \\target triple = {f"}
9568 \\9407 \\
9569 , .{self.target_triple.fmt(self)});9408 , .{self.target_triple.fmt(self)});
9570 }9409 }
95719410
9572 if (self.module_asm.items.len > 0) {9411 if (self.module_asm.items.len > 0) {
9573 if (need_newline) try writer.writeByte('\n') else need_newline = true;9412 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9574 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');9413 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
9575 while (line_it.next()) |line| {9414 while (line_it.next()) |line| {
9576 try writer.writeAll("module asm ");9415 try bw.writeAll("module asm ");
9577 try printEscapedString(line, .always_quote, writer);9416 try printEscapedString(line, .always_quote, bw);
9578 try writer.writeByte('\n');9417 try bw.writeByte('\n');
9579 }9418 }
9580 }9419 }
95819420
9582 if (self.types.count() > 0) {9421 if (self.types.count() > 0) {
9583 if (need_newline) try writer.writeByte('\n') else need_newline = true;9422 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9584 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(9423 for (self.types.keys(), self.types.values()) |id, ty| try bw.print(
9585 \\%{} = type {}9424 \\%{f} = type {f}
9586 \\9425 \\
9587 , .{ id.fmt(self), ty.fmt(self) });9426 , .{ id.fmt(self), ty.fmt(self) });
9588 }9427 }
95899428
9590 if (self.variables.items.len > 0) {9429 if (self.variables.items.len > 0) {
9591 if (need_newline) try writer.writeByte('\n') else need_newline = true;9430 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9592 for (self.variables.items) |variable| {9431 for (self.variables.items) |variable| {
9593 if (variable.global.getReplacement(self) != .none) continue;9432 if (variable.global.getReplacement(self) != .none) continue;
9594 const global = variable.global.ptrConst(self);9433 const global = variable.global.ptrConst(self);
9595 metadata_formatter.need_comma = true;9434 metadata_formatter.need_comma = true;
9596 defer metadata_formatter.need_comma = undefined;9435 defer metadata_formatter.need_comma = undefined;
9597 try writer.print(9436 try bw.print(
9598 \\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}9437 \\{f} ={f}{f}{f}{f}{f }{f}{f }{f} {s} {f%}{f }{f, }{f}
9599 \\9438 \\
9600 , .{9439 , .{
9601 variable.global.fmt(self),9440 variable.global.fmt(self),
...@@ -9618,14 +9457,14 @@ pub fn printUnbuffered(...@@ -9618,14 +9457,14 @@ pub fn printUnbuffered(
9618 }9457 }
96199458
9620 if (self.aliases.items.len > 0) {9459 if (self.aliases.items.len > 0) {
9621 if (need_newline) try writer.writeByte('\n') else need_newline = true;9460 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9622 for (self.aliases.items) |alias| {9461 for (self.aliases.items) |alias| {
9623 if (alias.global.getReplacement(self) != .none) continue;9462 if (alias.global.getReplacement(self) != .none) continue;
9624 const global = alias.global.ptrConst(self);9463 const global = alias.global.ptrConst(self);
9625 metadata_formatter.need_comma = true;9464 metadata_formatter.need_comma = true;
9626 defer metadata_formatter.need_comma = undefined;9465 defer metadata_formatter.need_comma = undefined;
9627 try writer.print(9466 try bw.print(
9628 \\{} ={}{}{}{}{ }{} alias {%}, {%}{}9467 \\{f} ={f}{f}{f}{f}{f }{f} alias {f%}, {f%}{f}
9629 \\9468 \\
9630 , .{9469 , .{
9631 alias.global.fmt(self),9470 alias.global.fmt(self),
...@@ -9647,17 +9486,17 @@ pub fn printUnbuffered(...@@ -9647,17 +9486,17 @@ pub fn printUnbuffered(
96479486
9648 for (0.., self.functions.items) |function_i, function| {9487 for (0.., self.functions.items) |function_i, function| {
9649 if (function.global.getReplacement(self) != .none) continue;9488 if (function.global.getReplacement(self) != .none) continue;
9650 if (need_newline) try writer.writeByte('\n') else need_newline = true;9489 if (need_newline) try bw.writeByte('\n') else need_newline = true;
9651 const function_index: Function.Index = @enumFromInt(function_i);9490 const function_index: Function.Index = @enumFromInt(function_i);
9652 const global = function.global.ptrConst(self);9491 const global = function.global.ptrConst(self);
9653 const params_len = global.type.functionParameters(self).len;9492 const params_len = global.type.functionParameters(self).len;
9654 const function_attributes = function.attributes.func(self);9493 const function_attributes = function.attributes.func(self);
9655 if (function_attributes != .none) try writer.print(9494 if (function_attributes != .none) try bw.print(
9656 \\; Function Attrs:{}9495 \\; Function Attrs:{f}
9657 \\9496 \\
9658 , .{function_attributes.fmt(self)});9497 , .{function_attributes.fmt(self)});
9659 try writer.print(9498 try bw.print(
9660 \\{s}{}{}{}{}{}{"} {%} {}(9499 \\{s}{f}{f}{f}{f}{f}{f"} {f%} {f}(
9661 , .{9500 , .{
9662 if (function.instructions.len > 0) "define" else "declare",9501 if (function.instructions.len > 0) "define" else "declare",
9663 global.linkage,9502 global.linkage,
...@@ -9670,40 +9509,40 @@ pub fn printUnbuffered(...@@ -9670,40 +9509,40 @@ pub fn printUnbuffered(
9670 function.global.fmt(self),9509 function.global.fmt(self),
9671 });9510 });
9672 for (0..params_len) |arg| {9511 for (0..params_len) |arg| {
9673 if (arg > 0) try writer.writeAll(", ");9512 if (arg > 0) try bw.writeAll(", ");
9674 try writer.print(9513 try bw.print(
9675 \\{%}{"}9514 \\{f%}{f"}
9676 , .{9515 , .{
9677 global.type.functionParameters(self)[arg].fmt(self),9516 global.type.functionParameters(self)[arg].fmt(self),
9678 function.attributes.param(arg, self).fmt(self),9517 function.attributes.param(arg, self).fmt(self),
9679 });9518 });
9680 if (function.instructions.len > 0)9519 if (function.instructions.len > 0)
9681 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})9520 try bw.print(" {f}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
9682 else9521 else
9683 try writer.print(" %{d}", .{arg});9522 try bw.print(" %{d}", .{arg});
9684 }9523 }
9685 switch (global.type.functionKind(self)) {9524 switch (global.type.functionKind(self)) {
9686 .normal => {},9525 .normal => {},
9687 .vararg => {9526 .vararg => {
9688 if (params_len > 0) try writer.writeAll(", ");9527 if (params_len > 0) try bw.writeAll(", ");
9689 try writer.writeAll("...");9528 try bw.writeAll("...");
9690 },9529 },
9691 }9530 }
9692 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });9531 try bw.print("){f}{f }", .{ global.unnamed_addr, global.addr_space });
9693 if (function_attributes != .none) try writer.print(" #{d}", .{9532 if (function_attributes != .none) try bw.print(" #{d}", .{
9694 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,9533 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9695 });9534 });
9696 {9535 {
9697 metadata_formatter.need_comma = false;9536 metadata_formatter.need_comma = false;
9698 defer metadata_formatter.need_comma = undefined;9537 defer metadata_formatter.need_comma = undefined;
9699 try writer.print("{ }{}", .{9538 try bw.print("{f }{f}", .{
9700 function.alignment,9539 function.alignment,
9701 try metadata_formatter.fmt(" !dbg ", global.dbg),9540 try metadata_formatter.fmt(" !dbg ", global.dbg),
9702 });9541 });
9703 }9542 }
9704 if (function.instructions.len > 0) {9543 if (function.instructions.len > 0) {
9705 var block_incoming_len: u32 = undefined;9544 var block_incoming_len: u32 = undefined;
9706 try writer.writeAll(" {\n");9545 try bw.writeAll(" {\n");
9707 var maybe_dbg_index: ?u32 = null;9546 var maybe_dbg_index: ?u32 = null;
9708 for (params_len..function.instructions.len) |instruction_i| {9547 for (params_len..function.instructions.len) |instruction_i| {
9709 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);9548 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
...@@ -9801,7 +9640,7 @@ pub fn printUnbuffered(...@@ -9801,7 +9640,7 @@ pub fn printUnbuffered(
9801 .xor,9640 .xor,
9802 => |tag| {9641 => |tag| {
9803 const extra = function.extraData(Function.Instruction.Binary, instruction.data);9642 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9804 try writer.print(" %{} = {s} {%}, {}", .{9643 try bw.print(" %{f} = {s} {f%}, {f}", .{
9805 instruction_index.name(&function).fmt(self),9644 instruction_index.name(&function).fmt(self),
9806 @tagName(tag),9645 @tagName(tag),
9807 extra.lhs.fmt(function_index, self),9646 extra.lhs.fmt(function_index, self),
...@@ -9823,7 +9662,7 @@ pub fn printUnbuffered(...@@ -9823,7 +9662,7 @@ pub fn printUnbuffered(
9823 .zext,9662 .zext,
9824 => |tag| {9663 => |tag| {
9825 const extra = function.extraData(Function.Instruction.Cast, instruction.data);9664 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9826 try writer.print(" %{} = {s} {%} to {%}", .{9665 try bw.print(" %{f} = {s} {f%} to {f%}", .{
9827 instruction_index.name(&function).fmt(self),9666 instruction_index.name(&function).fmt(self),
9828 @tagName(tag),9667 @tagName(tag),
9829 extra.val.fmt(function_index, self),9668 extra.val.fmt(function_index, self),
...@@ -9834,7 +9673,7 @@ pub fn printUnbuffered(...@@ -9834,7 +9673,7 @@ pub fn printUnbuffered(
9834 .@"alloca inalloca",9673 .@"alloca inalloca",
9835 => |tag| {9674 => |tag| {
9836 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);9675 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9837 try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{9676 try bw.print(" %{f} = {s} {f%}{f,%}{f, }{f, }", .{
9838 instruction_index.name(&function).fmt(self),9677 instruction_index.name(&function).fmt(self),
9839 @tagName(tag),9678 @tagName(tag),
9840 extra.type.fmt(self),9679 extra.type.fmt(self),
...@@ -9850,7 +9689,7 @@ pub fn printUnbuffered(...@@ -9850,7 +9689,7 @@ pub fn printUnbuffered(
9850 .atomicrmw => |tag| {9689 .atomicrmw => |tag| {
9851 const extra =9690 const extra =
9852 function.extraData(Function.Instruction.AtomicRmw, instruction.data);9691 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9853 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{9692 try bw.print(" %{f} = {s}{f } {s} {f%}, {f%}{f }{f }{f, }", .{
9854 instruction_index.name(&function).fmt(self),9693 instruction_index.name(&function).fmt(self),
9855 @tagName(tag),9694 @tagName(tag),
9856 extra.info.access_kind,9695 extra.info.access_kind,
...@@ -9866,19 +9705,19 @@ pub fn printUnbuffered(...@@ -9866,19 +9705,19 @@ pub fn printUnbuffered(
9866 block_incoming_len = instruction.data;9705 block_incoming_len = instruction.data;
9867 const name = instruction_index.name(&function);9706 const name = instruction_index.name(&function);
9868 if (@intFromEnum(instruction_index) > params_len)9707 if (@intFromEnum(instruction_index) > params_len)
9869 try writer.writeByte('\n');9708 try bw.writeByte('\n');
9870 try writer.print("{}:\n", .{name.fmt(self)});9709 try bw.print("{f}:\n", .{name.fmt(self)});
9871 continue;9710 continue;
9872 },9711 },
9873 .br => |tag| {9712 .br => |tag| {
9874 const target: Function.Block.Index = @enumFromInt(instruction.data);9713 const target: Function.Block.Index = @enumFromInt(instruction.data);
9875 try writer.print(" {s} {%}", .{9714 try bw.print(" {s} {f%}", .{
9876 @tagName(tag), target.toInst(&function).fmt(function_index, self),9715 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9877 });9716 });
9878 },9717 },
9879 .br_cond => {9718 .br_cond => {
9880 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);9719 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9881 try writer.print(" br {%}, {%}, {%}", .{9720 try bw.print(" br {f%}, {f%}, {f%}", .{
9882 extra.cond.fmt(function_index, self),9721 extra.cond.fmt(function_index, self),
9883 extra.then.toInst(&function).fmt(function_index, self),9722 extra.then.toInst(&function).fmt(function_index, self),
9884 extra.@"else".toInst(&function).fmt(function_index, self),9723 extra.@"else".toInst(&function).fmt(function_index, self),
...@@ -9887,8 +9726,8 @@ pub fn printUnbuffered(...@@ -9887,8 +9726,8 @@ pub fn printUnbuffered(
9887 defer metadata_formatter.need_comma = undefined;9726 defer metadata_formatter.need_comma = undefined;
9888 switch (extra.weights) {9727 switch (extra.weights) {
9889 .none => {},9728 .none => {},
9890 .unpredictable => try writer.writeAll("!unpredictable !{}"),9729 .unpredictable => try bw.writeAll("!unpredictable !{}"),
9891 _ => try writer.print("{}", .{9730 _ => try bw.print("{f}", .{
9892 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),9731 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),
9893 }),9732 }),
9894 }9733 }
...@@ -9905,16 +9744,16 @@ pub fn printUnbuffered(...@@ -9905,16 +9744,16 @@ pub fn printUnbuffered(
9905 var extra =9744 var extra =
9906 function.extraDataTrail(Function.Instruction.Call, instruction.data);9745 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9907 const args = extra.trail.next(extra.data.args_len, Value, &function);9746 const args = extra.trail.next(extra.data.args_len, Value, &function);
9908 try writer.writeAll(" ");9747 try bw.writeAll(" ");
9909 const ret_ty = extra.data.ty.functionReturn(self);9748 const ret_ty = extra.data.ty.functionReturn(self);
9910 switch (ret_ty) {9749 switch (ret_ty) {
9911 .void => {},9750 .void => {},
9912 else => try writer.print("%{} = ", .{9751 else => try bw.print("%{f} = ", .{
9913 instruction_index.name(&function).fmt(self),9752 instruction_index.name(&function).fmt(self),
9914 }),9753 }),
9915 .none => unreachable,9754 .none => unreachable,
9916 }9755 }
9917 try writer.print("{s}{}{}{} {%} {}(", .{9756 try bw.print("{s}{f}{f}{f} {f%} {f}(", .{
9918 @tagName(tag),9757 @tagName(tag),
9919 extra.data.info.call_conv,9758 extra.data.info.call_conv,
9920 extra.data.attributes.ret(self).fmt(self),9759 extra.data.attributes.ret(self).fmt(self),
...@@ -9926,21 +9765,21 @@ pub fn printUnbuffered(...@@ -9926,21 +9765,21 @@ pub fn printUnbuffered(
9926 extra.data.callee.fmt(function_index, self),9765 extra.data.callee.fmt(function_index, self),
9927 });9766 });
9928 for (0.., args) |arg_index, arg| {9767 for (0.., args) |arg_index, arg| {
9929 if (arg_index > 0) try writer.writeAll(", ");9768 if (arg_index > 0) try bw.writeAll(", ");
9930 metadata_formatter.need_comma = false;9769 metadata_formatter.need_comma = false;
9931 defer metadata_formatter.need_comma = undefined;9770 defer metadata_formatter.need_comma = undefined;
9932 try writer.print("{%}{}{}", .{9771 try bw.print("{f%}{f}{f}", .{
9933 arg.typeOf(function_index, self).fmt(self),9772 arg.typeOf(function_index, self).fmt(self),
9934 extra.data.attributes.param(arg_index, self).fmt(self),9773 extra.data.attributes.param(arg_index, self).fmt(self),
9935 try metadata_formatter.fmtLocal(" ", arg, function_index),9774 try metadata_formatter.fmtLocal(" ", arg, function_index),
9936 });9775 });
9937 }9776 }
9938 try writer.writeByte(')');9777 try bw.writeByte(')');
9939 if (extra.data.info.has_op_bundle_cold) {9778 if (extra.data.info.has_op_bundle_cold) {
9940 try writer.writeAll(" [ \"cold\"() ]");9779 try bw.writeAll(" [ \"cold\"() ]");
9941 }9780 }
9942 const call_function_attributes = extra.data.attributes.func(self);9781 const call_function_attributes = extra.data.attributes.func(self);
9943 if (call_function_attributes != .none) try writer.print(" #{d}", .{9782 if (call_function_attributes != .none) try bw.print(" #{d}", .{
9944 (try attribute_groups.getOrPutValue(9783 (try attribute_groups.getOrPutValue(
9945 self.gpa,9784 self.gpa,
9946 call_function_attributes,9785 call_function_attributes,
...@@ -9953,7 +9792,7 @@ pub fn printUnbuffered(...@@ -9953,7 +9792,7 @@ pub fn printUnbuffered(
9953 => |tag| {9792 => |tag| {
9954 const extra =9793 const extra =
9955 function.extraData(Function.Instruction.CmpXchg, instruction.data);9794 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9956 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{9795 try bw.print(" %{f} = {s}{f } {f%}, {f%}, {f%}{f }{f }{f }{f, }", .{
9957 instruction_index.name(&function).fmt(self),9796 instruction_index.name(&function).fmt(self),
9958 @tagName(tag),9797 @tagName(tag),
9959 extra.info.access_kind,9798 extra.info.access_kind,
...@@ -9969,7 +9808,7 @@ pub fn printUnbuffered(...@@ -9969,7 +9808,7 @@ pub fn printUnbuffered(
9969 .extractelement => |tag| {9808 .extractelement => |tag| {
9970 const extra =9809 const extra =
9971 function.extraData(Function.Instruction.ExtractElement, instruction.data);9810 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9972 try writer.print(" %{} = {s} {%}, {%}", .{9811 try bw.print(" %{f} = {s} {f%}, {f%}", .{
9973 instruction_index.name(&function).fmt(self),9812 instruction_index.name(&function).fmt(self),
9974 @tagName(tag),9813 @tagName(tag),
9975 extra.val.fmt(function_index, self),9814 extra.val.fmt(function_index, self),
...@@ -9982,16 +9821,16 @@ pub fn printUnbuffered(...@@ -9982,16 +9821,16 @@ pub fn printUnbuffered(
9982 instruction.data,9821 instruction.data,
9983 );9822 );
9984 const indices = extra.trail.next(extra.data.indices_len, u32, &function);9823 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9985 try writer.print(" %{} = {s} {%}", .{9824 try bw.print(" %{f} = {s} {f%}", .{
9986 instruction_index.name(&function).fmt(self),9825 instruction_index.name(&function).fmt(self),
9987 @tagName(tag),9826 @tagName(tag),
9988 extra.data.val.fmt(function_index, self),9827 extra.data.val.fmt(function_index, self),
9989 });9828 });
9990 for (indices) |index| try writer.print(", {d}", .{index});9829 for (indices) |index| try bw.print(", {d}", .{index});
9991 },9830 },
9992 .fence => |tag| {9831 .fence => |tag| {
9993 const info: MemoryAccessInfo = @bitCast(instruction.data);9832 const info: MemoryAccessInfo = @bitCast(instruction.data);
9994 try writer.print(" {s}{ }{ }", .{9833 try bw.print(" {s}{f }{f }", .{
9995 @tagName(tag),9834 @tagName(tag),
9996 info.sync_scope,9835 info.sync_scope,
9997 info.success_ordering,9836 info.success_ordering,
...@@ -10001,7 +9840,7 @@ pub fn printUnbuffered(...@@ -10001,7 +9840,7 @@ pub fn printUnbuffered(
10001 .@"fneg fast",9840 .@"fneg fast",
10002 => |tag| {9841 => |tag| {
10003 const val: Value = @enumFromInt(instruction.data);9842 const val: Value = @enumFromInt(instruction.data);
10004 try writer.print(" %{} = {s} {%}", .{9843 try bw.print(" %{f} = {s} {f%}", .{
10005 instruction_index.name(&function).fmt(self),9844 instruction_index.name(&function).fmt(self),
10006 @tagName(tag),9845 @tagName(tag),
10007 val.fmt(function_index, self),9846 val.fmt(function_index, self),
...@@ -10015,13 +9854,13 @@ pub fn printUnbuffered(...@@ -10015,13 +9854,13 @@ pub fn printUnbuffered(
10015 instruction.data,9854 instruction.data,
10016 );9855 );
10017 const indices = extra.trail.next(extra.data.indices_len, Value, &function);9856 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
10018 try writer.print(" %{} = {s} {%}, {%}", .{9857 try bw.print(" %{f} = {s} {f%}, {f%}", .{
10019 instruction_index.name(&function).fmt(self),9858 instruction_index.name(&function).fmt(self),
10020 @tagName(tag),9859 @tagName(tag),
10021 extra.data.type.fmt(self),9860 extra.data.type.fmt(self),
10022 extra.data.base.fmt(function_index, self),9861 extra.data.base.fmt(function_index, self),
10023 });9862 });
10024 for (indices) |index| try writer.print(", {%}", .{9863 for (indices) |index| try bw.print(", {f%}", .{
10025 index.fmt(function_index, self),9864 index.fmt(function_index, self),
10026 });9865 });
10027 },9866 },
...@@ -10030,22 +9869,22 @@ pub fn printUnbuffered(...@@ -10030,22 +9869,22 @@ pub fn printUnbuffered(
10030 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);9869 function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
10031 const targets =9870 const targets =
10032 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);9871 extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
10033 try writer.print(" {s} {%}, [", .{9872 try bw.print(" {s} {f%}, [", .{
10034 @tagName(tag),9873 @tagName(tag),
10035 extra.data.addr.fmt(function_index, self),9874 extra.data.addr.fmt(function_index, self),
10036 });9875 });
10037 for (0.., targets) |target_index, target| {9876 for (0.., targets) |target_index, target| {
10038 if (target_index > 0) try writer.writeAll(", ");9877 if (target_index > 0) try bw.writeAll(", ");
10039 try writer.print("{%}", .{9878 try bw.print("{f%}", .{
10040 target.toInst(&function).fmt(function_index, self),9879 target.toInst(&function).fmt(function_index, self),
10041 });9880 });
10042 }9881 }
10043 try writer.writeByte(']');9882 try bw.writeByte(']');
10044 },9883 },
10045 .insertelement => |tag| {9884 .insertelement => |tag| {
10046 const extra =9885 const extra =
10047 function.extraData(Function.Instruction.InsertElement, instruction.data);9886 function.extraData(Function.Instruction.InsertElement, instruction.data);
10048 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9887 try bw.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10049 instruction_index.name(&function).fmt(self),9888 instruction_index.name(&function).fmt(self),
10050 @tagName(tag),9889 @tagName(tag),
10051 extra.val.fmt(function_index, self),9890 extra.val.fmt(function_index, self),
...@@ -10057,19 +9896,19 @@ pub fn printUnbuffered(...@@ -10057,19 +9896,19 @@ pub fn printUnbuffered(
10057 var extra =9896 var extra =
10058 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);9897 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
10059 const indices = extra.trail.next(extra.data.indices_len, u32, &function);9898 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
10060 try writer.print(" %{} = {s} {%}, {%}", .{9899 try bw.print(" %{f} = {s} {f%}, {f%}", .{
10061 instruction_index.name(&function).fmt(self),9900 instruction_index.name(&function).fmt(self),
10062 @tagName(tag),9901 @tagName(tag),
10063 extra.data.val.fmt(function_index, self),9902 extra.data.val.fmt(function_index, self),
10064 extra.data.elem.fmt(function_index, self),9903 extra.data.elem.fmt(function_index, self),
10065 });9904 });
10066 for (indices) |index| try writer.print(", {d}", .{index});9905 for (indices) |index| try bw.print(", {d}", .{index});
10067 },9906 },
10068 .load,9907 .load,
10069 .@"load atomic",9908 .@"load atomic",
10070 => |tag| {9909 => |tag| {
10071 const extra = function.extraData(Function.Instruction.Load, instruction.data);9910 const extra = function.extraData(Function.Instruction.Load, instruction.data);
10072 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{9911 try bw.print(" %{f} = {s}{f } {f%}, {f%}{f }{f }{f, }", .{
10073 instruction_index.name(&function).fmt(self),9912 instruction_index.name(&function).fmt(self),
10074 @tagName(tag),9913 @tagName(tag),
10075 extra.info.access_kind,9914 extra.info.access_kind,
...@@ -10087,14 +9926,14 @@ pub fn printUnbuffered(...@@ -10087,14 +9926,14 @@ pub fn printUnbuffered(
10087 const vals = extra.trail.next(block_incoming_len, Value, &function);9926 const vals = extra.trail.next(block_incoming_len, Value, &function);
10088 const blocks =9927 const blocks =
10089 extra.trail.next(block_incoming_len, Function.Block.Index, &function);9928 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
10090 try writer.print(" %{} = {s} {%} ", .{9929 try bw.print(" %{f} = {s} {f%} ", .{
10091 instruction_index.name(&function).fmt(self),9930 instruction_index.name(&function).fmt(self),
10092 @tagName(tag),9931 @tagName(tag),
10093 vals[0].typeOf(function_index, self).fmt(self),9932 vals[0].typeOf(function_index, self).fmt(self),
10094 });9933 });
10095 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {9934 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
10096 if (incoming_index > 0) try writer.writeAll(", ");9935 if (incoming_index > 0) try bw.writeAll(", ");
10097 try writer.print("[ {}, {} ]", .{9936 try bw.print("[ {f}, {f} ]", .{
10098 incoming_val.fmt(function_index, self),9937 incoming_val.fmt(function_index, self),
10099 incoming_block.toInst(&function).fmt(function_index, self),9938 incoming_block.toInst(&function).fmt(function_index, self),
10100 });9939 });
...@@ -10102,19 +9941,19 @@ pub fn printUnbuffered(...@@ -10102,19 +9941,19 @@ pub fn printUnbuffered(
10102 },9941 },
10103 .ret => |tag| {9942 .ret => |tag| {
10104 const val: Value = @enumFromInt(instruction.data);9943 const val: Value = @enumFromInt(instruction.data);
10105 try writer.print(" {s} {%}", .{9944 try bw.print(" {s} {f%}", .{
10106 @tagName(tag),9945 @tagName(tag),
10107 val.fmt(function_index, self),9946 val.fmt(function_index, self),
10108 });9947 });
10109 },9948 },
10110 .@"ret void",9949 .@"ret void",
10111 .@"unreachable",9950 .@"unreachable",
10112 => |tag| try writer.print(" {s}", .{@tagName(tag)}),9951 => |tag| try bw.print(" {s}", .{@tagName(tag)}),
10113 .select,9952 .select,
10114 .@"select fast",9953 .@"select fast",
10115 => |tag| {9954 => |tag| {
10116 const extra = function.extraData(Function.Instruction.Select, instruction.data);9955 const extra = function.extraData(Function.Instruction.Select, instruction.data);
10117 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9956 try bw.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10118 instruction_index.name(&function).fmt(self),9957 instruction_index.name(&function).fmt(self),
10119 @tagName(tag),9958 @tagName(tag),
10120 extra.cond.fmt(function_index, self),9959 extra.cond.fmt(function_index, self),
...@@ -10125,7 +9964,7 @@ pub fn printUnbuffered(...@@ -10125,7 +9964,7 @@ pub fn printUnbuffered(
10125 .shufflevector => |tag| {9964 .shufflevector => |tag| {
10126 const extra =9965 const extra =
10127 function.extraData(Function.Instruction.ShuffleVector, instruction.data);9966 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
10128 try writer.print(" %{} = {s} {%}, {%}, {%}", .{9967 try bw.print(" %{f} = {s} {f%}, {f%}, {f%}", .{
10129 instruction_index.name(&function).fmt(self),9968 instruction_index.name(&function).fmt(self),
10130 @tagName(tag),9969 @tagName(tag),
10131 extra.lhs.fmt(function_index, self),9970 extra.lhs.fmt(function_index, self),
...@@ -10137,7 +9976,7 @@ pub fn printUnbuffered(...@@ -10137,7 +9976,7 @@ pub fn printUnbuffered(
10137 .@"store atomic",9976 .@"store atomic",
10138 => |tag| {9977 => |tag| {
10139 const extra = function.extraData(Function.Instruction.Store, instruction.data);9978 const extra = function.extraData(Function.Instruction.Store, instruction.data);
10140 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{9979 try bw.print(" {s}{f } {f%}, {f%}{f }{f }{f, }", .{
10141 @tagName(tag),9980 @tagName(tag),
10142 extra.info.access_kind,9981 extra.info.access_kind,
10143 extra.val.fmt(function_index, self),9982 extra.val.fmt(function_index, self),
...@@ -10153,32 +9992,32 @@ pub fn printUnbuffered(...@@ -10153,32 +9992,32 @@ pub fn printUnbuffered(
10153 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);9992 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
10154 const blocks =9993 const blocks =
10155 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);9994 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
10156 try writer.print(" {s} {%}, {%} [\n", .{9995 try bw.print(" {s} {f%}, {f%} [\n", .{
10157 @tagName(tag),9996 @tagName(tag),
10158 extra.data.val.fmt(function_index, self),9997 extra.data.val.fmt(function_index, self),
10159 extra.data.default.toInst(&function).fmt(function_index, self),9998 extra.data.default.toInst(&function).fmt(function_index, self),
10160 });9999 });
10161 for (vals, blocks) |case_val, case_block| try writer.print(10000 for (vals, blocks) |case_val, case_block| try bw.print(
10162 " {%}, {%}\n",10001 " {f%}, {f%}\n",
10163 .{10002 .{
10164 case_val.fmt(self),10003 case_val.fmt(self),
10165 case_block.toInst(&function).fmt(function_index, self),10004 case_block.toInst(&function).fmt(function_index, self),
10166 },10005 },
10167 );10006 );
10168 try writer.writeAll(" ]");10007 try bw.writeAll(" ]");
10169 metadata_formatter.need_comma = true;10008 metadata_formatter.need_comma = true;
10170 defer metadata_formatter.need_comma = undefined;10009 defer metadata_formatter.need_comma = undefined;
10171 switch (extra.data.weights) {10010 switch (extra.data.weights) {
10172 .none => {},10011 .none => {},
10173 .unpredictable => try writer.writeAll("!unpredictable !{}"),10012 .unpredictable => try bw.writeAll("!unpredictable !{}"),
10174 _ => try writer.print("{}", .{10013 _ => try bw.print("{f}", .{
10175 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),10014 try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),
10176 }),10015 }),
10177 }10016 }
10178 },10017 },
10179 .va_arg => |tag| {10018 .va_arg => |tag| {
10180 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);10019 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
10181 try writer.print(" %{} = {s} {%}, {%}", .{10020 try bw.print(" %{f} = {s} {f%}, {f%}", .{
10182 instruction_index.name(&function).fmt(self),10021 instruction_index.name(&function).fmt(self),
10183 @tagName(tag),10022 @tagName(tag),
10184 extra.list.fmt(function_index, self),10023 extra.list.fmt(function_index, self),
...@@ -10188,45 +10027,45 @@ pub fn printUnbuffered(...@@ -10188,45 +10027,45 @@ pub fn printUnbuffered(
10188 }10027 }
1018910028
10190 if (maybe_dbg_index) |dbg_index| {10029 if (maybe_dbg_index) |dbg_index| {
10191 try writer.print(", !dbg !{}", .{dbg_index});10030 try bw.print(", !dbg !{d}", .{dbg_index});
10192 }10031 }
10193 try writer.writeByte('\n');10032 try bw.writeByte('\n');
10194 }10033 }
10195 try writer.writeByte('}');10034 try bw.writeByte('}');
10196 }10035 }
10197 try writer.writeByte('\n');10036 try bw.writeByte('\n');
10198 }10037 }
1019910038
10200 if (attribute_groups.count() > 0) {10039 if (attribute_groups.count() > 0) {
10201 if (need_newline) try writer.writeByte('\n') else need_newline = true;10040 if (need_newline) try bw.writeByte('\n') else need_newline = true;
10202 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|10041 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
10203 try writer.print(10042 try bw.print(
10204 \\attributes #{d} = {{{#"} }}10043 \\attributes #{d} = {{{f#"} }}
10205 \\10044 \\
10206 , .{ attribute_group_index, attribute_group.fmt(self) });10045 , .{ attribute_group_index, attribute_group.fmt(self) });
10207 }10046 }
1020810047
10209 if (self.metadata_named.count() > 0) {10048 if (self.metadata_named.count() > 0) {
10210 if (need_newline) try writer.writeByte('\n') else need_newline = true;10049 if (need_newline) try bw.writeByte('\n') else need_newline = true;
10211 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {10050 for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
10212 const elements: []const Metadata =10051 const elements: []const Metadata =
10213 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);10052 @ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
10214 try writer.writeByte('!');10053 try bw.writeByte('!');
10215 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);10054 try printEscapedString(name.slice(self), .quote_unless_valid_identifier, bw);
10216 try writer.writeAll(" = !{");10055 try bw.writeAll(" = !{");
10217 metadata_formatter.need_comma = false;10056 metadata_formatter.need_comma = false;
10218 defer metadata_formatter.need_comma = undefined;10057 defer metadata_formatter.need_comma = undefined;
10219 for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});10058 for (elements) |element| try bw.print("{f}", .{try metadata_formatter.fmt("", element)});
10220 try writer.writeAll("}\n");10059 try bw.writeAll("}\n");
10221 }10060 }
10222 }10061 }
1022310062
10224 if (metadata_formatter.map.count() > 0) {10063 if (metadata_formatter.map.count() > 0) {
10225 if (need_newline) try writer.writeByte('\n') else need_newline = true;10064 if (need_newline) try bw.writeByte('\n') else need_newline = true;
10226 var metadata_index: usize = 0;10065 var metadata_index: usize = 0;
10227 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {10066 while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
10228 @setEvalBranchQuota(10_000);10067 @setEvalBranchQuota(10_000);
10229 try writer.print("!{} = ", .{metadata_index});10068 try bw.print("!{d} = ", .{metadata_index});
10230 metadata_formatter.need_comma = false;10069 metadata_formatter.need_comma = false;
10231 defer metadata_formatter.need_comma = undefined;10070 defer metadata_formatter.need_comma = undefined;
1023210071
...@@ -10239,7 +10078,7 @@ pub fn printUnbuffered(...@@ -10239,7 +10078,7 @@ pub fn printUnbuffered(
10239 .scope = location.scope,10078 .scope = location.scope,
10240 .inlinedAt = location.inlined_at,10079 .inlinedAt = location.inlined_at,
10241 .isImplicitCode = false,10080 .isImplicitCode = false,
10242 }, writer);10081 }, bw);
10243 continue;10082 continue;
10244 },10083 },
10245 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),10084 .metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
...@@ -10255,7 +10094,7 @@ pub fn printUnbuffered(...@@ -10255,7 +10094,7 @@ pub fn printUnbuffered(
10255 .checksumkind = null,10094 .checksumkind = null,
10256 .checksum = null,10095 .checksum = null,
10257 .source = null,10096 .source = null,
10258 }, writer);10097 }, bw);
10259 },10098 },
10260 .compile_unit,10099 .compile_unit,
10261 .@"compile_unit optimized",10100 .@"compile_unit optimized",
...@@ -10286,7 +10125,7 @@ pub fn printUnbuffered(...@@ -10286,7 +10125,7 @@ pub fn printUnbuffered(
10286 .rangesBaseAddress = null,10125 .rangesBaseAddress = null,
10287 .sysroot = null,10126 .sysroot = null,
10288 .sdk = null,10127 .sdk = null,
10289 }, writer);10128 }, bw);
10290 },10129 },
10291 .subprogram,10130 .subprogram,
10292 .@"subprogram local",10131 .@"subprogram local",
...@@ -10320,7 +10159,7 @@ pub fn printUnbuffered(...@@ -10320,7 +10159,7 @@ pub fn printUnbuffered(
10320 .thrownTypes = null,10159 .thrownTypes = null,
10321 .annotations = null,10160 .annotations = null,
10322 .targetFuncName = null,10161 .targetFuncName = null,
10323 }, writer);10162 }, bw);
10324 },10163 },
10325 .lexical_block => {10164 .lexical_block => {
10326 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);10165 const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
...@@ -10329,7 +10168,7 @@ pub fn printUnbuffered(...@@ -10329,7 +10168,7 @@ pub fn printUnbuffered(
10329 .file = extra.file,10168 .file = extra.file,
10330 .line = extra.line,10169 .line = extra.line,
10331 .column = extra.column,10170 .column = extra.column,
10332 }, writer);10171 }, bw);
10333 },10172 },
10334 .location => {10173 .location => {
10335 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);10174 const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
...@@ -10339,7 +10178,7 @@ pub fn printUnbuffered(...@@ -10339,7 +10178,7 @@ pub fn printUnbuffered(
10339 .scope = extra.scope,10178 .scope = extra.scope,
10340 .inlinedAt = extra.inlined_at,10179 .inlinedAt = extra.inlined_at,
10341 .isImplicitCode = false,10180 .isImplicitCode = false,
10342 }, writer);10181 }, bw);
10343 },10182 },
10344 .basic_bool_type,10183 .basic_bool_type,
10345 .basic_unsigned_type,10184 .basic_unsigned_type,
...@@ -10368,7 +10207,7 @@ pub fn printUnbuffered(...@@ -10368,7 +10207,7 @@ pub fn printUnbuffered(
10368 else => unreachable,10207 else => unreachable,
10369 }),10208 }),
10370 .flags = null,10209 .flags = null,
10371 }, writer);10210 }, bw);
10372 },10211 },
10373 .composite_struct_type,10212 .composite_struct_type,
10374 .composite_union_type,10213 .composite_union_type,
...@@ -10413,7 +10252,7 @@ pub fn printUnbuffered(...@@ -10413,7 +10252,7 @@ pub fn printUnbuffered(
10413 .allocated = null,10252 .allocated = null,
10414 .rank = null,10253 .rank = null,
10415 .annotations = null,10254 .annotations = null,
10416 }, writer);10255 }, bw);
10417 },10256 },
10418 .derived_pointer_type,10257 .derived_pointer_type,
10419 .derived_member_type,10258 .derived_member_type,
...@@ -10446,7 +10285,7 @@ pub fn printUnbuffered(...@@ -10446,7 +10285,7 @@ pub fn printUnbuffered(
10446 .extraData = null,10285 .extraData = null,
10447 .dwarfAddressSpace = null,10286 .dwarfAddressSpace = null,
10448 .annotations = null,10287 .annotations = null,
10449 }, writer);10288 }, bw);
10450 },10289 },
10451 .subroutine_type => {10290 .subroutine_type => {
10452 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);10291 const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
...@@ -10454,7 +10293,7 @@ pub fn printUnbuffered(...@@ -10454,7 +10293,7 @@ pub fn printUnbuffered(
10454 .flags = null,10293 .flags = null,
10455 .cc = null,10294 .cc = null,
10456 .types = extra.types_tuple,10295 .types = extra.types_tuple,
10457 }, writer);10296 }, bw);
10458 },10297 },
10459 .enumerator_unsigned,10298 .enumerator_unsigned,
10460 .enumerator_signed_positive,10299 .enumerator_signed_positive,
...@@ -10504,7 +10343,7 @@ pub fn printUnbuffered(...@@ -10504,7 +10343,7 @@ pub fn printUnbuffered(
10504 => false,10343 => false,
10505 else => unreachable,10344 else => unreachable,
10506 },10345 },
10507 }, writer);10346 }, bw);
10508 },10347 },
10509 .subrange => {10348 .subrange => {
10510 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);10349 const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
...@@ -10513,31 +10352,31 @@ pub fn printUnbuffered(...@@ -10513,31 +10352,31 @@ pub fn printUnbuffered(
10513 .lowerBound = extra.lower_bound,10352 .lowerBound = extra.lower_bound,
10514 .upperBound = null,10353 .upperBound = null,
10515 .stride = null,10354 .stride = null,
10516 }, writer);10355 }, bw);
10517 },10356 },
10518 .tuple => {10357 .tuple => {
10519 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);10358 var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
10520 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10359 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10521 try writer.writeAll("!{");10360 try bw.writeAll("!{");
10522 for (elements) |element| try writer.print("{[element]%}", .{10361 for (elements) |element| try bw.print("{[element]f%}", .{
10523 .element = try metadata_formatter.fmt("", element),10362 .element = try metadata_formatter.fmt("", element),
10524 });10363 });
10525 try writer.writeAll("}\n");10364 try bw.writeAll("}\n");
10526 },10365 },
10527 .str_tuple => {10366 .str_tuple => {
10528 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);10367 var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);
10529 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);10368 const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
10530 try writer.print("!{{{[str]%}", .{10369 try bw.print("!{{{[str]f%}", .{
10531 .str = try metadata_formatter.fmt("", extra.data.str),10370 .str = try metadata_formatter.fmt("", extra.data.str),
10532 });10371 });
10533 for (elements) |element| try writer.print("{[element]%}", .{10372 for (elements) |element| try bw.print("{[element]f%}", .{
10534 .element = try metadata_formatter.fmt("", element),10373 .element = try metadata_formatter.fmt("", element),
10535 });10374 });
10536 try writer.writeAll("}\n");10375 try bw.writeAll("}\n");
10537 },10376 },
10538 .module_flag => {10377 .module_flag => {
10539 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);10378 const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);
10540 try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{10379 try bw.print("!{{{[behavior]f%}{[name]f%}{[constant]f%}}}\n", .{
10541 .behavior = try metadata_formatter.fmt("", extra.behavior),10380 .behavior = try metadata_formatter.fmt("", extra.behavior),
10542 .name = try metadata_formatter.fmt("", extra.name),10381 .name = try metadata_formatter.fmt("", extra.name),
10543 .constant = try metadata_formatter.fmt("", extra.constant),10382 .constant = try metadata_formatter.fmt("", extra.constant),
...@@ -10555,7 +10394,7 @@ pub fn printUnbuffered(...@@ -10555,7 +10394,7 @@ pub fn printUnbuffered(
10555 .flags = null,10394 .flags = null,
10556 .@"align" = null,10395 .@"align" = null,
10557 .annotations = null,10396 .annotations = null,
10558 }, writer);10397 }, bw);
10559 },10398 },
10560 .parameter => {10399 .parameter => {
10561 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);10400 const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
...@@ -10569,7 +10408,7 @@ pub fn printUnbuffered(...@@ -10569,7 +10408,7 @@ pub fn printUnbuffered(
10569 .flags = null,10408 .flags = null,
10570 .@"align" = null,10409 .@"align" = null,
10571 .annotations = null,10410 .annotations = null,
10572 }, writer);10411 }, bw);
10573 },10412 },
10574 .global_var,10413 .global_var,
10575 .@"global_var local",10414 .@"global_var local",
...@@ -10592,7 +10431,7 @@ pub fn printUnbuffered(...@@ -10592,7 +10431,7 @@ pub fn printUnbuffered(
10592 .templateParams = null,10431 .templateParams = null,
10593 .@"align" = null,10432 .@"align" = null,
10594 .annotations = null,10433 .annotations = null,
10595 }, writer);10434 }, bw);
10596 },10435 },
10597 .global_var_expression => {10436 .global_var_expression => {
10598 const extra =10437 const extra =
...@@ -10600,7 +10439,7 @@ pub fn printUnbuffered(...@@ -10600,7 +10439,7 @@ pub fn printUnbuffered(
10600 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{10439 try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
10601 .@"var" = extra.variable,10440 .@"var" = extra.variable,
10602 .expr = extra.expression,10441 .expr = extra.expression,
10603 }, writer);10442 }, bw);
10604 },10443 },
10605 }10444 }
10606 }10445 }
...@@ -10619,22 +10458,18 @@ fn isValidIdentifier(id: []const u8) bool {...@@ -10619,22 +10458,18 @@ fn isValidIdentifier(id: []const u8) bool {
10619}10458}
1062010459
10621const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };10460const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
10622fn printEscapedString(10461fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, bw: *std.io.BufferedWriter) anyerror!void {
10623 slice: []const u8,
10624 quotes: QuoteBehavior,
10625 writer: anytype,
10626) @TypeOf(writer).Error!void {
10627 const need_quotes = switch (quotes) {10462 const need_quotes = switch (quotes) {
10628 .always_quote => true,10463 .always_quote => true,
10629 .quote_unless_valid_identifier => !isValidIdentifier(slice),10464 .quote_unless_valid_identifier => !isValidIdentifier(slice),
10630 };10465 };
10631 if (need_quotes) try writer.writeByte('"');10466 if (need_quotes) try bw.writeByte('"');
10632 for (slice) |byte| switch (byte) {10467 for (slice) |byte| switch (byte) {
10633 '\\' => try writer.writeAll("\\\\"),10468 '\\' => try bw.writeAll("\\\\"),
10634 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte),10469 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try bw.writeByte(byte),
10635 else => try writer.print("\\{X:0>2}", .{byte}),10470 else => try bw.print("\\{X:0>2}", .{byte}),
10636 };10471 };
10637 if (need_quotes) try writer.writeByte('"');10472 if (need_quotes) try bw.writeByte('"');
10638}10473}
1063910474
10640fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {10475fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {
...@@ -12019,7 +11854,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:...@@ -12019,7 +11854,7 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:
12019}11854}
1202011855
12021pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {11856pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {
12022 self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;11857 self.metadata_string_bytes.printAssumeCapacity(fmt_str, fmt_args);
12023 return self.trailingMetadataStringAssumeCapacity();11858 return self.trailingMetadataStringAssumeCapacity();
12024}11859}
1202511860
lib/std/zig/render.zig+23-13
...@@ -77,7 +77,7 @@ const Render = struct {...@@ -77,7 +77,7 @@ const Render = struct {
7777
78pub fn renderTree(gpa: Allocator, bw: *std.io.BufferedWriter, tree: Ast, fixups: Fixups) anyerror!void {78pub fn renderTree(gpa: Allocator, bw: *std.io.BufferedWriter, tree: Ast, fixups: Fixups) anyerror!void {
79 assert(tree.errors.len == 0); // Cannot render an invalid tree.79 assert(tree.errors.len == 0); // Cannot render an invalid tree.
80 var auto_indenting_stream: AutoIndentingStream = .init(bw, indent_delta);80 var auto_indenting_stream: AutoIndentingStream = .init(gpa, bw, indent_delta);
81 defer auto_indenting_stream.deinit();81 defer auto_indenting_stream.deinit();
82 var r: Render = .{82 var r: Render = .{
83 .gpa = gpa,83 .gpa = gpa,
...@@ -2135,13 +2135,13 @@ fn renderArrayInit(...@@ -2135,13 +2135,13 @@ fn renderArrayInit(
2135 const section_exprs = row_exprs[0..section_end];2135 const section_exprs = row_exprs[0..section_end];
21362136
2137 var sub_expr_buffer: std.io.AllocatingWriter = undefined;2137 var sub_expr_buffer: std.io.AllocatingWriter = undefined;
2138 const sub_expr_buffer_writer = sub_expr_buffer.init(gpa);2138 sub_expr_buffer.init(gpa);
2139 defer sub_expr_buffer.deinit();2139 defer sub_expr_buffer.deinit();
21402140
2141 const sub_expr_buffer_starts = try gpa.alloc(usize, section_exprs.len + 1);2141 const sub_expr_buffer_starts = try gpa.alloc(usize, section_exprs.len + 1);
2142 defer gpa.free(sub_expr_buffer_starts);2142 defer gpa.free(sub_expr_buffer_starts);
21432143
2144 var auto_indenting_stream: AutoIndentingStream = .init(sub_expr_buffer_writer, indent_delta);2144 var auto_indenting_stream: AutoIndentingStream = .init(gpa, &sub_expr_buffer.buffered_writer, indent_delta);
2145 defer auto_indenting_stream.deinit();2145 defer auto_indenting_stream.deinit();
2146 var sub_render: Render = .{2146 var sub_render: Render = .{
2147 .gpa = r.gpa,2147 .gpa = r.gpa,
...@@ -2160,8 +2160,9 @@ fn renderArrayInit(...@@ -2160,8 +2160,9 @@ fn renderArrayInit(
21602160
2161 if (i + 1 < section_exprs.len) {2161 if (i + 1 < section_exprs.len) {
2162 try renderExpression(&sub_render, expr, .none);2162 try renderExpression(&sub_render, expr, .none);
2163 const width = sub_expr_buffer.getWritten().len - start;2163 const written = sub_expr_buffer.getWritten();
2164 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.getWritten()[start..], '\n') != null;2164 const width = written.len - start;
2165 const this_contains_newline = mem.indexOfScalar(u8, written[start..], '\n') != null;
2165 contains_newline = contains_newline or this_contains_newline;2166 contains_newline = contains_newline or this_contains_newline;
2166 expr_widths[i] = width;2167 expr_widths[i] = width;
2167 expr_newlines[i] = this_contains_newline;2168 expr_newlines[i] = this_contains_newline;
...@@ -2183,8 +2184,9 @@ fn renderArrayInit(...@@ -2183,8 +2184,9 @@ fn renderArrayInit(
2183 try renderExpression(&sub_render, expr, .comma);2184 try renderExpression(&sub_render, expr, .comma);
2184 ais.popSpace();2185 ais.popSpace();
21852186
2186 const width = sub_expr_buffer.items.len - start - 2;2187 const written = sub_expr_buffer.getWritten();
2187 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.getWritten()[start .. sub_expr_buffer.items.len - 1], '\n') != null;2188 const width = written.len - start - 2;
2189 const this_contains_newline = mem.indexOfScalar(u8, written[start .. written.len - 1], '\n') != null;
2188 contains_newline = contains_newline or this_contains_newline;2190 contains_newline = contains_newline or this_contains_newline;
2189 expr_widths[i] = width;2191 expr_widths[i] = width;
2190 expr_newlines[i] = contains_newline;2192 expr_newlines[i] = contains_newline;
...@@ -2682,7 +2684,7 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:...@@ -2682,7 +2684,7 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
2682 const tree = r.tree;2684 const tree = r.tree;
2683 const ais = r.ais;2685 const ais = r.ais;
2684 const lexeme = tokenSliceForRender(tree, token_index);2686 const lexeme = tokenSliceForRender(tree, token_index);
2685 try ais.writer().writeAll(lexeme);2687 try ais.writeAll(lexeme);
2686 ais.enableSpaceMode(override_space);2688 ais.enableSpaceMode(override_space);
2687 defer ais.disableSpaceMode();2689 defer ais.disableSpaceMode();
2688 try renderSpace(r, token_index, lexeme.len, space);2690 try renderSpace(r, token_index, lexeme.len, space);
...@@ -3259,6 +3261,14 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi...@@ -3259,6 +3261,14 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
3259const AutoIndentingStream = struct {3261const AutoIndentingStream = struct {
3260 underlying_writer: *std.io.BufferedWriter,3262 underlying_writer: *std.io.BufferedWriter,
32613263
3264 /// Offset into the source at which formatting has been disabled with
3265 /// a `zig fmt: off` comment.
3266 ///
3267 /// If non-null, the AutoIndentingStream will not write any bytes
3268 /// to the underlying writer. It will however continue to track the
3269 /// indentation level.
3270 disabled_offset: ?usize = null,
3271
3262 indent_count: usize = 0,3272 indent_count: usize = 0,
3263 indent_delta: usize,3273 indent_delta: usize,
3264 indent_stack: std.ArrayList(StackElem),3274 indent_stack: std.ArrayList(StackElem),
...@@ -3284,12 +3294,12 @@ const AutoIndentingStream = struct {...@@ -3284,12 +3294,12 @@ const AutoIndentingStream = struct {
3284 indent_count: usize,3294 indent_count: usize,
3285 };3295 };
32863296
3287 pub fn init(buffer: *std.ArrayList(u8), indent_delta_: usize) AutoIndentingStream {3297 pub fn init(gpa: Allocator, bw: *std.io.BufferedWriter, indent_delta_: usize) AutoIndentingStream {
3288 return .{3298 return .{
3289 .underlying_writer = buffer.writer(),3299 .underlying_writer = bw,
3290 .indent_delta = indent_delta_,3300 .indent_delta = indent_delta_,
3291 .indent_stack = std.ArrayList(StackElem).init(buffer.allocator),3301 .indent_stack = .init(gpa),
3292 .space_stack = std.ArrayList(SpaceElem).init(buffer.allocator),3302 .space_stack = .init(gpa),
3293 };3303 };
3294 }3304 }
32953305
...@@ -3477,7 +3487,7 @@ const AutoIndentingStream = struct {...@@ -3477,7 +3487,7 @@ const AutoIndentingStream = struct {
3477 const current_indent = ais.currentIndent();3487 const current_indent = ais.currentIndent();
3478 if (ais.current_line_empty and current_indent > 0) {3488 if (ais.current_line_empty and current_indent > 0) {
3479 if (ais.disabled_offset == null) {3489 if (ais.disabled_offset == null) {
3480 try ais.underlying_writer.writeByteNTimes(' ', current_indent);3490 try ais.underlying_writer.splatByteAll(' ', current_indent);
3481 }3491 }
3482 ais.applied_indent = current_indent;3492 ais.applied_indent = current_indent;
3483 }3493 }
lib/std/zig/string_literal.zig+16-22
...@@ -44,50 +44,44 @@ pub const Error = union(enum) {...@@ -44,50 +44,44 @@ pub const Error = union(enum) {
44 raw_string: []const u8,44 raw_string: []const u8,
45 };45 };
4646
47 fn formatMessage(47 fn formatMessage(self: FormatMessage, bw: *std.io.BufferedWriter, comptime f: []const u8) anyerror!void {
48 self: FormatMessage,
49 comptime f: []const u8,
50 options: std.fmt.FormatOptions,
51 writer: anytype,
52 ) !void {
53 _ = f;48 _ = f;
54 _ = options;
55 switch (self.err) {49 switch (self.err) {
56 .invalid_escape_character => |bad_index| try writer.print(50 .invalid_escape_character => |bad_index| try bw.print(
57 "invalid escape character: '{c}'",51 "invalid escape character: '{c}'",
58 .{self.raw_string[bad_index]},52 .{self.raw_string[bad_index]},
59 ),53 ),
60 .expected_hex_digit => |bad_index| try writer.print(54 .expected_hex_digit => |bad_index| try bw.print(
61 "expected hex digit, found '{c}'",55 "expected hex digit, found '{c}'",
62 .{self.raw_string[bad_index]},56 .{self.raw_string[bad_index]},
63 ),57 ),
64 .empty_unicode_escape_sequence => try writer.writeAll(58 .empty_unicode_escape_sequence => try bw.writeAll(
65 "empty unicode escape sequence",59 "empty unicode escape sequence",
66 ),60 ),
67 .expected_hex_digit_or_rbrace => |bad_index| try writer.print(61 .expected_hex_digit_or_rbrace => |bad_index| try bw.print(
68 "expected hex digit or '}}', found '{c}'",62 "expected hex digit or '}}', found '{c}'",
69 .{self.raw_string[bad_index]},63 .{self.raw_string[bad_index]},
70 ),64 ),
71 .invalid_unicode_codepoint => try writer.writeAll(65 .invalid_unicode_codepoint => try bw.writeAll(
72 "unicode escape does not correspond to a valid unicode scalar value",66 "unicode escape does not correspond to a valid unicode scalar value",
73 ),67 ),
74 .expected_lbrace => |bad_index| try writer.print(68 .expected_lbrace => |bad_index| try bw.print(
75 "expected '{{', found '{c}'",69 "expected '{{', found '{c}'",
76 .{self.raw_string[bad_index]},70 .{self.raw_string[bad_index]},
77 ),71 ),
78 .expected_rbrace => |bad_index| try writer.print(72 .expected_rbrace => |bad_index| try bw.print(
79 "expected '}}', found '{c}'",73 "expected '}}', found '{c}'",
80 .{self.raw_string[bad_index]},74 .{self.raw_string[bad_index]},
81 ),75 ),
82 .expected_single_quote => |bad_index| try writer.print(76 .expected_single_quote => |bad_index| try bw.print(
83 "expected single quote ('), found '{c}'",77 "expected single quote ('), found '{c}'",
84 .{self.raw_string[bad_index]},78 .{self.raw_string[bad_index]},
85 ),79 ),
86 .invalid_character => |bad_index| try writer.print(80 .invalid_character => |bad_index| try bw.print(
87 "invalid byte in string or character literal: '{c}'",81 "invalid byte in string or character literal: '{c}'",
88 .{self.raw_string[bad_index]},82 .{self.raw_string[bad_index]},
89 ),83 ),
90 .empty_char_literal => try writer.writeAll(84 .empty_char_literal => try bw.writeAll(
91 "empty character literal",85 "empty character literal",
92 ),86 ),
93 }87 }
...@@ -363,13 +357,13 @@ pub fn parseWrite(writer: *std.io.BufferedWriter, bytes: []const u8) anyerror!Re...@@ -363,13 +357,13 @@ pub fn parseWrite(writer: *std.io.BufferedWriter, bytes: []const u8) anyerror!Re
363/// Higher level API. Does not return extra info about parse errors.357/// Higher level API. Does not return extra info about parse errors.
364/// Caller owns returned memory.358/// Caller owns returned memory.
365pub fn parseAlloc(allocator: std.mem.Allocator, bytes: []const u8) ParseError![]u8 {359pub fn parseAlloc(allocator: std.mem.Allocator, bytes: []const u8) ParseError![]u8 {
366 var buf: std.io.AllocatingWriter = undefined;360 var aw: std.io.AllocatingWriter = undefined;
367 const bw = buf.init(allocator);361 aw.init(allocator);
368 defer buf.deinit();362 defer aw.deinit();
369 // TODO try @errorCast(...)363 // TODO try @errorCast(...)
370 const result = parseWrite(bw, bytes) catch |err| return @errorCast(err);364 const result = parseWrite(&aw.buffered_writer, bytes) catch |err| return @errorCast(err);
371 switch (result) {365 switch (result) {
372 .success => return buf.toOwnedSlice(),366 .success => return aw.toOwnedSlice(),
373 .failure => return error.InvalidLiteral,367 .failure => return error.InvalidLiteral,
374 }368 }
375}369}
lib/std/zon/stringify.zig+5-5
...@@ -583,7 +583,7 @@ pub const Serializer = struct {...@@ -583,7 +583,7 @@ pub const Serializer = struct {
583583
584 /// Serialize an integer.584 /// Serialize an integer.
585 pub fn int(self: *Serializer, val: anytype) anyerror!void {585 pub fn int(self: *Serializer, val: anytype) anyerror!void {
586 try std.fmt.formatInt(val, 10, .lower, .{}, self.writer);586 try self.writer.printIntOptions(val, 10, .lower, .{});
587 }587 }
588588
589 /// Serialize a float.589 /// Serialize a float.
...@@ -613,7 +613,7 @@ pub const Serializer = struct {...@@ -613,7 +613,7 @@ pub const Serializer = struct {
613 ///613 ///
614 /// Escapes the identifier if necessary.614 /// Escapes the identifier if necessary.
615 pub fn ident(self: *Serializer, name: []const u8) anyerror!void {615 pub fn ident(self: *Serializer, name: []const u8) anyerror!void {
616 try self.writer.print(".{p_}", .{std.zig.fmtId(name)});616 try self.writer.print(".{fp_}", .{std.zig.fmtId(name)});
617 }617 }
618618
619 /// Serialize `val` as a Unicode codepoint.619 /// Serialize `val` as a Unicode codepoint.
...@@ -626,7 +626,7 @@ pub const Serializer = struct {...@@ -626,7 +626,7 @@ pub const Serializer = struct {
626 var buf: [8]u8 = undefined;626 var buf: [8]u8 = undefined;
627 const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint;627 const len = std.unicode.utf8Encode(val, &buf) catch return error.InvalidCodepoint;
628 const str = buf[0..len];628 const str = buf[0..len];
629 try std.fmt.format(self.writer, "'{'}'", .{std.zig.fmtEscapes(str)});629 try std.fmt.format(self.writer, "'{f'}'", .{std.zig.fmtEscapes(str)});
630 }630 }
631631
632 /// Like `value`, but always serializes `val` as a tuple.632 /// Like `value`, but always serializes `val` as a tuple.
...@@ -684,7 +684,7 @@ pub const Serializer = struct {...@@ -684,7 +684,7 @@ pub const Serializer = struct {
684684
685 /// Like `value`, but always serializes `val` as a string.685 /// Like `value`, but always serializes `val` as a string.
686 pub fn string(self: *Serializer, val: []const u8) anyerror!void {686 pub fn string(self: *Serializer, val: []const u8) anyerror!void {
687 try std.fmt.format(self.writer, "\"{}\"", .{std.zig.fmtEscapes(val)});687 try std.fmt.format(self.writer, "\"{f}\"", .{std.zig.fmtEscapes(val)});
688 }688 }
689689
690 /// Options for formatting multiline strings.690 /// Options for formatting multiline strings.
...@@ -758,7 +758,7 @@ pub const Serializer = struct {...@@ -758,7 +758,7 @@ pub const Serializer = struct {
758758
759 fn indent(self: *Serializer) anyerror!void {759 fn indent(self: *Serializer) anyerror!void {
760 if (self.options.whitespace) {760 if (self.options.whitespace) {
761 try self.writer.writeByteNTimes(' ', 4 * self.indent_level);761 try self.writer.splatByteAll(' ', 4 * self.indent_level);
762 }762 }
763 }763 }
764764
src/Air.zig+4-9
...@@ -957,18 +957,13 @@ pub const Inst = struct {...@@ -957,18 +957,13 @@ pub const Inst = struct {
957 return index.unwrap().target;957 return index.unwrap().target;
958 }958 }
959959
960 pub fn format(960 pub fn format(index: Index, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
961 index: Index,961 try bw.writeByte('%');
962 comptime _: []const u8,
963 _: std.fmt.Options,
964 writer: *std.io.BufferedWriter,
965 ) anyerror!void {
966 try writer.writeByte('%');
967 switch (index.unwrap()) {962 switch (index.unwrap()) {
968 .ref => {},963 .ref => {},
969 .target => try writer.writeByte('t'),964 .target => try bw.writeByte('t'),
970 }965 }
971 try writer.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});966 try bw.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});
972 }967 }
973 };968 };
974969
src/Air/Liveness.zig+25-25
...@@ -1323,7 +1323,7 @@ fn analyzeOperands(...@@ -1323,7 +1323,7 @@ fn analyzeOperands(
1323 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));1323 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));
13241324
1325 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {1325 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {
1326 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, @intFromEnum(inst), operand });1326 log.debug("[{}] %{}: added %{f} to live set (operand dies here)", .{ pass, @intFromEnum(inst), operand });
1327 tomb_bits |= mask;1327 tomb_bits |= mask;
1328 }1328 }
1329 }1329 }
...@@ -1462,19 +1462,19 @@ fn analyzeInstBlock(...@@ -1462,19 +1462,19 @@ fn analyzeInstBlock(
1462 },1462 },
14631463
1464 .main_analysis => {1464 .main_analysis => {
1465 log.debug("[{}] %{}: block live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1465 log.debug("[{}] %{f}: block live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
1466 // We can move the live set because the body should have a noreturn1466 // We can move the live set because the body should have a noreturn
1467 // instruction which overrides the set.1467 // instruction which overrides the set.
1468 try data.block_scopes.put(gpa, inst, .{1468 try data.block_scopes.put(gpa, inst, .{
1469 .live_set = data.live_set.move(),1469 .live_set = data.live_set.move(),
1470 });1470 });
1471 defer {1471 defer {
1472 log.debug("[{}] %{}: popped block scope", .{ pass, inst });1472 log.debug("[{}] %{f}: popped block scope", .{ pass, inst });
1473 var scope = data.block_scopes.fetchRemove(inst).?.value;1473 var scope = data.block_scopes.fetchRemove(inst).?.value;
1474 scope.live_set.deinit(gpa);1474 scope.live_set.deinit(gpa);
1475 }1475 }
14761476
1477 log.debug("[{}] %{}: pushed new block scope", .{ pass, inst });1477 log.debug("[{}] %{f}: pushed new block scope", .{ pass, inst });
1478 try analyzeBody(a, pass, data, body);1478 try analyzeBody(a, pass, data, body);
14791479
1480 // If the block is noreturn, block deaths not only aren't useful, they're impossible to1480 // If the block is noreturn, block deaths not only aren't useful, they're impossible to
...@@ -1501,7 +1501,7 @@ fn analyzeInstBlock(...@@ -1501,7 +1501,7 @@ fn analyzeInstBlock(
1501 }1501 }
1502 assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set1502 assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set
1503 try a.special.put(gpa, inst, extra_index);1503 try a.special.put(gpa, inst, extra_index);
1504 log.debug("[{}] %{}: block deaths are {}", .{1504 log.debug("[{}] %{f}: block deaths are {f}", .{
1505 pass,1505 pass,
1506 inst,1506 inst,
1507 fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])),1507 fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])),
...@@ -1538,7 +1538,7 @@ fn writeLoopInfo(...@@ -1538,7 +1538,7 @@ fn writeLoopInfo(
1538 const block_inst = key.*;1538 const block_inst = key.*;
1539 a.extra.appendAssumeCapacity(@intFromEnum(block_inst));1539 a.extra.appendAssumeCapacity(@intFromEnum(block_inst));
1540 }1540 }
1541 log.debug("[{}] %{}: includes breaks to {}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) });1541 log.debug("[{}] %{f}: includes breaks to {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) });
15421542
1543 // Now we put the live operands from the loop body in too1543 // Now we put the live operands from the loop body in too
1544 const num_live = data.live_set.count();1544 const num_live = data.live_set.count();
...@@ -1550,7 +1550,7 @@ fn writeLoopInfo(...@@ -1550,7 +1550,7 @@ fn writeLoopInfo(
1550 const alive = key.*;1550 const alive = key.*;
1551 a.extra.appendAssumeCapacity(@intFromEnum(alive));1551 a.extra.appendAssumeCapacity(@intFromEnum(alive));
1552 }1552 }
1553 log.debug("[{}] %{}: maintain liveness of {}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) });1553 log.debug("[{}] %{f}: maintain liveness of {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) });
15541554
1555 try a.special.put(gpa, inst, extra_index);1555 try a.special.put(gpa, inst, extra_index);
15561556
...@@ -1591,7 +1591,7 @@ fn resolveLoopLiveSet(...@@ -1591,7 +1591,7 @@ fn resolveLoopLiveSet(
1591 try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len));1591 try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len));
1592 for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {});1592 for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {});
15931593
1594 log.debug("[{}] %{}: block live set is {}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });1594 log.debug("[{}] %{f}: block live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });
15951595
1596 for (breaks) |block_inst| {1596 for (breaks) |block_inst| {
1597 // We might break to this block, so include every operand that the block needs alive1597 // We might break to this block, so include every operand that the block needs alive
...@@ -1604,7 +1604,7 @@ fn resolveLoopLiveSet(...@@ -1604,7 +1604,7 @@ fn resolveLoopLiveSet(
1604 }1604 }
1605 }1605 }
16061606
1607 log.debug("[{}] %{}: loop live set is {}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });1607 log.debug("[{}] %{f}: loop live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) });
1608}1608}
16091609
1610fn analyzeInstLoop(1610fn analyzeInstLoop(
...@@ -1642,7 +1642,7 @@ fn analyzeInstLoop(...@@ -1642,7 +1642,7 @@ fn analyzeInstLoop(
1642 .live_set = data.live_set.move(),1642 .live_set = data.live_set.move(),
1643 });1643 });
1644 defer {1644 defer {
1645 log.debug("[{}] %{}: popped loop block scop", .{ pass, inst });1645 log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst });
1646 var scope = data.block_scopes.fetchRemove(inst).?.value;1646 var scope = data.block_scopes.fetchRemove(inst).?.value;
1647 scope.live_set.deinit(gpa);1647 scope.live_set.deinit(gpa);
1648 }1648 }
...@@ -1743,13 +1743,13 @@ fn analyzeInstCondBr(...@@ -1743,13 +1743,13 @@ fn analyzeInstCondBr(
1743 }1743 }
1744 }1744 }
17451745
1746 log.debug("[{}] %{}: 'then' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) });1746 log.debug("[{}] %{f}: 'then' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) });
1747 log.debug("[{}] %{}: 'else' branch mirrored deaths are {}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) });1747 log.debug("[{}] %{f}: 'else' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) });
17481748
1749 data.live_set.deinit(gpa);1749 data.live_set.deinit(gpa);
1750 data.live_set = then_live.move(); // Really the union of both live sets1750 data.live_set = then_live.move(); // Really the union of both live sets
17511751
1752 log.debug("[{}] %{}: new live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1752 log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
17531753
1754 // Write the mirrored deaths to `extra`1754 // Write the mirrored deaths to `extra`
1755 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));1755 const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len));
...@@ -1817,7 +1817,7 @@ fn analyzeInstSwitchBr(...@@ -1817,7 +1817,7 @@ fn analyzeInstSwitchBr(
1817 });1817 });
1818 }1818 }
1819 defer if (is_dispatch_loop) {1819 defer if (is_dispatch_loop) {
1820 log.debug("[{}] %{}: popped loop block scop", .{ pass, inst });1820 log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst });
1821 var scope = data.block_scopes.fetchRemove(inst).?.value;1821 var scope = data.block_scopes.fetchRemove(inst).?.value;
1822 scope.live_set.deinit(gpa);1822 scope.live_set.deinit(gpa);
1823 };1823 };
...@@ -1875,13 +1875,13 @@ fn analyzeInstSwitchBr(...@@ -1875,13 +1875,13 @@ fn analyzeInstSwitchBr(
1875 }1875 }
18761876
1877 for (mirrored_deaths, 0..) |mirrored, i| {1877 for (mirrored_deaths, 0..) |mirrored, i| {
1878 log.debug("[{}] %{}: case {} mirrored deaths are {}", .{ pass, inst, i, fmtInstList(mirrored.items) });1878 log.debug("[{}] %{f}: case {} mirrored deaths are {f}", .{ pass, inst, i, fmtInstList(mirrored.items) });
1879 }1879 }
18801880
1881 data.live_set.deinit(gpa);1881 data.live_set.deinit(gpa);
1882 data.live_set = all_alive.move();1882 data.live_set = all_alive.move();
18831883
1884 log.debug("[{}] %{}: new live set is {}", .{ pass, inst, fmtInstSet(&data.live_set) });1884 log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) });
1885 }1885 }
18861886
1887 const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len));1887 const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len));
...@@ -1980,7 +1980,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1980,7 +1980,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
19801980
1981 .main_analysis => {1981 .main_analysis => {
1982 if ((try big.data.live_set.fetchPut(gpa, operand, {})) == null) {1982 if ((try big.data.live_set.fetchPut(gpa, operand, {})) == null) {
1983 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, big.inst, operand });1983 log.debug("[{}] %{f}: added %{f} to live set (operand dies here)", .{ pass, big.inst, operand });
1984 big.extra_tombs[extra_byte] |= @as(u32, 1) << extra_bit;1984 big.extra_tombs[extra_byte] |= @as(u32, 1) << extra_bit;
1985 }1985 }
1986 },1986 },
...@@ -2036,15 +2036,15 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns...@@ -2036,15 +2036,15 @@ fn fmtInstSet(set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void)) FmtIns
2036const FmtInstSet = struct {2036const FmtInstSet = struct {
2037 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),2037 set: *const std.AutoHashMapUnmanaged(Air.Inst.Index, void),
20382038
2039 pub fn format(val: FmtInstSet, comptime _: []const u8, _: std.fmt.FormatOptions, w: anytype) !void {2039 pub fn format(val: FmtInstSet, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
2040 if (val.set.count() == 0) {2040 if (val.set.count() == 0) {
2041 try w.writeAll("[no instructions]");2041 try bw.writeAll("[no instructions]");
2042 return;2042 return;
2043 }2043 }
2044 var it = val.set.keyIterator();2044 var it = val.set.keyIterator();
2045 try w.print("%{}", .{it.next().?.*});2045 try bw.print("%{f}", .{it.next().?.*});
2046 while (it.next()) |key| {2046 while (it.next()) |key| {
2047 try w.print(" %{}", .{key.*});2047 try bw.print(" %{f}", .{key.*});
2048 }2048 }
2049 }2049 }
2050};2050};
...@@ -2056,14 +2056,14 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {...@@ -2056,14 +2056,14 @@ fn fmtInstList(list: []const Air.Inst.Index) FmtInstList {
2056const FmtInstList = struct {2056const FmtInstList = struct {
2057 list: []const Air.Inst.Index,2057 list: []const Air.Inst.Index,
20582058
2059 pub fn format(val: FmtInstList, comptime _: []const u8, _: std.fmt.FormatOptions, w: anytype) !void {2059 pub fn format(val: FmtInstList, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
2060 if (val.list.len == 0) {2060 if (val.list.len == 0) {
2061 try w.writeAll("[no instructions]");2061 try bw.writeAll("[no instructions]");
2062 return;2062 return;
2063 }2063 }
2064 try w.print("%{}", .{val.list[0]});2064 try bw.print("%{f}", .{val.list[0]});
2065 for (val.list[1..]) |inst| {2065 for (val.list[1..]) |inst| {
2066 try w.print(" %{}", .{inst});2066 try bw.print(" %{f}", .{inst});
2067 }2067 }
2068 }2068 }
2069};2069};
src/Air/Liveness/Verify.zig+8-8
...@@ -73,7 +73,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -73,7 +73,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
73 .trap, .unreach => {73 .trap, .unreach => {
74 try self.verifyInstOperands(inst, .{ .none, .none, .none });74 try self.verifyInstOperands(inst, .{ .none, .none, .none });
75 // This instruction terminates the function, so everything should be dead75 // This instruction terminates the function, so everything should be dead
76 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});76 if (self.live.count() > 0) return invalid("%{f}: instructions still alive", .{inst});
77 },77 },
7878
79 // unary79 // unary
...@@ -166,7 +166,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -166,7 +166,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
166 const un_op = data[@intFromEnum(inst)].un_op;166 const un_op = data[@intFromEnum(inst)].un_op;
167 try self.verifyInstOperands(inst, .{ un_op, .none, .none });167 try self.verifyInstOperands(inst, .{ un_op, .none, .none });
168 // This instruction terminates the function, so everything should be dead168 // This instruction terminates the function, so everything should be dead
169 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});169 if (self.live.count() > 0) return invalid("%{f}: instructions still alive", .{inst});
170 },170 },
171 .dbg_var_ptr,171 .dbg_var_ptr,
172 .dbg_var_val,172 .dbg_var_val,
...@@ -450,7 +450,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -450,7 +450,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
450 .repeat => {450 .repeat => {
451 const repeat = data[@intFromEnum(inst)].repeat;451 const repeat = data[@intFromEnum(inst)].repeat;
452 const expected_live = self.loops.get(repeat.loop_inst) orelse452 const expected_live = self.loops.get(repeat.loop_inst) orelse
453 return invalid("%{}: loop %{} not in scope", .{ @intFromEnum(inst), @intFromEnum(repeat.loop_inst) });453 return invalid("%{d}: loop %{d} not in scope", .{ @intFromEnum(inst), @intFromEnum(repeat.loop_inst) });
454454
455 try self.verifyMatchingLiveness(repeat.loop_inst, expected_live);455 try self.verifyMatchingLiveness(repeat.loop_inst, expected_live);
456 },456 },
...@@ -460,7 +460,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -460,7 +460,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
460 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));460 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));
461461
462 const expected_live = self.loops.get(br.block_inst) orelse462 const expected_live = self.loops.get(br.block_inst) orelse
463 return invalid("%{}: loop %{} not in scope", .{ @intFromEnum(inst), @intFromEnum(br.block_inst) });463 return invalid("%{d}: loop %{d} not in scope", .{ @intFromEnum(inst), @intFromEnum(br.block_inst) });
464464
465 try self.verifyMatchingLiveness(br.block_inst, expected_live);465 try self.verifyMatchingLiveness(br.block_inst, expected_live);
466 },466 },
...@@ -601,9 +601,9 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies...@@ -601,9 +601,9 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies
601 return;601 return;
602 };602 };
603 if (dies) {603 if (dies) {
604 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });604 if (!self.live.remove(operand)) return invalid("%{f}: dead operand %{f} reused and killed again", .{ inst, operand });
605 } else {605 } else {
606 if (!self.live.contains(operand)) return invalid("%{}: dead operand %{} reused", .{ inst, operand });606 if (!self.live.contains(operand)) return invalid("%{f}: dead operand %{f} reused", .{ inst, operand });
607 }607 }
608}608}
609609
...@@ -628,9 +628,9 @@ fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {...@@ -628,9 +628,9 @@ fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
628}628}
629629
630fn verifyMatchingLiveness(self: *Verify, block: Air.Inst.Index, live: LiveMap) Error!void {630fn verifyMatchingLiveness(self: *Verify, block: Air.Inst.Index, live: LiveMap) Error!void {
631 if (self.live.count() != live.count()) return invalid("%{}: different deaths across branches", .{block});631 if (self.live.count() != live.count()) return invalid("%{f}: different deaths across branches", .{block});
632 var live_it = self.live.keyIterator();632 var live_it = self.live.keyIterator();
633 while (live_it.next()) |live_inst| if (!live.contains(live_inst.*)) return invalid("%{}: different deaths across branches", .{block});633 while (live_it.next()) |live_inst| if (!live.contains(live_inst.*)) return invalid("%{f}: different deaths across branches", .{block});
634}634}
635635
636fn invalid(comptime fmt: []const u8, args: anytype) error{LivenessInvalid} {636fn invalid(comptime fmt: []const u8, args: anytype) error{LivenessInvalid} {
src/Air/print.zig+14-14
...@@ -101,7 +101,7 @@ const Writer = struct {...@@ -101,7 +101,7 @@ const Writer = struct {
101 fn writeInst(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {101 fn writeInst(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {
102 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];102 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
103 try s.splatByteAll(' ', w.indent);103 try s.splatByteAll(' ', w.indent);
104 try s.print("{}{c}= {s}(", .{104 try s.print("{f}{c}= {s}(", .{
105 inst,105 inst,
106 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),106 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),
107 @tagName(tag),107 @tagName(tag),
...@@ -416,7 +416,7 @@ const Writer = struct {...@@ -416,7 +416,7 @@ const Writer = struct {
416 try s.writeAll("}");416 try s.writeAll("}");
417417
418 for (liveness_block.deaths) |operand| {418 for (liveness_block.deaths) |operand| {
419 try s.print(" {}!", .{operand});419 try s.print(" {f}!", .{operand});
420 }420 }
421 }421 }
422422
...@@ -708,7 +708,7 @@ const Writer = struct {...@@ -708,7 +708,7 @@ const Writer = struct {
708 }708 }
709 }709 }
710 const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len];710 const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len];
711 try s.print(", \"{}\"", .{std.zig.fmtEscapes(asm_source)});711 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(asm_source)});
712 }712 }
713713
714 fn writeDbgStmt(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {714 fn writeDbgStmt(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {
...@@ -720,7 +720,7 @@ const Writer = struct {...@@ -720,7 +720,7 @@ const Writer = struct {
720 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;720 const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
721 try w.writeOperand(s, inst, 0, pl_op.operand);721 try w.writeOperand(s, inst, 0, pl_op.operand);
722 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);722 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
723 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});723 try s.print(", \"{f}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});
724 }724 }
725725
726 fn writeCall(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {726 fn writeCall(w: *Writer, s: *std.io.BufferedWriter, inst: Air.Inst.Index) anyerror!void {
...@@ -767,7 +767,7 @@ const Writer = struct {...@@ -767,7 +767,7 @@ const Writer = struct {
767 try s.splatByteAll(' ', w.indent);767 try s.splatByteAll(' ', w.indent);
768 for (liveness_condbr.else_deaths, 0..) |operand, i| {768 for (liveness_condbr.else_deaths, 0..) |operand, i| {
769 if (i != 0) try s.writeAll(" ");769 if (i != 0) try s.writeAll(" ");
770 try s.print("{}!", .{operand});770 try s.print("{f}!", .{operand});
771 }771 }
772 try s.writeAll("\n");772 try s.writeAll("\n");
773 }773 }
...@@ -778,7 +778,7 @@ const Writer = struct {...@@ -778,7 +778,7 @@ const Writer = struct {
778 try s.writeAll("}");778 try s.writeAll("}");
779779
780 for (liveness_condbr.then_deaths) |operand| {780 for (liveness_condbr.then_deaths) |operand| {
781 try s.print(" {}!", .{operand});781 try s.print(" {f}!", .{operand});
782 }782 }
783 }783 }
784784
...@@ -804,7 +804,7 @@ const Writer = struct {...@@ -804,7 +804,7 @@ const Writer = struct {
804 try s.splatByteAll(' ', w.indent);804 try s.splatByteAll(' ', w.indent);
805 for (liveness_condbr.else_deaths, 0..) |operand, i| {805 for (liveness_condbr.else_deaths, 0..) |operand, i| {
806 if (i != 0) try s.writeAll(" ");806 if (i != 0) try s.writeAll(" ");
807 try s.print("{}!", .{operand});807 try s.print("{f}!", .{operand});
808 }808 }
809 try s.writeAll("\n");809 try s.writeAll("\n");
810 }810 }
...@@ -815,7 +815,7 @@ const Writer = struct {...@@ -815,7 +815,7 @@ const Writer = struct {
815 try s.writeAll("}");815 try s.writeAll("}");
816816
817 for (liveness_condbr.then_deaths) |operand| {817 for (liveness_condbr.then_deaths) |operand| {
818 try s.print(" {}!", .{operand});818 try s.print(" {f}!", .{operand});
819 }819 }
820 }820 }
821821
...@@ -846,7 +846,7 @@ const Writer = struct {...@@ -846,7 +846,7 @@ const Writer = struct {
846 try s.splatByteAll(' ', w.indent);846 try s.splatByteAll(' ', w.indent);
847 for (liveness_condbr.then_deaths, 0..) |operand, i| {847 for (liveness_condbr.then_deaths, 0..) |operand, i| {
848 if (i != 0) try s.writeAll(" ");848 if (i != 0) try s.writeAll(" ");
849 try s.print("{}!", .{operand});849 try s.print("{f}!", .{operand});
850 }850 }
851 try s.writeAll("\n");851 try s.writeAll("\n");
852 }852 }
...@@ -866,7 +866,7 @@ const Writer = struct {...@@ -866,7 +866,7 @@ const Writer = struct {
866 try s.splatByteAll(' ', w.indent);866 try s.splatByteAll(' ', w.indent);
867 for (liveness_condbr.else_deaths, 0..) |operand, i| {867 for (liveness_condbr.else_deaths, 0..) |operand, i| {
868 if (i != 0) try s.writeAll(" ");868 if (i != 0) try s.writeAll(" ");
869 try s.print("{}!", .{operand});869 try s.print("{f}!", .{operand});
870 }870 }
871 try s.writeAll("\n");871 try s.writeAll("\n");
872 }872 }
...@@ -923,7 +923,7 @@ const Writer = struct {...@@ -923,7 +923,7 @@ const Writer = struct {
923 try s.splatByteAll(' ', w.indent);923 try s.splatByteAll(' ', w.indent);
924 for (deaths, 0..) |operand, i| {924 for (deaths, 0..) |operand, i| {
925 if (i != 0) try s.writeAll(" ");925 if (i != 0) try s.writeAll(" ");
926 try s.print("{}!", .{operand});926 try s.print("{f}!", .{operand});
927 }927 }
928 try s.writeAll("\n");928 try s.writeAll("\n");
929 }929 }
...@@ -949,7 +949,7 @@ const Writer = struct {...@@ -949,7 +949,7 @@ const Writer = struct {
949 try s.splatByteAll(' ', w.indent);949 try s.splatByteAll(' ', w.indent);
950 for (deaths, 0..) |operand, i| {950 for (deaths, 0..) |operand, i| {
951 if (i != 0) try s.writeAll(" ");951 if (i != 0) try s.writeAll(" ");
952 try s.print("{}!", .{operand});952 try s.print("{f}!", .{operand});
953 }953 }
954 try s.writeAll("\n");954 try s.writeAll("\n");
955 }955 }
...@@ -1017,7 +1017,7 @@ const Writer = struct {...@@ -1017,7 +1017,7 @@ const Writer = struct {
1017 } else if (operand.toInterned()) |ip_index| {1017 } else if (operand.toInterned()) |ip_index| {
1018 const pt = w.pt;1018 const pt = w.pt;
1019 const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf());1019 const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf());
1020 try s.print("<{}, {}>", .{1020 try s.print("<{f}, {f}>", .{
1021 ty.fmt(pt),1021 ty.fmt(pt),
1022 Value.fromInterned(ip_index).fmtValue(pt),1022 Value.fromInterned(ip_index).fmtValue(pt),
1023 });1023 });
...@@ -1033,7 +1033,7 @@ const Writer = struct {...@@ -1033,7 +1033,7 @@ const Writer = struct {
1033 dies: bool,1033 dies: bool,
1034 ) anyerror!void {1034 ) anyerror!void {
1035 _ = w;1035 _ = w;
1036 try s.print("{}", .{inst});1036 try s.print("{f}", .{inst});
1037 if (dies) try s.writeByte('!');1037 if (dies) try s.writeByte('!');
1038 }1038 }
10391039
src/Builtin.zig+17-17
...@@ -57,18 +57,18 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -57,18 +57,18 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
57 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.57 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
58 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;58 \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
59 \\pub const zig_version_string = "{s}";59 \\pub const zig_version_string = "{s}";
60 \\pub const zig_backend = std.builtin.CompilerBackend.{p_};60 \\pub const zig_backend = std.builtin.CompilerBackend.{fp_};
61 \\61 \\
62 \\pub const output_mode: std.builtin.OutputMode = .{p_};62 \\pub const output_mode: std.builtin.OutputMode = .{fp_};
63 \\pub const link_mode: std.builtin.LinkMode = .{p_};63 \\pub const link_mode: std.builtin.LinkMode = .{fp_};
64 \\pub const unwind_tables: std.builtin.UnwindTables = .{p_};64 \\pub const unwind_tables: std.builtin.UnwindTables = .{fp_};
65 \\pub const is_test = {};65 \\pub const is_test = {};
66 \\pub const single_threaded = {};66 \\pub const single_threaded = {};
67 \\pub const abi: std.Target.Abi = .{p_};67 \\pub const abi: std.Target.Abi = .{fp_};
68 \\pub const cpu: std.Target.Cpu = .{{68 \\pub const cpu: std.Target.Cpu = .{{
69 \\ .arch = .{p_},69 \\ .arch = .{fp_},
70 \\ .model = &std.Target.{p_}.cpu.{p_},70 \\ .model = &std.Target.{fp_}.cpu.{fp_},
71 \\ .features = std.Target.{p_}.featureSet(&.{{71 \\ .features = std.Target.{fp_}.featureSet(&.{{
72 \\72 \\
73 , .{73 , .{
74 build_options.version,74 build_options.version,
...@@ -89,14 +89,14 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -89,14 +89,14 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
89 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));89 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
90 const is_enabled = target.cpu.features.isEnabled(index);90 const is_enabled = target.cpu.features.isEnabled(index);
91 if (is_enabled) {91 if (is_enabled) {
92 try buffer.print(" .{p_},\n", .{std.zig.fmtId(feature.name)});92 try buffer.print(" .{fp_},\n", .{std.zig.fmtId(feature.name)});
93 }93 }
94 }94 }
95 try buffer.print(95 try buffer.print(
96 \\ }}),96 \\ }}),
97 \\}};97 \\}};
98 \\pub const os: std.Target.Os = .{{98 \\pub const os: std.Target.Os = .{{
99 \\ .tag = .{p_},99 \\ .tag = .{fp_},
100 \\ .version_range = .{{100 \\ .version_range = .{{
101 ,101 ,
102 .{std.zig.fmtId(@tagName(target.os.tag))},102 .{std.zig.fmtId(@tagName(target.os.tag))},
...@@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
200 }),200 }),
201 .windows => |windows| try buffer.print(201 .windows => |windows| try buffer.print(
202 \\ .windows = .{{202 \\ .windows = .{{
203 \\ .min = {c},203 \\ .min = {fc},
204 \\ .max = {c},204 \\ .max = {fc},
205 \\ }}}},205 \\ }}}},
206 \\206 \\
207 , .{ windows.min, windows.max }),207 , .{ windows.min, windows.max }),
...@@ -238,8 +238,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -238,8 +238,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
238 const link_libc = opts.link_libc;238 const link_libc = opts.link_libc;
239239
240 try buffer.print(240 try buffer.print(
241 \\pub const object_format: std.Target.ObjectFormat = .{p_};241 \\pub const object_format: std.Target.ObjectFormat = .{fp_};
242 \\pub const mode: std.builtin.OptimizeMode = .{p_};242 \\pub const mode: std.builtin.OptimizeMode = .{fp_};
243 \\pub const link_libc = {};243 \\pub const link_libc = {};
244 \\pub const link_libcpp = {};244 \\pub const link_libcpp = {};
245 \\pub const have_error_return_tracing = {};245 \\pub const have_error_return_tracing = {};
...@@ -249,7 +249,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -249,7 +249,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
249 \\pub const position_independent_code = {};249 \\pub const position_independent_code = {};
250 \\pub const position_independent_executable = {};250 \\pub const position_independent_executable = {};
251 \\pub const strip_debug_info = {};251 \\pub const strip_debug_info = {};
252 \\pub const code_model: std.builtin.CodeModel = .{p_};252 \\pub const code_model: std.builtin.CodeModel = .{fp_};
253 \\pub const omit_frame_pointer = {};253 \\pub const omit_frame_pointer = {};
254 \\254 \\
255 , .{255 , .{
...@@ -270,7 +270,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -270,7 +270,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
270270
271 if (target.os.tag == .wasi) {271 if (target.os.tag == .wasi) {
272 try buffer.print(272 try buffer.print(
273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_};273 \\pub const wasi_exec_model: std.builtin.WasiExecModel = .{fp_};
274 \\274 \\
275 , .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});275 , .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});
276 }276 }
...@@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {...@@ -317,7 +317,7 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
317 if (root_dir.statFile(sub_path)) |stat| {317 if (root_dir.statFile(sub_path)) |stat| {
318 if (stat.size != file.source.?.len) {318 if (stat.size != file.source.?.len) {
319 std.log.warn(319 std.log.warn(
320 "the cached file '{}' had the wrong size. Expected {d}, found {d}. " ++320 "the cached file '{f}{s}' had the wrong size. Expected {d}, found {d}. " ++
321 "Overwriting with correct file contents now",321 "Overwriting with correct file contents now",
322 .{ file.path.fmt(comp), file.source.?.len, stat.size },322 .{ file.path.fmt(comp), file.source.?.len, stat.size },
323 );323 );
src/Compilation.zig+20-23
...@@ -1068,11 +1068,12 @@ pub const CObject = struct {...@@ -1068,11 +1068,12 @@ pub const CObject = struct {
1068 }1068 }
1069 };1069 };
10701070
1071 var buffer: [1024]u8 = undefined;
1071 const file = try std.fs.cwd().openFile(path, .{});1072 const file = try std.fs.cwd().openFile(path, .{});
1072 defer file.close();1073 defer file.close();
1073 var br = std.io.bufferedReader(file.reader());1074 var br: std.io.BufferedReader = undefined;
1074 const reader = br.reader();1075 br.init(file.reader(), &buffer);
1075 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .reader = reader.any() });1076 var bc = std.zig.llvm.BitcodeReader.init(gpa, .{ .br = &br });
1076 defer bc.deinit();1077 defer bc.deinit();
10771078
1078 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;1079 var file_names: std.AutoArrayHashMapUnmanaged(u32, []const u8) = .empty;
...@@ -2709,7 +2710,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2709,7 +2710,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2709 const prefix = man.cache.prefixes()[pp.prefix];2710 const prefix = man.cache.prefixes()[pp.prefix];
2710 return comp.setMiscFailure(2711 return comp.setMiscFailure(
2711 .check_whole_cache,2712 .check_whole_cache,
2712 "failed to check cache: '{}{s}' {s} {s}",2713 "failed to check cache: '{f}{s}' {s} {s}",
2713 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },2714 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },
2714 );2715 );
2715 },2716 },
...@@ -2926,7 +2927,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2926,7 +2927,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2926 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {2927 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
2927 return comp.setMiscFailure(2928 return comp.setMiscFailure(
2928 .rename_results,2929 .rename_results,
2929 "failed to rename compilation results ('{}{s}') into local cache ('{}{s}'): {s}",2930 "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {s}",
2930 .{2931 .{
2931 comp.dirs.local_cache, tmp_dir_sub_path,2932 comp.dirs.local_cache, tmp_dir_sub_path,
2932 comp.dirs.local_cache, o_sub_path,2933 comp.dirs.local_cache, o_sub_path,
...@@ -4847,7 +4848,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4847,7 +4848,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4847 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {4848 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
4848 return comp.lockAndSetMiscFailure(4849 return comp.lockAndSetMiscFailure(
4849 .docs_copy,4850 .docs_copy,
4850 "unable to create output directory '{}': {s}",4851 "unable to create output directory '{f}': {s}",
4851 .{ docs_path, @errorName(err) },4852 .{ docs_path, @errorName(err) },
4852 );4853 );
4853 };4854 };
...@@ -4867,7 +4868,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4867,7 +4868,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4867 var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {4868 var tar_file = out_dir.createFile("sources.tar", .{}) catch |err| {
4868 return comp.lockAndSetMiscFailure(4869 return comp.lockAndSetMiscFailure(
4869 .docs_copy,4870 .docs_copy,
4870 "unable to create '{}/sources.tar': {s}",4871 "unable to create '{f}/sources.tar': {s}",
4871 .{ docs_path, @errorName(err) },4872 .{ docs_path, @errorName(err) },
4872 );4873 );
4873 };4874 };
...@@ -4896,7 +4897,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4896,7 +4897,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4896 const root_dir, const sub_path = root.openInfo(comp.dirs);4897 const root_dir, const sub_path = root.openInfo(comp.dirs);
4897 break :d root_dir.openDir(sub_path, .{ .iterate = true });4898 break :d root_dir.openDir(sub_path, .{ .iterate = true });
4898 } catch |err| {4899 } catch |err| {
4899 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{}': {s}", .{4900 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {s}", .{
4900 root.fmt(comp), @errorName(err),4901 root.fmt(comp), @errorName(err),
4901 });4902 });
4902 };4903 };
...@@ -5142,7 +5143,7 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {...@@ -5142,7 +5143,7 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {
5142 defer comp.mutex.unlock();5143 defer comp.mutex.unlock();
5143 comp.setMiscFailure(5144 comp.setMiscFailure(
5144 .write_builtin_zig,5145 .write_builtin_zig,
5145 "unable to write '{}': {s}",5146 "unable to write '{f}': {s}",
5146 .{ file.path.fmt(comp), @errorName(err) },5147 .{ file.path.fmt(comp), @errorName(err) },
5147 );5148 );
5148 };5149 };
...@@ -5863,7 +5864,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5863,7 +5864,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
58635864
5864 try child.spawn();5865 try child.spawn();
58655866
5866 const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));5867 const stderr = try child.stderr.?.readToEndAlloc(arena, .unlimited);
58675868
5868 const term = child.wait() catch |err| {5869 const term = child.wait() catch |err| {
5869 return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) });5870 return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) });
...@@ -6023,13 +6024,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6023,13 +6024,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
60236024
6024 // In .rc files, a " within a quoted string is escaped as ""6025 // In .rc files, a " within a quoted string is escaped as ""
6025 const fmtRcEscape = struct {6026 const fmtRcEscape = struct {
6026 fn formatRcEscape(bytes: []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {6027 fn formatRcEscape(bytes: []const u8, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
6027 _ = fmt;6028 _ = fmt;
6028 _ = options;
6029 for (bytes) |byte| switch (byte) {6029 for (bytes) |byte| switch (byte) {
6030 '"' => try writer.writeAll("\"\""),6030 '"' => try bw.writeAll("\"\""),
6031 '\\' => try writer.writeAll("\\\\"),6031 '\\' => try bw.writeAll("\\\\"),
6032 else => try writer.writeByte(byte),6032 else => try bw.writeByte(byte),
6033 };6033 };
6034 }6034 }
60356035
...@@ -6047,7 +6047,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6047,7 +6047,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6047 // 24 is RT_MANIFEST6047 // 24 is RT_MANIFEST
6048 const resource_type = 24;6048 const resource_type = 24;
60496049
6050 const input = try std.fmt.allocPrint(arena, "{} {} \"{s}\"", .{ resource_id, resource_type, fmtRcEscape(src_path) });6050 const input = try std.fmt.allocPrint(arena, "{} {} \"{f}\"", .{ resource_id, resource_type, fmtRcEscape(src_path) });
60516051
6052 try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input });6052 try o_dir.writeFile(.{ .sub_path = rc_basename, .data = input });
60536053
...@@ -6227,13 +6227,10 @@ fn spawnZigRc(...@@ -6227,13 +6227,10 @@ fn spawnZigRc(
6227 const stdout = poller.fifo(.stdout);6227 const stdout = poller.fifo(.stdout);
62286228
6229 poll: while (true) {6229 poll: while (true) {
6230 while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) {6230 while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) if (!try poller.poll()) break :poll;
6231 if (!(try poller.poll())) break :poll;6231 var header: std.zig.Server.Message.Header = undefined;
6232 }6232 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(std.zig.Server.Message.Header));
6233 const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable;6233 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll;
6234 while (stdout.readableLength() < header.bytes_len) {
6235 if (!(try poller.poll())) break :poll;
6236 }
6237 const body = stdout.readableSliceOfLen(header.bytes_len);6234 const body = stdout.readableSliceOfLen(header.bytes_len);
62386235
6239 switch (header.tag) {6236 switch (header.tag) {
src/InternPool.zig+6-11
...@@ -1888,17 +1888,12 @@ pub const NullTerminatedString = enum(u32) {...@@ -1888,17 +1888,12 @@ pub const NullTerminatedString = enum(u32) {
1888 string: NullTerminatedString,1888 string: NullTerminatedString,
1889 ip: *const InternPool,1889 ip: *const InternPool,
1890 };1890 };
1891 fn format(1891 fn format(data: FormatData, bw: *std.io.BufferedWriter, comptime specifier: []const u8) anyerror!void {
1892 data: FormatData,
1893 comptime specifier: []const u8,
1894 _: std.fmt.FormatOptions,
1895 writer: anytype,
1896 ) @TypeOf(writer).Error!void {
1897 const slice = data.string.toSlice(data.ip);1892 const slice = data.string.toSlice(data.ip);
1898 if (comptime std.mem.eql(u8, specifier, "")) {1893 if (comptime std.mem.eql(u8, specifier, "")) {
1899 try writer.writeAll(slice);1894 try bw.writeAll(slice);
1900 } else if (comptime std.mem.eql(u8, specifier, "i")) {1895 } else if (comptime std.mem.eql(u8, specifier, "i")) {
1901 try writer.print("{p}", .{std.zig.fmtId(slice)});1896 try bw.print("{fp}", .{std.zig.fmtId(slice)});
1902 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");1897 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");
1903 }1898 }
19041899
...@@ -9758,7 +9753,7 @@ fn finishFuncInstance(...@@ -9758,7 +9753,7 @@ fn finishFuncInstance(
9758 const fn_namespace = fn_owner_nav.analysis.?.namespace;9753 const fn_namespace = fn_owner_nav.analysis.?.namespace;
97599754
9760 // TODO: improve this name9755 // TODO: improve this name
9761 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{9756 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{f}__anon_{d}", .{
9762 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),9757 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9763 }, .no_embedded_nulls);9758 }, .no_embedded_nulls);
9764 const nav_index = try ip.createNav(gpa, tid, .{9759 const nav_index = try ip.createNav(gpa, tid, .{
...@@ -11415,12 +11410,12 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11415,12 +11410,12 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11415 var it = instances.iterator();11410 var it = instances.iterator();
11416 while (it.next()) |entry| {11411 while (it.next()) |entry| {
11417 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);11412 const generic_fn_owner_nav = ip.getNav(ip.funcDeclInfo(entry.key_ptr.*).owner_nav);
11418 try bw.print("{} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });11413 try bw.print("{f} ({}): \n", .{ generic_fn_owner_nav.name.fmt(ip), entry.value_ptr.items.len });
11419 for (entry.value_ptr.items) |index| {11414 for (entry.value_ptr.items) |index| {
11420 const unwrapped_index = index.unwrap(ip);11415 const unwrapped_index = index.unwrap(ip);
11421 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));11416 const func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), unwrapped_index.getData(ip));
11422 const owner_nav = ip.getNav(func.owner_nav);11417 const owner_nav = ip.getNav(func.owner_nav);
11423 try bw.print(" {}: (", .{owner_nav.name.fmt(ip)});11418 try bw.print(" {f}: (", .{owner_nav.name.fmt(ip)});
11424 for (func.comptime_args.get(ip)) |arg| {11419 for (func.comptime_args.get(ip)) |arg| {
11425 if (arg != .none) {11420 if (arg != .none) {
11426 const key = ip.indexToKey(arg);11421 const key = ip.indexToKey(arg);
src/Package.zig+1-1
...@@ -134,7 +134,7 @@ pub const Hash = struct {...@@ -134,7 +134,7 @@ pub const Hash = struct {
134 }134 }
135 var bin_digest: [Algo.digest_length]u8 = undefined;135 var bin_digest: [Algo.digest_length]u8 = undefined;
136 Algo.hash(sub_path, &bin_digest, .{});136 Algo.hash(sub_path, &bin_digest, .{});
137 _ = std.fmt.bufPrint(result.bytes[i..], "{}", .{std.fmt.fmtSliceHexLower(&bin_digest)}) catch unreachable;137 _ = std.fmt.bufPrint(result.bytes[i..], "{x}", .{&bin_digest}) catch unreachable;
138 return result;138 return result;
139 }139 }
140};140};
src/Package/Fetch.zig+15-15
...@@ -185,7 +185,7 @@ pub const JobQueue = struct {...@@ -185,7 +185,7 @@ pub const JobQueue = struct {
185 const hash_slice = hash.toSlice();185 const hash_slice = hash.toSlice();
186186
187 try buf.print(187 try buf.print(
188 \\ pub const {} = struct {{188 \\ pub const {f} = struct {{
189 \\189 \\
190 , .{std.zig.fmtId(hash_slice)});190 , .{std.zig.fmtId(hash_slice)});
191191
...@@ -211,13 +211,13 @@ pub const JobQueue = struct {...@@ -211,13 +211,13 @@ pub const JobQueue = struct {
211 }211 }
212212
213 try buf.print(213 try buf.print(
214 \\ pub const build_root = "{q}";214 \\ pub const build_root = "{fq}";
215 \\215 \\
216 , .{fetch.package_root});216 , .{fetch.package_root});
217217
218 if (fetch.has_build_zig) {218 if (fetch.has_build_zig) {
219 try buf.print(219 try buf.print(
220 \\ pub const build_zig = @import("{}");220 \\ pub const build_zig = @import("{f}");
221 \\221 \\
222 , .{std.zig.fmtEscapes(hash_slice)});222 , .{std.zig.fmtEscapes(hash_slice)});
223 }223 }
...@@ -230,7 +230,7 @@ pub const JobQueue = struct {...@@ -230,7 +230,7 @@ pub const JobQueue = struct {
230 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {230 for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| {
231 const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue;231 const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue;
232 try buf.print(232 try buf.print(
233 " .{{ \"{}\", \"{}\" }},\n",233 " .{{ \"{f}\", \"{f}\" }},\n",
234 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },234 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },
235 );235 );
236 }236 }
...@@ -262,7 +262,7 @@ pub const JobQueue = struct {...@@ -262,7 +262,7 @@ pub const JobQueue = struct {
262 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {262 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
263 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;263 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;
264 try buf.print(264 try buf.print(
265 " .{{ \"{}\", \"{}\" }},\n",265 " .{{ \"{f}\", \"{f}\" }},\n",
266 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },266 .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) },
267 );267 );
268 }268 }
...@@ -353,7 +353,7 @@ pub fn run(f: *Fetch) RunError!void {...@@ -353,7 +353,7 @@ pub fn run(f: *Fetch) RunError!void {
353 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {353 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {
354 return f.fail(354 return f.fail(
355 f.location_tok,355 f.location_tok,
356 try eb.printString("dependency path outside project: '{}'", .{pkg_root}),356 try eb.printString("dependency path outside project: '{f}'", .{pkg_root}),
357 );357 );
358 }358 }
359 }359 }
...@@ -604,7 +604,7 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash {...@@ -604,7 +604,7 @@ pub fn computedPackageHash(f: *const Fetch) Package.Hash {
604 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);604 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);
605 if (f.manifest) |man| {605 if (f.manifest) |man| {
606 var version_buffer: [32]u8 = undefined;606 var version_buffer: [32]u8 = undefined;
607 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{}", .{man.version}) catch &version_buffer;607 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{f}", .{man.version}) catch &version_buffer;
608 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);608 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);
609 }609 }
610 // In the future build.zig.zon fields will be added to allow overriding these values610 // In the future build.zig.zon fields will be added to allow overriding these values
...@@ -622,7 +622,7 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void {...@@ -622,7 +622,7 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void {
622 error.FileNotFound => {},622 error.FileNotFound => {},
623 else => |e| {623 else => |e| {
624 try eb.addRootErrorMessage(.{624 try eb.addRootErrorMessage(.{
625 .msg = try eb.printString("unable to access '{}{s}': {s}", .{625 .msg = try eb.printString("unable to access '{f}{s}': {s}", .{
626 f.package_root, Package.build_zig_basename, @errorName(e),626 f.package_root, Package.build_zig_basename, @errorName(e),
627 }),627 }),
628 });628 });
...@@ -636,9 +636,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -636,9 +636,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
636 const eb = &f.error_bundle;636 const eb = &f.error_bundle;
637 const arena = f.arena.allocator();637 const arena = f.arena.allocator();
638 const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions(638 const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions(
639 arena,
640 try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }),639 try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }),
641 Manifest.max_bytes,640 arena,
641 .limited(Manifest.max_bytes),
642 null,642 null,
643 .@"1",643 .@"1",
644 0,644 0,
...@@ -647,7 +647,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -647,7 +647,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
647 else => |e| {647 else => |e| {
648 const file_path = try pkg_root.join(arena, Manifest.basename);648 const file_path = try pkg_root.join(arena, Manifest.basename);
649 try eb.addRootErrorMessage(.{649 try eb.addRootErrorMessage(.{
650 .msg = try eb.printString("unable to load package manifest '{}': {s}", .{650 .msg = try eb.printString("unable to load package manifest '{f}': {s}", .{
651 file_path, @errorName(e),651 file_path, @errorName(e),
652 }),652 }),
653 });653 });
...@@ -659,7 +659,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -659,7 +659,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
659 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon);659 ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon);
660660
661 if (ast.errors.len > 0) {661 if (ast.errors.len > 0) {
662 const file_path = try std.fmt.allocPrint(arena, "{}" ++ fs.path.sep_str ++ Manifest.basename, .{pkg_root});662 const file_path = try std.fmt.allocPrint(arena, "{f}" ++ fs.path.sep_str ++ Manifest.basename, .{pkg_root});
663 try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb);663 try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb);
664 return error.FetchFailed;664 return error.FetchFailed;
665 }665 }
...@@ -672,7 +672,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -672,7 +672,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
672 const manifest = &f.manifest.?;672 const manifest = &f.manifest.?;
673673
674 if (manifest.errors.len > 0) {674 if (manifest.errors.len > 0) {
675 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ "{s}", .{ pkg_root, Manifest.basename });675 const src_path = try eb.printString("{f}" ++ fs.path.sep_str ++ "{s}", .{ pkg_root, Manifest.basename });
676 try manifest.copyErrorsIntoBundle(ast.*, src_path, eb);676 try manifest.copyErrorsIntoBundle(ast.*, src_path, eb);
677 return error.FetchFailed;677 return error.FetchFailed;
678 }678 }
...@@ -827,7 +827,7 @@ fn srcLoc(...@@ -827,7 +827,7 @@ fn srcLoc(
827 const ast = f.parent_manifest_ast orelse return .none;827 const ast = f.parent_manifest_ast orelse return .none;
828 const eb = &f.error_bundle;828 const eb = &f.error_bundle;
829 const start_loc = ast.tokenLocation(0, tok);829 const start_loc = ast.tokenLocation(0, tok);
830 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});830 const src_path = try eb.printString("{f}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});
831 const msg_off = 0;831 const msg_off = 0;
832 return eb.addSourceLocation(.{832 return eb.addSourceLocation(.{
833 .src_path = src_path,833 .src_path = src_path,
...@@ -1512,7 +1512,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute...@@ -1512,7 +1512,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
15121512
1513 while (walker.next() catch |err| {1513 while (walker.next() catch |err| {
1514 try eb.addRootErrorMessage(.{ .msg = try eb.printString(1514 try eb.addRootErrorMessage(.{ .msg = try eb.printString(
1515 "unable to walk temporary directory '{}': {s}",1515 "unable to walk temporary directory '{f}': {s}",
1516 .{ pkg_path, @errorName(err) },1516 .{ pkg_path, @errorName(err) },
1517 ) });1517 ) });
1518 return error.FetchFailed;1518 return error.FetchFailed;
src/Package/Fetch/git.zig+2-8
...@@ -119,15 +119,9 @@ pub const Oid = union(Format) {...@@ -119,15 +119,9 @@ pub const Oid = union(Format) {
119 } else error.InvalidOid;119 } else error.InvalidOid;
120 }120 }
121121
122 pub fn format(122 pub fn format(oid: Oid, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
123 oid: Oid,
124 comptime fmt: []const u8,
125 options: std.fmt.Options,
126 writer: *std.io.BufferedWriter,
127 ) anyerror!void {
128 _ = fmt;123 _ = fmt;
129 _ = options;124 try bw.print("{x}", .{oid.slice()});
130 try writer.print("{x}", .{oid.slice()});
131 }125 }
132126
133 pub fn slice(oid: *const Oid) []const u8 {127 pub fn slice(oid: *const Oid) []const u8 {
src/Package/Manifest.zig+2-2
...@@ -401,7 +401,7 @@ const Parse = struct {...@@ -401,7 +401,7 @@ const Parse = struct {
401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});
402402
403 if (name.len > max_name_len)403 if (name.len > max_name_len)
404 return fail(p, main_token, "name '{}' exceeds max length of {d}", .{404 return fail(p, main_token, "name '{f}' exceeds max length of {d}", .{
405 std.zig.fmtId(name), max_name_len,405 std.zig.fmtId(name), max_name_len,
406 });406 });
407407
...@@ -416,7 +416,7 @@ const Parse = struct {...@@ -416,7 +416,7 @@ const Parse = struct {
416 return fail(p, main_token, "name must be a valid bare zig identifier", .{});416 return fail(p, main_token, "name must be a valid bare zig identifier", .{});
417417
418 if (ident_name.len > max_name_len)418 if (ident_name.len > max_name_len)
419 return fail(p, main_token, "name '{}' exceeds max length of {d}", .{419 return fail(p, main_token, "name '{f}' exceeds max length of {d}", .{
420 std.zig.fmtId(ident_name), max_name_len,420 std.zig.fmtId(ident_name), max_name_len,
421 });421 });
422422
src/Sema.zig+419-416
...@@ -888,7 +888,7 @@ const ComptimeReason = union(enum) {...@@ -888,7 +888,7 @@ const ComptimeReason = union(enum) {
888 /// Evaluating at comptime because of a comptime-only type. This field is separate so that888 /// Evaluating at comptime because of a comptime-only type. This field is separate so that
889 /// the type in question can be included in the error message. AstGen could never emit this889 /// the type in question can be included in the error message. AstGen could never emit this
890 /// reason, because it knows nothing of types.890 /// reason, because it knows nothing of types.
891 /// The format string looks like "foo '{}' bar", where "{}" is the comptime-only type.891 /// The format string looks like "foo '{f}' bar", where "{f}" is the comptime-only type.
892 /// We will then explain why this type is comptime-only.892 /// We will then explain why this type is comptime-only.
893 comptime_only: struct {893 comptime_only: struct {
894 ty: Type,894 ty: Type,
...@@ -930,17 +930,17 @@ const ComptimeReason = union(enum) {...@@ -930,17 +930,17 @@ const ComptimeReason = union(enum) {
930 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" },930 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" },
931 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" },931 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" },
932 };932 };
933 try sema.errNote(src, err_msg, "{s} '{}' {s}", .{ pre, co.ty.fmt(sema.pt), post });933 try sema.errNote(src, err_msg, "{s} '{f}' {s}", .{ pre, co.ty.fmt(sema.pt), post });
934 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);934 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
935 },935 },
936 .comptime_only_param_ty => |co| {936 .comptime_only_param_ty => |co| {
937 try sema.errNote(src, err_msg, "argument to parameter with comptime-only type '{}' must be comptime-known", .{co.ty.fmt(sema.pt)});937 try sema.errNote(src, err_msg, "argument to parameter with comptime-only type '{f}' must be comptime-known", .{co.ty.fmt(sema.pt)});
938 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{});938 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{});
939 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);939 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
940 },940 },
941 .comptime_only_ret_ty => |co| {941 .comptime_only_ret_ty => |co| {
942 const function_with: []const u8 = if (co.is_generic_inst) "generic function instantiated with" else "function with";942 const function_with: []const u8 = if (co.is_generic_inst) "generic function instantiated with" else "function with";
943 try sema.errNote(src, err_msg, "call to {s} comptime-only return type '{}' is evaluated at comptime", .{ function_with, co.ty.fmt(sema.pt) });943 try sema.errNote(src, err_msg, "call to {s} comptime-only return type '{f}' is evaluated at comptime", .{ function_with, co.ty.fmt(sema.pt) });
944 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{});944 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{});
945 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);945 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty);
946 },946 },
...@@ -1909,7 +1909,7 @@ fn analyzeBodyInner(...@@ -1909,7 +1909,7 @@ fn analyzeBodyInner(
1909 const err_union = try sema.resolveInst(extra.data.operand);1909 const err_union = try sema.resolveInst(extra.data.operand);
1910 const err_union_ty = sema.typeOf(err_union);1910 const err_union_ty = sema.typeOf(err_union);
1911 if (err_union_ty.zigTypeTag(zcu) != .error_union) {1911 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
1912 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{1912 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{
1913 err_union_ty.fmt(pt),1913 err_union_ty.fmt(pt),
1914 });1914 });
1915 }1915 }
...@@ -2343,7 +2343,7 @@ pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) Compile...@@ -2343,7 +2343,7 @@ pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) Compile
23432343
2344fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError {2344fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError {
2345 const pt = sema.pt;2345 const pt = sema.pt;
2346 return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{2346 return sema.fail(block, src, "remainder division with '{f}' and '{f}': signed integers and floats must use @rem or @mod", .{
2347 lhs_ty.fmt(pt), rhs_ty.fmt(pt),2347 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
2348 });2348 });
2349}2349}
...@@ -2351,7 +2351,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T...@@ -2351,7 +2351,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
2351fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {2351fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {
2352 const pt = sema.pt;2352 const pt = sema.pt;
2353 const msg = msg: {2353 const msg = msg: {
2354 const msg = try sema.errMsg(src, "expected optional type, found '{}'", .{2354 const msg = try sema.errMsg(src, "expected optional type, found '{f}'", .{
2355 non_optional_ty.fmt(pt),2355 non_optional_ty.fmt(pt),
2356 });2356 });
2357 errdefer msg.destroy(sema.gpa);2357 errdefer msg.destroy(sema.gpa);
...@@ -2367,12 +2367,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non...@@ -2367,12 +2367,12 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non
2367fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {2367fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2368 const pt = sema.pt;2368 const pt = sema.pt;
2369 const msg = msg: {2369 const msg = msg: {
2370 const msg = try sema.errMsg(src, "type '{}' does not support array initialization syntax", .{2370 const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{
2371 ty.fmt(pt),2371 ty.fmt(pt),
2372 });2372 });
2373 errdefer msg.destroy(sema.gpa);2373 errdefer msg.destroy(sema.gpa);
2374 if (ty.isSlice(pt.zcu)) {2374 if (ty.isSlice(pt.zcu)) {
2375 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(pt.zcu).fmt(pt)});2375 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.elemType2(pt.zcu).fmt(pt)});
2376 }2376 }
2377 break :msg msg;2377 break :msg msg;
2378 };2378 };
...@@ -2381,7 +2381,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty...@@ -2381,7 +2381,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty
23812381
2382fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {2382fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2383 const pt = sema.pt;2383 const pt = sema.pt;
2384 return sema.fail(block, src, "type '{}' does not support struct initialization syntax", .{2384 return sema.fail(block, src, "type '{f}' does not support struct initialization syntax", .{
2385 ty.fmt(pt),2385 ty.fmt(pt),
2386 });2386 });
2387}2387}
...@@ -2394,7 +2394,7 @@ fn failWithErrorSetCodeMissing(...@@ -2394,7 +2394,7 @@ fn failWithErrorSetCodeMissing(
2394 src_err_set_ty: Type,2394 src_err_set_ty: Type,
2395) CompileError {2395) CompileError {
2396 const pt = sema.pt;2396 const pt = sema.pt;
2397 return sema.fail(block, src, "expected type '{}', found type '{}'", .{2397 return sema.fail(block, src, "expected type '{f}', found type '{f}'", .{
2398 dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt),2398 dest_err_set_ty.fmt(pt), src_err_set_ty.fmt(pt),
2399 });2399 });
2400}2400}
...@@ -2402,7 +2402,7 @@ fn failWithErrorSetCodeMissing(...@@ -2402,7 +2402,7 @@ fn failWithErrorSetCodeMissing(
2402pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError {2402pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError {
2403 const pt = sema.pt;2403 const pt = sema.pt;
2404 return sema.failWithOwnedErrorMsg(block, msg: {2404 return sema.failWithOwnedErrorMsg(block, msg: {
2405 const msg = try sema.errMsg(src, "overflow of integer type '{}' with value '{}'", .{2405 const msg = try sema.errMsg(src, "overflow of integer type '{f}' with value '{f}'", .{
2406 int_ty.fmt(pt), val.fmtValueSema(pt, sema),2406 int_ty.fmt(pt), val.fmtValueSema(pt, sema),
2407 });2407 });
2408 errdefer msg.destroy(sema.gpa);2408 errdefer msg.destroy(sema.gpa);
...@@ -2452,7 +2452,7 @@ fn failWithInvalidFieldAccess(...@@ -2452,7 +2452,7 @@ fn failWithInvalidFieldAccess(
2452 const child_ty = inner_ty.optionalChild(zcu);2452 const child_ty = inner_ty.optionalChild(zcu);
2453 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt;2453 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt;
2454 const msg = msg: {2454 const msg = msg: {
2455 const msg = try sema.errMsg(src, "optional type '{}' does not support field access", .{object_ty.fmt(pt)});2455 const msg = try sema.errMsg(src, "optional type '{f}' does not support field access", .{object_ty.fmt(pt)});
2456 errdefer msg.destroy(sema.gpa);2456 errdefer msg.destroy(sema.gpa);
2457 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{});2457 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{});
2458 break :msg msg;2458 break :msg msg;
...@@ -2462,14 +2462,14 @@ fn failWithInvalidFieldAccess(...@@ -2462,14 +2462,14 @@ fn failWithInvalidFieldAccess(
2462 const child_ty = inner_ty.errorUnionPayload(zcu);2462 const child_ty = inner_ty.errorUnionPayload(zcu);
2463 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err;2463 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err;
2464 const msg = msg: {2464 const msg = msg: {
2465 const msg = try sema.errMsg(src, "error union type '{}' does not support field access", .{object_ty.fmt(pt)});2465 const msg = try sema.errMsg(src, "error union type '{f}' does not support field access", .{object_ty.fmt(pt)});
2466 errdefer msg.destroy(sema.gpa);2466 errdefer msg.destroy(sema.gpa);
2467 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});2467 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
2468 break :msg msg;2468 break :msg msg;
2469 };2469 };
2470 return sema.failWithOwnedErrorMsg(block, msg);2470 return sema.failWithOwnedErrorMsg(block, msg);
2471 }2471 }
2472 return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(pt)});2472 return sema.fail(block, src, "type '{f}' does not support field access", .{object_ty.fmt(pt)});
2473}2473}
24742474
2475fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool {2475fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool {
...@@ -2498,7 +2498,7 @@ fn failWithComptimeErrorRetTrace(...@@ -2498,7 +2498,7 @@ fn failWithComptimeErrorRetTrace(
2498 const pt = sema.pt;2498 const pt = sema.pt;
2499 const zcu = pt.zcu;2499 const zcu = pt.zcu;
2500 const msg = msg: {2500 const msg = msg: {
2501 const msg = try sema.errMsg(src, "caught unexpected error '{}'", .{name.fmt(&zcu.intern_pool)});2501 const msg = try sema.errMsg(src, "caught unexpected error '{f}'", .{name.fmt(&zcu.intern_pool)});
2502 errdefer msg.destroy(sema.gpa);2502 errdefer msg.destroy(sema.gpa);
25032503
2504 for (sema.comptime_err_ret_trace.items) |src_loc| {2504 for (sema.comptime_err_ret_trace.items) |src_loc| {
...@@ -3009,7 +3009,7 @@ pub fn createTypeName(...@@ -3009,7 +3009,7 @@ pub fn createTypeName(
3009 inst: ?Zir.Inst.Index,3009 inst: ?Zir.Inst.Index,
3010 /// This is used purely to give the type a unique name in the `anon` case.3010 /// This is used purely to give the type a unique name in the `anon` case.
3011 type_index: InternPool.Index,3011 type_index: InternPool.Index,
3012) !struct {3012) CompileError!struct {
3013 name: InternPool.NullTerminatedString,3013 name: InternPool.NullTerminatedString,
3014 nav: InternPool.Nav.Index.Optional,3014 nav: InternPool.Nav.Index.Optional,
3015} {3015} {
...@@ -3028,11 +3028,11 @@ pub fn createTypeName(...@@ -3028,11 +3028,11 @@ pub fn createTypeName(
3028 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);3028 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
3029 const zir_tags = sema.code.instructions.items(.tag);3029 const zir_tags = sema.code.instructions.items(.tag);
30303030
3031 var buf: std.ArrayListUnmanaged(u8) = .empty;3031 var aw: std.io.AllocatingWriter = undefined;
3032 defer buf.deinit(gpa);3032 aw.init(gpa);
30333033 defer aw.deinit();
3034 const writer = buf.writer(gpa);3034 const bw = &aw.buffered_writer;
3035 try writer.print("{}(", .{block.type_name_ctx.fmt(ip)});3035 bw.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch |err| return @errorCast(err);
30363036
3037 var arg_i: usize = 0;3037 var arg_i: usize = 0;
3038 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {3038 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
...@@ -3045,18 +3045,18 @@ pub fn createTypeName(...@@ -3045,18 +3045,18 @@ pub fn createTypeName(
3045 // result in a compile error.3045 // result in a compile error.
3046 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat3046 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat
30473047
3048 if (arg_i != 0) try writer.writeByte(',');3048 if (arg_i != 0) bw.writeByte(',') catch |err| return @errorCast(err);
30493049
3050 // Limiting the depth here helps avoid type names getting too long, which3050 // Limiting the depth here helps avoid type names getting too long, which
3051 // in turn helps to avoid unreasonably long symbol names for namespaced3051 // in turn helps to avoid unreasonably long symbol names for namespaced
3052 // symbols. Such names should ideally be human-readable, and additionally,3052 // symbols. Such names should ideally be human-readable, and additionally,
3053 // some tooling may not support very long symbol names.3053 // some tooling may not support very long symbol names.
3054 try writer.print("{}", .{Value.fmtValueSemaFull(.{3054 bw.print("{f}", .{Value.fmtValueSemaFull(.{
3055 .val = arg_val,3055 .val = arg_val,
3056 .pt = pt,3056 .pt = pt,
3057 .opt_sema = sema,3057 .opt_sema = sema,
3058 .depth = 1,3058 .depth = 1,
3059 })});3059 })}) catch |err| return @errorCast(err);
30603060
3061 arg_i += 1;3061 arg_i += 1;
3062 continue;3062 continue;
...@@ -3064,9 +3064,9 @@ pub fn createTypeName(...@@ -3064,9 +3064,9 @@ pub fn createTypeName(
3064 else => continue,3064 else => continue,
3065 };3065 };
30663066
3067 try writer.writeByte(')');3067 try bw.writeByte(')');
3068 return .{3068 return .{
3069 .name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls),3069 .name = try ip.getOrPutString(gpa, pt.tid, aw.getWritten(), .no_embedded_nulls),
3070 .nav = .none,3070 .nav = .none,
3071 };3071 };
3072 },3072 },
...@@ -3078,7 +3078,7 @@ pub fn createTypeName(...@@ -3078,7 +3078,7 @@ pub fn createTypeName(
3078 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {3078 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
3079 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {3079 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
3080 return .{3080 return .{
3081 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{3081 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{
3082 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),3082 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3083 }, .no_embedded_nulls),3083 }, .no_embedded_nulls),
3084 .nav = .none,3084 .nav = .none,
...@@ -3101,7 +3101,7 @@ pub fn createTypeName(...@@ -3101,7 +3101,7 @@ pub fn createTypeName(
3101 // that builtin from the language, we can consider this.3101 // that builtin from the language, we can consider this.
31023102
3103 return .{3103 return .{
3104 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{3104 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{
3105 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),3105 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3106 }, .no_embedded_nulls),3106 }, .no_embedded_nulls),
3107 .nav = .none,3107 .nav = .none,
...@@ -3585,7 +3585,7 @@ fn ensureResultUsed(...@@ -3585,7 +3585,7 @@ fn ensureResultUsed(
3585 },3585 },
3586 else => {3586 else => {
3587 const msg = msg: {3587 const msg = msg: {
3588 const msg = try sema.errMsg(src, "value of type '{}' ignored", .{ty.fmt(pt)});3588 const msg = try sema.errMsg(src, "value of type '{f}' ignored", .{ty.fmt(pt)});
3589 errdefer msg.destroy(sema.gpa);3589 errdefer msg.destroy(sema.gpa);
3590 try sema.errNote(src, msg, "all non-void values must be used", .{});3590 try sema.errNote(src, msg, "all non-void values must be used", .{});
3591 try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{});3591 try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{});
...@@ -3855,7 +3855,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3855,7 +3855,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3855 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.3855 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
3856 // TODO: source location of runtime control flow3856 // TODO: source location of runtime control flow
3857 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });3857 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
3858 return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)});3858 return sema.fail(block, init_src, "value with comptime-only type '{f}' depends on runtime control flow", .{elem_ty.fmt(pt)});
3859 }3859 }
38603860
3861 // This is a runtime value.3861 // This is a runtime value.
...@@ -4352,7 +4352,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4352,7 +4352,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4352 // The alloc wasn't comptime-known per the above logic, so the4352 // The alloc wasn't comptime-known per the above logic, so the
4353 // type cannot be comptime-only.4353 // type cannot be comptime-only.
4354 // TODO: source location of runtime control flow4354 // TODO: source location of runtime control flow
4355 return sema.fail(block, src, "value with comptime-only type '{}' depends on runtime control flow", .{final_elem_ty.fmt(pt)});4355 return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)});
4356 }4356 }
4357 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {4357 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {
4358 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });4358 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
...@@ -4449,7 +4449,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4449,7 +4449,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4449 if (!object_ty.isIndexable(zcu)) {4449 if (!object_ty.isIndexable(zcu)) {
4450 // Instead of using checkIndexable we customize this error.4450 // Instead of using checkIndexable we customize this error.
4451 const msg = msg: {4451 const msg = msg: {
4452 const msg = try sema.errMsg(arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(pt)});4452 const msg = try sema.errMsg(arg_src, "type '{f}' is not indexable and not a range", .{object_ty.fmt(pt)});
4453 errdefer msg.destroy(sema.gpa);4453 errdefer msg.destroy(sema.gpa);
4454 try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});4454 try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});
44554455
...@@ -4484,10 +4484,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4484,10 +4484,10 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4484 .for_node_offset = inst_data.src_node,4484 .for_node_offset = inst_data.src_node,
4485 .input_index = len_idx,4485 .input_index = len_idx,
4486 } });4486 } });
4487 try sema.errNote(a_src, msg, "length {} here", .{4487 try sema.errNote(a_src, msg, "length {f} here", .{
4488 v.fmtValueSema(pt, sema),4488 v.fmtValueSema(pt, sema),
4489 });4489 });
4490 try sema.errNote(arg_src, msg, "length {} here", .{4490 try sema.errNote(arg_src, msg, "length {f} here", .{
4491 arg_val.fmtValueSema(pt, sema),4491 arg_val.fmtValueSema(pt, sema),
4492 });4492 });
4493 break :msg msg;4493 break :msg msg;
...@@ -4519,7 +4519,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4519,7 +4519,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4519 .for_node_offset = inst_data.src_node,4519 .for_node_offset = inst_data.src_node,
4520 .input_index = i,4520 .input_index = i,
4521 } });4521 } });
4522 try sema.errNote(arg_src, msg, "type '{}' has no upper bound", .{4522 try sema.errNote(arg_src, msg, "type '{f}' has no upper bound", .{
4523 object_ty.fmt(pt),4523 object_ty.fmt(pt),
4524 });4524 });
4525 }4525 }
...@@ -4595,7 +4595,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -4595,7 +4595,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4595 switch (val_ty.zigTypeTag(zcu)) {4595 switch (val_ty.zigTypeTag(zcu)) {
4596 .array, .vector => {},4596 .array, .vector => {},
4597 else => if (!val_ty.isTuple(zcu)) {4597 else => if (!val_ty.isTuple(zcu)) {
4598 return sema.fail(block, src, "expected array of '{}', found '{}'", .{ elem_ty.fmt(pt), val_ty.fmt(pt) });4598 return sema.fail(block, src, "expected array of '{f}', found '{f}'", .{ elem_ty.fmt(pt), val_ty.fmt(pt) });
4599 },4599 },
4600 }4600 }
4601 const want_ty = try pt.arrayType(.{4601 const want_ty = try pt.arrayType(.{
...@@ -4669,7 +4669,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4669,7 +4669,7 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4669 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;4669 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return;
4670 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {4670 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) {
4671 return sema.failWithOwnedErrorMsg(block, msg: {4671 return sema.failWithOwnedErrorMsg(block, msg: {
4672 const msg = try sema.errMsg(src, "expected type '{}', found pointer", .{ty_operand.fmt(pt)});4672 const msg = try sema.errMsg(src, "expected type '{f}', found pointer", .{ty_operand.fmt(pt)});
4673 errdefer msg.destroy(sema.gpa);4673 errdefer msg.destroy(sema.gpa);
4674 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{});4674 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{});
4675 break :msg msg;4675 break :msg msg;
...@@ -5078,7 +5078,7 @@ fn validateStructInit(...@@ -5078,7 +5078,7 @@ fn validateStructInit(
5078 }5078 }
5079 continue;5079 continue;
5080 };5080 };
5081 const template = "missing struct field: {}";5081 const template = "missing struct field: {f}";
5082 const args = .{field_name.fmt(ip)};5082 const args = .{field_name.fmt(ip)};
5083 if (root_msg) |msg| {5083 if (root_msg) |msg| {
5084 try sema.errNote(init_src, msg, template, args);5084 try sema.errNote(init_src, msg, template, args);
...@@ -5208,7 +5208,7 @@ fn validateStructInit(...@@ -5208,7 +5208,7 @@ fn validateStructInit(
5208 }5208 }
5209 continue;5209 continue;
5210 };5210 };
5211 const template = "missing struct field: {}";5211 const template = "missing struct field: {f}";
5212 const args = .{field_name.fmt(ip)};5212 const args = .{field_name.fmt(ip)};
5213 if (root_msg) |msg| {5213 if (root_msg) |msg| {
5214 try sema.errNote(init_src, msg, template, args);5214 try sema.errNote(init_src, msg, template, args);
...@@ -5512,11 +5512,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -5512,11 +5512,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
5512 const operand_ty = sema.typeOf(operand);5512 const operand_ty = sema.typeOf(operand);
55135513
5514 if (operand_ty.zigTypeTag(zcu) != .pointer) {5514 if (operand_ty.zigTypeTag(zcu) != .pointer) {
5515 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(pt)});5515 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{operand_ty.fmt(pt)});
5516 } else switch (operand_ty.ptrSize(zcu)) {5516 } else switch (operand_ty.ptrSize(zcu)) {
5517 .one, .c => {},5517 .one, .c => {},
5518 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(pt)}),5518 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{operand_ty.fmt(pt)}),
5519 .slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(pt)}),5519 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
5520 }5520 }
55215521
5522 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {5522 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {
...@@ -5533,7 +5533,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -5533,7 +5533,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
5533 const msg = msg: {5533 const msg = msg: {
5534 const msg = try sema.errMsg(5534 const msg = try sema.errMsg(
5535 src,5535 src,
5536 "values of type '{}' must be comptime-known, but operand value is runtime-known",5536 "values of type '{f}' must be comptime-known, but operand value is runtime-known",
5537 .{elem_ty.fmt(pt)},5537 .{elem_ty.fmt(pt)},
5538 );5538 );
5539 errdefer msg.destroy(sema.gpa);5539 errdefer msg.destroy(sema.gpa);
...@@ -5565,7 +5565,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -5565,7 +5565,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
55655565
5566 if (!typeIsDestructurable(operand_ty, zcu)) {5566 if (!typeIsDestructurable(operand_ty, zcu)) {
5567 return sema.failWithOwnedErrorMsg(block, msg: {5567 return sema.failWithOwnedErrorMsg(block, msg: {
5568 const msg = try sema.errMsg(src, "type '{}' cannot be destructured", .{operand_ty.fmt(pt)});5568 const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)});
5569 errdefer msg.destroy(sema.gpa);5569 errdefer msg.destroy(sema.gpa);
5570 try sema.errNote(destructure_src, msg, "result destructured here", .{});5570 try sema.errNote(destructure_src, msg, "result destructured here", .{});
5571 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {5571 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
...@@ -5608,12 +5608,12 @@ fn failWithBadMemberAccess(...@@ -5608,12 +5608,12 @@ fn failWithBadMemberAccess(
5608 else => unreachable,5608 else => unreachable,
5609 };5609 };
5610 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {5610 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {
5611 return sema.fail(block, field_src, "root source file struct '{}' has no member named '{}'", .{5611 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
5612 agg_ty.fmt(pt), field_name.fmt(ip),5612 agg_ty.fmt(pt), field_name.fmt(ip),
5613 });5613 });
5614 };5614 };
56155615
5616 return sema.fail(block, field_src, "{s} '{}' has no member named '{}'", .{5616 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
5617 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),5617 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
5618 });5618 });
5619}5619}
...@@ -5633,7 +5633,7 @@ fn failWithBadStructFieldAccess(...@@ -5633,7 +5633,7 @@ fn failWithBadStructFieldAccess(
5633 const msg = msg: {5633 const msg = msg: {
5634 const msg = try sema.errMsg(5634 const msg = try sema.errMsg(
5635 field_src,5635 field_src,
5636 "no field named '{}' in struct '{}'",5636 "no field named '{f}' in struct '{f}'",
5637 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },5637 .{ field_name.fmt(ip), struct_type.name.fmt(ip) },
5638 );5638 );
5639 errdefer msg.destroy(sema.gpa);5639 errdefer msg.destroy(sema.gpa);
...@@ -5659,7 +5659,7 @@ fn failWithBadUnionFieldAccess(...@@ -5659,7 +5659,7 @@ fn failWithBadUnionFieldAccess(
5659 const msg = msg: {5659 const msg = msg: {
5660 const msg = try sema.errMsg(5660 const msg = try sema.errMsg(
5661 field_src,5661 field_src,
5662 "no field named '{}' in union '{}'",5662 "no field named '{f}' in union '{f}'",
5663 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },5663 .{ field_name.fmt(ip), union_obj.name.fmt(ip) },
5664 );5664 );
5665 errdefer msg.destroy(gpa);5665 errdefer msg.destroy(gpa);
...@@ -5911,30 +5911,30 @@ fn zirCompileLog(...@@ -5911,30 +5911,30 @@ fn zirCompileLog(
5911 const zcu = pt.zcu;5911 const zcu = pt.zcu;
5912 const gpa = zcu.gpa;5912 const gpa = zcu.gpa;
59135913
5914 var buf: std.ArrayListUnmanaged(u8) = .empty;5914 var aw: std.io.AllocatingWriter = undefined;
5915 defer buf.deinit(gpa);5915 const bw = aw.init(sema.gpa);
59165916 defer aw.deinit();
5917 const writer = buf.writer(gpa);
59185917
5919 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);5918 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
5920 const src_node = extra.data.src_node;5919 const src_node = extra.data.src_node;
5921 const args = sema.code.refSlice(extra.end, extended.small);5920 const args = sema.code.refSlice(extra.end, extended.small);
59225921
5923 for (args, 0..) |arg_ref, i| {5922 for (args, 0..) |arg_ref, i| {
5924 if (i != 0) try writer.print(", ", .{});5923 if (i != 0) bw.writeAll(", ") catch |err| return @errorCast(err);
59255924
5926 const arg = try sema.resolveInst(arg_ref);5925 const arg = try sema.resolveInst(arg_ref);
5927 const arg_ty = sema.typeOf(arg);5926 const arg_ty = sema.typeOf(arg);
5928 if (try sema.resolveValueResolveLazy(arg)) |val| {5927 if (try sema.resolveValueResolveLazy(arg)) |val| {
5929 try writer.print("@as({}, {})", .{5928 bw.print("@as({f}, {f})", .{
5930 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),5929 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),
5931 });5930 }) catch |err| return @errorCast(err);
5932 } else {5931 } else {
5933 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(pt)});5932 bw.print("@as({f}, [runtime value])", .{arg_ty.fmt(pt)}) catch |err| return @errorCast(err);
5934 }5933 }
5935 }5934 }
5935 try bw.print("\n", .{});
59365936
5937 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);5937 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, aw.getWritten(), .no_embedded_nulls);
59385938
5939 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {5939 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {
5940 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{5940 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{
...@@ -6476,7 +6476,7 @@ fn resolveAnalyzedBlock(...@@ -6476,7 +6476,7 @@ fn resolveAnalyzedBlock(
6476 const type_src = src; // TODO: better source location6476 const type_src = src; // TODO: better source location
6477 if (try resolved_ty.comptimeOnlySema(pt)) {6477 if (try resolved_ty.comptimeOnlySema(pt)) {
6478 const msg = msg: {6478 const msg = msg: {
6479 const msg = try sema.errMsg(type_src, "value with comptime-only type '{}' depends on runtime control flow", .{resolved_ty.fmt(pt)});6479 const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)});
6480 errdefer msg.destroy(sema.gpa);6480 errdefer msg.destroy(sema.gpa);
64816481
6482 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;6482 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?;
...@@ -6592,7 +6592,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6592,7 +6592,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
65926592
6593 {6593 {
6594 if (ptr_ty.zigTypeTag(zcu) != .pointer) {6594 if (ptr_ty.zigTypeTag(zcu) != .pointer) {
6595 return sema.fail(block, ptr_src, "expected pointer type, found '{}'", .{ptr_ty.fmt(pt)});6595 return sema.fail(block, ptr_src, "expected pointer type, found '{f}'", .{ptr_ty.fmt(pt)});
6596 }6596 }
6597 const ptr_ty_info = ptr_ty.ptrInfo(zcu);6597 const ptr_ty_info = ptr_ty.ptrInfo(zcu);
6598 if (ptr_ty_info.flags.size == .slice) {6598 if (ptr_ty_info.flags.size == .slice) {
...@@ -6615,7 +6615,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6615,7 +6615,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
6615 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);6615 const export_ty = Value.fromInterned(uav.val).typeOf(zcu);
6616 if (!try sema.validateExternType(export_ty, .other)) {6616 if (!try sema.validateExternType(export_ty, .other)) {
6617 return sema.failWithOwnedErrorMsg(block, msg: {6617 return sema.failWithOwnedErrorMsg(block, msg: {
6618 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});6618 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
6619 errdefer msg.destroy(sema.gpa);6619 errdefer msg.destroy(sema.gpa);
6620 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6620 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
6621 try sema.addDeclaredHereNote(msg, export_ty);6621 try sema.addDeclaredHereNote(msg, export_ty);
...@@ -6667,7 +6667,7 @@ pub fn analyzeExport(...@@ -6667,7 +6667,7 @@ pub fn analyzeExport(
66676667
6668 if (!try sema.validateExternType(export_ty, .other)) {6668 if (!try sema.validateExternType(export_ty, .other)) {
6669 return sema.failWithOwnedErrorMsg(block, msg: {6669 return sema.failWithOwnedErrorMsg(block, msg: {
6670 const msg = try sema.errMsg(src, "unable to export type '{}'", .{export_ty.fmt(pt)});6670 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)});
6671 errdefer msg.destroy(gpa);6671 errdefer msg.destroy(gpa);
66726672
6673 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);6673 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other);
...@@ -7363,7 +7363,7 @@ fn checkCallArgumentCount(...@@ -7363,7 +7363,7 @@ fn checkCallArgumentCount(
7363 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))7363 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn"))
7364 {7364 {
7365 const msg = msg: {7365 const msg = msg: {
7366 const msg = try sema.errMsg(func_src, "cannot call optional type '{}'", .{7366 const msg = try sema.errMsg(func_src, "cannot call optional type '{f}'", .{
7367 callee_ty.fmt(pt),7367 callee_ty.fmt(pt),
7368 });7368 });
7369 errdefer msg.destroy(sema.gpa);7369 errdefer msg.destroy(sema.gpa);
...@@ -7375,7 +7375,7 @@ fn checkCallArgumentCount(...@@ -7375,7 +7375,7 @@ fn checkCallArgumentCount(
7375 },7375 },
7376 else => {},7376 else => {},
7377 }7377 }
7378 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(pt)});7378 return sema.fail(block, func_src, "type '{f}' not a function", .{callee_ty.fmt(pt)});
7379 };7379 };
73807380
7381 const func_ty_info = zcu.typeToFunc(func_ty).?;7381 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7438,7 +7438,7 @@ fn callBuiltin(...@@ -7438,7 +7438,7 @@ fn callBuiltin(
7438 },7438 },
7439 else => {},7439 else => {},
7440 }7440 }
7441 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});7441 std.debug.panic("type '{f}' is not a function calling builtin fn", .{callee_ty.fmt(pt)});
7442 };7442 };
74437443
7444 const func_ty_info = zcu.typeToFunc(func_ty).?;7444 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7826,7 +7826,7 @@ fn analyzeCall(...@@ -7826,7 +7826,7 @@ fn analyzeCall(
78267826
7827 if (!param_ty.isValidParamType(zcu)) {7827 if (!param_ty.isValidParamType(zcu)) {
7828 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7828 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
7829 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{7829 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
7830 opaque_str, param_ty.fmt(pt),7830 opaque_str, param_ty.fmt(pt),
7831 });7831 });
7832 }7832 }
...@@ -7923,7 +7923,7 @@ fn analyzeCall(...@@ -7923,7 +7923,7 @@ fn analyzeCall(
79237923
7924 if (!full_ty.isValidReturnType(zcu)) {7924 if (!full_ty.isValidReturnType(zcu)) {
7925 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";7925 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
7926 return sema.fail(block, func_ret_ty_src, "{s}return type '{}' not allowed", .{7926 return sema.fail(block, func_ret_ty_src, "{s}return type '{f}' not allowed", .{
7927 opaque_str, full_ty.fmt(pt),7927 opaque_str, full_ty.fmt(pt),
7928 });7928 });
7929 }7929 }
...@@ -8382,7 +8382,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -8382,7 +8382,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
8382 }8382 }
8383 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);8383 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty);
8384 if (owner_func_ty.toIntern() != func_ty.toIntern()) {8384 if (owner_func_ty.toIntern() != func_ty.toIntern()) {
8385 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{8385 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{f}' does not match type of calling function '{f}'", .{
8386 func_ty.fmt(pt), owner_func_ty.fmt(pt),8386 func_ty.fmt(pt), owner_func_ty.fmt(pt),
8387 });8387 });
8388 }8388 }
...@@ -8406,9 +8406,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -8406,9 +8406,9 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
8406 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });8406 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node });
8407 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);8407 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
8408 if (child_type.zigTypeTag(zcu) == .@"opaque") {8408 if (child_type.zigTypeTag(zcu) == .@"opaque") {
8409 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(pt)});8409 return sema.fail(block, operand_src, "opaque type '{f}' cannot be optional", .{child_type.fmt(pt)});
8410 } else if (child_type.zigTypeTag(zcu) == .null) {8410 } else if (child_type.zigTypeTag(zcu) == .null) {
8411 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(pt)});8411 return sema.fail(block, operand_src, "type '{f}' cannot be optional", .{child_type.fmt(pt)});
8412 }8412 }
8413 const opt_type = try pt.optionalType(child_type.toIntern());8413 const opt_type = try pt.optionalType(child_type.toIntern());
84148414
...@@ -8469,7 +8469,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8469,7 +8469,7 @@ fn zirVecArrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8469 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;8469 const vec_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type;
8470 switch (vec_ty.zigTypeTag(zcu)) {8470 switch (vec_ty.zigTypeTag(zcu)) {
8471 .array, .vector => {},8471 .array, .vector => {},
8472 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{}'", .{vec_ty.fmt(pt)}),8472 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}),
8473 }8473 }
8474 return Air.internedToRef(vec_ty.childType(zcu).toIntern());8474 return Air.internedToRef(vec_ty.childType(zcu).toIntern());
8475}8475}
...@@ -8537,7 +8537,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:...@@ -8537,7 +8537,7 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src:
8537 const pt = sema.pt;8537 const pt = sema.pt;
8538 const zcu = pt.zcu;8538 const zcu = pt.zcu;
8539 if (elem_type.zigTypeTag(zcu) == .@"opaque") {8539 if (elem_type.zigTypeTag(zcu) == .@"opaque") {
8540 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(pt)});8540 return sema.fail(block, elem_src, "array of opaque type '{f}' not allowed", .{elem_type.fmt(pt)});
8541 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {8541 } else if (elem_type.zigTypeTag(zcu) == .noreturn) {
8542 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});8542 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
8543 }8543 }
...@@ -8573,7 +8573,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8573,7 +8573,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8573 const payload = try sema.resolveType(block, rhs_src, extra.rhs);8573 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
85748574
8575 if (error_set.zigTypeTag(zcu) != .error_set) {8575 if (error_set.zigTypeTag(zcu) != .error_set) {
8576 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{8576 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{
8577 error_set.fmt(pt),8577 error_set.fmt(pt),
8578 });8578 });
8579 }8579 }
...@@ -8586,11 +8586,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p...@@ -8586,11 +8586,11 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p
8586 const pt = sema.pt;8586 const pt = sema.pt;
8587 const zcu = pt.zcu;8587 const zcu = pt.zcu;
8588 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {8588 if (payload_ty.zigTypeTag(zcu) == .@"opaque") {
8589 return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{8589 return sema.fail(block, payload_src, "error union with payload of opaque type '{f}' not allowed", .{
8590 payload_ty.fmt(pt),8590 payload_ty.fmt(pt),
8591 });8591 });
8592 } else if (payload_ty.zigTypeTag(zcu) == .error_set) {8592 } else if (payload_ty.zigTypeTag(zcu) == .error_set) {
8593 return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{8593 return sema.fail(block, payload_src, "error union with payload of error set type '{f}' not allowed", .{
8594 payload_ty.fmt(pt),8594 payload_ty.fmt(pt),
8595 });8595 });
8596 }8596 }
...@@ -8728,9 +8728,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8728,9 +8728,9 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8728 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);8728 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
8729 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);8729 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
8730 if (lhs_ty.zigTypeTag(zcu) != .error_set)8730 if (lhs_ty.zigTypeTag(zcu) != .error_set)
8731 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(pt)});8731 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)});
8732 if (rhs_ty.zigTypeTag(zcu) != .error_set)8732 if (rhs_ty.zigTypeTag(zcu) != .error_set)
8733 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(pt)});8733 return sema.fail(block, rhs_src, "expected error set type, found '{f}'", .{rhs_ty.fmt(pt)});
87348734
8735 // Anything merged with anyerror is anyerror.8735 // Anything merged with anyerror is anyerror.
8736 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {8736 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {
...@@ -8840,7 +8840,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8840,7 +8840,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8840 return sema.fail(8840 return sema.fail(
8841 block,8841 block,
8842 operand_src,8842 operand_src,
8843 "untagged union '{}' cannot be converted to integer",8843 "untagged union '{f}' cannot be converted to integer",
8844 .{operand_ty.fmt(pt)},8844 .{operand_ty.fmt(pt)},
8845 );8845 );
8846 };8846 };
...@@ -8848,7 +8848,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8848,7 +8848,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8848 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);8848 break :blk try sema.unionToTag(block, tag_ty, operand, operand_src);
8849 },8849 },
8850 else => {8850 else => {
8851 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{8851 return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{
8852 operand_ty.fmt(pt),8852 operand_ty.fmt(pt),
8853 });8853 });
8854 },8854 },
...@@ -8859,7 +8859,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8859,7 +8859,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8859 // TODO: use correct solution8859 // TODO: use correct solution
8860 // https://github.com/ziglang/zig/issues/159098860 // https://github.com/ziglang/zig/issues/15909
8861 if (enum_tag_ty.enumFieldCount(zcu) == 0 and !enum_tag_ty.isNonexhaustiveEnum(zcu)) {8861 if (enum_tag_ty.enumFieldCount(zcu) == 0 and !enum_tag_ty.isNonexhaustiveEnum(zcu)) {
8862 return sema.fail(block, operand_src, "cannot use @intFromEnum on empty enum '{}'", .{8862 return sema.fail(block, operand_src, "cannot use @intFromEnum on empty enum '{f}'", .{
8863 enum_tag_ty.fmt(pt),8863 enum_tag_ty.fmt(pt),
8864 });8864 });
8865 }8865 }
...@@ -8893,7 +8893,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8893,7 +8893,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8893 const operand_ty = sema.typeOf(operand);8893 const operand_ty = sema.typeOf(operand);
88948894
8895 if (dest_ty.zigTypeTag(zcu) != .@"enum") {8895 if (dest_ty.zigTypeTag(zcu) != .@"enum") {
8896 return sema.fail(block, src, "expected enum, found '{}'", .{dest_ty.fmt(pt)});8896 return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)});
8897 }8897 }
8898 _ = try sema.checkIntType(block, operand_src, operand_ty);8898 _ = try sema.checkIntType(block, operand_src, operand_ty);
88998899
...@@ -8903,7 +8903,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8903,7 +8903,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8903 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {8903 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
8904 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());8904 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern());
8905 }8905 }
8906 return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{8906 return sema.fail(block, src, "int value '{f}' out of range of non-exhaustive enum '{f}'", .{
8907 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),8907 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt),
8908 });8908 });
8909 }8909 }
...@@ -8911,7 +8911,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8911,7 +8911,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8911 return sema.failWithUseOfUndef(block, operand_src);8911 return sema.failWithUseOfUndef(block, operand_src);
8912 }8912 }
8913 if (!(try sema.enumHasInt(dest_ty, int_val))) {8913 if (!(try sema.enumHasInt(dest_ty, int_val))) {
8914 return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{8914 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{
8915 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),8915 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema),
8916 });8916 });
8917 }8917 }
...@@ -9105,7 +9105,7 @@ fn zirErrUnionPayload(...@@ -9105,7 +9105,7 @@ fn zirErrUnionPayload(
9105 const operand_src = src;9105 const operand_src = src;
9106 const err_union_ty = sema.typeOf(operand);9106 const err_union_ty = sema.typeOf(operand);
9107 if (err_union_ty.zigTypeTag(zcu) != .error_union) {9107 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
9108 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{9108 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{
9109 err_union_ty.fmt(pt),9109 err_union_ty.fmt(pt),
9110 });9110 });
9111 }9111 }
...@@ -9173,7 +9173,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -9173,7 +9173,7 @@ fn analyzeErrUnionPayloadPtr(
9173 assert(operand_ty.zigTypeTag(zcu) == .pointer);9173 assert(operand_ty.zigTypeTag(zcu) == .pointer);
91749174
9175 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9175 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9176 return sema.fail(block, src, "expected error union type, found '{}'", .{9176 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9177 operand_ty.childType(zcu).fmt(pt),9177 operand_ty.childType(zcu).fmt(pt),
9178 });9178 });
9179 }9179 }
...@@ -9250,7 +9250,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air...@@ -9250,7 +9250,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
9250 const zcu = pt.zcu;9250 const zcu = pt.zcu;
9251 const operand_ty = sema.typeOf(operand);9251 const operand_ty = sema.typeOf(operand);
9252 if (operand_ty.zigTypeTag(zcu) != .error_union) {9252 if (operand_ty.zigTypeTag(zcu) != .error_union) {
9253 return sema.fail(block, src, "expected error union type, found '{}'", .{9253 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9254 operand_ty.fmt(pt),9254 operand_ty.fmt(pt),
9255 });9255 });
9256 }9256 }
...@@ -9286,7 +9286,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:...@@ -9286,7 +9286,7 @@ fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand:
9286 assert(operand_ty.zigTypeTag(zcu) == .pointer);9286 assert(operand_ty.zigTypeTag(zcu) == .pointer);
92879287
9288 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {9288 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) {
9289 return sema.fail(block, src, "expected error union type, found '{}'", .{9289 return sema.fail(block, src, "expected error union type, found '{f}'", .{
9290 operand_ty.childType(zcu).fmt(pt),9290 operand_ty.childType(zcu).fmt(pt),
9291 });9291 });
9292 }9292 }
...@@ -9544,19 +9544,18 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {...@@ -9544,19 +9544,18 @@ fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
9544fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {9544fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
9545 const CallingConventionsSupportingVarArgsList = struct {9545 const CallingConventionsSupportingVarArgsList = struct {
9546 arch: std.Target.Cpu.Arch,9546 arch: std.Target.Cpu.Arch,
9547 pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9547 pub fn format(ctx: @This(), bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
9548 _ = fmt;9548 _ = fmt;
9549 _ = options;
9550 var first = true;9549 var first = true;
9551 for (calling_conventions_supporting_var_args) |cc_inner| {9550 for (calling_conventions_supporting_var_args) |cc_inner| {
9552 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {9551 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
9553 if (supported_arch == ctx.arch) break;9552 if (supported_arch == ctx.arch) break;
9554 } else continue; // callconv not supported by this arch9553 } else continue; // callconv not supported by this arch
9555 if (!first) {9554 if (!first) {
9556 try writer.writeAll(", ");9555 try bw.writeAll(", ");
9557 }9556 }
9558 first = false;9557 first = false;
9559 try writer.print("'{s}'", .{@tagName(cc_inner)});9558 try bw.print("'{s}'", .{@tagName(cc_inner)});
9560 }9559 }
9561 }9560 }
9562 };9561 };
...@@ -9566,7 +9565,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:...@@ -9566,7 +9565,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
9566 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});9565 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
9567 errdefer msg.destroy(sema.gpa);9566 errdefer msg.destroy(sema.gpa);
9568 const target = sema.pt.zcu.getTarget();9567 const target = sema.pt.zcu.getTarget();
9569 try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});9568 try sema.errNote(src, msg, "supported calling conventions: {f}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});
9570 break :msg msg;9569 break :msg msg;
9571 });9570 });
9572 }9571 }
...@@ -9614,7 +9613,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)...@@ -9614,7 +9613,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
9614 }9613 }
96159614
9616 return sema.failWithOwnedErrorMsg(block, msg: {9615 return sema.failWithOwnedErrorMsg(block, msg: {
9617 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{}' depends on runtime control flow", .{peer_ty.fmt(pt)});9616 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{f}' depends on runtime control flow", .{peer_ty.fmt(pt)});
9618 errdefer msg.destroy(sema.gpa);9617 errdefer msg.destroy(sema.gpa);
96199618
9620 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;9619 const runtime_src = block.runtime_cond orelse block.runtime_loop.?;
...@@ -9692,13 +9691,13 @@ fn funcCommon(...@@ -9692,13 +9691,13 @@ fn funcCommon(
9692 }9691 }
9693 if (!param_ty.isValidParamType(zcu)) {9692 if (!param_ty.isValidParamType(zcu)) {
9694 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9693 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9695 return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{9694 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
9696 opaque_str, param_ty.fmt(pt),9695 opaque_str, param_ty.fmt(pt),
9697 });9696 });
9698 }9697 }
9699 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {9698 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {
9700 const msg = msg: {9699 const msg = msg: {
9701 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9700 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
9702 param_ty.fmt(pt), @tagName(cc),9701 param_ty.fmt(pt), @tagName(cc),
9703 });9702 });
9704 errdefer msg.destroy(sema.gpa);9703 errdefer msg.destroy(sema.gpa);
...@@ -9712,7 +9711,7 @@ fn funcCommon(...@@ -9712,7 +9711,7 @@ fn funcCommon(
9712 }9711 }
9713 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {9712 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9714 const msg = msg: {9713 const msg = msg: {
9715 const msg = try sema.errMsg(param_src, "parameter of type '{}' must be declared comptime", .{9714 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
9716 param_ty.fmt(pt),9715 param_ty.fmt(pt),
9717 });9716 });
9718 errdefer msg.destroy(sema.gpa);9717 errdefer msg.destroy(sema.gpa);
...@@ -9892,7 +9891,7 @@ fn finishFunc(...@@ -9892,7 +9891,7 @@ fn finishFunc(
98929891
9893 if (!return_type.isValidReturnType(zcu)) {9892 if (!return_type.isValidReturnType(zcu)) {
9894 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9893 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9895 return sema.fail(block, ret_ty_src, "{s}return type '{}' not allowed", .{9894 return sema.fail(block, ret_ty_src, "{s}return type '{f}' not allowed", .{
9896 opaque_str, return_type.fmt(pt),9895 opaque_str, return_type.fmt(pt),
9897 });9896 });
9898 }9897 }
...@@ -9900,7 +9899,7 @@ fn finishFunc(...@@ -9900,7 +9899,7 @@ fn finishFunc(
9900 !try sema.validateExternType(return_type, .ret_ty))9899 !try sema.validateExternType(return_type, .ret_ty))
9901 {9900 {
9902 const msg = msg: {9901 const msg = msg: {
9903 const msg = try sema.errMsg(ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{9902 const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{s}'", .{
9904 return_type.fmt(pt), @tagName(cc_resolved),9903 return_type.fmt(pt), @tagName(cc_resolved),
9905 });9904 });
9906 errdefer msg.destroy(gpa);9905 errdefer msg.destroy(gpa);
...@@ -9922,7 +9921,7 @@ fn finishFunc(...@@ -9922,7 +9921,7 @@ fn finishFunc(
99229921
9923 const msg = try sema.errMsg(9922 const msg = try sema.errMsg(
9924 ret_ty_src,9923 ret_ty_src,
9925 "function with comptime-only return type '{}' requires all parameters to be comptime",9924 "function with comptime-only return type '{f}' requires all parameters to be comptime",
9926 .{return_type.fmt(pt)},9925 .{return_type.fmt(pt)},
9927 );9926 );
9928 errdefer msg.destroy(sema.gpa);9927 errdefer msg.destroy(sema.gpa);
...@@ -9991,17 +9990,16 @@ fn finishFunc(...@@ -9991,17 +9990,16 @@ fn finishFunc(
9991 .bad_arch => |allowed_archs| {9990 .bad_arch => |allowed_archs| {
9992 const ArchListFormatter = struct {9991 const ArchListFormatter = struct {
9993 archs: []const std.Target.Cpu.Arch,9992 archs: []const std.Target.Cpu.Arch,
9994 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {9993 pub fn format(formatter: @This(), bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
9995 _ = fmt;9994 _ = fmt;
9996 _ = options;
9997 for (formatter.archs, 0..) |arch, i| {9995 for (formatter.archs, 0..) |arch, i| {
9998 if (i != 0)9996 if (i != 0)
9999 try writer.writeAll(", ");9997 try bw.writeAll(", ");
10000 try writer.print("'{s}'", .{@tagName(arch)});9998 try bw.print("'{s}'", .{@tagName(arch)});
10001 }9999 }
10002 }10000 }
10003 };10001 };
10004 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {}", .{10002 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{
10005 @tagName(cc_resolved),10003 @tagName(cc_resolved),
10006 ArchListFormatter{ .archs = allowed_archs },10004 ArchListFormatter{ .archs = allowed_archs },
10007 });10005 });
...@@ -10102,7 +10100,7 @@ fn analyzeAs(...@@ -10102,7 +10100,7 @@ fn analyzeAs(
10102 const operand = try sema.resolveInst(zir_operand);10100 const operand = try sema.resolveInst(zir_operand);
10103 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;10101 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand;
10104 switch (dest_ty.zigTypeTag(zcu)) {10102 switch (dest_ty.zigTypeTag(zcu)) {
10105 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{}'", .{dest_ty.fmt(pt)}),10103 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}),
10106 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),10104 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}),
10107 else => {},10105 else => {},
10108 }10106 }
...@@ -10130,12 +10128,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10130,12 +10128,12 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10130 const ptr_ty = operand_ty.scalarType(zcu);10128 const ptr_ty = operand_ty.scalarType(zcu);
10131 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;10129 const is_vector = operand_ty.zigTypeTag(zcu) == .vector;
10132 if (!ptr_ty.isPtrAtRuntime(zcu)) {10130 if (!ptr_ty.isPtrAtRuntime(zcu)) {
10133 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)});10131 return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)});
10134 }10132 }
10135 const pointee_ty = ptr_ty.childType(zcu);10133 const pointee_ty = ptr_ty.childType(zcu);
10136 if (try ptr_ty.comptimeOnlySema(pt)) {10134 if (try ptr_ty.comptimeOnlySema(pt)) {
10137 const msg = msg: {10135 const msg = msg: {
10138 const msg = try sema.errMsg(ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(pt)});10136 const msg = try sema.errMsg(ptr_src, "comptime-only type '{f}' has no pointer address", .{pointee_ty.fmt(pt)});
10139 errdefer msg.destroy(sema.gpa);10137 errdefer msg.destroy(sema.gpa);
10140 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);10138 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);
10141 break :msg msg;10139 break :msg msg;
...@@ -10383,14 +10381,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10383,14 +10381,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10383 .type,10381 .type,
10384 .undefined,10382 .undefined,
10385 .void,10383 .void,
10386 => return sema.fail(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)}),10384 => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}),
1038710385
10388 .@"enum" => {10386 .@"enum" => {
10389 const msg = msg: {10387 const msg = msg: {
10390 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});10388 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
10391 errdefer msg.destroy(sema.gpa);10389 errdefer msg.destroy(sema.gpa);
10392 switch (operand_ty.zigTypeTag(zcu)) {10390 switch (operand_ty.zigTypeTag(zcu)) {
10393 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),10391 .int, .comptime_int => try sema.errNote(src, msg, "use @enumFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
10394 else => {},10392 else => {},
10395 }10393 }
1039610394
...@@ -10401,11 +10399,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10401,11 +10399,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1040110399
10402 .pointer => {10400 .pointer => {
10403 const msg = msg: {10401 const msg = msg: {
10404 const msg = try sema.errMsg(src, "cannot @bitCast to '{}'", .{dest_ty.fmt(pt)});10402 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
10405 errdefer msg.destroy(sema.gpa);10403 errdefer msg.destroy(sema.gpa);
10406 switch (operand_ty.zigTypeTag(zcu)) {10404 switch (operand_ty.zigTypeTag(zcu)) {
10407 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(pt)}),10405 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}),
10408 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(pt)}),10406 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}),
10409 else => {},10407 else => {},
10410 }10408 }
1041110409
...@@ -10419,7 +10417,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10419,7 +10417,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10419 .@"union" => "union",10417 .@"union" => "union",
10420 else => unreachable,10418 else => unreachable,
10421 };10419 };
10422 return sema.fail(block, src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{10420 return sema.fail(block, src, "cannot @bitCast to '{f}'; {s} does not have a guaranteed in-memory layout", .{
10423 dest_ty.fmt(pt), container,10421 dest_ty.fmt(pt), container,
10424 });10422 });
10425 },10423 },
...@@ -10447,14 +10445,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10447,14 +10445,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10447 .type,10445 .type,
10448 .undefined,10446 .undefined,
10449 .void,10447 .void,
10450 => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)}),10448 => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}),
1045110449
10452 .@"enum" => {10450 .@"enum" => {
10453 const msg = msg: {10451 const msg = msg: {
10454 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});10452 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
10455 errdefer msg.destroy(sema.gpa);10453 errdefer msg.destroy(sema.gpa);
10456 switch (dest_ty.zigTypeTag(zcu)) {10454 switch (dest_ty.zigTypeTag(zcu)) {
10457 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{}'", .{dest_ty.fmt(pt)}),10455 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromEnum to cast to '{f}'", .{dest_ty.fmt(pt)}),
10458 else => {},10456 else => {},
10459 }10457 }
1046010458
...@@ -10464,11 +10462,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10464,11 +10462,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10464 },10462 },
10465 .pointer => {10463 .pointer => {
10466 const msg = msg: {10464 const msg = msg: {
10467 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(pt)});10465 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
10468 errdefer msg.destroy(sema.gpa);10466 errdefer msg.destroy(sema.gpa);
10469 switch (dest_ty.zigTypeTag(zcu)) {10467 switch (dest_ty.zigTypeTag(zcu)) {
10470 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{}'", .{dest_ty.fmt(pt)}),10468 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{f}'", .{dest_ty.fmt(pt)}),
10471 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(pt)}),10469 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}),
10472 else => {},10470 else => {},
10473 }10471 }
1047410472
...@@ -10482,7 +10480,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10482,7 +10480,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10482 .@"union" => "union",10480 .@"union" => "union",
10483 else => unreachable,10481 else => unreachable,
10484 };10482 };
10485 return sema.fail(block, operand_src, "cannot @bitCast from '{}'; {s} does not have a guaranteed in-memory layout", .{10483 return sema.fail(block, operand_src, "cannot @bitCast from '{f}'; {s} does not have a guaranteed in-memory layout", .{
10486 operand_ty.fmt(pt), container,10484 operand_ty.fmt(pt), container,
10487 });10485 });
10488 },10486 },
...@@ -10525,7 +10523,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10525,7 +10523,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10525 else => return sema.fail(10523 else => return sema.fail(
10526 block,10524 block,
10527 src,10525 src,
10528 "expected float or vector type, found '{}'",10526 "expected float or vector type, found '{f}'",
10529 .{dest_ty.fmt(pt)},10527 .{dest_ty.fmt(pt)},
10530 ),10528 ),
10531 };10529 };
...@@ -10535,7 +10533,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10535,7 +10533,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10535 else => return sema.fail(10533 else => return sema.fail(
10536 block,10534 block,
10537 operand_src,10535 operand_src,
10538 "expected float or vector type, found '{}'",10536 "expected float or vector type, found '{f}'",
10539 .{operand_ty.fmt(pt)},10537 .{operand_ty.fmt(pt)},
10540 ),10538 ),
10541 }10539 }
...@@ -10619,7 +10617,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10619,7 +10617,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10619 if (indexable_ty.zigTypeTag(zcu) != .pointer) {10617 if (indexable_ty.zigTypeTag(zcu) != .pointer) {
10620 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });10618 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node });
10621 const msg = msg: {10619 const msg = msg: {
10622 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{}'", .{10620 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{f}'", .{
10623 indexable_ty.fmt(pt),10621 indexable_ty.fmt(pt),
10624 });10622 });
10625 errdefer msg.destroy(sema.gpa);10623 errdefer msg.destroy(sema.gpa);
...@@ -10761,7 +10759,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10761,7 +10759,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
10761 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));10759 const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand));
10762 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {10760 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) {
10763 .pointer => lhs_ptr_ty.childType(zcu),10761 .pointer => lhs_ptr_ty.childType(zcu),
10764 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{lhs_ptr_ty.fmt(pt)}),10762 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}),
10765 };10763 };
1076610764
10767 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {10765 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) {
...@@ -10776,7 +10774,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -10776,7 +10774,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
10776 };10774 };
10777 },10775 },
10778 },10776 },
10779 else => return sema.fail(block, src, "slice of non-array type '{}'", .{lhs_ty.fmt(pt)}),10777 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{lhs_ty.fmt(pt)}),
10780 };10778 };
1078110779
10782 return Air.internedToRef(sentinel_ty.toIntern());10780 return Air.internedToRef(sentinel_ty.toIntern());
...@@ -10971,7 +10969,7 @@ const SwitchProngAnalysis = struct {...@@ -10971,7 +10969,7 @@ const SwitchProngAnalysis = struct {
10971 .base_node_inst = capture_src.base_node_inst,10969 .base_node_inst = capture_src.base_node_inst,
10972 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },10970 .offset = .{ .switch_tag_capture = capture_src.offset.switch_capture },
10973 };10971 };
10974 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{}'", .{10972 return sema.fail(block, tag_capture_src, "cannot capture tag of non-union type '{f}'", .{
10975 operand_ty.fmt(pt),10973 operand_ty.fmt(pt),
10976 });10974 });
10977 }10975 }
...@@ -11403,7 +11401,7 @@ fn switchCond(...@@ -11403,7 +11401,7 @@ fn switchCond(
11403 .@"enum",11401 .@"enum",
11404 => {11402 => {
11405 if (operand_ty.isSlice(zcu)) {11403 if (operand_ty.isSlice(zcu)) {
11406 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)});11404 return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
11407 }11405 }
11408 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {11406 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
11409 return Air.internedToRef(opv.toIntern());11407 return Air.internedToRef(opv.toIntern());
...@@ -11438,7 +11436,7 @@ fn switchCond(...@@ -11438,7 +11436,7 @@ fn switchCond(
11438 .vector,11436 .vector,
11439 .frame,11437 .frame,
11440 .@"anyframe",11438 .@"anyframe",
11441 => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(pt)}),11439 => return sema.fail(block, src, "switch on type '{f}'", .{operand_ty.fmt(pt)}),
11442 }11440 }
11443}11441}
1144411442
...@@ -11539,7 +11537,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11539,7 +11537,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11539 operand_ty;11537 operand_ty;
1154011538
11541 if (operand_err_set.zigTypeTag(zcu) != .error_union) {11539 if (operand_err_set.zigTypeTag(zcu) != .error_union) {
11542 return sema.fail(block, switch_src, "expected error union type, found '{}'", .{11540 return sema.fail(block, switch_src, "expected error union type, found '{f}'", .{
11543 operand_ty.fmt(pt),11541 operand_ty.fmt(pt),
11544 });11542 });
11545 }11543 }
...@@ -11793,7 +11791,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11793,7 +11791,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11793 // Even if the operand is comptime-known, this `switch` is runtime.11791 // Even if the operand is comptime-known, this `switch` is runtime.
11794 if (try operand_ty.comptimeOnlySema(pt)) {11792 if (try operand_ty.comptimeOnlySema(pt)) {
11795 return sema.failWithOwnedErrorMsg(block, msg: {11793 return sema.failWithOwnedErrorMsg(block, msg: {
11796 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{}'", .{operand_ty.fmt(pt)});11794 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)});
11797 errdefer msg.destroy(gpa);11795 errdefer msg.destroy(gpa);
11798 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});11796 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
11799 break :msg msg;11797 break :msg msg;
...@@ -12017,14 +12015,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12017,14 +12015,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12017 cond_ty,12015 cond_ty,
12018 i,12016 i,
12019 msg,12017 msg,
12020 "unhandled enumeration value: '{}'",12018 "unhandled enumeration value: '{f}'",
12021 .{field_name.fmt(&zcu.intern_pool)},12019 .{field_name.fmt(&zcu.intern_pool)},
12022 );12020 );
12023 }12021 }
12024 try sema.errNote(12022 try sema.errNote(
12025 cond_ty.srcLoc(zcu),12023 cond_ty.srcLoc(zcu),
12026 msg,12024 msg,
12027 "enum '{}' declared here",12025 "enum '{f}' declared here",
12028 .{cond_ty.fmt(pt)},12026 .{cond_ty.fmt(pt)},
12029 );12027 );
12030 break :msg msg;12028 break :msg msg;
...@@ -12236,7 +12234,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12236,7 +12234,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12236 return sema.fail(12234 return sema.fail(
12237 block,12235 block,
12238 src,12236 src,
12239 "else prong required when switching on type '{}'",12237 "else prong required when switching on type '{f}'",
12240 .{cond_ty.fmt(pt)},12238 .{cond_ty.fmt(pt)},
12241 );12239 );
12242 }12240 }
...@@ -12312,7 +12310,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12312,7 +12310,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12312 .@"anyframe",12310 .@"anyframe",
12313 .comptime_float,12311 .comptime_float,
12314 .float,12312 .float,
12315 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{12313 => return sema.fail(block, operand_src, "invalid switch operand type '{f}'", .{
12316 raw_operand_ty.fmt(pt),12314 raw_operand_ty.fmt(pt),
12317 }),12315 }),
12318 }12316 }
...@@ -12841,7 +12839,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12841,7 +12839,7 @@ fn analyzeSwitchRuntimeBlock(
12841 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {12839 if (special.is_inline) switch (operand_ty.zigTypeTag(zcu)) {
12842 .@"enum" => {12840 .@"enum" => {
12843 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {12841 if (operand_ty.isNonexhaustiveEnum(zcu) and !union_originally) {
12844 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{12842 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
12845 operand_ty.fmt(pt),12843 operand_ty.fmt(pt),
12846 });12844 });
12847 }12845 }
...@@ -12897,7 +12895,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12897,7 +12895,7 @@ fn analyzeSwitchRuntimeBlock(
12897 },12895 },
12898 .error_set => {12896 .error_set => {
12899 if (operand_ty.isAnyError(zcu)) {12897 if (operand_ty.isAnyError(zcu)) {
12900 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{12898 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
12901 operand_ty.fmt(pt),12899 operand_ty.fmt(pt),
12902 });12900 });
12903 }12901 }
...@@ -13058,7 +13056,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -13058,7 +13056,7 @@ fn analyzeSwitchRuntimeBlock(
13058 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));13056 cases_extra.appendSliceAssumeCapacity(@ptrCast(case_block.instructions.items));
13059 }13057 }
13060 },13058 },
13061 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{13059 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{f}' for 'inline else'", .{
13062 operand_ty.fmt(pt),13060 operand_ty.fmt(pt),
13063 }),13061 }),
13064 };13062 };
...@@ -13572,7 +13570,7 @@ fn validateErrSetSwitch(...@@ -13572,7 +13570,7 @@ fn validateErrSetSwitch(
13572 try sema.errNote(13570 try sema.errNote(
13573 src,13571 src,
13574 msg,13572 msg,
13575 "unhandled error value: 'error.{}'",13573 "unhandled error value: 'error.{f}'",
13576 .{error_name.fmt(ip)},13574 .{error_name.fmt(ip)},
13577 );13575 );
13578 }13576 }
...@@ -13798,7 +13796,7 @@ fn validateSwitchNoRange(...@@ -13798,7 +13796,7 @@ fn validateSwitchNoRange(
13798 const msg = msg: {13796 const msg = msg: {
13799 const msg = try sema.errMsg(13797 const msg = try sema.errMsg(
13800 operand_src,13798 operand_src,
13801 "ranges not allowed when switching on type '{}'",13799 "ranges not allowed when switching on type '{f}'",
13802 .{operand_ty.fmt(sema.pt)},13800 .{operand_ty.fmt(sema.pt)},
13803 );13801 );
13804 errdefer msg.destroy(sema.gpa);13802 errdefer msg.destroy(sema.gpa);
...@@ -13956,7 +13954,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13956,7 +13954,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13956 .array_type => break :hf field_name.eqlSlice("len", ip),13954 .array_type => break :hf field_name.eqlSlice("len", ip),
13957 else => {},13955 else => {},
13958 }13956 }
13959 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{13957 return sema.fail(block, ty_src, "type '{f}' does not support '@hasField'", .{
13960 ty.fmt(pt),13958 ty.fmt(pt),
13961 });13959 });
13962 };13960 };
...@@ -14145,7 +14143,7 @@ fn zirShl(...@@ -14145,7 +14143,7 @@ fn zirShl(
14145 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14143 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14146 const rhs_elem = try rhs_val.elemValue(pt, i);14144 const rhs_elem = try rhs_val.elemValue(pt, i);
14147 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14145 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
14148 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{14146 return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
14149 rhs_elem.fmtValueSema(pt, sema),14147 rhs_elem.fmtValueSema(pt, sema),
14150 i,14148 i,
14151 scalar_ty.fmt(pt),14149 scalar_ty.fmt(pt),
...@@ -14153,7 +14151,7 @@ fn zirShl(...@@ -14153,7 +14151,7 @@ fn zirShl(
14153 }14151 }
14154 }14152 }
14155 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14153 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14156 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{14154 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
14157 rhs_val.fmtValueSema(pt, sema),14155 rhs_val.fmtValueSema(pt, sema),
14158 scalar_ty.fmt(pt),14156 scalar_ty.fmt(pt),
14159 });14157 });
...@@ -14164,14 +14162,14 @@ fn zirShl(...@@ -14164,14 +14162,14 @@ fn zirShl(
14164 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14162 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14165 const rhs_elem = try rhs_val.elemValue(pt, i);14163 const rhs_elem = try rhs_val.elemValue(pt, i);
14166 if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {14164 if (rhs_elem.compareHetero(.lt, try pt.intValue(scalar_rhs_ty, 0), zcu)) {
14167 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{14165 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
14168 rhs_elem.fmtValueSema(pt, sema),14166 rhs_elem.fmtValueSema(pt, sema),
14169 i,14167 i,
14170 });14168 });
14171 }14169 }
14172 }14170 }
14173 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14171 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14174 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{14172 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
14175 rhs_val.fmtValueSema(pt, sema),14173 rhs_val.fmtValueSema(pt, sema),
14176 });14174 });
14177 }14175 }
...@@ -14326,7 +14324,7 @@ fn zirShr(...@@ -14326,7 +14324,7 @@ fn zirShr(
14326 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14324 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14327 const rhs_elem = try rhs_val.elemValue(pt, i);14325 const rhs_elem = try rhs_val.elemValue(pt, i);
14328 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {14326 if (rhs_elem.compareHetero(.gte, bit_value, zcu)) {
14329 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{14327 return sema.fail(block, rhs_src, "shift amount '{f}' at index '{d}' is too large for operand type '{f}'", .{
14330 rhs_elem.fmtValueSema(pt, sema),14328 rhs_elem.fmtValueSema(pt, sema),
14331 i,14329 i,
14332 scalar_ty.fmt(pt),14330 scalar_ty.fmt(pt),
...@@ -14334,7 +14332,7 @@ fn zirShr(...@@ -14334,7 +14332,7 @@ fn zirShr(
14334 }14332 }
14335 }14333 }
14336 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {14334 } else if (rhs_val.compareHetero(.gte, bit_value, zcu)) {
14337 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{14335 return sema.fail(block, rhs_src, "shift amount '{f}' is too large for operand type '{f}'", .{
14338 rhs_val.fmtValueSema(pt, sema),14336 rhs_val.fmtValueSema(pt, sema),
14339 scalar_ty.fmt(pt),14337 scalar_ty.fmt(pt),
14340 });14338 });
...@@ -14345,14 +14343,14 @@ fn zirShr(...@@ -14345,14 +14343,14 @@ fn zirShr(
14345 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {14343 while (i < rhs_ty.vectorLen(zcu)) : (i += 1) {
14346 const rhs_elem = try rhs_val.elemValue(pt, i);14344 const rhs_elem = try rhs_val.elemValue(pt, i);
14347 if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {14345 if (rhs_elem.compareHetero(.lt, try pt.intValue(rhs_ty.childType(zcu), 0), zcu)) {
14348 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{14346 return sema.fail(block, rhs_src, "shift by negative amount '{f}' at index '{d}'", .{
14349 rhs_elem.fmtValueSema(pt, sema),14347 rhs_elem.fmtValueSema(pt, sema),
14350 i,14348 i,
14351 });14349 });
14352 }14350 }
14353 }14351 }
14354 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {14352 } else if (rhs_val.compareHetero(.lt, try pt.intValue(rhs_ty, 0), zcu)) {
14355 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{14353 return sema.fail(block, rhs_src, "shift by negative amount '{f}'", .{
14356 rhs_val.fmtValueSema(pt, sema),14354 rhs_val.fmtValueSema(pt, sema),
14357 });14355 });
14358 }14356 }
...@@ -14638,11 +14636,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14638,11 +14636,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1463814636
14639 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {14637 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
14640 if (lhs_is_tuple) break :lhs_info undefined;14638 if (lhs_is_tuple) break :lhs_info undefined;
14641 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});14639 return sema.fail(block, lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
14642 };14640 };
14643 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {14641 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
14644 assert(!rhs_is_tuple);14642 assert(!rhs_is_tuple);
14645 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(pt)});14643 return sema.fail(block, rhs_src, "expected indexable; found '{f}'", .{rhs_ty.fmt(pt)});
14646 };14644 };
1464714645
14648 const resolved_elem_ty = t: {14646 const resolved_elem_ty = t: {
...@@ -15095,7 +15093,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15095,7 +15093,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15095 // Analyze the lhs first, to catch the case that someone tried to do exponentiation15093 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
15096 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {15094 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
15097 const msg = msg: {15095 const msg = msg: {
15098 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)});15096 const msg = try sema.errMsg(lhs_src, "expected indexable; found '{f}'", .{lhs_ty.fmt(pt)});
15099 errdefer msg.destroy(sema.gpa);15097 errdefer msg.destroy(sema.gpa);
15100 switch (lhs_ty.zigTypeTag(zcu)) {15098 switch (lhs_ty.zigTypeTag(zcu)) {
15101 .int, .float, .comptime_float, .comptime_int, .vector => {15099 .int, .float, .comptime_float, .comptime_int, .vector => {
...@@ -15227,7 +15225,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15227,7 +15225,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15227 .int, .comptime_int, .float, .comptime_float => false,15225 .int, .comptime_int, .float, .comptime_float => false,
15228 else => true,15226 else => true,
15229 }) {15227 }) {
15230 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)});15228 return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)});
15231 }15229 }
1523215230
15233 if (rhs_scalar_ty.isAnyFloat()) {15231 if (rhs_scalar_ty.isAnyFloat()) {
...@@ -15258,7 +15256,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -15258,7 +15256,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1525815256
15259 switch (rhs_scalar_ty.zigTypeTag(zcu)) {15257 switch (rhs_scalar_ty.zigTypeTag(zcu)) {
15260 .int, .comptime_int, .float, .comptime_float => {},15258 .int, .comptime_int, .float, .comptime_float => {},
15261 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(pt)}),15259 else => return sema.fail(block, src, "negation of type '{f}'", .{rhs_ty.fmt(pt)}),
15262 }15260 }
1526315261
15264 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());15262 const lhs = Air.internedToRef((try sema.splat(rhs_ty, try pt.intValue(rhs_scalar_ty, 0))).toIntern());
...@@ -15332,7 +15330,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15332,7 +15330,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15332 return sema.fail(15330 return sema.fail(
15333 block,15331 block,
15334 src,15332 src,
15335 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",15333 "ambiguous coercion of division operands '{f}' and '{f}'; non-zero remainder '{f}'",
15336 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },15334 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), rem.fmtValueSema(pt, sema) },
15337 );15335 );
15338 }15336 }
...@@ -15384,7 +15382,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15384,7 +15382,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15384 return sema.fail(15382 return sema.fail(
15385 block,15383 block,
15386 src,15384 src,
15387 "division with '{}' and '{}': signed integers must use @divTrunc, @divFloor, or @divExact",15385 "division with '{f}' and '{f}': signed integers must use @divTrunc, @divFloor, or @divExact",
15388 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },15386 .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt) },
15389 );15387 );
15390 }15388 }
...@@ -16046,7 +16044,7 @@ fn zirOverflowArithmetic(...@@ -16046,7 +16044,7 @@ fn zirOverflowArithmetic(
16046 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);16044 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
1604716045
16048 if (dest_ty.scalarType(zcu).zigTypeTag(zcu) != .int) {16046 if (dest_ty.scalarType(zcu).zigTypeTag(zcu) != .int) {
16049 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(pt)});16047 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{f}'", .{dest_ty.fmt(pt)});
16050 }16048 }
1605116049
16052 const maybe_lhs_val = try sema.resolveValue(lhs);16050 const maybe_lhs_val = try sema.resolveValue(lhs);
...@@ -16252,14 +16250,14 @@ fn analyzeArithmetic(...@@ -16252,14 +16250,14 @@ fn analyzeArithmetic(
16252 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");16250 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");
16253 }16251 }
16254 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {16252 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {
16255 return sema.fail(block, src, "incompatible pointer arithmetic operands '{}' and '{}'", .{16253 return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{
16256 lhs_ty.fmt(pt), rhs_ty.fmt(pt),16254 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
16257 });16255 });
16258 }16256 }
1625916257
16260 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);16258 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
16261 if (elem_size == 0) {16259 if (elem_size == 0) {
16262 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{16260 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
16263 lhs_ty.elemType2(zcu).fmt(pt),16261 lhs_ty.elemType2(zcu).fmt(pt),
16264 });16262 });
16265 }16263 }
...@@ -16310,7 +16308,7 @@ fn analyzeArithmetic(...@@ -16310,7 +16308,7 @@ fn analyzeArithmetic(
16310 };16308 };
1631116309
16312 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {16310 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {
16313 return sema.fail(block, src, "pointer arithmetic requires element type '{}' to have runtime bits", .{16311 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
16314 lhs_ty.elemType2(zcu).fmt(pt),16312 lhs_ty.elemType2(zcu).fmt(pt),
16315 });16313 });
16316 }16314 }
...@@ -16714,7 +16712,7 @@ fn zirCmpEq(...@@ -16714,7 +16712,7 @@ fn zirCmpEq(
1671416712
16715 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {16713 if (lhs_ty_tag == .null or rhs_ty_tag == .null) {
16716 const non_null_type = if (lhs_ty_tag == .null) rhs_ty else lhs_ty;16714 const non_null_type = if (lhs_ty_tag == .null) rhs_ty else lhs_ty;
16717 return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(pt)});16715 return sema.fail(block, src, "comparison of '{f}' with null", .{non_null_type.fmt(pt)});
16718 }16716 }
1671916717
16720 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {16718 if (lhs_ty_tag == .@"union" and (rhs_ty_tag == .enum_literal or rhs_ty_tag == .@"enum")) {
...@@ -16771,7 +16769,7 @@ fn analyzeCmpUnionTag(...@@ -16771,7 +16769,7 @@ fn analyzeCmpUnionTag(
16771 const msg = msg: {16769 const msg = msg: {
16772 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});16770 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
16773 errdefer msg.destroy(sema.gpa);16771 errdefer msg.destroy(sema.gpa);
16774 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{}' is not a tagged union", .{union_ty.fmt(pt)});16772 try sema.errNote(union_ty.srcLoc(zcu), msg, "union '{f}' is not a tagged union", .{union_ty.fmt(pt)});
16775 break :msg msg;16773 break :msg msg;
16776 };16774 };
16777 return sema.failWithOwnedErrorMsg(block, msg);16775 return sema.failWithOwnedErrorMsg(block, msg);
...@@ -16857,7 +16855,7 @@ fn analyzeCmp(...@@ -16857,7 +16855,7 @@ fn analyzeCmp(
16857 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };16855 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
16858 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });16856 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
16859 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {16857 if (!resolved_type.isSelfComparable(zcu, is_equality_cmp)) {
16860 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{16858 return sema.fail(block, src, "operator {s} not allowed for type '{f}'", .{
16861 compareOperatorName(op), resolved_type.fmt(pt),16859 compareOperatorName(op), resolved_type.fmt(pt),
16862 });16860 });
16863 }16861 }
...@@ -16966,7 +16964,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -16966,7 +16964,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
16966 .undefined,16964 .undefined,
16967 .null,16965 .null,
16968 .@"opaque",16966 .@"opaque",
16969 => return sema.fail(block, operand_src, "no size available for type '{}'", .{ty.fmt(pt)}),16967 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{ty.fmt(pt)}),
1697016968
16971 .type,16969 .type,
16972 .enum_literal,16970 .enum_literal,
...@@ -17007,7 +17005,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -17007,7 +17005,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
17007 .undefined,17005 .undefined,
17008 .null,17006 .null,
17009 .@"opaque",17007 .@"opaque",
17010 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(pt)}),17008 => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}),
1701117009
17012 .type,17010 .type,
17013 .enum_literal,17011 .enum_literal,
...@@ -18319,7 +18317,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi...@@ -18319,7 +18317,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
18319 return sema.fail(18317 return sema.fail(
18320 block,18318 block,
18321 src,18319 src,
18322 "bit shifting operation expected integer type, found '{}'",18320 "bit shifting operation expected integer type, found '{f}'",
18323 .{operand.fmt(pt)},18321 .{operand.fmt(pt)},
18324 );18322 );
18325}18323}
...@@ -18558,7 +18556,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi...@@ -18558,7 +18556,7 @@ fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
18558 const pt = sema.pt;18556 const pt = sema.pt;
18559 const zcu = pt.zcu;18557 const zcu = pt.zcu;
18560 if (!ty.isSelfComparable(zcu, true)) {18558 if (!ty.isSelfComparable(zcu, true)) {
18561 return sema.fail(block, src, "non-scalar sentinel type '{}'", .{ty.fmt(pt)});18559 return sema.fail(block, src, "non-scalar sentinel type '{f}'", .{ty.fmt(pt)});
18562 }18560 }
18563}18561}
1856418562
...@@ -18608,7 +18606,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -18608,7 +18606,7 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
18608 const zcu = pt.zcu;18606 const zcu = pt.zcu;
18609 switch (ty.zigTypeTag(zcu)) {18607 switch (ty.zigTypeTag(zcu)) {
18610 .error_set, .error_union, .undefined => return,18608 .error_set, .error_union, .undefined => return,
18611 else => return sema.fail(block, src, "expected error union type, found '{}'", .{18609 else => return sema.fail(block, src, "expected error union type, found '{f}'", .{
18612 ty.fmt(pt),18610 ty.fmt(pt),
18613 }),18611 }),
18614 }18612 }
...@@ -18752,7 +18750,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -18752,7 +18750,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
18752 const pt = sema.pt;18750 const pt = sema.pt;
18753 const zcu = pt.zcu;18751 const zcu = pt.zcu;
18754 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18752 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18755 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{18753 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
18756 err_union_ty.fmt(pt),18754 err_union_ty.fmt(pt),
18757 });18755 });
18758 }18756 }
...@@ -18812,7 +18810,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -18812,7 +18810,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
18812 const pt = sema.pt;18810 const pt = sema.pt;
18813 const zcu = pt.zcu;18811 const zcu = pt.zcu;
18814 if (err_union_ty.zigTypeTag(zcu) != .error_union) {18812 if (err_union_ty.zigTypeTag(zcu) != .error_union) {
18815 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{18813 return sema.fail(parent_block, operand_src, "expected error union type, found '{f}'", .{
18816 err_union_ty.fmt(pt),18814 err_union_ty.fmt(pt),
18817 });18815 });
18818 }18816 }
...@@ -19010,7 +19008,7 @@ fn zirRetImplicit(...@@ -19010,7 +19008,7 @@ fn zirRetImplicit(
19010 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);19008 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
19011 if (base_tag == .noreturn) {19009 if (base_tag == .noreturn) {
19012 const msg = msg: {19010 const msg = msg: {
19013 const msg = try sema.errMsg(ret_ty_src, "function declared '{}' implicitly returns", .{19011 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{
19014 sema.fn_ret_ty.fmt(pt),19012 sema.fn_ret_ty.fmt(pt),
19015 });19013 });
19016 errdefer msg.destroy(sema.gpa);19014 errdefer msg.destroy(sema.gpa);
...@@ -19020,7 +19018,7 @@ fn zirRetImplicit(...@@ -19020,7 +19018,7 @@ fn zirRetImplicit(
19020 return sema.failWithOwnedErrorMsg(block, msg);19018 return sema.failWithOwnedErrorMsg(block, msg);
19021 } else if (base_tag != .void) {19019 } else if (base_tag != .void) {
19022 const msg = msg: {19020 const msg = msg: {
19023 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{}' implicitly returns", .{19021 const msg = try sema.errMsg(ret_ty_src, "function with non-void return type '{f}' implicitly returns", .{
19024 sema.fn_ret_ty.fmt(pt),19022 sema.fn_ret_ty.fmt(pt),
19025 });19023 });
19026 errdefer msg.destroy(sema.gpa);19024 errdefer msg.destroy(sema.gpa);
...@@ -19409,13 +19407,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19409,13 +19407,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1940919407
19410 if (host_size != 0) {19408 if (host_size != 0) {
19411 if (bit_offset >= host_size * 8) {19409 if (bit_offset >= host_size * 8) {
19412 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{19410 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{
19413 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,19411 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
19414 });19412 });
19415 }19413 }
19416 const elem_bit_size = try elem_ty.bitSizeSema(pt);19414 const elem_bit_size = try elem_ty.bitSizeSema(pt);
19417 if (elem_bit_size > host_size * 8 - bit_offset) {19415 if (elem_bit_size > host_size * 8 - bit_offset) {
19418 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{19416 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{
19419 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,19417 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
19420 });19418 });
19421 }19419 }
...@@ -19430,7 +19428,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19430,7 +19428,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19430 } else if (inst_data.size == .c) {19428 } else if (inst_data.size == .c) {
19431 if (!try sema.validateExternType(elem_ty, .other)) {19429 if (!try sema.validateExternType(elem_ty, .other)) {
19432 const msg = msg: {19430 const msg = msg: {
19433 const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(pt)});19431 const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
19434 errdefer msg.destroy(sema.gpa);19432 errdefer msg.destroy(sema.gpa);
1943519433
19436 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);19434 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
...@@ -19447,7 +19445,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19447,7 +19445,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1944719445
19448 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {19446 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {
19449 return sema.failWithOwnedErrorMsg(block, msg: {19447 return sema.failWithOwnedErrorMsg(block, msg: {
19450 const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{}'", .{elem_ty.fmt(pt)});19448 const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)});
19451 errdefer msg.destroy(sema.gpa);19449 errdefer msg.destroy(sema.gpa);
19452 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);19450 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);
19453 break :msg msg;19451 break :msg msg;
...@@ -19616,7 +19614,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19616,7 +19614,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19616 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;19614 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
19617 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);19615 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
19618 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {19616 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
19619 return sema.fail(block, ty_src, "expected union type, found '{}'", .{union_ty.fmt(pt)});19617 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
19620 }19618 }
19621 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });19619 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });
19622 const init = try sema.resolveInst(extra.init);19620 const init = try sema.resolveInst(extra.init);
...@@ -19779,7 +19777,7 @@ fn zirStructInit(...@@ -19779,7 +19777,7 @@ fn zirStructInit(
19779 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});19777 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
19780 errdefer msg.destroy(sema.gpa);19778 errdefer msg.destroy(sema.gpa);
1978119779
19782 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{}' declared here", .{19780 try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{f}' declared here", .{
19783 field_name.fmt(ip),19781 field_name.fmt(ip),
19784 });19782 });
19785 try sema.addDeclaredHereNote(msg, resolved_ty);19783 try sema.addDeclaredHereNote(msg, resolved_ty);
...@@ -19898,7 +19896,7 @@ fn finishStructInit(...@@ -19898,7 +19896,7 @@ fn finishStructInit(
19898 const field_init = struct_type.fieldInit(ip, i);19896 const field_init = struct_type.fieldInit(ip, i);
19899 if (field_init == .none) {19897 if (field_init == .none) {
19900 const field_name = struct_type.field_names.get(ip)[i];19898 const field_name = struct_type.field_names.get(ip)[i];
19901 const template = "missing struct field: {}";19899 const template = "missing struct field: {f}";
19902 const args = .{field_name.fmt(ip)};19900 const args = .{field_name.fmt(ip)};
19903 if (root_msg) |msg| {19901 if (root_msg) |msg| {
19904 try sema.errNote(init_src, msg, template, args);19902 try sema.errNote(init_src, msg, template, args);
...@@ -20513,7 +20511,7 @@ fn fieldType(...@@ -20513,7 +20511,7 @@ fn fieldType(
20513 },20511 },
20514 else => {},20512 else => {},
20515 }20513 }
20516 return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{20514 return sema.fail(block, ty_src, "expected struct or union; found '{f}'", .{
20517 cur_ty.fmt(pt),20515 cur_ty.fmt(pt),
20518 });20516 });
20519 }20517 }
...@@ -20560,7 +20558,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20560,7 +20558,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20560 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);20558 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
20561 const ty = try sema.resolveType(block, operand_src, inst_data.operand);20559 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
20562 if (ty.isNoReturn(zcu)) {20560 if (ty.isNoReturn(zcu)) {
20563 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.pt)});20561 return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)});
20564 }20562 }
20565 const val = try ty.lazyAbiAlignment(sema.pt);20563 const val = try ty.lazyAbiAlignment(sema.pt);
20566 return Air.internedToRef(val.toIntern());20564 return Air.internedToRef(val.toIntern());
...@@ -20638,7 +20636,7 @@ fn zirAbs(...@@ -20638,7 +20636,7 @@ fn zirAbs(
20638 else => return sema.fail(20636 else => return sema.fail(
20639 block,20637 block,
20640 operand_src,20638 operand_src,
20641 "expected integer, float, or vector of either integers or floats, found '{}'",20639 "expected integer, float, or vector of either integers or floats, found '{f}'",
20642 .{operand_ty.fmt(pt)},20640 .{operand_ty.fmt(pt)},
20643 ),20641 ),
20644 };20642 };
...@@ -20707,7 +20705,7 @@ fn zirUnaryMath(...@@ -20707,7 +20705,7 @@ fn zirUnaryMath(
20707 else => return sema.fail(20705 else => return sema.fail(
20708 block,20706 block,
20709 operand_src,20707 operand_src,
20710 "expected vector of floats or float type, found '{}'",20708 "expected vector of floats or float type, found '{f}'",
20711 .{operand_ty.fmt(pt)},20709 .{operand_ty.fmt(pt)},
20712 ),20710 ),
20713 }20711 }
...@@ -20736,8 +20734,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20736,8 +20734,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20736 },20734 },
20737 .@"enum" => operand_ty,20735 .@"enum" => operand_ty,
20738 .@"union" => operand_ty.unionTagType(zcu) orelse20736 .@"union" => operand_ty.unionTagType(zcu) orelse
20739 return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(pt)}),20737 return sema.fail(block, src, "union '{f}' is untagged", .{operand_ty.fmt(pt)}),
20740 else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{20738 else => return sema.fail(block, operand_src, "expected enum or union; found '{f}'", .{
20741 operand_ty.fmt(pt),20739 operand_ty.fmt(pt),
20742 }),20740 }),
20743 };20741 };
...@@ -20745,7 +20743,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20745,7 +20743,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20745 // TODO I don't think this is the correct way to handle this but20743 // TODO I don't think this is the correct way to handle this but
20746 // it prevents a crash.20744 // it prevents a crash.
20747 // https://github.com/ziglang/zig/issues/1590920745 // https://github.com/ziglang/zig/issues/15909
20748 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{20746 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{f}'", .{
20749 enum_ty.fmt(pt),20747 enum_ty.fmt(pt),
20750 });20748 });
20751 }20749 }
...@@ -20753,7 +20751,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20753,7 +20751,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20753 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {20751 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
20754 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {20752 const field_index = enum_ty.enumTagFieldIndex(val, zcu) orelse {
20755 const msg = msg: {20753 const msg = msg: {
20756 const msg = try sema.errMsg(src, "no field with value '{}' in enum '{}'", .{20754 const msg = try sema.errMsg(src, "no field with value '{f}' in enum '{f}'", .{
20757 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),20755 val.fmtValueSema(pt, sema), enum_ty.fmt(pt),
20758 });20756 });
20759 errdefer msg.destroy(sema.gpa);20757 errdefer msg.destroy(sema.gpa);
...@@ -20940,7 +20938,7 @@ fn zirReify(...@@ -20940,7 +20938,7 @@ fn zirReify(
20940 } else if (ptr_size == .c) {20938 } else if (ptr_size == .c) {
20941 if (!try sema.validateExternType(elem_ty, .other)) {20939 if (!try sema.validateExternType(elem_ty, .other)) {
20942 const msg = msg: {20940 const msg = msg: {
20943 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(pt)});20941 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20944 errdefer msg.destroy(gpa);20942 errdefer msg.destroy(gpa);
2094520943
20946 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);20944 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);
...@@ -21053,7 +21051,7 @@ fn zirReify(...@@ -21053,7 +21051,7 @@ fn zirReify(
21053 _ = try pt.getErrorValue(name);21051 _ = try pt.getErrorValue(name);
21054 const gop = names.getOrPutAssumeCapacity(name);21052 const gop = names.getOrPutAssumeCapacity(name);
21055 if (gop.found_existing) {21053 if (gop.found_existing) {
21056 return sema.fail(block, src, "duplicate error '{}'", .{21054 return sema.fail(block, src, "duplicate error '{f}'", .{
21057 name.fmt(ip),21055 name.fmt(ip),
21058 });21056 });
21059 }21057 }
...@@ -21401,7 +21399,7 @@ fn reifyEnum(...@@ -21401,7 +21399,7 @@ fn reifyEnum(
2140121399
21402 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {21400 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {
21403 // TODO: better source location21401 // TODO: better source location
21404 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{21402 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{
21405 field_name.fmt(ip),21403 field_name.fmt(ip),
21406 field_value_val.fmtValueSema(pt, sema),21404 field_value_val.fmtValueSema(pt, sema),
21407 tag_ty.fmt(pt),21405 tag_ty.fmt(pt),
...@@ -21412,14 +21410,14 @@ fn reifyEnum(...@@ -21412,14 +21410,14 @@ fn reifyEnum(
21412 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {21410 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {
21413 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {21411 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21414 .name => msg: {21412 .name => msg: {
21415 const msg = try sema.errMsg(src, "duplicate enum field '{}'", .{field_name.fmt(ip)});21413 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21416 errdefer msg.destroy(gpa);21414 errdefer msg.destroy(gpa);
21417 _ = conflict.prev_field_idx; // TODO: this note is incorrect21415 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21418 try sema.errNote(src, msg, "other field here", .{});21416 try sema.errNote(src, msg, "other field here", .{});
21419 break :msg msg;21417 break :msg msg;
21420 },21418 },
21421 .value => msg: {21419 .value => msg: {
21422 const msg = try sema.errMsg(src, "enum tag value {} already taken", .{field_value_val.fmtValueSema(pt, sema)});21420 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});
21423 errdefer msg.destroy(gpa);21421 errdefer msg.destroy(gpa);
21424 _ = conflict.prev_field_idx; // TODO: this note is incorrect21422 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21425 try sema.errNote(src, msg, "other enum tag value here", .{});21423 try sema.errNote(src, msg, "other enum tag value here", .{});
...@@ -21567,13 +21565,13 @@ fn reifyUnion(...@@ -21567,13 +21565,13 @@ fn reifyUnion(
2156721565
21568 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {21566 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
21569 // TODO: better source location21567 // TODO: better source location
21570 return sema.fail(block, src, "no field named '{}' in enum '{}'", .{21568 return sema.fail(block, src, "no field named '{f}' in enum '{f}'", .{
21571 field_name.fmt(ip), enum_tag_ty.fmt(pt),21569 field_name.fmt(ip), enum_tag_ty.fmt(pt),
21572 });21570 });
21573 };21571 };
21574 if (seen_tags.isSet(enum_index)) {21572 if (seen_tags.isSet(enum_index)) {
21575 // TODO: better source location21573 // TODO: better source location
21576 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});21574 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21577 }21575 }
21578 seen_tags.set(enum_index);21576 seen_tags.set(enum_index);
2157921577
...@@ -21594,7 +21592,7 @@ fn reifyUnion(...@@ -21594,7 +21592,7 @@ fn reifyUnion(
21594 var it = seen_tags.iterator(.{ .kind = .unset });21592 var it = seen_tags.iterator(.{ .kind = .unset });
21595 while (it.next()) |enum_index| {21593 while (it.next()) |enum_index| {
21596 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);21594 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);
21597 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{}' missing, declared here", .{21595 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
21598 field_name.fmt(ip),21596 field_name.fmt(ip),
21599 });21597 });
21600 }21598 }
...@@ -21619,7 +21617,7 @@ fn reifyUnion(...@@ -21619,7 +21617,7 @@ fn reifyUnion(
21619 const gop = field_names.getOrPutAssumeCapacity(field_name);21617 const gop = field_names.getOrPutAssumeCapacity(field_name);
21620 if (gop.found_existing) {21618 if (gop.found_existing) {
21621 // TODO: better source location21619 // TODO: better source location
21622 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});21620 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21623 }21621 }
2162421622
21625 field_ty.* = field_type_val.toIntern();21623 field_ty.* = field_type_val.toIntern();
...@@ -21651,7 +21649,7 @@ fn reifyUnion(...@@ -21651,7 +21649,7 @@ fn reifyUnion(
21651 }21649 }
21652 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {21650 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
21653 return sema.failWithOwnedErrorMsg(block, msg: {21651 return sema.failWithOwnedErrorMsg(block, msg: {
21654 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21652 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21655 errdefer msg.destroy(gpa);21653 errdefer msg.destroy(gpa);
2165621654
21657 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);21655 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);
...@@ -21661,7 +21659,7 @@ fn reifyUnion(...@@ -21661,7 +21659,7 @@ fn reifyUnion(
21661 });21659 });
21662 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21660 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21663 return sema.failWithOwnedErrorMsg(block, msg: {21661 return sema.failWithOwnedErrorMsg(block, msg: {
21664 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21662 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21665 errdefer msg.destroy(gpa);21663 errdefer msg.destroy(gpa);
2166621664
21667 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21665 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -21743,7 +21741,7 @@ fn reifyTuple(...@@ -21743,7 +21741,7 @@ fn reifyTuple(
21743 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(21741 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
21744 block,21742 block,
21745 src,21743 src,
21746 "tuple cannot have non-numeric field '{}'",21744 "tuple cannot have non-numeric field '{f}'",
21747 .{field_name.fmt(ip)},21745 .{field_name.fmt(ip)},
21748 );21746 );
21749 if (field_name_index != field_idx) {21747 if (field_name_index != field_idx) {
...@@ -21921,7 +21919,7 @@ fn reifyStruct(...@@ -21921,7 +21919,7 @@ fn reifyStruct(
21921 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);21919 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21922 if (struct_type.addFieldName(ip, field_name)) |prev_index| {21920 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
21923 _ = prev_index; // TODO: better source location21921 _ = prev_index; // TODO: better source location
21924 return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)});21922 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21925 }21923 }
2192621924
21927 if (any_aligned_fields) {21925 if (any_aligned_fields) {
...@@ -21990,7 +21988,7 @@ fn reifyStruct(...@@ -21990,7 +21988,7 @@ fn reifyStruct(
21990 }21988 }
21991 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {21989 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
21992 return sema.failWithOwnedErrorMsg(block, msg: {21990 return sema.failWithOwnedErrorMsg(block, msg: {
21993 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});21991 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21994 errdefer msg.destroy(gpa);21992 errdefer msg.destroy(gpa);
2199521993
21996 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);21994 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);
...@@ -22000,7 +21998,7 @@ fn reifyStruct(...@@ -22000,7 +21998,7 @@ fn reifyStruct(
22000 });21998 });
22001 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21999 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
22002 return sema.failWithOwnedErrorMsg(block, msg: {22000 return sema.failWithOwnedErrorMsg(block, msg: {
22003 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});22001 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
22004 errdefer msg.destroy(gpa);22002 errdefer msg.destroy(gpa);
2200522003
22006 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);22004 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
...@@ -22077,7 +22075,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -22077,7 +22075,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2207722075
22078 if (!try sema.validateExternType(arg_ty, .param_ty)) {22076 if (!try sema.validateExternType(arg_ty, .param_ty)) {
22079 const msg = msg: {22077 const msg = msg: {
22080 const msg = try sema.errMsg(ty_src, "cannot get '{}' from variadic argument", .{arg_ty.fmt(sema.pt)});22078 const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)});
22081 errdefer msg.destroy(sema.gpa);22079 errdefer msg.destroy(sema.gpa);
2208222080
22083 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);22081 try sema.explainWhyTypeIsNotExtern(msg, ty_src, arg_ty, .param_ty);
...@@ -22136,7 +22134,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -22136,7 +22134,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
22136 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);22134 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
22137 const ty = try sema.resolveType(block, ty_src, inst_data.operand);22135 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
2213822136
22139 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{}", .{ty.fmt(pt)}, .no_embedded_nulls);22137 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls);
22140 return sema.addNullTerminatedStrLit(type_name);22138 return sema.addNullTerminatedStrLit(type_name);
22141}22139}
2214222140
...@@ -22270,7 +22268,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22270,7 +22268,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2227022268
22271 if (ptr_ty.isSlice(zcu)) {22269 if (ptr_ty.isSlice(zcu)) {
22272 const msg = msg: {22270 const msg = msg: {
22273 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(pt)});22271 const msg = try sema.errMsg(src, "integer cannot be converted to slice type '{f}'", .{ptr_ty.fmt(pt)});
22274 errdefer msg.destroy(sema.gpa);22272 errdefer msg.destroy(sema.gpa);
22275 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});22273 try sema.errNote(src, msg, "slice length cannot be inferred from address", .{});
22276 break :msg msg;22274 break :msg msg;
...@@ -22297,7 +22295,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22297,7 +22295,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22297 }22295 }
22298 if (try ptr_ty.comptimeOnlySema(pt)) {22296 if (try ptr_ty.comptimeOnlySema(pt)) {
22299 return sema.failWithOwnedErrorMsg(block, msg: {22297 return sema.failWithOwnedErrorMsg(block, msg: {
22300 const msg = try sema.errMsg(src, "pointer to comptime-only type '{}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)});22298 const msg = try sema.errMsg(src, "pointer to comptime-only type '{f}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)});
22301 errdefer msg.destroy(sema.gpa);22299 errdefer msg.destroy(sema.gpa);
2230222300
22303 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);22301 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);
...@@ -22354,7 +22352,7 @@ fn ptrFromIntVal(...@@ -22354,7 +22352,7 @@ fn ptrFromIntVal(
22354 }22352 }
22355 const addr = try operand_val.toUnsignedIntSema(pt);22353 const addr = try operand_val.toUnsignedIntSema(pt);
22356 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)22354 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)
22357 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(pt)});22355 return sema.fail(block, operand_src, "pointer type '{f}' does not allow address zero", .{ptr_ty.fmt(pt)});
22358 if (addr != 0 and ptr_align != .none) {22356 if (addr != 0 and ptr_align != .none) {
22359 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|22357 const masked_addr = if (ptr_ty.childType(zcu).fnPtrMaskOrNull(zcu)) |mask|
22360 addr & mask22358 addr & mask
...@@ -22407,8 +22405,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22407,8 +22405,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22407 errdefer msg.destroy(sema.gpa);22405 errdefer msg.destroy(sema.gpa);
22408 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);22406 const dest_payload_ty = dest_ty.errorUnionPayload(zcu);
22409 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);22407 const operand_payload_ty = operand_ty.errorUnionPayload(zcu);
22410 try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)});22408 try sema.errNote(src, msg, "destination payload is '{f}'", .{dest_payload_ty.fmt(pt)});
22411 try sema.errNote(src, msg, "operand payload is '{}'", .{operand_payload_ty.fmt(pt)});22409 try sema.errNote(src, msg, "operand payload is '{f}'", .{operand_payload_ty.fmt(pt)});
22412 try addDeclaredHereNote(sema, msg, dest_ty);22410 try addDeclaredHereNote(sema, msg, dest_ty);
22413 try addDeclaredHereNote(sema, msg, operand_ty);22411 try addDeclaredHereNote(sema, msg, operand_ty);
22414 break :msg msg;22412 break :msg msg;
...@@ -22453,7 +22451,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22453,7 +22451,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22453 break :disjoint true;22451 break :disjoint true;
22454 };22452 };
22455 if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) {22453 if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) {
22456 return sema.fail(block, src, "error sets '{}' and '{}' have no common errors", .{22454 return sema.fail(block, src, "error sets '{f}' and '{f}' have no common errors", .{
22457 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),22455 operand_err_ty.fmt(pt), dest_err_ty.fmt(pt),
22458 });22456 });
22459 }22457 }
...@@ -22473,7 +22471,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22473,7 +22471,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22473 };22471 };
2247422472
22475 if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) {22473 if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) {
22476 return sema.fail(block, src, "'error.{}' not a member of error set '{}'", .{22474 return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{
22477 err_name.fmt(ip), dest_err_ty.fmt(pt),22475 err_name.fmt(ip), dest_err_ty.fmt(pt),
22478 });22476 });
22479 }22477 }
...@@ -22633,13 +22631,15 @@ fn ptrCastFull(...@@ -22633,13 +22631,15 @@ fn ptrCastFull(
22633 const src_elem_size = src_elem_ty.abiSize(zcu);22631 const src_elem_size = src_elem_ty.abiSize(zcu);
22634 const dest_elem_size = dest_elem_ty.abiSize(zcu);22632 const dest_elem_size = dest_elem_ty.abiSize(zcu);
22635 if (dest_elem_size == 0) {22633 if (dest_elem_size == 0) {
22636 return sema.fail(block, src, "cannot infer length of slice of zero-bit '{}' from '{}'", .{ dest_elem_ty.fmt(pt), operand_ty.fmt(pt) });22634 return sema.fail(block, src, "cannot infer length of slice of zero-bit '{f}' from '{f}'", .{
22635 dest_elem_ty.fmt(pt), operand_ty.fmt(pt),
22636 });
22637 }22637 }
22638 if (opt_src_len) |src_len| {22638 if (opt_src_len) |src_len| {
22639 const bytes = src_len * src_elem_size;22639 const bytes = src_len * src_elem_size;
22640 const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) {22640 const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) {
22641 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),22641 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),
22642 .one => return sema.fail(block, src, "type '{}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),22642 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22643 else => unreachable,22643 else => unreachable,
22644 };22644 };
22645 break :len .{ .constant = dest_len };22645 break :len .{ .constant = dest_len };
...@@ -22657,7 +22657,9 @@ fn ptrCastFull(...@@ -22657,7 +22657,9 @@ fn ptrCastFull(
22657 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.22657 // The source value has `src_len * src_base_per_elem` values of type `src_base_ty`.
22658 // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`.22658 // The result value will have `dest_len * dest_base_per_elem` values of type `dest_base_ty`.
22659 if (dest_base_ty.toIntern() != src_base_ty.toIntern()) {22659 if (dest_base_ty.toIntern() != src_base_ty.toIntern()) {
22660 return sema.fail(block, src, "cannot infer length of comptime-only '{}' from incompatible '{}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });22660 return sema.fail(block, src, "cannot infer length of comptime-only '{f}' from incompatible '{f}'", .{
22661 dest_ty.fmt(pt), operand_ty.fmt(pt),
22662 });
22661 }22663 }
22662 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is22664 // `src_base_ty` is comptime-only, so `src_elem_ty` is comptime-only, so `operand_ty` is
22663 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.22665 // comptime-only, so `operand` is comptime-known, so `opt_src_len` is non-`null`.
...@@ -22665,7 +22667,7 @@ fn ptrCastFull(...@@ -22665,7 +22667,7 @@ fn ptrCastFull(
22665 const base_len = src_len * src_base_per_elem;22667 const base_len = src_len * src_base_per_elem;
22666 const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) {22668 const dest_len = std.math.divExact(u64, base_len, dest_base_per_elem) catch switch (src_info.flags.size) {
22667 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),22669 .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}),
22668 .one => return sema.fail(block, src, "type '{}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),22670 .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}),
22669 else => unreachable,22671 else => unreachable,
22670 };22672 };
22671 break :len .{ .constant = dest_len };22673 break :len .{ .constant = dest_len };
...@@ -22726,7 +22728,7 @@ fn ptrCastFull(...@@ -22726,7 +22728,7 @@ fn ptrCastFull(
22726 );22728 );
22727 if (imc_res == .ok) break :check_child;22729 if (imc_res == .ok) break :check_child;
22728 return sema.failWithOwnedErrorMsg(block, msg: {22730 return sema.failWithOwnedErrorMsg(block, msg: {
22729 const msg = try sema.errMsg(src, "pointer element type '{}' cannot coerce into element type '{}'", .{22731 const msg = try sema.errMsg(src, "pointer element type '{f}' cannot coerce into element type '{f}'", .{
22730 src_child.fmt(pt), dest_child.fmt(pt),22732 src_child.fmt(pt), dest_child.fmt(pt),
22731 });22733 });
22732 errdefer msg.destroy(sema.gpa);22734 errdefer msg.destroy(sema.gpa);
...@@ -22753,11 +22755,11 @@ fn ptrCastFull(...@@ -22753,11 +22755,11 @@ fn ptrCastFull(
22753 }22755 }
22754 return sema.failWithOwnedErrorMsg(block, msg: {22756 return sema.failWithOwnedErrorMsg(block, msg: {
22755 const msg = if (src_info.sentinel == .none) blk: {22757 const msg = if (src_info.sentinel == .none) blk: {
22756 break :blk try sema.errMsg(src, "destination pointer requires '{}' sentinel", .{22758 break :blk try sema.errMsg(src, "destination pointer requires '{f}' sentinel", .{
22757 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22759 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22758 });22760 });
22759 } else blk: {22761 } else blk: {
22760 break :blk try sema.errMsg(src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{22762 break :blk try sema.errMsg(src, "pointer sentinel '{f}' cannot coerce into pointer sentinel '{f}'", .{
22761 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),22763 Value.fromInterned(src_info.sentinel).fmtValueSema(pt, sema),
22762 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),22764 Value.fromInterned(dest_info.sentinel).fmtValueSema(pt, sema),
22763 });22765 });
...@@ -22799,7 +22801,7 @@ fn ptrCastFull(...@@ -22799,7 +22801,7 @@ fn ptrCastFull(
22799 if (dest_allows_zero) break :check_allowzero;22801 if (dest_allows_zero) break :check_allowzero;
2280022802
22801 return sema.failWithOwnedErrorMsg(block, msg: {22803 return sema.failWithOwnedErrorMsg(block, msg: {
22802 const msg = try sema.errMsg(src, "'{}' could have null values which are illegal in type '{}'", .{22804 const msg = try sema.errMsg(src, "'{f}' could have null values which are illegal in type '{f}'", .{
22803 operand_ty.fmt(pt),22805 operand_ty.fmt(pt),
22804 dest_ty.fmt(pt),22806 dest_ty.fmt(pt),
22805 });22807 });
...@@ -22827,10 +22829,10 @@ fn ptrCastFull(...@@ -22827,10 +22829,10 @@ fn ptrCastFull(
22827 return sema.failWithOwnedErrorMsg(block, msg: {22829 return sema.failWithOwnedErrorMsg(block, msg: {
22828 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});22830 const msg = try sema.errMsg(src, "{s} increases pointer alignment", .{operation});
22829 errdefer msg.destroy(sema.gpa);22831 errdefer msg.destroy(sema.gpa);
22830 try sema.errNote(operand_src, msg, "'{}' has alignment '{d}'", .{22832 try sema.errNote(operand_src, msg, "'{f}' has alignment '{d}'", .{
22831 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,22833 operand_ty.fmt(pt), src_align.toByteUnits() orelse 0,
22832 });22834 });
22833 try sema.errNote(src, msg, "'{}' has alignment '{d}'", .{22835 try sema.errNote(src, msg, "'{f}' has alignment '{d}'", .{
22834 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,22836 dest_ty.fmt(pt), dest_align.toByteUnits() orelse 0,
22835 });22837 });
22836 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});22838 try sema.errNote(src, msg, "use @alignCast to assert pointer alignment", .{});
...@@ -22844,10 +22846,10 @@ fn ptrCastFull(...@@ -22844,10 +22846,10 @@ fn ptrCastFull(
22844 return sema.failWithOwnedErrorMsg(block, msg: {22846 return sema.failWithOwnedErrorMsg(block, msg: {
22845 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});22847 const msg = try sema.errMsg(src, "{s} changes pointer address space", .{operation});
22846 errdefer msg.destroy(sema.gpa);22848 errdefer msg.destroy(sema.gpa);
22847 try sema.errNote(operand_src, msg, "'{}' has address space '{s}'", .{22849 try sema.errNote(operand_src, msg, "'{f}' has address space '{s}'", .{
22848 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),22850 operand_ty.fmt(pt), @tagName(src_info.flags.address_space),
22849 });22851 });
22850 try sema.errNote(src, msg, "'{}' has address space '{s}'", .{22852 try sema.errNote(src, msg, "'{f}' has address space '{s}'", .{
22851 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),22853 dest_ty.fmt(pt), @tagName(dest_info.flags.address_space),
22852 });22854 });
22853 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});22855 try sema.errNote(src, msg, "use @addrSpaceCast to cast pointer address space", .{});
...@@ -22914,7 +22916,7 @@ fn ptrCastFull(...@@ -22914,7 +22916,7 @@ fn ptrCastFull(
2291422916
22915 if (operand_val.isNull(zcu)) {22917 if (operand_val.isNull(zcu)) {
22916 if (!dest_ty.ptrAllowsZero(zcu)) {22918 if (!dest_ty.ptrAllowsZero(zcu)) {
22917 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(pt)});22919 return sema.fail(block, operand_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
22918 }22920 }
22919 if (dest_ty.zigTypeTag(zcu) == .optional) {22921 if (dest_ty.zigTypeTag(zcu) == .optional) {
22920 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());22922 return Air.internedToRef((try pt.nullValue(dest_ty)).toIntern());
...@@ -23205,7 +23207,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23205,7 +23207,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23205 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;23207 const operand_is_vector = operand_ty.zigTypeTag(zcu) == .vector;
23206 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;23208 const dest_is_vector = dest_ty.zigTypeTag(zcu) == .vector;
23207 if (operand_is_vector != dest_is_vector) {23209 if (operand_is_vector != dest_is_vector) {
23208 return sema.fail(block, operand_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });23210 return sema.fail(block, operand_src, "expected type '{f}', found '{f}'", .{ dest_ty.fmt(pt), operand_ty.fmt(pt) });
23209 }23211 }
2321023212
23211 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {23213 if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) {
...@@ -23225,7 +23227,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23225,7 +23227,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23225 }23227 }
2322623228
23227 if (operand_info.signedness != dest_info.signedness) {23229 if (operand_info.signedness != dest_info.signedness) {
23228 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{23230 return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{
23229 @tagName(dest_info.signedness), operand_ty.fmt(pt),23231 @tagName(dest_info.signedness), operand_ty.fmt(pt),
23230 });23232 });
23231 }23233 }
...@@ -23234,7 +23236,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23234,7 +23236,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23234 const msg = msg: {23236 const msg = msg: {
23235 const msg = try sema.errMsg(23237 const msg = try sema.errMsg(
23236 src,23238 src,
23237 "destination type '{}' has more bits than source type '{}'",23239 "destination type '{f}' has more bits than source type '{f}'",
23238 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },23240 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },
23239 );23241 );
23240 errdefer msg.destroy(sema.gpa);23242 errdefer msg.destroy(sema.gpa);
...@@ -23352,7 +23354,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -23352,7 +23354,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
23352 return sema.fail(23354 return sema.fail(
23353 block,23355 block,
23354 operand_src,23356 operand_src,
23355 "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits",23357 "@byteSwap requires the number of bits to be evenly divisible by 8, but {f} has {} bits",
23356 .{ scalar_ty.fmt(pt), bits },23358 .{ scalar_ty.fmt(pt), bits },
23357 );23359 );
23358 }23360 }
...@@ -23472,7 +23474,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -23472,7 +23474,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
23472 try ty.resolveLayout(pt);23474 try ty.resolveLayout(pt);
23473 switch (ty.zigTypeTag(zcu)) {23475 switch (ty.zigTypeTag(zcu)) {
23474 .@"struct" => {},23476 .@"struct" => {},
23475 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),23477 else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}),
23476 }23478 }
2347723479
23478 const field_index = if (ty.isTuple(zcu)) blk: {23480 const field_index = if (ty.isTuple(zcu)) blk: {
...@@ -23507,7 +23509,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com...@@ -23507,7 +23509,7 @@ fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Com
23507 const zcu = pt.zcu;23509 const zcu = pt.zcu;
23508 switch (ty.zigTypeTag(zcu)) {23510 switch (ty.zigTypeTag(zcu)) {
23509 .@"struct", .@"enum", .@"union", .@"opaque" => return,23511 .@"struct", .@"enum", .@"union", .@"opaque" => return,
23510 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(pt)}),23512 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{f}'", .{ty.fmt(pt)}),
23511 }23513 }
23512}23514}
2351323515
...@@ -23518,7 +23520,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr...@@ -23518,7 +23520,7 @@ fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileEr
23518 switch (ty.zigTypeTag(zcu)) {23520 switch (ty.zigTypeTag(zcu)) {
23519 .comptime_int => return true,23521 .comptime_int => return true,
23520 .int => return false,23522 .int => return false,
23521 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(pt)}),23523 else => return sema.fail(block, src, "expected integer type, found '{f}'", .{ty.fmt(pt)}),
23522 }23524 }
23523}23525}
2352423526
...@@ -23572,7 +23574,7 @@ fn checkPtrOperand(...@@ -23572,7 +23574,7 @@ fn checkPtrOperand(
23572 const msg = msg: {23574 const msg = msg: {
23573 const msg = try sema.errMsg(23575 const msg = try sema.errMsg(
23574 ty_src,23576 ty_src,
23575 "expected pointer, found '{}'",23577 "expected pointer, found '{f}'",
23576 .{ty.fmt(pt)},23578 .{ty.fmt(pt)},
23577 );23579 );
23578 errdefer msg.destroy(sema.gpa);23580 errdefer msg.destroy(sema.gpa);
...@@ -23586,7 +23588,7 @@ fn checkPtrOperand(...@@ -23586,7 +23588,7 @@ fn checkPtrOperand(
23586 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23588 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23587 else => {},23589 else => {},
23588 }23590 }
23589 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});23591 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
23590}23592}
2359123593
23592fn checkPtrType(23594fn checkPtrType(
...@@ -23604,7 +23606,7 @@ fn checkPtrType(...@@ -23604,7 +23606,7 @@ fn checkPtrType(
23604 const msg = msg: {23606 const msg = msg: {
23605 const msg = try sema.errMsg(23607 const msg = try sema.errMsg(
23606 ty_src,23608 ty_src,
23607 "expected pointer type, found '{}'",23609 "expected pointer type, found '{f}'",
23608 .{ty.fmt(pt)},23610 .{ty.fmt(pt)},
23609 );23611 );
23610 errdefer msg.destroy(sema.gpa);23612 errdefer msg.destroy(sema.gpa);
...@@ -23618,7 +23620,7 @@ fn checkPtrType(...@@ -23618,7 +23620,7 @@ fn checkPtrType(
23618 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,23620 .optional => if (ty.childType(zcu).zigTypeTag(zcu) == .pointer) return,
23619 else => {},23621 else => {},
23620 }23622 }
23621 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});23623 return sema.fail(block, ty_src, "expected pointer type, found '{f}'", .{ty.fmt(pt)});
23622}23624}
2362323625
23624fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {23626fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
...@@ -23629,7 +23631,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -23629,7 +23631,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
23629 const as = ty.ptrAddressSpace(zcu);23631 const as = ty.ptrAddressSpace(zcu);
23630 if (target_util.arePointersLogical(target, as)) {23632 if (target_util.arePointersLogical(target, as)) {
23631 return sema.failWithOwnedErrorMsg(block, msg: {23633 return sema.failWithOwnedErrorMsg(block, msg: {
23632 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{}'", .{ty.fmt(pt)});23634 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{f}'", .{ty.fmt(pt)});
23633 errdefer msg.destroy(sema.gpa);23635 errdefer msg.destroy(sema.gpa);
23634 try sema.errNote(23636 try sema.errNote(
23635 src,23637 src,
...@@ -23660,7 +23662,7 @@ fn checkVectorElemType(...@@ -23660,7 +23662,7 @@ fn checkVectorElemType(
23660 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,23662 .optional, .pointer => if (ty.isPtrAtRuntime(zcu)) return,
23661 else => {},23663 else => {},
23662 }23664 }
23663 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(pt)});23665 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{f}'", .{ty.fmt(pt)});
23664}23666}
2366523667
23666fn checkFloatType(23668fn checkFloatType(
...@@ -23673,7 +23675,7 @@ fn checkFloatType(...@@ -23673,7 +23675,7 @@ fn checkFloatType(
23673 const zcu = pt.zcu;23675 const zcu = pt.zcu;
23674 switch (ty.zigTypeTag(zcu)) {23676 switch (ty.zigTypeTag(zcu)) {
23675 .comptime_int, .comptime_float, .float => {},23677 .comptime_int, .comptime_float, .float => {},
23676 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(pt)}),23678 else => return sema.fail(block, ty_src, "expected float type, found '{f}'", .{ty.fmt(pt)}),
23677 }23679 }
23678}23680}
2367923681
...@@ -23691,7 +23693,7 @@ fn checkNumericType(...@@ -23691,7 +23693,7 @@ fn checkNumericType(
23691 .comptime_float, .float, .comptime_int, .int => {},23693 .comptime_float, .float, .comptime_int, .int => {},
23692 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),23694 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),
23693 },23695 },
23694 else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(pt)}),23696 else => return sema.fail(block, ty_src, "expected number, found '{f}'", .{ty.fmt(pt)}),
23695 }23697 }
23696}23698}
2369723699
...@@ -23725,7 +23727,7 @@ fn checkAtomicPtrOperand(...@@ -23725,7 +23727,7 @@ fn checkAtomicPtrOperand(
23725 error.BadType => return sema.fail(23727 error.BadType => return sema.fail(
23726 block,23728 block,
23727 elem_ty_src,23729 elem_ty_src,
23728 "expected bool, integer, float, enum, packed struct, or pointer type; found '{}'",23730 "expected bool, integer, float, enum, packed struct, or pointer type; found '{f}'",
23729 .{elem_ty.fmt(pt)},23731 .{elem_ty.fmt(pt)},
23730 ),23732 ),
23731 };23733 };
...@@ -23786,12 +23788,12 @@ fn checkIntOrVector(...@@ -23786,12 +23788,12 @@ fn checkIntOrVector(
23786 const elem_ty = operand_ty.childType(zcu);23788 const elem_ty = operand_ty.childType(zcu);
23787 switch (elem_ty.zigTypeTag(zcu)) {23789 switch (elem_ty.zigTypeTag(zcu)) {
23788 .int => return elem_ty,23790 .int => return elem_ty,
23789 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{23791 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
23790 elem_ty.fmt(pt),23792 elem_ty.fmt(pt),
23791 }),23793 }),
23792 }23794 }
23793 },23795 },
23794 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{23796 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
23795 operand_ty.fmt(pt),23797 operand_ty.fmt(pt),
23796 }),23798 }),
23797 }23799 }
...@@ -23811,12 +23813,12 @@ fn checkIntOrVectorAllowComptime(...@@ -23811,12 +23813,12 @@ fn checkIntOrVectorAllowComptime(
23811 const elem_ty = operand_ty.childType(zcu);23813 const elem_ty = operand_ty.childType(zcu);
23812 switch (elem_ty.zigTypeTag(zcu)) {23814 switch (elem_ty.zigTypeTag(zcu)) {
23813 .int, .comptime_int => return elem_ty,23815 .int, .comptime_int => return elem_ty,
23814 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{23816 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{f}'", .{
23815 elem_ty.fmt(pt),23817 elem_ty.fmt(pt),
23816 }),23818 }),
23817 }23819 }
23818 },23820 },
23819 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{23821 else => return sema.fail(block, operand_src, "expected integer or vector, found '{f}'", .{
23820 operand_ty.fmt(pt),23822 operand_ty.fmt(pt),
23821 }),23823 }),
23822 }23824 }
...@@ -23907,7 +23909,7 @@ fn checkVectorizableBinaryOperands(...@@ -23907,7 +23909,7 @@ fn checkVectorizableBinaryOperands(
23907 }23909 }
23908 } else {23910 } else {
23909 const msg = msg: {23911 const msg = msg: {
23910 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{}' and '{}'", .{23912 const msg = try sema.errMsg(src, "mixed scalar and vector operands: '{f}' and '{f}'", .{
23911 lhs_ty.fmt(pt), rhs_ty.fmt(pt),23913 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
23912 });23914 });
23913 errdefer msg.destroy(sema.gpa);23915 errdefer msg.destroy(sema.gpa);
...@@ -24041,7 +24043,7 @@ fn zirCmpxchg(...@@ -24041,7 +24043,7 @@ fn zirCmpxchg(
24041 return sema.fail(24043 return sema.fail(
24042 block,24044 block,
24043 elem_ty_src,24045 elem_ty_src,
24044 "expected bool, integer, enum, packed struct, or pointer type; found '{}'",24046 "expected bool, integer, enum, packed struct, or pointer type; found '{f}'",
24045 .{elem_ty.fmt(pt)},24047 .{elem_ty.fmt(pt)},
24046 );24048 );
24047 }24049 }
...@@ -24125,7 +24127,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -24125,7 +24127,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2412524127
24126 switch (dest_ty.zigTypeTag(zcu)) {24128 switch (dest_ty.zigTypeTag(zcu)) {
24127 .array, .vector => {},24129 .array, .vector => {},
24128 else => return sema.fail(block, src, "expected array or vector type, found '{}'", .{dest_ty.fmt(pt)}),24130 else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(pt)}),
24129 }24131 }
2413024132
24131 const operand = try sema.resolveInst(extra.rhs);24133 const operand = try sema.resolveInst(extra.rhs);
...@@ -24201,7 +24203,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24201,7 +24203,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24201 const zcu = pt.zcu;24203 const zcu = pt.zcu;
2420224204
24203 if (operand_ty.zigTypeTag(zcu) != .vector) {24205 if (operand_ty.zigTypeTag(zcu) != .vector) {
24204 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(pt)});24206 return sema.fail(block, operand_src, "expected vector, found '{f}'", .{operand_ty.fmt(pt)});
24205 }24207 }
2420624208
24207 const scalar_ty = operand_ty.childType(zcu);24209 const scalar_ty = operand_ty.childType(zcu);
...@@ -24210,13 +24212,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24210,13 +24212,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24210 switch (operation) {24212 switch (operation) {
24211 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {24213 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
24212 .int, .bool => {},24214 .int, .bool => {},
24213 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{24215 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{f}'", .{
24214 @tagName(operation), operand_ty.fmt(pt),24216 @tagName(operation), operand_ty.fmt(pt),
24215 }),24217 }),
24216 },24218 },
24217 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {24219 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
24218 .int, .float => {},24220 .int, .float => {},
24219 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{24221 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{f}'", .{
24220 @tagName(operation), operand_ty.fmt(pt),24222 @tagName(operation), operand_ty.fmt(pt),
24221 }),24223 }),
24222 },24224 },
...@@ -24270,7 +24272,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -24270,7 +24272,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2427024272
24271 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {24273 const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) {
24272 .array, .vector => sema.typeOf(mask).arrayLen(zcu),24274 .array, .vector => sema.typeOf(mask).arrayLen(zcu),
24273 else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(pt)}),24275 else => return sema.fail(block, mask_src, "expected vector or array, found '{f}'", .{sema.typeOf(mask).fmt(pt)}),
24274 };24276 };
24275 mask_ty = try pt.vectorType(.{24277 mask_ty = try pt.vectorType(.{
24276 .len = @intCast(mask_len),24278 .len = @intCast(mask_len),
...@@ -24297,11 +24299,14 @@ fn analyzeShuffle(...@@ -24297,11 +24299,14 @@ fn analyzeShuffle(
24297 const b_src = block.builtinCallArgSrc(src_node, 2);24299 const b_src = block.builtinCallArgSrc(src_node, 2);
24298 const mask_src = block.builtinCallArgSrc(src_node, 3);24300 const mask_src = block.builtinCallArgSrc(src_node, 3);
2429924301
24300 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector.24302 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped,
24303 // this is 0, because it is an error to index into this vector.
24301 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {24304 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
24302 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),24305 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
24303 .undefined => 0,24306 .undefined => 0,
24304 else => return sema.fail(block, a_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt) }),24307 else => return sema.fail(block, a_src, "expected vector of '{f}', found '{f}'", .{
24308 elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt),
24309 }),
24305 };24310 };
24306 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });24311 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });
24307 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);24312 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);
...@@ -24310,7 +24315,9 @@ fn analyzeShuffle(...@@ -24310,7 +24315,9 @@ fn analyzeShuffle(
24310 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {24315 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
24311 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),24316 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
24312 .undefined => 0,24317 .undefined => 0,
24313 else => return sema.fail(block, b_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt) }),24318 else => return sema.fail(block, b_src, "expected vector of '{f}', found '{f}'", .{
24319 elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt),
24320 }),
24314 };24321 };
24315 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });24322 const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() });
24316 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);24323 const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src);
...@@ -24348,7 +24355,7 @@ fn analyzeShuffle(...@@ -24348,7 +24355,7 @@ fn analyzeShuffle(
24348 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {24355 if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: {
24349 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});24356 const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx});
24350 errdefer msg.destroy(sema.gpa);24357 errdefer msg.destroy(sema.gpa);
24351 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, a_ty.fmt(pt) });24358 try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{f}' given here", .{ idx, a_ty.fmt(pt) });
24352 if (idx < b_len) {24359 if (idx < b_len) {
24353 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});24360 try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx});
24354 }24361 }
...@@ -24464,7 +24471,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -24464,7 +24471,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2446424471
24465 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {24472 const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) {
24466 .vector, .array => pred_ty.arrayLen(zcu),24473 .vector, .array => pred_ty.arrayLen(zcu),
24467 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(pt)}),24474 else => return sema.fail(block, pred_src, "expected vector or array, found '{f}'", .{pred_ty.fmt(pt)}),
24468 };24475 };
24469 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));24476 const vec_len: u32 = @intCast(try sema.usizeCast(block, pred_src, vec_len_u64));
2447024477
...@@ -24724,7 +24731,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24724,7 +24731,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2472424731
24725 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {24732 switch (ty.scalarType(zcu).zigTypeTag(zcu)) {
24726 .comptime_float, .float => {},24733 .comptime_float, .float => {},
24727 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(pt)}),24734 else => return sema.fail(block, src, "expected vector of floats or float type, found '{f}'", .{ty.fmt(pt)}),
24728 }24735 }
2472924736
24730 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {24737 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
...@@ -24833,7 +24840,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24833,7 +24840,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2483324840
24834 const args_ty = sema.typeOf(args);24841 const args_ty = sema.typeOf(args);
24835 if (!args_ty.isTuple(zcu)) {24842 if (!args_ty.isTuple(zcu)) {
24836 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(pt)});24843 return sema.fail(block, args_src, "expected a tuple, found '{f}'", .{args_ty.fmt(pt)});
24837 }24844 }
2483824845
24839 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));24846 const resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(zcu));
...@@ -24878,12 +24885,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24878,12 +24885,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24878 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);24885 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);
24879 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);24886 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
24880 if (parent_ptr_info.flags.size != .one) {24887 if (parent_ptr_info.flags.size != .one) {
24881 return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(pt)});24888 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});
24882 }24889 }
24883 const parent_ty: Type = .fromInterned(parent_ptr_info.child);24890 const parent_ty: Type = .fromInterned(parent_ptr_info.child);
24884 switch (parent_ty.zigTypeTag(zcu)) {24891 switch (parent_ty.zigTypeTag(zcu)) {
24885 .@"struct", .@"union" => {},24892 .@"struct", .@"union" => {},
24886 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(pt)}),24893 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}),
24887 }24894 }
24888 try parent_ty.resolveLayout(pt);24895 try parent_ty.resolveLayout(pt);
2488924896
...@@ -25033,7 +25040,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -25033,7 +25040,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
25033 }25040 }
2503425041
25035 if (field.index != field_index) {25042 if (field.index != field_index) {
25036 return sema.fail(block, inst_src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{25043 return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{
25037 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),25044 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt),
25038 });25045 });
25039 }25046 }
...@@ -25492,10 +25499,10 @@ fn zirMemcpy(...@@ -25492,10 +25499,10 @@ fn zirMemcpy(
25492 const msg = msg: {25499 const msg = msg: {
25493 const msg = try sema.errMsg(src, "unknown copy length", .{});25500 const msg = try sema.errMsg(src, "unknown copy length", .{});
25494 errdefer msg.destroy(sema.gpa);25501 errdefer msg.destroy(sema.gpa);
25495 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{25502 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
25496 dest_ty.fmt(pt),25503 dest_ty.fmt(pt),
25497 });25504 });
25498 try sema.errNote(src_src, msg, "source type '{}' provides no length", .{25505 try sema.errNote(src_src, msg, "source type '{f}' provides no length", .{
25499 src_ty.fmt(pt),25506 src_ty.fmt(pt),
25500 });25507 });
25501 break :msg msg;25508 break :msg msg;
...@@ -25519,7 +25526,7 @@ fn zirMemcpy(...@@ -25519,7 +25526,7 @@ fn zirMemcpy(
25519 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {25526 if (imc != .ok) return sema.failWithOwnedErrorMsg(block, msg: {
25520 const msg = try sema.errMsg(25527 const msg = try sema.errMsg(
25521 src,25528 src,
25522 "pointer element type '{}' cannot coerce into element type '{}'",25529 "pointer element type '{f}' cannot coerce into element type '{f}'",
25523 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },25530 .{ src_elem_ty.fmt(pt), dest_elem_ty.fmt(pt) },
25524 );25531 );
25525 errdefer msg.destroy(sema.gpa);25532 errdefer msg.destroy(sema.gpa);
...@@ -25538,10 +25545,10 @@ fn zirMemcpy(...@@ -25538,10 +25545,10 @@ fn zirMemcpy(
25538 const msg = msg: {25545 const msg = msg: {
25539 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});25546 const msg = try sema.errMsg(src, "non-matching copy lengths", .{});
25540 errdefer msg.destroy(sema.gpa);25547 errdefer msg.destroy(sema.gpa);
25541 try sema.errNote(dest_src, msg, "length {} here", .{25548 try sema.errNote(dest_src, msg, "length {f} here", .{
25542 dest_len_val.fmtValueSema(pt, sema),25549 dest_len_val.fmtValueSema(pt, sema),
25543 });25550 });
25544 try sema.errNote(src_src, msg, "length {} here", .{25551 try sema.errNote(src_src, msg, "length {f} here", .{
25545 src_len_val.fmtValueSema(pt, sema),25552 src_len_val.fmtValueSema(pt, sema),
25546 });25553 });
25547 break :msg msg;25554 break :msg msg;
...@@ -25756,7 +25763,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25756,7 +25763,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25756 return sema.failWithOwnedErrorMsg(block, msg: {25763 return sema.failWithOwnedErrorMsg(block, msg: {
25757 const msg = try sema.errMsg(src, "unknown @memset length", .{});25764 const msg = try sema.errMsg(src, "unknown @memset length", .{});
25758 errdefer msg.destroy(sema.gpa);25765 errdefer msg.destroy(sema.gpa);
25759 try sema.errNote(dest_src, msg, "destination type '{}' provides no length", .{25766 try sema.errNote(dest_src, msg, "destination type '{f}' provides no length", .{
25760 dest_ptr_ty.fmt(pt),25767 dest_ptr_ty.fmt(pt),
25761 });25768 });
25762 break :msg msg;25769 break :msg msg;
...@@ -25964,7 +25971,7 @@ fn zirCUndef(...@@ -25964,7 +25971,7 @@ fn zirCUndef(
25964 const src = block.builtinCallArgSrc(extra.node, 0);25971 const src = block.builtinCallArgSrc(extra.node, 0);
2596525972
25966 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });25973 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cUndef_macro_name });
25967 try block.c_import_buf.?.writer().print("#undef {s}\n", .{name});25974 try block.c_import_buf.?.print("#undef {s}\n", .{name});
25968 return .void_value;25975 return .void_value;
25969}25976}
2597025977
...@@ -25977,7 +25984,7 @@ fn zirCInclude(...@@ -25977,7 +25984,7 @@ fn zirCInclude(
25977 const src = block.builtinCallArgSrc(extra.node, 0);25984 const src = block.builtinCallArgSrc(extra.node, 0);
2597825985
25979 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });25986 const name = try sema.resolveConstString(block, src, extra.operand, .{ .simple = .operand_cInclude_file_name });
25980 try block.c_import_buf.?.writer().print("#include <{s}>\n", .{name});25987 try block.c_import_buf.?.print("#include <{s}>\n", .{name});
25981 return .void_value;25988 return .void_value;
25982}25989}
2598325990
...@@ -25996,9 +26003,9 @@ fn zirCDefine(...@@ -25996,9 +26003,9 @@ fn zirCDefine(
25996 const rhs = try sema.resolveInst(extra.rhs);26003 const rhs = try sema.resolveInst(extra.rhs);
25997 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {26004 if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) {
25998 const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });26005 const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value });
25999 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });26006 try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value });
26000 } else {26007 } else {
26001 try block.c_import_buf.?.writer().print("#define {s}\n", .{name});26008 try block.c_import_buf.?.print("#define {s}\n", .{name});
26002 }26009 }
26003 return .void_value;26010 return .void_value;
26004}26011}
...@@ -26216,7 +26223,7 @@ fn zirBuiltinExtern(...@@ -26216,7 +26223,7 @@ fn zirBuiltinExtern(
26216 }26223 }
26217 if (!try sema.validateExternType(ty, .other)) {26224 if (!try sema.validateExternType(ty, .other)) {
26218 const msg = msg: {26225 const msg = msg: {
26219 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(pt)});26226 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)});
26220 errdefer msg.destroy(sema.gpa);26227 errdefer msg.destroy(sema.gpa);
26221 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);26228 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);
26222 break :msg msg;26229 break :msg msg;
...@@ -26456,7 +26463,7 @@ pub fn validateVarType(...@@ -26456,7 +26463,7 @@ pub fn validateVarType(
26456 if (is_extern) {26463 if (is_extern) {
26457 if (!try sema.validateExternType(var_ty, .other)) {26464 if (!try sema.validateExternType(var_ty, .other)) {
26458 const msg = msg: {26465 const msg = msg: {
26459 const msg = try sema.errMsg(src, "extern variable cannot have type '{}'", .{var_ty.fmt(pt)});26466 const msg = try sema.errMsg(src, "extern variable cannot have type '{f}'", .{var_ty.fmt(pt)});
26460 errdefer msg.destroy(sema.gpa);26467 errdefer msg.destroy(sema.gpa);
26461 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);26468 try sema.explainWhyTypeIsNotExtern(msg, src, var_ty, .other);
26462 break :msg msg;26469 break :msg msg;
...@@ -26468,7 +26475,7 @@ pub fn validateVarType(...@@ -26468,7 +26475,7 @@ pub fn validateVarType(
26468 return sema.fail(26475 return sema.fail(
26469 block,26476 block,
26470 src,26477 src,
26471 "non-extern variable with opaque type '{}'",26478 "non-extern variable with opaque type '{f}'",
26472 .{var_ty.fmt(pt)},26479 .{var_ty.fmt(pt)},
26473 );26480 );
26474 }26481 }
...@@ -26477,7 +26484,7 @@ pub fn validateVarType(...@@ -26477,7 +26484,7 @@ pub fn validateVarType(
26477 if (!try var_ty.comptimeOnlySema(pt)) return;26484 if (!try var_ty.comptimeOnlySema(pt)) return;
2647826485
26479 const msg = msg: {26486 const msg = msg: {
26480 const msg = try sema.errMsg(src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(pt)});26487 const msg = try sema.errMsg(src, "variable of type '{f}' must be const or comptime", .{var_ty.fmt(pt)});
26481 errdefer msg.destroy(sema.gpa);26488 errdefer msg.destroy(sema.gpa);
2648226489
26483 try sema.explainWhyTypeIsComptime(msg, src, var_ty);26490 try sema.explainWhyTypeIsComptime(msg, src, var_ty);
...@@ -26527,7 +26534,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26527,7 +26534,7 @@ fn explainWhyTypeIsComptimeInner(
26527 => return,26534 => return,
2652826535
26529 .@"fn" => {26536 .@"fn" => {
26530 try sema.errNote(src_loc, msg, "use '*const {}' for a function pointer type", .{ty.fmt(pt)});26537 try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)});
26531 },26538 },
2653226539
26533 .type => {26540 .type => {
...@@ -26543,7 +26550,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -26543,7 +26550,7 @@ fn explainWhyTypeIsComptimeInner(
26543 => return,26550 => return,
2654426551
26545 .@"opaque" => {26552 .@"opaque" => {
26546 try sema.errNote(src_loc, msg, "opaque type '{}' has undefined size", .{ty.fmt(pt)});26553 try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)});
26547 },26554 },
2654826555
26549 .array, .vector => {26556 .array, .vector => {
...@@ -26730,7 +26737,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26730,7 +26737,7 @@ fn explainWhyTypeIsNotExtern(
26730 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {26737 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {
26731 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});26738 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});
26732 } else if (try ty.comptimeOnlySema(pt)) {26739 } else if (try ty.comptimeOnlySema(pt)) {
26733 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(pt)});26740 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)});
26734 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);26741 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
26735 }26742 }
26736 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);26743 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);
...@@ -26758,7 +26765,7 @@ fn explainWhyTypeIsNotExtern(...@@ -26758,7 +26765,7 @@ fn explainWhyTypeIsNotExtern(
26758 },26765 },
26759 .@"enum" => {26766 .@"enum" => {
26760 const tag_ty = ty.intTagType(zcu);26767 const tag_ty = ty.intTagType(zcu);
26761 try sema.errNote(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(pt)});26768 try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
26762 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);26769 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
26763 },26770 },
26764 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),26771 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
...@@ -27194,7 +27201,7 @@ fn fieldVal(...@@ -27194,7 +27201,7 @@ fn fieldVal(
27194 return sema.fail(27201 return sema.fail(
27195 block,27202 block,
27196 field_name_src,27203 field_name_src,
27197 "no member named '{}' in '{}'",27204 "no member named '{f}' in '{f}'",
27198 .{ field_name.fmt(ip), object_ty.fmt(pt) },27205 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27199 );27206 );
27200 }27207 }
...@@ -27218,7 +27225,7 @@ fn fieldVal(...@@ -27218,7 +27225,7 @@ fn fieldVal(
27218 return sema.fail(27225 return sema.fail(
27219 block,27226 block,
27220 field_name_src,27227 field_name_src,
27221 "no member named '{}' in '{}'",27228 "no member named '{f}' in '{f}'",
27222 .{ field_name.fmt(ip), object_ty.fmt(pt) },27229 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27223 );27230 );
27224 }27231 }
...@@ -27238,7 +27245,7 @@ fn fieldVal(...@@ -27238,7 +27245,7 @@ fn fieldVal(
27238 switch (ip.indexToKey(child_type.toIntern())) {27245 switch (ip.indexToKey(child_type.toIntern())) {
27239 .error_set_type => |error_set_type| blk: {27246 .error_set_type => |error_set_type| blk: {
27240 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;27247 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;
27241 return sema.fail(block, src, "no error named '{}' in '{}'", .{27248 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
27242 field_name.fmt(ip), child_type.fmt(pt),27249 field_name.fmt(ip), child_type.fmt(pt),
27243 });27250 });
27244 },27251 },
...@@ -27293,7 +27300,7 @@ fn fieldVal(...@@ -27293,7 +27300,7 @@ fn fieldVal(
27293 return sema.failWithBadMemberAccess(block, child_type, src, field_name);27300 return sema.failWithBadMemberAccess(block, child_type, src, field_name);
27294 },27301 },
27295 else => return sema.failWithOwnedErrorMsg(block, msg: {27302 else => return sema.failWithOwnedErrorMsg(block, msg: {
27296 const msg = try sema.errMsg(src, "type '{}' has no members", .{child_type.fmt(pt)});27303 const msg = try sema.errMsg(src, "type '{f}' has no members", .{child_type.fmt(pt)});
27297 errdefer msg.destroy(sema.gpa);27304 errdefer msg.destroy(sema.gpa);
27298 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});27305 if (child_type.isSlice(zcu)) try sema.errNote(src, msg, "slice values have 'len' and 'ptr' members", .{});
27299 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});27306 if (child_type.zigTypeTag(zcu) == .array) try sema.errNote(src, msg, "array values have 'len' member", .{});
...@@ -27339,7 +27346,7 @@ fn fieldPtr(...@@ -27339,7 +27346,7 @@ fn fieldPtr(
27339 const object_ptr_ty = sema.typeOf(object_ptr);27346 const object_ptr_ty = sema.typeOf(object_ptr);
27340 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {27347 const object_ty = switch (object_ptr_ty.zigTypeTag(zcu)) {
27341 .pointer => object_ptr_ty.childType(zcu),27348 .pointer => object_ptr_ty.childType(zcu),
27342 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(pt)}),27349 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{f}'", .{object_ptr_ty.fmt(pt)}),
27343 };27350 };
2734427351
27345 // Zig allows dereferencing a single pointer during field lookup. Note that27352 // Zig allows dereferencing a single pointer during field lookup. Note that
...@@ -27392,7 +27399,7 @@ fn fieldPtr(...@@ -27392,7 +27399,7 @@ fn fieldPtr(
27392 return sema.fail(27399 return sema.fail(
27393 block,27400 block,
27394 field_name_src,27401 field_name_src,
27395 "no member named '{}' in '{}'",27402 "no member named '{f}' in '{f}'",
27396 .{ field_name.fmt(ip), object_ty.fmt(pt) },27403 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27397 );27404 );
27398 }27405 }
...@@ -27447,7 +27454,7 @@ fn fieldPtr(...@@ -27447,7 +27454,7 @@ fn fieldPtr(
27447 return sema.fail(27454 return sema.fail(
27448 block,27455 block,
27449 field_name_src,27456 field_name_src,
27450 "no member named '{}' in '{}'",27457 "no member named '{f}' in '{f}'",
27451 .{ field_name.fmt(ip), object_ty.fmt(pt) },27458 .{ field_name.fmt(ip), object_ty.fmt(pt) },
27452 );27459 );
27453 }27460 }
...@@ -27470,7 +27477,7 @@ fn fieldPtr(...@@ -27470,7 +27477,7 @@ fn fieldPtr(
27470 if (error_set_type.nameIndex(ip, field_name) != null) {27477 if (error_set_type.nameIndex(ip, field_name) != null) {
27471 break :blk;27478 break :blk;
27472 }27479 }
27473 return sema.fail(block, src, "no error named '{}' in '{}'", .{27480 return sema.fail(block, src, "no error named '{f}' in '{f}'", .{
27474 field_name.fmt(ip), child_type.fmt(pt),27481 field_name.fmt(ip), child_type.fmt(pt),
27475 });27482 });
27476 },27483 },
...@@ -27524,7 +27531,7 @@ fn fieldPtr(...@@ -27524,7 +27531,7 @@ fn fieldPtr(
27524 }27531 }
27525 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);27532 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
27526 },27533 },
27527 else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(pt)}),27534 else => return sema.fail(block, src, "type '{f}' has no members", .{child_type.fmt(pt)}),
27528 }27535 }
27529 },27536 },
27530 .@"struct" => {27537 .@"struct" => {
...@@ -27579,7 +27586,7 @@ fn fieldCallBind(...@@ -27579,7 +27586,7 @@ fn fieldCallBind(
27579 const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .pointer and (raw_ptr_ty.ptrSize(zcu) == .one or raw_ptr_ty.ptrSize(zcu) == .c))27586 const inner_ty = if (raw_ptr_ty.zigTypeTag(zcu) == .pointer and (raw_ptr_ty.ptrSize(zcu) == .one or raw_ptr_ty.ptrSize(zcu) == .c))
27580 raw_ptr_ty.childType(zcu)27587 raw_ptr_ty.childType(zcu)
27581 else27588 else
27582 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(pt)});27589 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{f}'", .{raw_ptr_ty.fmt(pt)});
2758327590
27584 // Optionally dereference a second pointer to get the concrete type.27591 // Optionally dereference a second pointer to get the concrete type.
27585 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;27592 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;
...@@ -27698,7 +27705,7 @@ fn fieldCallBind(...@@ -27698,7 +27705,7 @@ fn fieldCallBind(
27698 };27705 };
2769927706
27700 const msg = msg: {27707 const msg = msg: {
27701 const msg = try sema.errMsg(src, "no field or member function named '{}' in '{}'", .{27708 const msg = try sema.errMsg(src, "no field or member function named '{f}' in '{f}'", .{
27702 field_name.fmt(ip),27709 field_name.fmt(ip),
27703 concrete_ty.fmt(pt),27710 concrete_ty.fmt(pt),
27704 });27711 });
...@@ -27708,7 +27715,7 @@ fn fieldCallBind(...@@ -27708,7 +27715,7 @@ fn fieldCallBind(
27708 try sema.errNote(27715 try sema.errNote(
27709 zcu.navSrcLoc(nav_index),27716 zcu.navSrcLoc(nav_index),
27710 msg,27717 msg,
27711 "'{}' is not a member function",27718 "'{f}' is not a member function",
27712 .{field_name.fmt(ip)},27719 .{field_name.fmt(ip)},
27713 );27720 );
27714 }27721 }
...@@ -27776,7 +27783,7 @@ fn namespaceLookup(...@@ -27776,7 +27783,7 @@ fn namespaceLookup(
27776 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| {27783 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| {
27777 if (!lookup.accessible) {27784 if (!lookup.accessible) {
27778 return sema.failWithOwnedErrorMsg(block, msg: {27785 return sema.failWithOwnedErrorMsg(block, msg: {
27779 const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{27786 const msg = try sema.errMsg(src, "'{f}' is not marked 'pub'", .{
27780 decl_name.fmt(&zcu.intern_pool),27787 decl_name.fmt(&zcu.intern_pool),
27781 });27788 });
27782 errdefer msg.destroy(gpa);27789 errdefer msg.destroy(gpa);
...@@ -28014,12 +28021,12 @@ fn tupleFieldIndex(...@@ -28014,12 +28021,12 @@ fn tupleFieldIndex(
28014 assert(!field_name.eqlSlice("len", ip));28021 assert(!field_name.eqlSlice("len", ip));
28015 if (field_name.toUnsigned(ip)) |field_index| {28022 if (field_name.toUnsigned(ip)) |field_index| {
28016 if (field_index < tuple_ty.structFieldCount(pt.zcu)) return field_index;28023 if (field_index < tuple_ty.structFieldCount(pt.zcu)) return field_index;
28017 return sema.fail(block, field_name_src, "index '{}' out of bounds of tuple '{}'", .{28024 return sema.fail(block, field_name_src, "index '{f}' out of bounds of tuple '{f}'", .{
28018 field_name.fmt(ip), tuple_ty.fmt(pt),28025 field_name.fmt(ip), tuple_ty.fmt(pt),
28019 });28026 });
28020 }28027 }
2802128028
28022 return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{28029 return sema.fail(block, field_name_src, "no field named '{f}' in tuple '{f}'", .{
28023 field_name.fmt(ip), tuple_ty.fmt(pt),28030 field_name.fmt(ip), tuple_ty.fmt(pt),
28024 });28031 });
28025}28032}
...@@ -28106,7 +28113,7 @@ fn unionFieldPtr(...@@ -28106,7 +28113,7 @@ fn unionFieldPtr(
28106 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});28113 const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{});
28107 errdefer msg.destroy(sema.gpa);28114 errdefer msg.destroy(sema.gpa);
2810828115
28109 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{28116 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
28110 field_name.fmt(ip),28117 field_name.fmt(ip),
28111 });28118 });
28112 try sema.addDeclaredHereNote(msg, union_ty);28119 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -28140,7 +28147,7 @@ fn unionFieldPtr(...@@ -28140,7 +28147,7 @@ fn unionFieldPtr(
28140 const msg = msg: {28147 const msg = msg: {
28141 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;28148 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
28142 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);28149 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
28143 const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{28150 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
28144 field_name.fmt(ip),28151 field_name.fmt(ip),
28145 active_field_name.fmt(ip),28152 active_field_name.fmt(ip),
28146 });28153 });
...@@ -28208,7 +28215,7 @@ fn unionFieldVal(...@@ -28208,7 +28215,7 @@ fn unionFieldVal(
28208 const msg = msg: {28215 const msg = msg: {
28209 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;28216 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
28210 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);28217 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
28211 const msg = try sema.errMsg(src, "access of union field '{}' while field '{}' is active", .{28218 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
28212 field_name.fmt(ip), active_field_name.fmt(ip),28219 field_name.fmt(ip), active_field_name.fmt(ip),
28213 });28220 });
28214 errdefer msg.destroy(sema.gpa);28221 errdefer msg.destroy(sema.gpa);
...@@ -28266,7 +28273,7 @@ fn elemPtr(...@@ -28266,7 +28273,7 @@ fn elemPtr(
2826628273
28267 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {28274 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(zcu)) {
28268 .pointer => indexable_ptr_ty.childType(zcu),28275 .pointer => indexable_ptr_ty.childType(zcu),
28269 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(pt)}),28276 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}),
28270 };28277 };
28271 try sema.checkIndexable(block, src, indexable_ty);28278 try sema.checkIndexable(block, src, indexable_ty);
2827228279
...@@ -28437,7 +28444,7 @@ fn validateRuntimeElemAccess(...@@ -28437,7 +28444,7 @@ fn validateRuntimeElemAccess(
28437 const msg = msg: {28444 const msg = msg: {
28438 const msg = try sema.errMsg(28445 const msg = try sema.errMsg(
28439 elem_index_src,28446 elem_index_src,
28440 "values of type '{}' must be comptime-known, but index value is runtime-known",28447 "values of type '{f}' must be comptime-known, but index value is runtime-known",
28441 .{parent_ty.fmt(sema.pt)},28448 .{parent_ty.fmt(sema.pt)},
28442 );28449 );
28443 errdefer msg.destroy(sema.gpa);28450 errdefer msg.destroy(sema.gpa);
...@@ -28453,7 +28460,7 @@ fn validateRuntimeElemAccess(...@@ -28453,7 +28460,7 @@ fn validateRuntimeElemAccess(
28453 const target = zcu.getTarget();28460 const target = zcu.getTarget();
28454 const as = parent_ty.ptrAddressSpace(zcu);28461 const as = parent_ty.ptrAddressSpace(zcu);
28455 if (target_util.arePointersLogical(target, as)) {28462 if (target_util.arePointersLogical(target, as)) {
28456 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{}'", .{parent_ty.fmt(pt)});28463 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{f}'", .{parent_ty.fmt(pt)});
28457 }28464 }
28458 }28465 }
28459}28466}
...@@ -29149,7 +29156,7 @@ fn coerceExtra(...@@ -29149,7 +29156,7 @@ fn coerceExtra(
29149 return sema.fail(29156 return sema.fail(
29150 block,29157 block,
29151 inst_src,29158 inst_src,
29152 "array literal requires address-of operator (&) to coerce to slice type '{}'",29159 "array literal requires address-of operator (&) to coerce to slice type '{f}'",
29153 .{dest_ty.fmt(pt)},29160 .{dest_ty.fmt(pt)},
29154 );29161 );
29155 }29162 }
...@@ -29176,7 +29183,7 @@ fn coerceExtra(...@@ -29176,7 +29183,7 @@ fn coerceExtra(
29176 // pointer to tuple to slice29183 // pointer to tuple to slice
29177 if (!dest_info.flags.is_const) {29184 if (!dest_info.flags.is_const) {
29178 const err_msg = err_msg: {29185 const err_msg = err_msg: {
29179 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(pt)});29186 const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)});
29180 errdefer err_msg.destroy(sema.gpa);29187 errdefer err_msg.destroy(sema.gpa);
29181 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});29188 try sema.errNote(dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
29182 break :err_msg err_msg;29189 break :err_msg err_msg;
...@@ -29231,7 +29238,7 @@ fn coerceExtra(...@@ -29231,7 +29238,7 @@ fn coerceExtra(
29231 // comptime-known integer to other number29238 // comptime-known integer to other number
29232 if (!(try sema.intFitsInType(val, dest_ty, null))) {29239 if (!(try sema.intFitsInType(val, dest_ty, null))) {
29233 if (!opts.report_err) return error.NotCoercible;29240 if (!opts.report_err) return error.NotCoercible;
29234 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });29241 return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });
29235 }29242 }
29236 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {29243 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
29237 .undef => try pt.undefRef(dest_ty),29244 .undef => try pt.undefRef(dest_ty),
...@@ -29273,7 +29280,7 @@ fn coerceExtra(...@@ -29273,7 +29280,7 @@ fn coerceExtra(
29273 return sema.fail(29280 return sema.fail(
29274 block,29281 block,
29275 inst_src,29282 inst_src,
29276 "type '{}' cannot represent float value '{}'",29283 "type '{f}' cannot represent float value '{f}'",
29277 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },29284 .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) },
29278 );29285 );
29279 }29286 }
...@@ -29306,7 +29313,7 @@ fn coerceExtra(...@@ -29306,7 +29313,7 @@ fn coerceExtra(
29306 // return sema.fail(29313 // return sema.fail(
29307 // block,29314 // block,
29308 // inst_src,29315 // inst_src,
29309 // "type '{}' cannot represent integer value '{}'",29316 // "type '{f}' cannot represent integer value '{}'",
29310 // .{ dest_ty.fmt(pt), val },29317 // .{ dest_ty.fmt(pt), val },
29311 // );29318 // );
29312 //}29319 //}
...@@ -29320,7 +29327,7 @@ fn coerceExtra(...@@ -29320,7 +29327,7 @@ fn coerceExtra(
29320 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);29327 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
29321 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;29328 const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal;
29322 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {29329 const field_index = dest_ty.enumFieldIndex(string, zcu) orelse {
29323 return sema.fail(block, inst_src, "no field named '{}' in enum '{}'", .{29330 return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{
29324 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),29331 string.fmt(&zcu.intern_pool), dest_ty.fmt(pt),
29325 });29332 });
29326 };29333 };
...@@ -29469,11 +29476,11 @@ fn coerceExtra(...@@ -29469,11 +29476,11 @@ fn coerceExtra(
29469 }29476 }
2947029477
29471 const msg = msg: {29478 const msg = msg: {
29472 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });29479 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{ dest_ty.fmt(pt), inst_ty.fmt(pt) });
29473 errdefer msg.destroy(sema.gpa);29480 errdefer msg.destroy(sema.gpa);
2947429481
29475 if (!can_coerce_to) {29482 if (!can_coerce_to) {
29476 try sema.errNote(inst_src, msg, "cannot coerce to '{}'", .{dest_ty.fmt(pt)});29483 try sema.errNote(inst_src, msg, "cannot coerce to '{f}'", .{dest_ty.fmt(pt)});
29477 }29484 }
2947829485
29479 // E!T to T29486 // E!T to T
...@@ -29662,13 +29669,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29662,13 +29669,13 @@ const InMemoryCoercionResult = union(enum) {
29662 break;29669 break;
29663 },29670 },
29664 .comptime_int_not_coercible => |int| {29671 .comptime_int_not_coercible => |int| {
29665 try sema.errNote(src, msg, "type '{}' cannot represent value '{}'", .{29672 try sema.errNote(src, msg, "type '{f}' cannot represent value '{f}'", .{
29666 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),29673 int.wanted.fmt(pt), int.actual.fmtValueSema(pt, sema),
29667 });29674 });
29668 break;29675 break;
29669 },29676 },
29670 .error_union_payload => |pair| {29677 .error_union_payload => |pair| {
29671 try sema.errNote(src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{29678 try sema.errNote(src, msg, "error union payload '{f}' cannot cast into error union payload '{f}'", .{
29672 pair.actual.fmt(pt), pair.wanted.fmt(pt),29679 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29673 });29680 });
29674 cur = pair.child;29681 cur = pair.child;
...@@ -29681,18 +29688,18 @@ const InMemoryCoercionResult = union(enum) {...@@ -29681,18 +29688,18 @@ const InMemoryCoercionResult = union(enum) {
29681 },29688 },
29682 .array_sentinel => |sentinel| {29689 .array_sentinel => |sentinel| {
29683 if (sentinel.actual.toIntern() != .unreachable_value) {29690 if (sentinel.actual.toIntern() != .unreachable_value) {
29684 try sema.errNote(src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{29691 try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{
29685 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),29692 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29686 });29693 });
29687 } else {29694 } else {
29688 try sema.errNote(src, msg, "destination array requires '{}' sentinel", .{29695 try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{
29689 sentinel.wanted.fmtValueSema(pt, sema),29696 sentinel.wanted.fmtValueSema(pt, sema),
29690 });29697 });
29691 }29698 }
29692 break;29699 break;
29693 },29700 },
29694 .array_elem => |pair| {29701 .array_elem => |pair| {
29695 try sema.errNote(src, msg, "array element type '{}' cannot cast into array element type '{}'", .{29702 try sema.errNote(src, msg, "array element type '{f}' cannot cast into array element type '{f}'", .{
29696 pair.actual.fmt(pt), pair.wanted.fmt(pt),29703 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29697 });29704 });
29698 cur = pair.child;29705 cur = pair.child;
...@@ -29704,19 +29711,19 @@ const InMemoryCoercionResult = union(enum) {...@@ -29704,19 +29711,19 @@ const InMemoryCoercionResult = union(enum) {
29704 break;29711 break;
29705 },29712 },
29706 .vector_elem => |pair| {29713 .vector_elem => |pair| {
29707 try sema.errNote(src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{29714 try sema.errNote(src, msg, "vector element type '{f}' cannot cast into vector element type '{f}'", .{
29708 pair.actual.fmt(pt), pair.wanted.fmt(pt),29715 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29709 });29716 });
29710 cur = pair.child;29717 cur = pair.child;
29711 },29718 },
29712 .optional_shape => |pair| {29719 .optional_shape => |pair| {
29713 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{29720 try sema.errNote(src, msg, "optional type child '{f}' cannot cast into optional type child '{f}'", .{
29714 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),29721 pair.actual.optionalChild(pt.zcu).fmt(pt), pair.wanted.optionalChild(pt.zcu).fmt(pt),
29715 });29722 });
29716 break;29723 break;
29717 },29724 },
29718 .optional_child => |pair| {29725 .optional_child => |pair| {
29719 try sema.errNote(src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{29726 try sema.errNote(src, msg, "optional type child '{f}' cannot cast into optional type child '{f}'", .{
29720 pair.actual.fmt(pt), pair.wanted.fmt(pt),29727 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29721 });29728 });
29722 cur = pair.child;29729 cur = pair.child;
...@@ -29727,7 +29734,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29727,7 +29734,7 @@ const InMemoryCoercionResult = union(enum) {
29727 },29734 },
29728 .missing_error => |missing_errors| {29735 .missing_error => |missing_errors| {
29729 for (missing_errors) |err| {29736 for (missing_errors) |err| {
29730 try sema.errNote(src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});29737 try sema.errNote(src, msg, "'error.{f}' not a member of destination error set", .{err.fmt(&pt.zcu.intern_pool)});
29731 }29738 }
29732 break;29739 break;
29733 },29740 },
...@@ -29780,7 +29787,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29780,7 +29787,7 @@ const InMemoryCoercionResult = union(enum) {
29780 break;29787 break;
29781 },29788 },
29782 .fn_param => |param| {29789 .fn_param => |param| {
29783 try sema.errNote(src, msg, "parameter {d} '{}' cannot cast into '{}'", .{29790 try sema.errNote(src, msg, "parameter {d} '{f}' cannot cast into '{f}'", .{
29784 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),29791 param.index, param.actual.fmt(pt), param.wanted.fmt(pt),
29785 });29792 });
29786 cur = param.child;29793 cur = param.child;
...@@ -29790,13 +29797,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29790,13 +29797,13 @@ const InMemoryCoercionResult = union(enum) {
29790 break;29797 break;
29791 },29798 },
29792 .fn_return_type => |pair| {29799 .fn_return_type => |pair| {
29793 try sema.errNote(src, msg, "return type '{}' cannot cast into return type '{}'", .{29800 try sema.errNote(src, msg, "return type '{f}' cannot cast into return type '{f}'", .{
29794 pair.actual.fmt(pt), pair.wanted.fmt(pt),29801 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29795 });29802 });
29796 cur = pair.child;29803 cur = pair.child;
29797 },29804 },
29798 .ptr_child => |pair| {29805 .ptr_child => |pair| {
29799 try sema.errNote(src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{29806 try sema.errNote(src, msg, "pointer type child '{f}' cannot cast into pointer type child '{f}'", .{
29800 pair.actual.fmt(pt), pair.wanted.fmt(pt),29807 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29801 });29808 });
29802 cur = pair.child;29809 cur = pair.child;
...@@ -29807,11 +29814,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29807,11 +29814,11 @@ const InMemoryCoercionResult = union(enum) {
29807 },29814 },
29808 .ptr_sentinel => |sentinel| {29815 .ptr_sentinel => |sentinel| {
29809 if (sentinel.actual.toIntern() != .unreachable_value) {29816 if (sentinel.actual.toIntern() != .unreachable_value) {
29810 try sema.errNote(src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{29817 try sema.errNote(src, msg, "pointer sentinel '{f}' cannot cast into pointer sentinel '{f}'", .{
29811 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),29818 sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema),
29812 });29819 });
29813 } else {29820 } else {
29814 try sema.errNote(src, msg, "destination pointer requires '{}' sentinel", .{29821 try sema.errNote(src, msg, "destination pointer requires '{f}' sentinel", .{
29815 sentinel.wanted.fmtValueSema(pt, sema),29822 sentinel.wanted.fmtValueSema(pt, sema),
29816 });29823 });
29817 }29824 }
...@@ -29825,11 +29832,11 @@ const InMemoryCoercionResult = union(enum) {...@@ -29825,11 +29832,11 @@ const InMemoryCoercionResult = union(enum) {
29825 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);29832 const wanted_allow_zero = pair.wanted.ptrAllowsZero(pt.zcu);
29826 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);29833 const actual_allow_zero = pair.actual.ptrAllowsZero(pt.zcu);
29827 if (actual_allow_zero and !wanted_allow_zero) {29834 if (actual_allow_zero and !wanted_allow_zero) {
29828 try sema.errNote(src, msg, "'{}' could have null values which are illegal in type '{}'", .{29835 try sema.errNote(src, msg, "'{f}' could have null values which are illegal in type '{f}'", .{
29829 pair.actual.fmt(pt), pair.wanted.fmt(pt),29836 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29830 });29837 });
29831 } else {29838 } else {
29832 try sema.errNote(src, msg, "mutable '{}' would allow illegal null values stored to type '{}'", .{29839 try sema.errNote(src, msg, "mutable '{f}' would allow illegal null values stored to type '{f}'", .{
29833 pair.wanted.fmt(pt), pair.actual.fmt(pt),29840 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29834 });29841 });
29835 }29842 }
...@@ -29841,7 +29848,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29841,7 +29848,7 @@ const InMemoryCoercionResult = union(enum) {
29841 if (actual_const and !wanted_const) {29848 if (actual_const and !wanted_const) {
29842 try sema.errNote(src, msg, "cast discards const qualifier", .{});29849 try sema.errNote(src, msg, "cast discards const qualifier", .{});
29843 } else {29850 } else {
29844 try sema.errNote(src, msg, "mutable '{}' would allow illegal const pointers stored to type '{}'", .{29851 try sema.errNote(src, msg, "mutable '{f}' would allow illegal const pointers stored to type '{f}'", .{
29845 pair.wanted.fmt(pt), pair.actual.fmt(pt),29852 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29846 });29853 });
29847 }29854 }
...@@ -29853,7 +29860,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -29853,7 +29860,7 @@ const InMemoryCoercionResult = union(enum) {
29853 if (actual_volatile and !wanted_volatile) {29860 if (actual_volatile and !wanted_volatile) {
29854 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});29861 try sema.errNote(src, msg, "cast discards volatile qualifier", .{});
29855 } else {29862 } else {
29856 try sema.errNote(src, msg, "mutable '{}' would allow illegal volatile pointers stored to type '{}'", .{29863 try sema.errNote(src, msg, "mutable '{f}' would allow illegal volatile pointers stored to type '{f}'", .{
29857 pair.wanted.fmt(pt), pair.actual.fmt(pt),29864 pair.wanted.fmt(pt), pair.actual.fmt(pt),
29858 });29865 });
29859 }29866 }
...@@ -29879,13 +29886,13 @@ const InMemoryCoercionResult = union(enum) {...@@ -29879,13 +29886,13 @@ const InMemoryCoercionResult = union(enum) {
29879 break;29886 break;
29880 },29887 },
29881 .double_ptr_to_anyopaque => |pair| {29888 .double_ptr_to_anyopaque => |pair| {
29882 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{29889 try sema.errNote(src, msg, "cannot implicitly cast double pointer '{f}' to anyopaque pointer '{f}'", .{
29883 pair.actual.fmt(pt), pair.wanted.fmt(pt),29890 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29884 });29891 });
29885 break;29892 break;
29886 },29893 },
29887 .slice_to_anyopaque => |pair| {29894 .slice_to_anyopaque => |pair| {
29888 try sema.errNote(src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{29895 try sema.errNote(src, msg, "cannot implicitly cast slice '{f}' to anyopaque pointer '{f}'", .{
29889 pair.actual.fmt(pt), pair.wanted.fmt(pt),29896 pair.actual.fmt(pt), pair.wanted.fmt(pt),
29890 });29897 });
29891 try sema.errNote(src, msg, "consider using '.ptr'", .{});29898 try sema.errNote(src, msg, "consider using '.ptr'", .{});
...@@ -30659,7 +30666,7 @@ fn coerceVarArgParam(...@@ -30659,7 +30666,7 @@ fn coerceVarArgParam(
30659 const coerced_ty = sema.typeOf(coerced);30666 const coerced_ty = sema.typeOf(coerced);
30660 if (!try sema.validateExternType(coerced_ty, .param_ty)) {30667 if (!try sema.validateExternType(coerced_ty, .param_ty)) {
30661 const msg = msg: {30668 const msg = msg: {
30662 const msg = try sema.errMsg(inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(pt)});30669 const msg = try sema.errMsg(inst_src, "cannot pass '{f}' to variadic function", .{coerced_ty.fmt(pt)});
30663 errdefer msg.destroy(sema.gpa);30670 errdefer msg.destroy(sema.gpa);
3066430671
30665 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);30672 try sema.explainWhyTypeIsNotExtern(msg, inst_src, coerced_ty, .param_ty);
...@@ -30762,7 +30769,7 @@ fn storePtr2(...@@ -30762,7 +30769,7 @@ fn storePtr2(
30762 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.30769 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
30763 if (try elem_ty.comptimeOnlySema(pt)) {30770 if (try elem_ty.comptimeOnlySema(pt)) {
30764 return sema.failWithOwnedErrorMsg(block, msg: {30771 return sema.failWithOwnedErrorMsg(block, msg: {
30765 const msg = try sema.errMsg(src, "cannot store comptime-only type '{}' at runtime", .{elem_ty.fmt(pt)});30772 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});
30766 errdefer msg.destroy(sema.gpa);30773 errdefer msg.destroy(sema.gpa);
30767 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});30774 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
30768 break :msg msg;30775 break :msg msg;
...@@ -30795,7 +30802,7 @@ fn storePtr2(...@@ -30795,7 +30802,7 @@ fn storePtr2(
30795 });30802 });
30796 return;30803 return;
30797 }30804 }
30798 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{30805 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
30799 ptr_ty.fmt(pt),30806 ptr_ty.fmt(pt),
30800 });30807 });
30801 }30808 }
...@@ -30964,19 +30971,19 @@ fn storePtrVal(...@@ -30964,19 +30971,19 @@ fn storePtrVal(
30964 .{},30971 .{},
30965 ),30972 ),
30966 .undef => return sema.failWithUseOfUndef(block, src),30973 .undef => return sema.failWithUseOfUndef(block, src),
30967 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),30974 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}),
30968 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),30975 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
30969 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),30976 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
30970 .needed_well_defined => |ty| return sema.fail(30977 .needed_well_defined => |ty| return sema.fail(
30971 block,30978 block,
30972 src,30979 src,
30973 "comptime dereference requires '{}' to have a well-defined layout",30980 "comptime dereference requires '{f}' to have a well-defined layout",
30974 .{ty.fmt(pt)},30981 .{ty.fmt(pt)},
30975 ),30982 ),
30976 .out_of_bounds => |ty| return sema.fail(30983 .out_of_bounds => |ty| return sema.fail(
30977 block,30984 block,
30978 src,30985 src,
30979 "dereference of '{}' exceeds bounds of containing decl of type '{}'",30986 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
30980 .{ ptr_ty.fmt(pt), ty.fmt(pt) },30987 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
30981 ),30988 ),
30982 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),30989 .exceeds_host_size => return sema.fail(block, src, "bit-pointer target exceeds host size", .{}),
...@@ -31002,7 +31009,7 @@ fn bitCast(...@@ -31002,7 +31009,7 @@ fn bitCast(
31002 const old_bits = old_ty.bitSize(zcu);31009 const old_bits = old_ty.bitSize(zcu);
3100331010
31004 if (old_bits != dest_bits) {31011 if (old_bits != dest_bits) {
31005 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{31012 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{f}' has {d} bits but source type '{f}' has {d} bits", .{
31006 dest_ty.fmt(pt),31013 dest_ty.fmt(pt),
31007 dest_bits,31014 dest_bits,
31008 old_ty.fmt(pt),31015 old_ty.fmt(pt),
...@@ -31120,7 +31127,7 @@ fn coerceCompatiblePtrs(...@@ -31120,7 +31127,7 @@ fn coerceCompatiblePtrs(
31120 const inst_ty = sema.typeOf(inst);31127 const inst_ty = sema.typeOf(inst);
31121 if (try sema.resolveValue(inst)) |val| {31128 if (try sema.resolveValue(inst)) |val| {
31122 if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) {31129 if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) {
31123 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(pt)});31130 return sema.fail(block, inst_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)});
31124 }31131 }
31125 // The comptime Value representation is compatible with both types.31132 // The comptime Value representation is compatible with both types.
31126 return Air.internedToRef(31133 return Air.internedToRef(
...@@ -31166,7 +31173,7 @@ fn coerceEnumToUnion(...@@ -31166,7 +31173,7 @@ fn coerceEnumToUnion(
3116631173
31167 const tag_ty = union_ty.unionTagType(zcu) orelse {31174 const tag_ty = union_ty.unionTagType(zcu) orelse {
31168 const msg = msg: {31175 const msg = msg: {
31169 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31176 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31170 union_ty.fmt(pt), inst_ty.fmt(pt),31177 union_ty.fmt(pt), inst_ty.fmt(pt),
31171 });31178 });
31172 errdefer msg.destroy(sema.gpa);31179 errdefer msg.destroy(sema.gpa);
...@@ -31180,7 +31187,7 @@ fn coerceEnumToUnion(...@@ -31180,7 +31187,7 @@ fn coerceEnumToUnion(
31180 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);31187 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);
31181 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {31188 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
31182 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {31189 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {
31183 return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{31190 return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{
31184 union_ty.fmt(pt), val.fmtValueSema(pt, sema),31191 union_ty.fmt(pt), val.fmtValueSema(pt, sema),
31185 });31192 });
31186 };31193 };
...@@ -31194,7 +31201,7 @@ fn coerceEnumToUnion(...@@ -31194,7 +31201,7 @@ fn coerceEnumToUnion(
31194 errdefer msg.destroy(sema.gpa);31201 errdefer msg.destroy(sema.gpa);
3119531202
31196 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31203 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31197 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{31204 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
31198 field_name.fmt(ip),31205 field_name.fmt(ip),
31199 });31206 });
31200 try sema.addDeclaredHereNote(msg, union_ty);31207 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31205,13 +31212,13 @@ fn coerceEnumToUnion(...@@ -31205,13 +31212,13 @@ fn coerceEnumToUnion(
31205 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {31212 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
31206 const msg = msg: {31213 const msg = msg: {
31207 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31214 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31208 const msg = try sema.errMsg(inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{31215 const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{
31209 inst_ty.fmt(pt), union_ty.fmt(pt),31216 inst_ty.fmt(pt), union_ty.fmt(pt),
31210 field_ty.fmt(pt), field_name.fmt(ip),31217 field_ty.fmt(pt), field_name.fmt(ip),
31211 });31218 });
31212 errdefer msg.destroy(sema.gpa);31219 errdefer msg.destroy(sema.gpa);
3121331220
31214 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{31221 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
31215 field_name.fmt(ip),31222 field_name.fmt(ip),
31216 });31223 });
31217 try sema.addDeclaredHereNote(msg, union_ty);31224 try sema.addDeclaredHereNote(msg, union_ty);
...@@ -31227,7 +31234,7 @@ fn coerceEnumToUnion(...@@ -31227,7 +31234,7 @@ fn coerceEnumToUnion(
3122731234
31228 if (tag_ty.isNonexhaustiveEnum(zcu)) {31235 if (tag_ty.isNonexhaustiveEnum(zcu)) {
31229 const msg = msg: {31236 const msg = msg: {
31230 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{31237 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{
31231 union_ty.fmt(pt),31238 union_ty.fmt(pt),
31232 });31239 });
31233 errdefer msg.destroy(sema.gpa);31240 errdefer msg.destroy(sema.gpa);
...@@ -31246,7 +31253,7 @@ fn coerceEnumToUnion(...@@ -31246,7 +31253,7 @@ fn coerceEnumToUnion(
31246 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {31253 if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) {
31247 const err_msg = msg orelse try sema.errMsg(31254 const err_msg = msg orelse try sema.errMsg(
31248 inst_src,31255 inst_src,
31249 "runtime coercion from enum '{}' to union '{}' which has a 'noreturn' field",31256 "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field",
31250 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31257 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31251 );31258 );
31252 msg = err_msg;31259 msg = err_msg;
...@@ -31269,7 +31276,7 @@ fn coerceEnumToUnion(...@@ -31269,7 +31276,7 @@ fn coerceEnumToUnion(
31269 const msg = msg: {31276 const msg = msg: {
31270 const msg = try sema.errMsg(31277 const msg = try sema.errMsg(
31271 inst_src,31278 inst_src,
31272 "runtime coercion from enum '{}' to union '{}' which has non-void fields",31279 "runtime coercion from enum '{f}' to union '{f}' which has non-void fields",
31273 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },31280 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
31274 );31281 );
31275 errdefer msg.destroy(sema.gpa);31282 errdefer msg.destroy(sema.gpa);
...@@ -31278,7 +31285,7 @@ fn coerceEnumToUnion(...@@ -31278,7 +31285,7 @@ fn coerceEnumToUnion(
31278 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];31285 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
31279 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);31286 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
31280 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;31287 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;
31281 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{31288 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{
31282 field_name.fmt(ip),31289 field_name.fmt(ip),
31283 field_ty.fmt(pt),31290 field_ty.fmt(pt),
31284 });31291 });
...@@ -31319,7 +31326,7 @@ fn coerceArrayLike(...@@ -31319,7 +31326,7 @@ fn coerceArrayLike(
31319 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));31326 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(zcu));
31320 if (dest_len != inst_len) {31327 if (dest_len != inst_len) {
31321 const msg = msg: {31328 const msg = msg: {
31322 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31329 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31323 dest_ty.fmt(pt), inst_ty.fmt(pt),31330 dest_ty.fmt(pt), inst_ty.fmt(pt),
31324 });31331 });
31325 errdefer msg.destroy(sema.gpa);31332 errdefer msg.destroy(sema.gpa);
...@@ -31407,7 +31414,7 @@ fn coerceTupleToArray(...@@ -31407,7 +31414,7 @@ fn coerceTupleToArray(
3140731414
31408 if (dest_len != inst_len) {31415 if (dest_len != inst_len) {
31409 const msg = msg: {31416 const msg = msg: {
31410 const msg = try sema.errMsg(inst_src, "expected type '{}', found '{}'", .{31417 const msg = try sema.errMsg(inst_src, "expected type '{f}', found '{f}'", .{
31411 dest_ty.fmt(pt), inst_ty.fmt(pt),31418 dest_ty.fmt(pt), inst_ty.fmt(pt),
31412 });31419 });
31413 errdefer msg.destroy(sema.gpa);31420 errdefer msg.destroy(sema.gpa);
...@@ -31883,10 +31890,10 @@ fn analyzeLoad(...@@ -31883,10 +31890,10 @@ fn analyzeLoad(
31883 const ptr_ty = sema.typeOf(ptr);31890 const ptr_ty = sema.typeOf(ptr);
31884 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {31891 const elem_ty = switch (ptr_ty.zigTypeTag(zcu)) {
31885 .pointer => ptr_ty.childType(zcu),31892 .pointer => ptr_ty.childType(zcu),
31886 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(pt)}),31893 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}),
31887 };31894 };
31888 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {31895 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {
31889 return sema.fail(block, ptr_src, "cannot load opaque type '{}'", .{elem_ty.fmt(pt)});31896 return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)});
31890 }31897 }
3189131898
31892 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {31899 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {
...@@ -31907,7 +31914,7 @@ fn analyzeLoad(...@@ -31907,7 +31914,7 @@ fn analyzeLoad(
31907 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;31914 const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
31908 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);31915 return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
31909 }31916 }
31910 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{31917 return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
31911 ptr_ty.fmt(pt),31918 ptr_ty.fmt(pt),
31912 });31919 });
31913 }31920 }
...@@ -32195,7 +32202,7 @@ fn analyzeSlice(...@@ -32195,7 +32202,7 @@ fn analyzeSlice(
32195 const ptr_ptr_ty = sema.typeOf(ptr_ptr);32202 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
32196 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {32203 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(zcu)) {
32197 .pointer => ptr_ptr_ty.childType(zcu),32204 .pointer => ptr_ptr_ty.childType(zcu),
32198 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(pt)}),32205 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ptr_ty.fmt(pt)}),
32199 };32206 };
3220032207
32201 var array_ty = ptr_ptr_child_ty;32208 var array_ty = ptr_ptr_child_ty;
...@@ -32244,7 +32251,7 @@ fn analyzeSlice(...@@ -32244,7 +32251,7 @@ fn analyzeSlice(
32244 try sema.errNote(32251 try sema.errNote(
32245 start_src,32252 start_src,
32246 msg,32253 msg,
32247 "expected '{}', found '{}'",32254 "expected '{f}', found '{f}'",
32248 .{32255 .{
32249 Value.zero_comptime_int.fmtValueSema(pt, sema),32256 Value.zero_comptime_int.fmtValueSema(pt, sema),
32250 start_value.fmtValueSema(pt, sema),32257 start_value.fmtValueSema(pt, sema),
...@@ -32260,7 +32267,7 @@ fn analyzeSlice(...@@ -32260,7 +32267,7 @@ fn analyzeSlice(
32260 try sema.errNote(32267 try sema.errNote(
32261 end_src,32268 end_src,
32262 msg,32269 msg,
32263 "expected '{}', found '{}'",32270 "expected '{f}', found '{f}'",
32264 .{32271 .{
32265 Value.one_comptime_int.fmtValueSema(pt, sema),32272 Value.one_comptime_int.fmtValueSema(pt, sema),
32266 end_value.fmtValueSema(pt, sema),32273 end_value.fmtValueSema(pt, sema),
...@@ -32275,7 +32282,7 @@ fn analyzeSlice(...@@ -32275,7 +32282,7 @@ fn analyzeSlice(
32275 return sema.fail(32282 return sema.fail(
32276 block,32283 block,
32277 end_src,32284 end_src,
32278 "end index {} out of bounds for slice of single-item pointer",32285 "end index {f} out of bounds for slice of single-item pointer",
32279 .{end_value.fmtValueSema(pt, sema)},32286 .{end_value.fmtValueSema(pt, sema)},
32280 );32287 );
32281 }32288 }
...@@ -32322,7 +32329,7 @@ fn analyzeSlice(...@@ -32322,7 +32329,7 @@ fn analyzeSlice(
32322 elem_ty = ptr_ptr_child_ty.childType(zcu);32329 elem_ty = ptr_ptr_child_ty.childType(zcu);
32323 },32330 },
32324 },32331 },
32325 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(pt)}),32332 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}),
32326 }32333 }
3232732334
32328 const ptr = if (slice_ty.isSlice(zcu))32335 const ptr = if (slice_ty.isSlice(zcu))
...@@ -32369,7 +32376,7 @@ fn analyzeSlice(...@@ -32369,7 +32376,7 @@ fn analyzeSlice(
32369 return sema.fail(32376 return sema.fail(
32370 block,32377 block,
32371 end_src,32378 end_src,
32372 "end index {} out of bounds for array of length {}{s}",32379 "end index {f} out of bounds for array of length {f}{s}",
32373 .{32380 .{
32374 end_val.fmtValueSema(pt, sema),32381 end_val.fmtValueSema(pt, sema),
32375 len_val.fmtValueSema(pt, sema),32382 len_val.fmtValueSema(pt, sema),
...@@ -32414,7 +32421,7 @@ fn analyzeSlice(...@@ -32414,7 +32421,7 @@ fn analyzeSlice(
32414 return sema.fail(32421 return sema.fail(
32415 block,32422 block,
32416 end_src,32423 end_src,
32417 "end index {} out of bounds for slice of length {d}{s}",32424 "end index {f} out of bounds for slice of length {d}{s}",
32418 .{32425 .{
32419 end_val.fmtValueSema(pt, sema),32426 end_val.fmtValueSema(pt, sema),
32420 try slice_val.sliceLen(pt),32427 try slice_val.sliceLen(pt),
...@@ -32473,7 +32480,7 @@ fn analyzeSlice(...@@ -32473,7 +32480,7 @@ fn analyzeSlice(
32473 return sema.fail(32480 return sema.fail(
32474 block,32481 block,
32475 start_src,32482 start_src,
32476 "start index {} is larger than end index {}",32483 "start index {f} is larger than end index {f}",
32477 .{32484 .{
32478 start_val.fmtValueSema(pt, sema),32485 start_val.fmtValueSema(pt, sema),
32479 end_val.fmtValueSema(pt, sema),32486 end_val.fmtValueSema(pt, sema),
...@@ -32497,13 +32504,13 @@ fn analyzeSlice(...@@ -32497,13 +32504,13 @@ fn analyzeSlice(
32497 .needed_well_defined => |ty| return sema.fail(32504 .needed_well_defined => |ty| return sema.fail(
32498 block,32505 block,
32499 src,32506 src,
32500 "comptime dereference requires '{}' to have a well-defined layout",32507 "comptime dereference requires '{f}' to have a well-defined layout",
32501 .{ty.fmt(pt)},32508 .{ty.fmt(pt)},
32502 ),32509 ),
32503 .out_of_bounds => |ty| return sema.fail(32510 .out_of_bounds => |ty| return sema.fail(
32504 block,32511 block,
32505 end_src,32512 end_src,
32506 "slice end index {d} exceeds bounds of containing decl of type '{}'",32513 "slice end index {d} exceeds bounds of containing decl of type '{f}'",
32507 .{ end_int, ty.fmt(pt) },32514 .{ end_int, ty.fmt(pt) },
32508 ),32515 ),
32509 };32516 };
...@@ -32512,7 +32519,7 @@ fn analyzeSlice(...@@ -32512,7 +32519,7 @@ fn analyzeSlice(
32512 const msg = msg: {32519 const msg = msg: {
32513 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});32520 const msg = try sema.errMsg(src, "value in memory does not match slice sentinel", .{});
32514 errdefer msg.destroy(sema.gpa);32521 errdefer msg.destroy(sema.gpa);
32515 try sema.errNote(src, msg, "expected '{}', found '{}'", .{32522 try sema.errNote(src, msg, "expected '{f}', found '{f}'", .{
32516 expected_sentinel.fmtValueSema(pt, sema),32523 expected_sentinel.fmtValueSema(pt, sema),
32517 actual_sentinel.fmtValueSema(pt, sema),32524 actual_sentinel.fmtValueSema(pt, sema),
32518 });32525 });
...@@ -33400,7 +33407,7 @@ const PeerResolveResult = union(enum) {...@@ -33400,7 +33407,7 @@ const PeerResolveResult = union(enum) {
33400 };33407 };
33401 },33408 },
33402 .field_error => |field_error| {33409 .field_error => |field_error| {
33403 const fmt = "struct field '{}' has conflicting types";33410 const fmt = "struct field '{f}' has conflicting types";
33404 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};33411 const args = .{field_error.field_name.fmt(&pt.zcu.intern_pool)};
33405 if (opt_msg) |msg| {33412 if (opt_msg) |msg| {
33406 try sema.errNote(src, msg, fmt, args);33413 try sema.errNote(src, msg, fmt, args);
...@@ -33431,7 +33438,7 @@ const PeerResolveResult = union(enum) {...@@ -33431,7 +33438,7 @@ const PeerResolveResult = union(enum) {
33431 candidate_srcs.resolve(block, conflict_idx[1]),33438 candidate_srcs.resolve(block, conflict_idx[1]),
33432 };33439 };
3343333440
33434 const fmt = "incompatible types: '{}' and '{}'";33441 const fmt = "incompatible types: '{f}' and '{f}'";
33435 const args = .{33442 const args = .{
33436 conflict_tys[0].fmt(pt),33443 conflict_tys[0].fmt(pt),
33437 conflict_tys[1].fmt(pt),33444 conflict_tys[1].fmt(pt),
...@@ -33445,8 +33452,8 @@ const PeerResolveResult = union(enum) {...@@ -33445,8 +33452,8 @@ const PeerResolveResult = union(enum) {
33445 break :msg msg;33452 break :msg msg;
33446 };33453 };
3344733454
33448 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[0].fmt(pt)});33455 if (conflict_srcs[0]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[0].fmt(pt)});
33449 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{}' here", .{conflict_tys[1].fmt(pt)});33456 if (conflict_srcs[1]) |src_loc| try sema.errNote(src_loc, msg, "type '{f}' here", .{conflict_tys[1].fmt(pt)});
3345033457
33451 // No child error33458 // No child error
33452 break;33459 break;
...@@ -34758,7 +34765,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34758,7 +34765,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34758 if (struct_type.setLayoutWip(ip)) {34765 if (struct_type.setLayoutWip(ip)) {
34759 const msg = try sema.errMsg(34766 const msg = try sema.errMsg(
34760 ty.srcLoc(zcu),34767 ty.srcLoc(zcu),
34761 "struct '{}' depends on itself",34768 "struct '{f}' depends on itself",
34762 .{ty.fmt(pt)},34769 .{ty.fmt(pt)},
34763 );34770 );
34764 return sema.failWithOwnedErrorMsg(null, msg);34771 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -34977,13 +34984,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_...@@ -34977,13 +34984,13 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
34977 const zcu = pt.zcu;34984 const zcu = pt.zcu;
3497834985
34979 if (!backing_int_ty.isInt(zcu)) {34986 if (!backing_int_ty.isInt(zcu)) {
34980 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(pt)});34987 return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)});
34981 }34988 }
34982 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {34989 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {
34983 return sema.fail(34990 return sema.fail(
34984 block,34991 block,
34985 src,34992 src,
34986 "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}",34993 "backing integer type '{f}' has bit size {} but the struct fields have a total bit size of {}",
34987 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },34994 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },
34988 );34995 );
34989 }34996 }
...@@ -34993,7 +35000,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {...@@ -34993,7 +35000,7 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
34993 const pt = sema.pt;35000 const pt = sema.pt;
34994 if (!ty.isIndexable(pt.zcu)) {35001 if (!ty.isIndexable(pt.zcu)) {
34995 const msg = msg: {35002 const msg = msg: {
34996 const msg = try sema.errMsg(src, "type '{}' does not support indexing", .{ty.fmt(pt)});35003 const msg = try sema.errMsg(src, "type '{f}' does not support indexing", .{ty.fmt(pt)});
34997 errdefer msg.destroy(sema.gpa);35004 errdefer msg.destroy(sema.gpa);
34998 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});35005 try sema.errNote(src, msg, "operand must be an array, slice, tuple, or vector", .{});
34999 break :msg msg;35006 break :msg msg;
...@@ -35017,7 +35024,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void...@@ -35017,7 +35024,7 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
35017 }35024 }
35018 }35025 }
35019 const msg = msg: {35026 const msg = msg: {
35020 const msg = try sema.errMsg(src, "type '{}' is not an indexable pointer", .{ty.fmt(pt)});35027 const msg = try sema.errMsg(src, "type '{f}' is not an indexable pointer", .{ty.fmt(pt)});
35021 errdefer msg.destroy(sema.gpa);35028 errdefer msg.destroy(sema.gpa);
35022 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});35029 try sema.errNote(src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{});
35023 break :msg msg;35030 break :msg msg;
...@@ -35085,7 +35092,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35085,7 +35092,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
35085 .field_types_wip, .layout_wip => {35092 .field_types_wip, .layout_wip => {
35086 const msg = try sema.errMsg(35093 const msg = try sema.errMsg(
35087 ty.srcLoc(pt.zcu),35094 ty.srcLoc(pt.zcu),
35088 "union '{}' depends on itself",35095 "union '{f}' depends on itself",
35089 .{ty.fmt(pt)},35096 .{ty.fmt(pt)},
35090 );35097 );
35091 return sema.failWithOwnedErrorMsg(null, msg);35098 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35273,7 +35280,7 @@ pub fn resolveStructFieldTypes(...@@ -35273,7 +35280,7 @@ pub fn resolveStructFieldTypes(
35273 if (struct_type.setFieldTypesWip(ip)) {35280 if (struct_type.setFieldTypesWip(ip)) {
35274 const msg = try sema.errMsg(35281 const msg = try sema.errMsg(
35275 Type.fromInterned(ty).srcLoc(zcu),35282 Type.fromInterned(ty).srcLoc(zcu),
35276 "struct '{}' depends on itself",35283 "struct '{f}' depends on itself",
35277 .{Type.fromInterned(ty).fmt(pt)},35284 .{Type.fromInterned(ty).fmt(pt)},
35278 );35285 );
35279 return sema.failWithOwnedErrorMsg(null, msg);35286 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35302,7 +35309,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -35302,7 +35309,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
35302 if (struct_type.setInitsWip(ip)) {35309 if (struct_type.setInitsWip(ip)) {
35303 const msg = try sema.errMsg(35310 const msg = try sema.errMsg(
35304 ty.srcLoc(zcu),35311 ty.srcLoc(zcu),
35305 "struct '{}' depends on itself",35312 "struct '{f}' depends on itself",
35306 .{ty.fmt(pt)},35313 .{ty.fmt(pt)},
35307 );35314 );
35308 return sema.failWithOwnedErrorMsg(null, msg);35315 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35328,7 +35335,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -35328,7 +35335,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
35328 .field_types_wip => {35335 .field_types_wip => {
35329 const msg = try sema.errMsg(35336 const msg = try sema.errMsg(
35330 ty.srcLoc(zcu),35337 ty.srcLoc(zcu),
35331 "union '{}' depends on itself",35338 "union '{f}' depends on itself",
35332 .{ty.fmt(pt)},35339 .{ty.fmt(pt)},
35333 );35340 );
35334 return sema.failWithOwnedErrorMsg(null, msg);35341 return sema.failWithOwnedErrorMsg(null, msg);
...@@ -35698,7 +35705,7 @@ fn structFields(...@@ -35698,7 +35705,7 @@ fn structFields(
35698 switch (struct_type.layout) {35705 switch (struct_type.layout) {
35699 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {35706 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
35700 const msg = msg: {35707 const msg = msg: {
35701 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});35708 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35702 errdefer msg.destroy(sema.gpa);35709 errdefer msg.destroy(sema.gpa);
3570335710
35704 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);35711 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);
...@@ -35710,7 +35717,7 @@ fn structFields(...@@ -35710,7 +35717,7 @@ fn structFields(
35710 },35717 },
35711 .@"packed" => if (!try sema.validatePackedType(field_ty)) {35718 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
35712 const msg = msg: {35719 const msg = msg: {
35713 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(pt)});35720 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35714 errdefer msg.destroy(sema.gpa);35721 errdefer msg.destroy(sema.gpa);
3571535722
35716 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);35723 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
...@@ -35957,7 +35964,7 @@ fn unionFields(...@@ -35957,7 +35964,7 @@ fn unionFields(
35957 // The provided type is an integer type and we must construct the enum tag type here.35964 // The provided type is an integer type and we must construct the enum tag type here.
35958 int_tag_ty = provided_ty;35965 int_tag_ty = provided_ty;
35959 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {35966 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {
35960 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(pt)});35967 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)});
35961 }35968 }
3596235969
35963 if (fields_len > 0) {35970 if (fields_len > 0) {
...@@ -35966,7 +35973,7 @@ fn unionFields(...@@ -35966,7 +35973,7 @@ fn unionFields(
35966 const msg = msg: {35973 const msg = msg: {
35967 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});35974 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});
35968 errdefer msg.destroy(sema.gpa);35975 errdefer msg.destroy(sema.gpa);
35969 try sema.errNote(tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{35976 try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{
35970 int_tag_ty.fmt(pt),35977 int_tag_ty.fmt(pt),
35971 fields_len - 1,35978 fields_len - 1,
35972 });35979 });
...@@ -35981,7 +35988,7 @@ fn unionFields(...@@ -35981,7 +35988,7 @@ fn unionFields(
35981 // The provided type is the enum tag type.35988 // The provided type is the enum tag type.
35982 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {35989 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
35983 .enum_type => ip.loadEnumType(provided_ty.toIntern()),35990 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
35984 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{provided_ty.fmt(pt)}),35991 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),
35985 };35992 };
35986 union_type.setTagType(ip, provided_ty.toIntern());35993 union_type.setTagType(ip, provided_ty.toIntern());
35987 // The fields of the union must match the enum exactly.35994 // The fields of the union must match the enum exactly.
...@@ -36078,7 +36085,7 @@ fn unionFields(...@@ -36078,7 +36085,7 @@ fn unionFields(
36078 if (result.overflow) return sema.fail(36085 if (result.overflow) return sema.fail(
36079 &block_scope,36086 &block_scope,
36080 value_src,36087 value_src,
36081 "enumeration value '{}' too large for type '{}'",36088 "enumeration value '{f}' too large for type '{f}'",
36082 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },36089 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
36083 );36090 );
36084 last_tag_val = result.val;36091 last_tag_val = result.val;
...@@ -36096,7 +36103,7 @@ fn unionFields(...@@ -36096,7 +36103,7 @@ fn unionFields(
36096 const msg = msg: {36103 const msg = msg: {
36097 const msg = try sema.errMsg(36104 const msg = try sema.errMsg(
36098 value_src,36105 value_src,
36099 "enum tag value {} already taken",36106 "enum tag value {f} already taken",
36100 .{enum_tag_val.fmtValueSema(pt, sema)},36107 .{enum_tag_val.fmtValueSema(pt, sema)},
36101 );36108 );
36102 errdefer msg.destroy(gpa);36109 errdefer msg.destroy(gpa);
...@@ -36124,7 +36131,7 @@ fn unionFields(...@@ -36124,7 +36131,7 @@ fn unionFields(
36124 const tag_ty = union_type.tagTypeUnordered(ip);36131 const tag_ty = union_type.tagTypeUnordered(ip);
36125 const tag_info = ip.loadEnumType(tag_ty);36132 const tag_info = ip.loadEnumType(tag_ty);
36126 const enum_index = tag_info.nameIndex(ip, field_name) orelse {36133 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
36127 return sema.fail(&block_scope, name_src, "no field named '{}' in enum '{}'", .{36134 return sema.fail(&block_scope, name_src, "no field named '{f}' in enum '{f}'", .{
36128 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),36135 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
36129 });36136 });
36130 };36137 };
...@@ -36141,7 +36148,7 @@ fn unionFields(...@@ -36141,7 +36148,7 @@ fn unionFields(
36141 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,36148 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
36142 .offset = .{ .container_field_name = enum_index },36149 .offset = .{ .container_field_name = enum_index },
36143 };36150 };
36144 const msg = try sema.errMsg(name_src, "union field '{}' ordered differently than corresponding enum field", .{36151 const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{
36145 field_name.fmt(ip),36152 field_name.fmt(ip),
36146 });36153 });
36147 errdefer msg.destroy(sema.gpa);36154 errdefer msg.destroy(sema.gpa);
...@@ -36167,7 +36174,7 @@ fn unionFields(...@@ -36167,7 +36174,7 @@ fn unionFields(
36167 !try sema.validateExternType(field_ty, .union_field))36174 !try sema.validateExternType(field_ty, .union_field))
36168 {36175 {
36169 const msg = msg: {36176 const msg = msg: {
36170 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});36177 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
36171 errdefer msg.destroy(sema.gpa);36178 errdefer msg.destroy(sema.gpa);
3617236179
36173 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);36180 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);
...@@ -36178,7 +36185,7 @@ fn unionFields(...@@ -36178,7 +36185,7 @@ fn unionFields(
36178 return sema.failWithOwnedErrorMsg(&block_scope, msg);36185 return sema.failWithOwnedErrorMsg(&block_scope, msg);
36179 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {36186 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
36180 const msg = msg: {36187 const msg = msg: {
36181 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(pt)});36188 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
36182 errdefer msg.destroy(sema.gpa);36189 errdefer msg.destroy(sema.gpa);
3618336190
36184 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);36191 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);
...@@ -36214,7 +36221,7 @@ fn unionFields(...@@ -36214,7 +36221,7 @@ fn unionFields(
3621436221
36215 for (tag_info.names.get(ip), 0..) |field_name, field_index| {36222 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
36216 if (explicit_tags_seen[field_index]) continue;36223 if (explicit_tags_seen[field_index]) continue;
36217 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{36224 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{
36218 field_name.fmt(ip),36225 field_name.fmt(ip),
36219 });36226 });
36220 }36227 }
...@@ -36250,7 +36257,7 @@ fn generateUnionTagTypeNumbered(...@@ -36250,7 +36257,7 @@ fn generateUnionTagTypeNumbered(
36250 const name = try ip.getOrPutStringFmt(36257 const name = try ip.getOrPutStringFmt(
36251 gpa,36258 gpa,
36252 pt.tid,36259 pt.tid,
36253 "@typeInfo({}).@\"union\".tag_type.?",36260 "@typeInfo({f}).@\"union\".tag_type.?",
36254 .{union_name.fmt(ip)},36261 .{union_name.fmt(ip)},
36255 .no_embedded_nulls,36262 .no_embedded_nulls,
36256 );36263 );
...@@ -36286,7 +36293,7 @@ fn generateUnionTagTypeSimple(...@@ -36286,7 +36293,7 @@ fn generateUnionTagTypeSimple(
36286 const name = try ip.getOrPutStringFmt(36293 const name = try ip.getOrPutStringFmt(
36287 gpa,36294 gpa,
36288 pt.tid,36295 pt.tid,
36289 "@typeInfo({}).@\"union\".tag_type.?",36296 "@typeInfo({f}).@\"union\".tag_type.?",
36290 .{union_name.fmt(ip)},36297 .{union_name.fmt(ip)},
36291 .no_embedded_nulls,36298 .no_embedded_nulls,
36292 );36299 );
...@@ -36820,13 +36827,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr...@@ -36820,13 +36827,13 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
36820 .needed_well_defined => |ty| return sema.fail(36827 .needed_well_defined => |ty| return sema.fail(
36821 block,36828 block,
36822 src,36829 src,
36823 "comptime dereference requires '{}' to have a well-defined layout",36830 "comptime dereference requires '{f}' to have a well-defined layout",
36824 .{ty.fmt(pt)},36831 .{ty.fmt(pt)},
36825 ),36832 ),
36826 .out_of_bounds => |ty| return sema.fail(36833 .out_of_bounds => |ty| return sema.fail(
36827 block,36834 block,
36828 src,36835 src,
36829 "dereference of '{}' exceeds bounds of containing decl of type '{}'",36836 "dereference of '{f}' exceeds bounds of containing decl of type '{f}'",
36830 .{ ptr_ty.fmt(pt), ty.fmt(pt) },36837 .{ ptr_ty.fmt(pt), ty.fmt(pt) },
36831 ),36838 ),
36832 }36839 }
...@@ -36846,7 +36853,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value...@@ -36846,7 +36853,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
36846 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },36853 .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) },
36847 .runtime_load => return .runtime_load,36854 .runtime_load => return .runtime_load,
36848 .undef => return sema.failWithUseOfUndef(block, src),36855 .undef => return sema.failWithUseOfUndef(block, src),
36849 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {}", .{err_name.fmt(ip)}),36856 .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}),
36850 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),36857 .null_payload => return sema.fail(block, src, "attempt to use null value", .{}),
36851 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),36858 .inactive_union_field => return sema.fail(block, src, "access of inactive union field", .{}),
36852 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },36859 .needed_well_defined => |ty| return .{ .needed_well_defined = ty },
...@@ -36971,12 +36978,12 @@ fn intFromFloatScalar(...@@ -36971,12 +36978,12 @@ fn intFromFloatScalar(
3697136978
36972 const float = val.toFloat(f128, zcu);36979 const float = val.toFloat(f128, zcu);
36973 if (std.math.isNan(float)) {36980 if (std.math.isNan(float)) {
36974 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{36981 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{f}'", .{
36975 int_ty.fmt(pt),36982 int_ty.fmt(pt),
36976 });36983 });
36977 }36984 }
36978 if (std.math.isInf(float)) {36985 if (std.math.isInf(float)) {
36979 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{}'", .{36986 return sema.fail(block, src, "float value Inf cannot be stored in integer type '{f}'", .{
36980 int_ty.fmt(pt),36987 int_ty.fmt(pt),
36981 });36988 });
36982 }36989 }
...@@ -36991,7 +36998,7 @@ fn intFromFloatScalar(...@@ -36991,7 +36998,7 @@ fn intFromFloatScalar(
36991 .exact => return sema.fail(36998 .exact => return sema.fail(
36992 block,36999 block,
36993 src,37000 src,
36994 "fractional component prevents float value '{}' from coercion to type '{}'",37001 "fractional component prevents float value '{f}' from coercion to type '{f}'",
36995 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },37002 .{ val.fmtValueSema(pt, sema), int_ty.fmt(pt) },
36996 ),37003 ),
36997 .truncate => {},37004 .truncate => {},
...@@ -37003,7 +37010,7 @@ fn intFromFloatScalar(...@@ -37003,7 +37010,7 @@ fn intFromFloatScalar(
3700337010
37004 const int_info = int_ty.intInfo(zcu);37011 const int_info = int_ty.intInfo(zcu);
37005 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {37012 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {
37006 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{37013 return sema.fail(block, src, "float value '{f}' cannot be stored in integer type '{f}'", .{
37007 val.fmtValueSema(pt, sema), int_ty.fmt(pt),37014 val.fmtValueSema(pt, sema), int_ty.fmt(pt),
37008 });37015 });
37009 }37016 }
...@@ -37335,9 +37342,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37335,9 +37342,9 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
3733537342
37336 var first_path: std.ArrayListUnmanaged(u8) = .empty;37343 var first_path: std.ArrayListUnmanaged(u8) = .empty;
37337 if (intermediate_value_count == 0) {37344 if (intermediate_value_count == 0) {
37338 try first_path.writer(arena).print("{i}", .{start_value_name.fmt(ip)});37345 try first_path.print(arena, "{fi}", .{start_value_name.fmt(ip)});
37339 } else {37346 } else {
37340 try first_path.writer(arena).print("v{}", .{intermediate_value_count - 1});37347 try first_path.print(arena, "v{}", .{intermediate_value_count - 1});
37341 }37348 }
3734237349
37343 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);37350 const comptime_ptr = try sema.notePathToComptimeAllocPtrInner(val, &first_path);
...@@ -37362,30 +37369,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37362,30 +37369,26 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37362 error.AnalysisFail => unreachable,37369 error.AnalysisFail => unreachable,
37363 };37370 };
3736437371
37365 var second_path: std.ArrayListUnmanaged(u8) = .empty;37372 var second_path_aw: std.io.AllocatingWriter = undefined;
37373 second_path_aw.init(arena);
37366 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});37374 const inter_name = try std.fmt.allocPrint(arena, "v{d}", .{intermediate_value_count});
37367 const deriv_start = @import("print_value.zig").printPtrDerivation(37375 const deriv_start = @import("print_value.zig").printPtrDerivation(
37368 derivation,37376 derivation,
37369 second_path.writer(arena),37377 &second_path_aw.buffered_writer,
37370 pt,37378 pt,
37371 .lvalue,37379 .lvalue,
37372 .{ .str = inter_name },37380 .{ .str = inter_name },
37373 20,37381 20,
37374 ) catch |err| switch (err) {37382 ) catch |err| return @errorCast(err);
37375 error.OutOfMemory => |e| return e,
37376 error.AnalysisFail => unreachable,
37377 error.ComptimeReturn => unreachable,
37378 error.ComptimeBreak => unreachable,
37379 };
3738037383
37381 switch (deriv_start) {37384 switch (deriv_start) {
37382 .int, .nav_ptr => unreachable,37385 .int, .nav_ptr => unreachable,
37383 .uav_ptr => |uav| {37386 .uav_ptr => |uav| {
37384 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37387 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
37385 return .{ .new_val = .fromInterned(uav.val) };37388 return .{ .new_val = .fromInterned(uav.val) };
37386 },37389 },
37387 .comptime_alloc_ptr => |cta_info| {37390 .comptime_alloc_ptr => |cta_info| {
37388 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37391 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
37389 const cta = sema.getComptimeAlloc(cta_info.idx);37392 const cta = sema.getComptimeAlloc(cta_info.idx);
37390 if (cta.is_const) {37393 if (cta.is_const) {
37391 return .{ .new_val = cta_info.val };37394 return .{ .new_val = cta_info.val };
...@@ -37395,7 +37398,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,...@@ -37395,7 +37398,7 @@ fn notePathToComptimeAllocPtr(sema: *Sema, msg: *Zcu.ErrorMsg, src: LazySrcLoc,
37395 }37398 }
37396 },37399 },
37397 .comptime_field_ptr => {37400 .comptime_field_ptr => {
37398 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path.items });37401 try sema.errNote(src, msg, "'{s}' points to '{s}', where", .{ first_path.items, second_path_aw.getWritten() });
37399 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});37402 try sema.errNote(src, msg, "'{s}' is a comptime field", .{inter_name});
37400 return .done;37403 return .done;
37401 },37404 },
...@@ -37435,7 +37438,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37435,7 +37438,7 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37435 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);37438 const backing_enum = union_ty.unionTagTypeHypothetical(zcu);
37436 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;37439 const field_idx = backing_enum.enumTagFieldIndex(.fromInterned(un.tag), zcu).?;
37437 const field_name = backing_enum.enumFieldName(field_idx, zcu);37440 const field_name = backing_enum.enumFieldName(field_idx, zcu);
37438 try path.writer(arena).print(".{i}", .{field_name.fmt(ip)});37441 try path.print(arena, ".{fi}", .{field_name.fmt(ip)});
37439 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);37442 return sema.notePathToComptimeAllocPtrInner(.fromInterned(un.val), path);
37440 },37443 },
37441 .aggregate => |agg| {37444 .aggregate => |agg| {
...@@ -37450,17 +37453,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList...@@ -37450,17 +37453,17 @@ fn notePathToComptimeAllocPtrInner(sema: *Sema, val: Value, path: *std.ArrayList
37450 };37453 };
37451 const agg_ty: Type = .fromInterned(agg.ty);37454 const agg_ty: Type = .fromInterned(agg.ty);
37452 switch (agg_ty.zigTypeTag(zcu)) {37455 switch (agg_ty.zigTypeTag(zcu)) {
37453 .array, .vector => try path.writer(arena).print("[{d}]", .{elem_idx}),37456 .array, .vector => try path.print(arena, "[{d}]", .{elem_idx}),
37454 .pointer => switch (elem_idx) {37457 .pointer => switch (elem_idx) {
37455 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),37458 Value.slice_ptr_index => try path.appendSlice(arena, ".ptr"),
37456 Value.slice_len_index => try path.appendSlice(arena, ".len"),37459 Value.slice_len_index => try path.appendSlice(arena, ".len"),
37457 else => unreachable,37460 else => unreachable,
37458 },37461 },
37459 .@"struct" => if (agg_ty.isTuple(zcu)) {37462 .@"struct" => if (agg_ty.isTuple(zcu)) {
37460 try path.writer(arena).print("[{d}]", .{elem_idx});37463 try path.print(arena, "[{d}]", .{elem_idx});
37461 } else {37464 } else {
37462 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;37465 const name = agg_ty.structFieldName(elem_idx, zcu).unwrap().?;
37463 try path.writer(arena).print(".{i}", .{name.fmt(ip)});37466 try path.print(arena, ".{fi}", .{name.fmt(ip)});
37464 },37467 },
37465 else => unreachable,37468 else => unreachable,
37466 }37469 }
...@@ -37737,7 +37740,7 @@ fn resolveDeclaredEnumInner(...@@ -37737,7 +37740,7 @@ fn resolveDeclaredEnumInner(
37737 if (tag_type_ref != .none) {37740 if (tag_type_ref != .none) {
37738 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);37741 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
37739 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {37742 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {
37740 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(pt)});37743 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)});
37741 }37744 }
37742 break :ty ty;37745 break :ty ty;
37743 } else if (fields_len == 0) {37746 } else if (fields_len == 0) {
...@@ -37791,7 +37794,7 @@ fn resolveDeclaredEnumInner(...@@ -37791,7 +37794,7 @@ fn resolveDeclaredEnumInner(
37791 .offset = .{ .container_field_value = conflict.prev_field_idx },37794 .offset = .{ .container_field_value = conflict.prev_field_idx },
37792 };37795 };
37793 const msg = msg: {37796 const msg = msg: {
37794 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});37797 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37795 errdefer msg.destroy(gpa);37798 errdefer msg.destroy(gpa);
37796 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37799 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37797 break :msg msg;37800 break :msg msg;
...@@ -37814,7 +37817,7 @@ fn resolveDeclaredEnumInner(...@@ -37814,7 +37817,7 @@ fn resolveDeclaredEnumInner(
37814 .offset = .{ .container_field_value = conflict.prev_field_idx },37817 .offset = .{ .container_field_value = conflict.prev_field_idx },
37815 };37818 };
37816 const msg = msg: {37819 const msg = msg: {
37817 const msg = try sema.errMsg(value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});37820 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37818 errdefer msg.destroy(gpa);37821 errdefer msg.destroy(gpa);
37819 try sema.errNote(other_field_src, msg, "other occurrence here", .{});37822 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37820 break :msg msg;37823 break :msg msg;
...@@ -37831,7 +37834,7 @@ fn resolveDeclaredEnumInner(...@@ -37831,7 +37834,7 @@ fn resolveDeclaredEnumInner(
37831 };37834 };
3783237835
37833 if (tag_overflow) {37836 if (tag_overflow) {
37834 const msg = try sema.errMsg(value_src, "enumeration value '{}' too large for type '{}'", .{37837 const msg = try sema.errMsg(value_src, "enumeration value '{f}' too large for type '{f}'", .{
37835 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),37838 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
37836 });37839 });
37837 return sema.failWithOwnedErrorMsg(block, msg);37840 return sema.failWithOwnedErrorMsg(block, msg);
src/Sema/LowerZon.zig+16-16
...@@ -338,7 +338,7 @@ fn failUnsupportedResultType(...@@ -338,7 +338,7 @@ fn failUnsupportedResultType(
338 const gpa = sema.gpa;338 const gpa = sema.gpa;
339 const pt = sema.pt;339 const pt = sema.pt;
340 return sema.failWithOwnedErrorMsg(self.block, msg: {340 return sema.failWithOwnedErrorMsg(self.block, msg: {
341 const msg = try sema.errMsg(self.import_loc, "type '{}' is not available in ZON", .{ty.fmt(pt)});341 const msg = try sema.errMsg(self.import_loc, "type '{f}' is not available in ZON", .{ty.fmt(pt)});
342 errdefer msg.destroy(gpa);342 errdefer msg.destroy(gpa);
343 if (opt_note) |n| try sema.errNote(self.import_loc, msg, "{s}", .{n});343 if (opt_note) |n| try sema.errNote(self.import_loc, msg, "{s}", .{n});
344 break :msg msg;344 break :msg msg;
...@@ -362,7 +362,7 @@ fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) Com...@@ -362,7 +362,7 @@ fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) Com
362 return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {362 return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {
363 error.WrongType => return self.fail(363 error.WrongType => return self.fail(
364 node,364 node,
365 "expected type '{}'",365 "expected type '{f}'",
366 .{res_ty.fmt(pt)},366 .{res_ty.fmt(pt)},
367 ),367 ),
368 else => |e| return e,368 else => |e| return e,
...@@ -428,7 +428,7 @@ fn lowerExprKnownResTyInner(...@@ -428,7 +428,7 @@ fn lowerExprKnownResTyInner(
428 .frame,428 .frame,
429 .@"anyframe",429 .@"anyframe",
430 .void,430 .void,
431 => return self.fail(node, "type '{}' not available in ZON", .{res_ty.fmt(pt)}),431 => return self.fail(node, "type '{f}' not available in ZON", .{res_ty.fmt(pt)}),
432 }432 }
433}433}
434434
...@@ -458,7 +458,7 @@ fn lowerInt(...@@ -458,7 +458,7 @@ fn lowerInt(
458 // If lhs is unsigned and rhs is less than 0, we're out of bounds458 // If lhs is unsigned and rhs is less than 0, we're out of bounds
459 if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail(459 if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail(
460 node,460 node,
461 "type '{}' cannot represent integer value '{}'",461 "type '{f}' cannot represent integer value '{}'",
462 .{ res_ty.fmt(self.sema.pt), rhs },462 .{ res_ty.fmt(self.sema.pt), rhs },
463 );463 );
464464
...@@ -478,7 +478,7 @@ fn lowerInt(...@@ -478,7 +478,7 @@ fn lowerInt(
478 if (rhs < min_int or rhs > max_int) {478 if (rhs < min_int or rhs > max_int) {
479 return self.fail(479 return self.fail(
480 node,480 node,
481 "type '{}' cannot represent integer value '{}'",481 "type '{f}' cannot represent integer value '{}'",
482 .{ res_ty.fmt(self.sema.pt), rhs },482 .{ res_ty.fmt(self.sema.pt), rhs },
483 );483 );
484 }484 }
...@@ -496,7 +496,7 @@ fn lowerInt(...@@ -496,7 +496,7 @@ fn lowerInt(
496 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {496 if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) {
497 return self.fail(497 return self.fail(
498 node,498 node,
499 "type '{}' cannot represent integer value '{}'",499 "type '{f}' cannot represent integer value '{f}'",
500 .{ res_ty.fmt(self.sema.pt), val },500 .{ res_ty.fmt(self.sema.pt), val },
501 );501 );
502 }502 }
...@@ -517,7 +517,7 @@ fn lowerInt(...@@ -517,7 +517,7 @@ fn lowerInt(
517 switch (big_int.setFloat(val, .trunc)) {517 switch (big_int.setFloat(val, .trunc)) {
518 .inexact => return self.fail(518 .inexact => return self.fail(
519 node,519 node,
520 "fractional component prevents float value '{}' from coercion to type '{}'",520 "fractional component prevents float value '{}' from coercion to type '{f}'",
521 .{ val, res_ty.fmt(self.sema.pt) },521 .{ val, res_ty.fmt(self.sema.pt) },
522 ),522 ),
523 .exact => {},523 .exact => {},
...@@ -528,7 +528,7 @@ fn lowerInt(...@@ -528,7 +528,7 @@ fn lowerInt(
528 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {528 if (!big_int.toConst().fitsInTwosComp(int_info.signedness, int_info.bits)) {
529 return self.fail(529 return self.fail(
530 node,530 node,
531 "type '{}' cannot represent integer value '{}'",531 "type '{}' cannot represent integer value '{f}'",
532 .{ val, res_ty.fmt(self.sema.pt) },532 .{ val, res_ty.fmt(self.sema.pt) },
533 );533 );
534 }534 }
...@@ -550,7 +550,7 @@ fn lowerInt(...@@ -550,7 +550,7 @@ fn lowerInt(
550 if (val >= out_of_range) {550 if (val >= out_of_range) {
551 return self.fail(551 return self.fail(
552 node,552 node,
553 "type '{}' cannot represent integer value '{}'",553 "type '{f}' cannot represent integer value '{}'",
554 .{ res_ty.fmt(self.sema.pt), val },554 .{ res_ty.fmt(self.sema.pt), val },
555 );555 );
556 }556 }
...@@ -584,7 +584,7 @@ fn lowerFloat(...@@ -584,7 +584,7 @@ fn lowerFloat(
584 .pos_inf => b: {584 .pos_inf => b: {
585 if (res_ty.toIntern() == .comptime_float_type) return self.fail(585 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
586 node,586 node,
587 "expected type '{}'",587 "expected type '{f}'",
588 .{res_ty.fmt(self.sema.pt)},588 .{res_ty.fmt(self.sema.pt)},
589 );589 );
590 break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128));590 break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128));
...@@ -592,7 +592,7 @@ fn lowerFloat(...@@ -592,7 +592,7 @@ fn lowerFloat(
592 .neg_inf => b: {592 .neg_inf => b: {
593 if (res_ty.toIntern() == .comptime_float_type) return self.fail(593 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
594 node,594 node,
595 "expected type '{}'",595 "expected type '{f}'",
596 .{res_ty.fmt(self.sema.pt)},596 .{res_ty.fmt(self.sema.pt)},
597 );597 );
598 break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128));598 break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128));
...@@ -600,7 +600,7 @@ fn lowerFloat(...@@ -600,7 +600,7 @@ fn lowerFloat(
600 .nan => b: {600 .nan => b: {
601 if (res_ty.toIntern() == .comptime_float_type) return self.fail(601 if (res_ty.toIntern() == .comptime_float_type) return self.fail(
602 node,602 node,
603 "expected type '{}'",603 "expected type '{f}'",
604 .{res_ty.fmt(self.sema.pt)},604 .{res_ty.fmt(self.sema.pt)},
605 );605 );
606 break :b try self.sema.pt.floatValue(res_ty, std.math.nan(f128));606 break :b try self.sema.pt.floatValue(res_ty, std.math.nan(f128));
...@@ -661,7 +661,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I...@@ -661,7 +661,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I
661 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {661 const field_index = res_ty.enumFieldIndex(field_name_interned, self.sema.pt.zcu) orelse {
662 return self.fail(662 return self.fail(
663 node,663 node,
664 "enum {} has no member named '{}'",664 "enum {f} has no member named '{f}'",
665 .{665 .{
666 res_ty.fmt(self.sema.pt),666 res_ty.fmt(self.sema.pt),
667 std.zig.fmtId(field_name.get(self.file.zoir.?)),667 std.zig.fmtId(field_name.get(self.file.zoir.?)),
...@@ -795,7 +795,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -795,7 +795,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
795 const field_node = fields.vals.at(@intCast(i));795 const field_node = fields.vals.at(@intCast(i));
796796
797 const name_index = struct_info.nameIndex(ip, field_name) orelse {797 const name_index = struct_info.nameIndex(ip, field_name) orelse {
798 return self.fail(field_node, "unexpected field '{}'", .{field_name.fmt(ip)});798 return self.fail(field_node, "unexpected field '{f}'", .{field_name.fmt(ip)});
799 };799 };
800800
801 const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);801 const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);
...@@ -816,7 +816,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -816,7 +816,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
816816
817 const field_names = struct_info.field_names.get(ip);817 const field_names = struct_info.field_names.get(ip);
818 for (field_values, field_names) |*value, name| {818 for (field_values, field_names) |*value, name| {
819 if (value.* == .none) return self.fail(node, "missing field '{}'", .{name.fmt(ip)});819 if (value.* == .none) return self.fail(node, "missing field '{f}'", .{name.fmt(ip)});
820 }820 }
821821
822 return self.sema.pt.intern(.{ .aggregate = .{822 return self.sema.pt.intern(.{ .aggregate = .{
...@@ -934,7 +934,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -934,7 +934,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
934 .struct_literal => b: {934 .struct_literal => b: {
935 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {935 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {
936 .struct_literal => |fields| fields,936 .struct_literal => |fields| fields,
937 else => return self.fail(node, "expected type '{}'", .{res_ty.fmt(self.sema.pt)}),937 else => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(self.sema.pt)}),
938 };938 };
939 if (fields.names.len != 1) {939 if (fields.names.len != 1) {
940 return error.WrongType;940 return error.WrongType;
src/Type.zig+67-91
...@@ -142,9 +142,9 @@ const FormatContext = struct {...@@ -142,9 +142,9 @@ const FormatContext = struct {
142 pt: Zcu.PerThread,142 pt: Zcu.PerThread,
143};143};
144144
145fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime f: []const u8) anyerror!usize {145fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime f: []const u8) anyerror!void {
146 comptime assert(f.len == 0);146 comptime assert(f.len == 0);
147 return print(ctx.ty, bw, ctx.pt);147 try print(ctx.ty, bw, ctx.pt);
148}148}
149149
150pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {150pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {
...@@ -153,20 +153,14 @@ pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {...@@ -153,20 +153,14 @@ pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {
153153
154/// This is a debug function. In order to print types in a meaningful way154/// This is a debug function. In order to print types in a meaningful way
155/// we also need access to the module.155/// we also need access to the module.
156pub fn dump(156pub fn dump(start_type: Type, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
157 start_type: Type,
158 comptime unused_format_string: []const u8,
159 options: std.fmt.FormatOptions,
160 writer: anytype,
161) @TypeOf(writer).Error!void {
162 _ = options;
163 comptime assert(unused_format_string.len == 0);157 comptime assert(unused_format_string.len == 0);
164 return writer.print("{any}", .{start_type.ip_index});158 return bw.print("{any}", .{start_type.ip_index});
165}159}
166160
167/// Prints a name suitable for `@typeName`.161/// Prints a name suitable for `@typeName`.
168/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.162/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
169pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!usize {163pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!void {
170 const zcu = pt.zcu;164 const zcu = pt.zcu;
171 const ip = &zcu.intern_pool;165 const ip = &zcu.intern_pool;
172 switch (ip.indexToKey(ty.toIntern())) {166 switch (ip.indexToKey(ty.toIntern())) {
...@@ -176,23 +170,22 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u...@@ -176,23 +170,22 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u
176 .signed => 'i',170 .signed => 'i',
177 .unsigned => 'u',171 .unsigned => 'u',
178 };172 };
179 return bw.print("{c}{d}", .{ sign_char, int_type.bits });173 try bw.print("{c}{d}", .{ sign_char, int_type.bits });
180 },174 },
181 .ptr_type => {175 .ptr_type => {
182 var n: usize = 0;
183 const info = ty.ptrInfo(zcu);176 const info = ty.ptrInfo(zcu);
184177
185 if (info.sentinel != .none) switch (info.flags.size) {178 if (info.sentinel != .none) switch (info.flags.size) {
186 .one, .c => unreachable,179 .one, .c => unreachable,
187 .many => n += try bw.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),180 .many => try bw.print("[*:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
188 .slice => n += try bw.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),181 .slice => try bw.print("[:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
189 } else switch (info.flags.size) {182 } else switch (info.flags.size) {
190 .one => n += try bw.writeAll("*"),183 .one => try bw.writeAll("*"),
191 .many => n += try bw.writeAll("[*]"),184 .many => try bw.writeAll("[*]"),
192 .c => n += try bw.writeAll("[*c]"),185 .c => try bw.writeAll("[*c]"),
193 .slice => n += try bw.writeAll("[]"),186 .slice => try bw.writeAll("[]"),
194 }187 }
195 if (info.flags.is_allowzero and info.flags.size != .c) n += try bw.writeAll("allowzero ");188 if (info.flags.is_allowzero and info.flags.size != .c) try bw.writeAll("allowzero ");
196 if (info.flags.alignment != .none or189 if (info.flags.alignment != .none or
197 info.packed_offset.host_size != 0 or190 info.packed_offset.host_size != 0 or
198 info.flags.vector_index != .none)191 info.flags.vector_index != .none)
...@@ -201,83 +194,72 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u...@@ -201,83 +194,72 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u
201 info.flags.alignment194 info.flags.alignment
202 else195 else
203 Type.fromInterned(info.child).abiAlignment(pt.zcu);196 Type.fromInterned(info.child).abiAlignment(pt.zcu);
204 n += try bw.print("align({d}", .{alignment.toByteUnits() orelse 0});197 try bw.print("align({d}", .{alignment.toByteUnits() orelse 0});
205198
206 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {199 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
207 n += try bw.print(":{d}:{d}", .{200 try bw.print(":{d}:{d}", .{
208 info.packed_offset.bit_offset, info.packed_offset.host_size,201 info.packed_offset.bit_offset, info.packed_offset.host_size,
209 });202 });
210 }203 }
211 if (info.flags.vector_index == .runtime) {204 if (info.flags.vector_index == .runtime) {
212 n += try bw.writeAll(":?");205 try bw.writeAll(":?");
213 } else if (info.flags.vector_index != .none) {206 } else if (info.flags.vector_index != .none) {
214 n += try bw.print(":{d}", .{@intFromEnum(info.flags.vector_index)});207 try bw.print(":{d}", .{@intFromEnum(info.flags.vector_index)});
215 }208 }
216 n += try bw.writeAll(") ");209 try bw.writeAll(") ");
217 }210 }
218 if (info.flags.address_space != .generic) {211 if (info.flags.address_space != .generic) {
219 n += try bw.print("addrspace(.{s}) ", .{@tagName(info.flags.address_space)});212 try bw.print("addrspace(.{s}) ", .{@tagName(info.flags.address_space)});
220 }213 }
221 if (info.flags.is_const) n += try bw.writeAll("const ");214 if (info.flags.is_const) try bw.writeAll("const ");
222 if (info.flags.is_volatile) n += try bw.writeAll("volatile ");215 if (info.flags.is_volatile) try bw.writeAll("volatile ");
223216
224 n += try print(Type.fromInterned(info.child), bw, pt);217 try print(Type.fromInterned(info.child), bw, pt);
225 return n;
226 },218 },
227 .array_type => |array_type| {219 .array_type => |array_type| {
228 var n: usize = 0;
229 if (array_type.sentinel == .none) {220 if (array_type.sentinel == .none) {
230 n += try bw.print("[{d}]", .{array_type.len});221 try bw.print("[{d}]", .{array_type.len});
231 n += try print(Type.fromInterned(array_type.child), bw, pt);222 try print(Type.fromInterned(array_type.child), bw, pt);
232 } else {223 } else {
233 n += try bw.print("[{d}:{}]", .{224 try bw.print("[{d}:{f}]", .{
234 array_type.len,225 array_type.len,
235 Value.fromInterned(array_type.sentinel).fmtValue(pt),226 Value.fromInterned(array_type.sentinel).fmtValue(pt),
236 });227 });
237 n += try print(Type.fromInterned(array_type.child), bw, pt);228 try print(Type.fromInterned(array_type.child), bw, pt);
238 }229 }
239 return n;
240 },230 },
241 .vector_type => |vector_type| {231 .vector_type => |vector_type| {
242 var n: usize = 0;232 try bw.print("@Vector({d}, ", .{vector_type.len});
243 n += try bw.print("@Vector({d}, ", .{vector_type.len});233 try print(Type.fromInterned(vector_type.child), bw, pt);
244 n += try print(Type.fromInterned(vector_type.child), bw, pt);234 try bw.writeAll(")");
245 n += try bw.writeAll(")");
246 return n;
247 },235 },
248 .opt_type => |child| {236 .opt_type => |child| {
249 var n: usize = 0;237 try bw.writeByte('?');
250 n += try bw.writeByte('?');238 try print(Type.fromInterned(child), bw, pt);
251 n += try print(Type.fromInterned(child), bw, pt);
252 return n;
253 },239 },
254 .error_union_type => |error_union_type| {240 .error_union_type => |error_union_type| {
255 var n: usize = 0;241 try print(Type.fromInterned(error_union_type.error_set_type), bw, pt);
256 n += try print(Type.fromInterned(error_union_type.error_set_type), bw, pt);242 try bw.writeByte('!');
257 n += try bw.writeByte('!');
258 if (error_union_type.payload_type == .generic_poison_type) {243 if (error_union_type.payload_type == .generic_poison_type) {
259 n += try bw.writeAll("anytype");244 try bw.writeAll("anytype");
260 } else {245 } else {
261 n += try print(Type.fromInterned(error_union_type.payload_type), bw, pt);246 try print(Type.fromInterned(error_union_type.payload_type), bw, pt);
262 }247 }
263 return n;
264 },248 },
265 .inferred_error_set_type => |func_index| {249 .inferred_error_set_type => |func_index| {
266 const func_nav = ip.getNav(zcu.funcInfo(func_index).owner_nav);250 const func_nav = ip.getNav(zcu.funcInfo(func_index).owner_nav);
267 return bw.print("@typeInfo(@typeInfo(@TypeOf({})).@\"fn\".return_type.?).error_union.error_set", .{251 return bw.print("@typeInfo(@typeInfo(@TypeOf({f})).@\"fn\".return_type.?).error_union.error_set", .{
268 func_nav.fqn.fmt(ip),252 func_nav.fqn.fmt(ip),
269 });253 });
270 },254 },
271 .error_set_type => |error_set_type| {255 .error_set_type => |error_set_type| {
272 var n: usize = 0;
273 const names = error_set_type.names;256 const names = error_set_type.names;
274 n += try bw.writeAll("error{");257 try bw.writeAll("error{");
275 for (names.get(ip), 0..) |name, i| {258 for (names.get(ip), 0..) |name, i| {
276 if (i != 0) n += try bw.writeByte(',');259 if (i != 0) try bw.writeByte(',');
277 n += try bw.print("{}", .{name.fmt(ip)});260 try bw.print("{f}", .{name.fmt(ip)});
278 }261 }
279 n += try bw.writeAll("}");262 try bw.writeAll("}");
280 return n;
281 },263 },
282 .simple_type => |s| switch (s) {264 .simple_type => |s| switch (s) {
283 .f16,265 .f16,
...@@ -318,91 +300,85 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u...@@ -318,91 +300,85 @@ pub fn print(ty: Type, bw: *std.io.BufferedWriter, pt: Zcu.PerThread) anyerror!u
318 },300 },
319 .struct_type => {301 .struct_type => {
320 const name = ip.loadStructType(ty.toIntern()).name;302 const name = ip.loadStructType(ty.toIntern()).name;
321 return bw.print("{}", .{name.fmt(ip)});303 return bw.print("{f}", .{name.fmt(ip)});
322 },304 },
323 .tuple_type => |tuple| {305 .tuple_type => |tuple| {
324 if (tuple.types.len == 0) {306 if (tuple.types.len == 0) {
325 return bw.writeAll("@TypeOf(.{})");307 return bw.writeAll("@TypeOf(.{})");
326 }308 }
327 var n: usize = 0;309 try bw.writeAll("struct {");
328 n += try bw.writeAll("struct {");
329 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, val, i| {310 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, val, i| {
330 n += try bw.writeAll(if (i == 0) " " else ", ");311 try bw.writeAll(if (i == 0) " " else ", ");
331 if (val != .none) n += try bw.writeAll("comptime ");312 if (val != .none) try bw.writeAll("comptime ");
332 n += try print(Type.fromInterned(field_ty), bw, pt);313 try print(Type.fromInterned(field_ty), bw, pt);
333 if (val != .none) n += try bw.print(" = {}", .{Value.fromInterned(val).fmtValue(pt)});314 if (val != .none) try bw.print(" = {f}", .{Value.fromInterned(val).fmtValue(pt)});
334 }315 }
335 n += try bw.writeAll(" }");316 try bw.writeAll(" }");
336 return n;
337 },317 },
338318
339 .union_type => {319 .union_type => {
340 const name = ip.loadUnionType(ty.toIntern()).name;320 const name = ip.loadUnionType(ty.toIntern()).name;
341 return bw.print("{}", .{name.fmt(ip)});321 return bw.print("{f}", .{name.fmt(ip)});
342 },322 },
343 .opaque_type => {323 .opaque_type => {
344 const name = ip.loadOpaqueType(ty.toIntern()).name;324 const name = ip.loadOpaqueType(ty.toIntern()).name;
345 return bw.print("{}", .{name.fmt(ip)});325 return bw.print("{f}", .{name.fmt(ip)});
346 },326 },
347 .enum_type => {327 .enum_type => {
348 const name = ip.loadEnumType(ty.toIntern()).name;328 const name = ip.loadEnumType(ty.toIntern()).name;
349 return bw.print("{}", .{name.fmt(ip)});329 return bw.print("{f}", .{name.fmt(ip)});
350 },330 },
351 .func_type => |fn_info| {331 .func_type => |fn_info| {
352 var n: usize = 0;
353 if (fn_info.is_noinline) {332 if (fn_info.is_noinline) {
354 n += try bw.writeAll("noinline ");333 try bw.writeAll("noinline ");
355 }334 }
356 n += try bw.writeAll("fn (");335 try bw.writeAll("fn (");
357 const param_types = fn_info.param_types.get(&zcu.intern_pool);336 const param_types = fn_info.param_types.get(&zcu.intern_pool);
358 for (param_types, 0..) |param_ty, i| {337 for (param_types, 0..) |param_ty, i| {
359 if (i != 0) n += try bw.writeAll(", ");338 if (i != 0) try bw.writeAll(", ");
360 if (std.math.cast(u5, i)) |index| {339 if (std.math.cast(u5, i)) |index| {
361 if (fn_info.paramIsComptime(index)) {340 if (fn_info.paramIsComptime(index)) {
362 n += try bw.writeAll("comptime ");341 try bw.writeAll("comptime ");
363 }342 }
364 if (fn_info.paramIsNoalias(index)) {343 if (fn_info.paramIsNoalias(index)) {
365 n += try bw.writeAll("noalias ");344 try bw.writeAll("noalias ");
366 }345 }
367 }346 }
368 if (param_ty == .generic_poison_type) {347 if (param_ty == .generic_poison_type) {
369 n += try bw.writeAll("anytype");348 try bw.writeAll("anytype");
370 } else {349 } else {
371 n += try print(Type.fromInterned(param_ty), bw, pt);350 try print(Type.fromInterned(param_ty), bw, pt);
372 }351 }
373 }352 }
374 if (fn_info.is_var_args) {353 if (fn_info.is_var_args) {
375 if (param_types.len != 0) {354 if (param_types.len != 0) {
376 n += try bw.writeAll(", ");355 try bw.writeAll(", ");
377 }356 }
378 n += try bw.writeAll("...");357 try bw.writeAll("...");
379 }358 }
380 n += try bw.writeAll(") ");359 try bw.writeAll(") ");
381 if (fn_info.cc != .auto) print_cc: {360 if (fn_info.cc != .auto) print_cc: {
382 if (zcu.getTarget().cCallingConvention()) |ccc| {361 if (zcu.getTarget().cCallingConvention()) |ccc| {
383 if (fn_info.cc.eql(ccc)) {362 if (fn_info.cc.eql(ccc)) {
384 n += try bw.writeAll("callconv(.c) ");363 try bw.writeAll("callconv(.c) ");
385 break :print_cc;364 break :print_cc;
386 }365 }
387 }366 }
388 switch (fn_info.cc) {367 switch (fn_info.cc) {
389 .auto, .@"async", .naked, .@"inline" => n += try bw.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),368 .auto, .@"async", .naked, .@"inline" => try bw.print("callconv(.{f}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),
390 else => n += try bw.print("callconv({any}) ", .{fn_info.cc}),369 else => try bw.print("callconv({any}) ", .{fn_info.cc}),
391 }370 }
392 }371 }
393 if (fn_info.return_type == .generic_poison_type) {372 if (fn_info.return_type == .generic_poison_type) {
394 n += try bw.writeAll("anytype");373 try bw.writeAll("anytype");
395 } else {374 } else {
396 n += try print(Type.fromInterned(fn_info.return_type), bw, pt);375 try print(Type.fromInterned(fn_info.return_type), bw, pt);
397 }376 }
398 return n;
399 },377 },
400 .anyframe_type => |child| {378 .anyframe_type => |child| {
401 if (child == .none) return bw.writeAll("anyframe");379 if (child == .none) return bw.writeAll("anyframe");
402 var n: usize = 0;380 try bw.writeAll("anyframe->");
403 n += try bw.writeAll("anyframe->");381 try print(Type.fromInterned(child), bw, pt);
404 n += print(Type.fromInterned(child), bw, pt);
405 return n;
406 },382 },
407383
408 // values, not types384 // values, not types
src/Zcu.zig+60-63
...@@ -862,7 +862,7 @@ pub const Namespace = struct {...@@ -862,7 +862,7 @@ pub const Namespace = struct {
862 try ns.fileScope(zcu).renderFullyQualifiedDebugName(writer);862 try ns.fileScope(zcu).renderFullyQualifiedDebugName(writer);
863 break :sep ':';863 break :sep ':';
864 };864 };
865 if (name != .empty) try writer.print("{c}{}", .{ sep, name.fmt(&zcu.intern_pool) });865 if (name != .empty) try writer.print("{c}{f}", .{ sep, name.fmt(&zcu.intern_pool) });
866 }866 }
867867
868 pub fn internFullyQualifiedName(868 pub fn internFullyQualifiedName(
...@@ -874,7 +874,7 @@ pub const Namespace = struct {...@@ -874,7 +874,7 @@ pub const Namespace = struct {
874 ) !InternPool.NullTerminatedString {874 ) !InternPool.NullTerminatedString {
875 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);875 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);
876 if (name == .empty) return ns_name;876 if (name == .empty) return ns_name;
877 return ip.getOrPutStringFmt(gpa, tid, "{}.{}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);877 return ip.getOrPutStringFmt(gpa, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);
878 }878 }
879};879};
880880
...@@ -1101,11 +1101,11 @@ pub const File = struct {...@@ -1101,11 +1101,11 @@ pub const File = struct {
1101 const gpa = pt.zcu.gpa;1101 const gpa = pt.zcu.gpa;
1102 const ip = &pt.zcu.intern_pool;1102 const ip = &pt.zcu.intern_pool;
1103 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);1103 const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);
1104 const slice = try strings.addManyAsSlice(file.fullyQualifiedNameLen());1104 var bw: std.io.BufferedWriter = undefined;
1105 var fbs = std.io.fixedBufferStream(slice[0]);1105 bw.initFixed((try strings.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);
1106 file.renderFullyQualifiedName(fbs.writer()) catch unreachable;1106 file.renderFullyQualifiedName(&bw) catch unreachable;
1107 assert(fbs.pos == slice[0].len);1107 assert(bw.end == bw.buffer.len);
1108 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls);1108 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(bw.end), .no_embedded_nulls);
1109 }1109 }
11101110
1111 pub const Index = InternPool.FileIndex;1111 pub const Index = InternPool.FileIndex;
...@@ -1194,13 +1194,8 @@ pub const ErrorMsg = struct {...@@ -1194,13 +1194,8 @@ pub const ErrorMsg = struct {
1194 gpa.destroy(err_msg);1194 gpa.destroy(err_msg);
1195 }1195 }
11961196
1197 pub fn init(1197 pub fn init(gpa: Allocator, src_loc: LazySrcLoc, comptime format: []const u8, args: anytype) !ErrorMsg {
1198 gpa: Allocator,1198 return .{
1199 src_loc: LazySrcLoc,
1200 comptime format: []const u8,
1201 args: anytype,
1202 ) !ErrorMsg {
1203 return ErrorMsg{
1204 .src_loc = src_loc,1199 .src_loc = src_loc,
1205 .msg = try std.fmt.allocPrint(gpa, format, args),1200 .msg = try std.fmt.allocPrint(gpa, format, args),
1206 };1201 };
...@@ -2822,7 +2817,9 @@ comptime {...@@ -2822,7 +2817,9 @@ comptime {
2822}2817}
28232818
2824pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {2819pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
2825 return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);2820 var header: Zir.Header = undefined;
2821 if (try cache_file.readAll(std.mem.asBytes(&header)) < @sizeOf(Zir.Header)) return error.EndOfStream;
2822 return loadZirCacheBody(gpa, header, cache_file);
2826}2823}
28272824
2828pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {2825pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
...@@ -3082,7 +3079,7 @@ pub fn markDependeeOutdated(...@@ -3082,7 +3079,7 @@ pub fn markDependeeOutdated(
3082 marked_po: enum { not_marked_po, marked_po },3079 marked_po: enum { not_marked_po, marked_po },
3083 dependee: InternPool.Dependee,3080 dependee: InternPool.Dependee,
3084) !void {3081) !void {
3085 log.debug("outdated dependee: {}", .{zcu.fmtDependee(dependee)});3082 log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3086 var it = zcu.intern_pool.dependencyIterator(dependee);3083 var it = zcu.intern_pool.dependencyIterator(dependee);
3087 while (it.next()) |depender| {3084 while (it.next()) |depender| {
3088 if (zcu.outdated.getPtr(depender)) |po_dep_count| {3085 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
...@@ -3090,9 +3087,9 @@ pub fn markDependeeOutdated(...@@ -3090,9 +3087,9 @@ pub fn markDependeeOutdated(
3090 .not_marked_po => {},3087 .not_marked_po => {},
3091 .marked_po => {3088 .marked_po => {
3092 po_dep_count.* -= 1;3089 po_dep_count.* -= 1;
3093 log.debug("outdated {} => already outdated {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });3090 log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3094 if (po_dep_count.* == 0) {3091 if (po_dep_count.* == 0) {
3095 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});3092 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3096 try zcu.outdated_ready.put(zcu.gpa, depender, {});3093 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3097 }3094 }
3098 },3095 },
...@@ -3113,9 +3110,9 @@ pub fn markDependeeOutdated(...@@ -3113,9 +3110,9 @@ pub fn markDependeeOutdated(
3113 depender,3110 depender,
3114 new_po_dep_count,3111 new_po_dep_count,
3115 );3112 );
3116 log.debug("outdated {} => new outdated {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });3113 log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });
3117 if (new_po_dep_count == 0) {3114 if (new_po_dep_count == 0) {
3118 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});3115 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3119 try zcu.outdated_ready.put(zcu.gpa, depender, {});3116 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3120 }3117 }
3121 // If this is a Decl and was not previously PO, we must recursively3118 // If this is a Decl and was not previously PO, we must recursively
...@@ -3128,16 +3125,16 @@ pub fn markDependeeOutdated(...@@ -3128,16 +3125,16 @@ pub fn markDependeeOutdated(
3128}3125}
31293126
3130pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {3127pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3131 log.debug("up-to-date dependee: {}", .{zcu.fmtDependee(dependee)});3128 log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)});
3132 var it = zcu.intern_pool.dependencyIterator(dependee);3129 var it = zcu.intern_pool.dependencyIterator(dependee);
3133 while (it.next()) |depender| {3130 while (it.next()) |depender| {
3134 if (zcu.outdated.getPtr(depender)) |po_dep_count| {3131 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
3135 // This depender is already outdated, but it now has one3132 // This depender is already outdated, but it now has one
3136 // less PO dependency!3133 // less PO dependency!
3137 po_dep_count.* -= 1;3134 po_dep_count.* -= 1;
3138 log.debug("up-to-date {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });3135 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3139 if (po_dep_count.* == 0) {3136 if (po_dep_count.* == 0) {
3140 log.debug("outdated ready: {}", .{zcu.fmtAnalUnit(depender)});3137 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3141 try zcu.outdated_ready.put(zcu.gpa, depender, {});3138 try zcu.outdated_ready.put(zcu.gpa, depender, {});
3142 }3139 }
3143 continue;3140 continue;
...@@ -3151,11 +3148,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -3151,11 +3148,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3151 };3148 };
3152 if (ptr.* > 1) {3149 if (ptr.* > 1) {
3153 ptr.* -= 1;3150 ptr.* -= 1;
3154 log.debug("up-to-date {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });3151 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });
3155 continue;3152 continue;
3156 }3153 }
31573154
3158 log.debug("up-to-date {} => {} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });3155 log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });
31593156
3160 // This dependency is no longer PO, i.e. is known to be up-to-date.3157 // This dependency is no longer PO, i.e. is known to be up-to-date.
3161 assert(zcu.potentially_outdated.swapRemove(depender));3158 assert(zcu.potentially_outdated.swapRemove(depender));
...@@ -3184,7 +3181,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -3184,7 +3181,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
3184 .func => |func_index| .{ .interned = func_index }, // IES3181 .func => |func_index| .{ .interned = func_index }, // IES
3185 .memoized_state => |stage| .{ .memoized_state = stage },3182 .memoized_state => |stage| .{ .memoized_state = stage },
3186 };3183 };
3187 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});3184 log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3188 var it = ip.dependencyIterator(dependee);3185 var it = ip.dependencyIterator(dependee);
3189 while (it.next()) |po| {3186 while (it.next()) |po| {
3190 if (zcu.outdated.getPtr(po)) |po_dep_count| {3187 if (zcu.outdated.getPtr(po)) |po_dep_count| {
...@@ -3194,17 +3191,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -3194,17 +3191,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
3194 _ = zcu.outdated_ready.swapRemove(po);3191 _ = zcu.outdated_ready.swapRemove(po);
3195 }3192 }
3196 po_dep_count.* += 1;3193 po_dep_count.* += 1;
3197 log.debug("po {} => {} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });3194 log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });
3198 continue;3195 continue;
3199 }3196 }
3200 if (zcu.potentially_outdated.getPtr(po)) |n| {3197 if (zcu.potentially_outdated.getPtr(po)) |n| {
3201 // There is now one more PO dependency.3198 // There is now one more PO dependency.
3202 n.* += 1;3199 n.* += 1;
3203 log.debug("po {} => {} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });3200 log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });
3204 continue;3201 continue;
3205 }3202 }
3206 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);3203 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);
3207 log.debug("po {} => {} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });3204 log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });
3208 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.3205 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.
3209 try zcu.markTransitiveDependersPotentiallyOutdated(po);3206 try zcu.markTransitiveDependersPotentiallyOutdated(po);
3210 }3207 }
...@@ -3233,7 +3230,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -3233,7 +3230,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
32333230
3234 if (zcu.outdated_ready.count() > 0) {3231 if (zcu.outdated_ready.count() > 0) {
3235 const unit = zcu.outdated_ready.keys()[0];3232 const unit = zcu.outdated_ready.keys()[0];
3236 log.debug("findOutdatedToAnalyze: trivial {}", .{zcu.fmtAnalUnit(unit)});3233 log.debug("findOutdatedToAnalyze: trivial {f}", .{zcu.fmtAnalUnit(unit)});
3237 return unit;3234 return unit;
3238 }3235 }
32393236
...@@ -3284,7 +3281,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -3284,7 +3281,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
3284 }3281 }
3285 }3282 }
32863283
3287 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{3284 log.debug("findOutdatedToAnalyze: heuristic returned '{f}' ({d} dependers)", .{
3288 zcu.fmtAnalUnit(chosen_unit.?),3285 zcu.fmtAnalUnit(chosen_unit.?),
3289 chosen_unit_dependers,3286 chosen_unit_dependers,
3290 });3287 });
...@@ -4094,7 +4091,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4094,7 +4091,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4094 const referencer = kv.value;4091 const referencer = kv.value;
4095 try checked_types.putNoClobber(gpa, ty, {});4092 try checked_types.putNoClobber(gpa, ty, {});
40964093
4097 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});4094 log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
40984095
4099 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.4096 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
4100 const has_resolution: bool = switch (ip.indexToKey(ty)) {4097 const has_resolution: bool = switch (ip.indexToKey(ty)) {
...@@ -4130,7 +4127,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4130,7 +4127,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4130 // `comptime` decls are always analyzed.4127 // `comptime` decls are always analyzed.
4131 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });4128 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
4132 if (!result.contains(unit)) {4129 if (!result.contains(unit)) {
4133 log.debug("type '{}': ref comptime %{}", .{4130 log.debug("type '{f}': ref comptime %{}", .{
4134 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4131 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4135 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),4132 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
4136 });4133 });
...@@ -4162,7 +4159,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4162,7 +4159,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4162 },4159 },
4163 };4160 };
4164 if (want_analysis) {4161 if (want_analysis) {
4165 log.debug("type '{}': ref test %{}", .{4162 log.debug("type '{f}': ref test %{}", .{
4166 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4163 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4167 @intFromEnum(inst_info.inst),4164 @intFromEnum(inst_info.inst),
4168 });4165 });
...@@ -4181,7 +4178,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4181,7 +4178,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4181 if (decl.linkage == .@"export") {4178 if (decl.linkage == .@"export") {
4182 const unit: AnalUnit = .wrap(.{ .nav_val = nav });4179 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
4183 if (!result.contains(unit)) {4180 if (!result.contains(unit)) {
4184 log.debug("type '{}': ref named %{}", .{4181 log.debug("type '{f}': ref named %{}", .{
4185 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4182 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4186 @intFromEnum(inst_info.inst),4183 @intFromEnum(inst_info.inst),
4187 });4184 });
...@@ -4197,7 +4194,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4197,7 +4194,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4197 if (decl.linkage == .@"export") {4194 if (decl.linkage == .@"export") {
4198 const unit: AnalUnit = .wrap(.{ .nav_val = nav });4195 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
4199 if (!result.contains(unit)) {4196 if (!result.contains(unit)) {
4200 log.debug("type '{}': ref named %{}", .{4197 log.debug("type '{f}': ref named %{}", .{
4201 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),4198 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
4202 @intFromEnum(inst_info.inst),4199 @intFromEnum(inst_info.inst),
4203 });4200 });
...@@ -4232,7 +4229,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4232,7 +4229,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4232 try unit_queue.put(gpa, other, kv.value); // same reference location4229 try unit_queue.put(gpa, other, kv.value); // same reference location
4233 }4230 }
42344231
4235 log.debug("handle unit '{}'", .{zcu.fmtAnalUnit(unit)});4232 log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
42364233
4237 if (zcu.reference_table.get(unit)) |first_ref_idx| {4234 if (zcu.reference_table.get(unit)) |first_ref_idx| {
4238 assert(first_ref_idx != std.math.maxInt(u32));4235 assert(first_ref_idx != std.math.maxInt(u32));
...@@ -4240,7 +4237,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4240,7 +4237,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4240 while (ref_idx != std.math.maxInt(u32)) {4237 while (ref_idx != std.math.maxInt(u32)) {
4241 const ref = zcu.all_references.items[ref_idx];4238 const ref = zcu.all_references.items[ref_idx];
4242 if (!result.contains(ref.referenced)) {4239 if (!result.contains(ref.referenced)) {
4243 log.debug("unit '{}': ref unit '{}'", .{4240 log.debug("unit '{f}': ref unit '{f}'", .{
4244 zcu.fmtAnalUnit(unit),4241 zcu.fmtAnalUnit(unit),
4245 zcu.fmtAnalUnit(ref.referenced),4242 zcu.fmtAnalUnit(ref.referenced),
4246 });4243 });
...@@ -4259,7 +4256,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4259,7 +4256,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4259 while (ref_idx != std.math.maxInt(u32)) {4256 while (ref_idx != std.math.maxInt(u32)) {
4260 const ref = zcu.all_type_references.items[ref_idx];4257 const ref = zcu.all_type_references.items[ref_idx];
4261 if (!checked_types.contains(ref.referenced)) {4258 if (!checked_types.contains(ref.referenced)) {
4262 log.debug("unit '{}': ref type '{}'", .{4259 log.debug("unit '{f}': ref type '{f}'", .{
4263 zcu.fmtAnalUnit(unit),4260 zcu.fmtAnalUnit(unit),
4264 Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip),4261 Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip),
4265 });4262 });
...@@ -4347,8 +4344,8 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDe...@@ -4347,8 +4344,8 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Formatter(formatDe
4347 return .{ .data = .{ .dependee = d, .zcu = zcu } };4344 return .{ .data = .{ .dependee = d, .zcu = zcu } };
4348}4345}
43494346
4350fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {4347fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
4351 _ = .{ fmt, options };4348 _ = fmt;
4352 const zcu = data.zcu;4349 const zcu = data.zcu;
4353 const ip = &zcu.intern_pool;4350 const ip = &zcu.intern_pool;
4354 switch (data.unit.unwrap()) {4351 switch (data.unit.unwrap()) {
...@@ -4356,69 +4353,69 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -4356,69 +4353,69 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
4356 const cu = ip.getComptimeUnit(cu_id);4353 const cu = ip.getComptimeUnit(cu_id);
4357 if (cu.zir_index.resolveFull(ip)) |resolved| {4354 if (cu.zir_index.resolveFull(ip)) |resolved| {
4358 const file_path = zcu.fileByIndex(resolved.file).path;4355 const file_path = zcu.fileByIndex(resolved.file).path;
4359 return writer.print("comptime(inst=('{}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });4356 return bw.print("comptime(inst=('{f}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });
4360 } else {4357 } else {
4361 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});4358 return bw.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});
4362 }4359 }
4363 },4360 },
4364 .nav_val => |nav| return writer.print("nav_val('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),4361 .nav_val => |nav| return bw.print("nav_val('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4365 .nav_ty => |nav| return writer.print("nav_ty('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),4362 .nav_ty => |nav| return bw.print("nav_ty('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4366 .type => |ty| return writer.print("ty('{}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),4363 .type => |ty| return bw.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
4367 .func => |func| {4364 .func => |func| {
4368 const nav = zcu.funcInfo(func).owner_nav;4365 const nav = zcu.funcInfo(func).owner_nav;
4369 return writer.print("func('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });4366 return bw.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });
4370 },4367 },
4371 .memoized_state => return writer.writeAll("memoized_state"),4368 .memoized_state => return bw.writeAll("memoized_state"),
4372 }4369 }
4373}4370}
4374fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {4371fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
4375 _ = .{ fmt, options };4372 _ = fmt;
4376 const zcu = data.zcu;4373 const zcu = data.zcu;
4377 const ip = &zcu.intern_pool;4374 const ip = &zcu.intern_pool;
4378 switch (data.dependee) {4375 switch (data.dependee) {
4379 .src_hash => |ti| {4376 .src_hash => |ti| {
4380 const info = ti.resolveFull(ip) orelse {4377 const info = ti.resolveFull(ip) orelse {
4381 return writer.writeAll("inst(<lost>)");4378 return bw.writeAll("inst(<lost>)");
4382 };4379 };
4383 const file_path = zcu.fileByIndex(info.file).path;4380 const file_path = zcu.fileByIndex(info.file).path;
4384 return writer.print("inst('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });4381 return bw.print("inst('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4385 },4382 },
4386 .nav_val => |nav| {4383 .nav_val => |nav| {
4387 const fqn = ip.getNav(nav).fqn;4384 const fqn = ip.getNav(nav).fqn;
4388 return writer.print("nav_val('{}')", .{fqn.fmt(ip)});4385 return bw.print("nav_val('{f}')", .{fqn.fmt(ip)});
4389 },4386 },
4390 .nav_ty => |nav| {4387 .nav_ty => |nav| {
4391 const fqn = ip.getNav(nav).fqn;4388 const fqn = ip.getNav(nav).fqn;
4392 return writer.print("nav_ty('{}')", .{fqn.fmt(ip)});4389 return bw.print("nav_ty('{f}')", .{fqn.fmt(ip)});
4393 },4390 },
4394 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {4391 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
4395 .struct_type, .union_type, .enum_type => return writer.print("type('{}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),4392 .struct_type, .union_type, .enum_type => return bw.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),
4396 .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}),4393 .func => |f| return bw.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}),
4397 else => unreachable,4394 else => unreachable,
4398 },4395 },
4399 .zon_file => |file| {4396 .zon_file => |file| {
4400 const file_path = zcu.fileByIndex(file).path;4397 const file_path = zcu.fileByIndex(file).path;
4401 return writer.print("zon_file('{}')", .{file_path.fmt(zcu.comp)});4398 return bw.print("zon_file('{f}')", .{file_path.fmt(zcu.comp)});
4402 },4399 },
4403 .embed_file => |ef_idx| {4400 .embed_file => |ef_idx| {
4404 const ef = ef_idx.get(zcu);4401 const ef = ef_idx.get(zcu);
4405 return writer.print("embed_file('{}')", .{ef.path.fmt(zcu.comp)});4402 return bw.print("embed_file('{f}')", .{ef.path.fmt(zcu.comp)});
4406 },4403 },
4407 .namespace => |ti| {4404 .namespace => |ti| {
4408 const info = ti.resolveFull(ip) orelse {4405 const info = ti.resolveFull(ip) orelse {
4409 return writer.writeAll("namespace(<lost>)");4406 return bw.writeAll("namespace(<lost>)");
4410 };4407 };
4411 const file_path = zcu.fileByIndex(info.file).path;4408 const file_path = zcu.fileByIndex(info.file).path;
4412 return writer.print("namespace('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });4409 return bw.print("namespace('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4413 },4410 },
4414 .namespace_name => |k| {4411 .namespace_name => |k| {
4415 const info = k.namespace.resolveFull(ip) orelse {4412 const info = k.namespace.resolveFull(ip) orelse {
4416 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});4413 return bw.print("namespace(<lost>, '{f}')", .{k.name.fmt(ip)});
4417 };4414 };
4418 const file_path = zcu.fileByIndex(info.file).path;4415 const file_path = zcu.fileByIndex(info.file).path;
4419 return writer.print("namespace('{}', %{d}, '{}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });4416 return bw.print("namespace('{f}', %{d}, '{f}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });
4420 },4417 },
4421 .memoized_state => return writer.writeAll("memoized_state"),4418 .memoized_state => return bw.writeAll("memoized_state"),
4422 }4419 }
4423}4420}
44244421
src/Zcu/PerThread.zig+21-21
...@@ -190,7 +190,7 @@ pub fn updateFile(...@@ -190,7 +190,7 @@ pub fn updateFile(
190 // failure was a race, or ENOENT, indicating deletion of the190 // failure was a race, or ENOENT, indicating deletion of the
191 // directory of our open handle.191 // directory of our open handle.
192 if (builtin.os.tag != .macos) {192 if (builtin.os.tag != .macos) {
193 std.process.fatal("cache directory '{}' unexpectedly removed during compiler execution", .{193 std.process.fatal("cache directory '{f}' unexpectedly removed during compiler execution", .{
194 cache_directory,194 cache_directory,
195 });195 });
196 }196 }
...@@ -202,7 +202,7 @@ pub fn updateFile(...@@ -202,7 +202,7 @@ pub fn updateFile(
202 }) catch |excl_err| switch (excl_err) {202 }) catch |excl_err| switch (excl_err) {
203 error.PathAlreadyExists => continue,203 error.PathAlreadyExists => continue,
204 error.FileNotFound => {204 error.FileNotFound => {
205 std.process.fatal("cache directory '{}' unexpectedly removed during compiler execution", .{205 std.process.fatal("cache directory '{f}' unexpectedly removed during compiler execution", .{
206 cache_directory,206 cache_directory,
207 });207 });
208 },208 },
...@@ -646,7 +646,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized...@@ -646,7 +646,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
646 // If this unit caused the error, it would have an entry in `failed_analysis`.646 // If this unit caused the error, it would have an entry in `failed_analysis`.
647 // Since it does not, this must be a transitive failure.647 // Since it does not, this must be a transitive failure.
648 try zcu.transitive_failed_analysis.put(gpa, unit, {});648 try zcu.transitive_failed_analysis.put(gpa, unit, {});
649 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(unit)});649 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)});
650 }650 }
651 break :res .{ !prev_failed, true };651 break :res .{ !prev_failed, true };
652 },652 },
...@@ -751,7 +751,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -751,7 +751,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
751751
752 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });752 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
753753
754 log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});754 log.debug("ensureComptimeUnitUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
755755
756 assert(!zcu.analysis_in_progress.contains(anal_unit));756 assert(!zcu.analysis_in_progress.contains(anal_unit));
757757
...@@ -802,7 +802,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -802,7 +802,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
802 // If this unit caused the error, it would have an entry in `failed_analysis`.802 // If this unit caused the error, it would have an entry in `failed_analysis`.
803 // Since it does not, this must be a transitive failure.803 // Since it does not, this must be a transitive failure.
804 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});804 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
805 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});805 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
806 }806 }
807 return error.AnalysisFail;807 return error.AnalysisFail;
808 },808 },
...@@ -832,7 +832,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -832,7 +832,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
832 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });832 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
833 const comptime_unit = ip.getComptimeUnit(cu_id);833 const comptime_unit = ip.getComptimeUnit(cu_id);
834834
835 log.debug("analyzeComptimeUnit {}", .{zcu.fmtAnalUnit(anal_unit)});835 log.debug("analyzeComptimeUnit {f}", .{zcu.fmtAnalUnit(anal_unit)});
836836
837 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;837 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
838 const file = zcu.fileByIndex(inst_resolved.file);838 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -878,7 +878,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -878,7 +878,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
878 .r = .{ .simple = .comptime_keyword },878 .r = .{ .simple = .comptime_keyword },
879 } },879 } },
880 .src_base_inst = comptime_unit.zir_index,880 .src_base_inst = comptime_unit.zir_index,
881 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{881 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.comptime", .{
882 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),882 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
883 }, .no_embedded_nulls),883 }, .no_embedded_nulls),
884 };884 };
...@@ -930,7 +930,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -930,7 +930,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
930 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });930 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
931 const nav = ip.getNav(nav_id);931 const nav = ip.getNav(nav_id);
932932
933 log.debug("ensureNavValUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});933 log.debug("ensureNavValUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
934934
935 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the935 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the
936 // status is `.unresolved`, which indicates that the value is outdated because it has *never*936 // status is `.unresolved`, which indicates that the value is outdated because it has *never*
...@@ -988,7 +988,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -988,7 +988,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
988 // If this unit caused the error, it would have an entry in `failed_analysis`.988 // If this unit caused the error, it would have an entry in `failed_analysis`.
989 // Since it does not, this must be a transitive failure.989 // Since it does not, this must be a transitive failure.
990 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});990 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
991 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});991 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
992 }992 }
993 break :res .{ !prev_failed, true };993 break :res .{ !prev_failed, true };
994 },994 },
...@@ -1059,7 +1059,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1059,7 +1059,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1059 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });1059 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
1060 const old_nav = ip.getNav(nav_id);1060 const old_nav = ip.getNav(nav_id);
10611061
1062 log.debug("analyzeNavVal {}", .{zcu.fmtAnalUnit(anal_unit)});1062 log.debug("analyzeNavVal {f}", .{zcu.fmtAnalUnit(anal_unit)});
10631063
1064 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1064 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1065 const file = zcu.fileByIndex(inst_resolved.file);1065 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -1240,10 +1240,10 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1240,10 +1240,10 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1240 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.1240 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.
1241 if (zir_decl.kind == .@"usingnamespace") {1241 if (zir_decl.kind == .@"usingnamespace") {
1242 if (nav_ty.toIntern() != .type_type) {1242 if (nav_ty.toIntern() != .type_type) {
1243 return sema.fail(&block, ty_src, "expected type, found {}", .{nav_ty.fmt(pt)});1243 return sema.fail(&block, ty_src, "expected type, found {f}", .{nav_ty.fmt(pt)});
1244 }1244 }
1245 if (nav_val.toType().getNamespace(zcu) == .none) {1245 if (nav_val.toType().getNamespace(zcu) == .none) {
1246 return sema.fail(&block, ty_src, "type {} has no namespace", .{nav_val.toType().fmt(pt)});1246 return sema.fail(&block, ty_src, "type {f} has no namespace", .{nav_val.toType().fmt(pt)});
1247 }1247 }
1248 ip.resolveNavValue(nav_id, .{1248 ip.resolveNavValue(nav_id, .{
1249 .val = nav_val.toIntern(),1249 .val = nav_val.toIntern(),
...@@ -1339,7 +1339,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1339,7 +1339,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
1339 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });1339 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1340 const nav = ip.getNav(nav_id);1340 const nav = ip.getNav(nav_id);
13411341
1342 log.debug("ensureNavTypeUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});1342 log.debug("ensureNavTypeUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
13431343
1344 const type_resolved_by_value: bool = from_val: {1344 const type_resolved_by_value: bool = from_val: {
1345 const analysis = nav.analysis orelse break :from_val false;1345 const analysis = nav.analysis orelse break :from_val false;
...@@ -1409,7 +1409,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1409,7 +1409,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
1409 // If this unit caused the error, it would have an entry in `failed_analysis`.1409 // If this unit caused the error, it would have an entry in `failed_analysis`.
1410 // Since it does not, this must be a transitive failure.1410 // Since it does not, this must be a transitive failure.
1411 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1411 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1412 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});1412 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1413 }1413 }
1414 break :res .{ !prev_failed, true };1414 break :res .{ !prev_failed, true };
1415 },1415 },
...@@ -1451,7 +1451,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr...@@ -1451,7 +1451,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
1451 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });1451 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1452 const old_nav = ip.getNav(nav_id);1452 const old_nav = ip.getNav(nav_id);
14531453
1454 log.debug("analyzeNavType {}", .{zcu.fmtAnalUnit(anal_unit)});1454 log.debug("analyzeNavType {f}", .{zcu.fmtAnalUnit(anal_unit)});
14551455
1456 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1456 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1457 const file = zcu.fileByIndex(inst_resolved.file);1457 const file = zcu.fileByIndex(inst_resolved.file);
...@@ -1582,7 +1582,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -1582,7 +1582,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
1582 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);1582 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);
1583 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });1583 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });
15841584
1585 log.debug("ensureFuncBodyUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});1585 log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
15861586
1587 const func = zcu.funcInfo(maybe_coerced_func_index);1587 const func = zcu.funcInfo(maybe_coerced_func_index);
15881588
...@@ -1626,7 +1626,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -1626,7 +1626,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
1626 // If this function caused the error, it would have an entry in `failed_analysis`.1626 // If this function caused the error, it would have an entry in `failed_analysis`.
1627 // Since it does not, this must be a transitive failure.1627 // Since it does not, this must be a transitive failure.
1628 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1628 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1629 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});1629 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1630 }1630 }
1631 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,1631 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
1632 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting1632 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
...@@ -1696,7 +1696,7 @@ fn analyzeFuncBody(...@@ -1696,7 +1696,7 @@ fn analyzeFuncBody(
1696 else1696 else
1697 .none;1697 .none;
16981698
1699 log.debug("analyze and generate fn body {}", .{zcu.fmtAnalUnit(anal_unit)});1699 log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)});
17001700
1701 var air = try pt.analyzeFnBodyInner(func_index);1701 var air = try pt.analyzeFnBodyInner(func_index);
1702 errdefer air.deinit(gpa);1702 errdefer air.deinit(gpa);
...@@ -2615,7 +2615,7 @@ const ScanDeclIter = struct {...@@ -2615,7 +2615,7 @@ const ScanDeclIter = struct {
2615 var gop = try iter.seen_decls.getOrPut(gpa, name);2615 var gop = try iter.seen_decls.getOrPut(gpa, name);
2616 var next_suffix: u32 = 0;2616 var next_suffix: u32 = 0;
2617 while (gop.found_existing) {2617 while (gop.found_existing) {
2618 name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);2618 name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);
2619 gop = try iter.seen_decls.getOrPut(gpa, name);2619 gop = try iter.seen_decls.getOrPut(gpa, name);
2620 next_suffix += 1;2620 next_suffix += 1;
2621 }2621 }
...@@ -2764,7 +2764,7 @@ const ScanDeclIter = struct {...@@ -2764,7 +2764,7 @@ const ScanDeclIter = struct {
27642764
2765 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {2765 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {
2766 log.debug(2766 log.debug(
2767 "scanDecl queue analyze_comptime_unit file='{s}' unit={}",2767 "scanDecl queue analyze_comptime_unit file='{s}' unit={f}",
2768 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },2768 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },
2769 );2769 );
2770 try comp.queueJob(.{ .analyze_comptime_unit = unit });2770 try comp.queueJob(.{ .analyze_comptime_unit = unit });
...@@ -3182,7 +3182,7 @@ fn processExportsInner(...@@ -3182,7 +3182,7 @@ fn processExportsInner(
3182 if (gop.found_existing) {3182 if (gop.found_existing) {
3183 new_export.status = .failed_retryable;3183 new_export.status = .failed_retryable;
3184 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);3184 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
3185 const msg = try Zcu.ErrorMsg.create(gpa, new_export.src, "exported symbol collision: {}", .{3185 const msg = try Zcu.ErrorMsg.create(gpa, new_export.src, "exported symbol collision: {f}", .{
3186 new_export.opts.name.fmt(ip),3186 new_export.opts.name.fmt(ip),
3187 });3187 });
3188 errdefer msg.destroy(gpa);3188 errdefer msg.destroy(gpa);
src/arch/aarch64/CodeGen.zig+3-3
...@@ -1011,7 +1011,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -1011,7 +1011,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1011 }1011 }
10121012
1013 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {1013 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
1014 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});1014 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
1015 };1015 };
1016 // TODO swap this for inst.ty.ptrAlign1016 // TODO swap this for inst.ty.ptrAlign
1017 const abi_align = elem_ty.abiAlignment(zcu);1017 const abi_align = elem_ty.abiAlignment(zcu);
...@@ -1022,7 +1022,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -1022,7 +1022,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1022fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {1022fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {
1023 const pt = self.pt;1023 const pt = self.pt;
1024 const abi_size = math.cast(u32, elem_ty.abiSize(pt.zcu)) orelse {1024 const abi_size = math.cast(u32, elem_ty.abiSize(pt.zcu)) orelse {
1025 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});1025 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
1026 };1026 };
1027 const abi_align = elem_ty.abiAlignment(pt.zcu);1027 const abi_align = elem_ty.abiAlignment(pt.zcu);
10281028
...@@ -4636,7 +4636,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -4636,7 +4636,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) InnerError!void {
4636 const mcv = try self.resolveInst(operand);4636 const mcv = try self.resolveInst(operand);
4637 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);4637 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
46384638
4639 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });4639 log.debug("airDbgVar: %{f}: {f}, {}", .{ inst, ty.fmtDebug(), mcv });
46404640
4641 try self.dbg_info_relocs.append(self.gpa, .{4641 try self.dbg_info_relocs.append(self.gpa, .{
4642 .tag = tag,4642 .tag = tag,
src/arch/aarch64/Emit.zig+15-18
...@@ -70,9 +70,11 @@ const BranchType = enum {...@@ -70,9 +70,11 @@ const BranchType = enum {
70 }70 }
71};71};
7272
73pub fn emitMir(73pub fn emitMir(emit: *Emit) InnerError!void {
74 emit: *Emit,74 return @errorCast(emit.emitMirInner());
75) !void {75}
76
77fn emitMirInner(emit: *Emit) anyerror!void {
76 const mir_tags = emit.mir.instructions.items(.tag);78 const mir_tags = emit.mir.instructions.items(.tag);
7779
78 // Find smallest lowerings for branch instructions80 // Find smallest lowerings for branch instructions
...@@ -439,7 +441,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {...@@ -439,7 +441,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
439 return error.EmitFail;441 return error.EmitFail;
440}442}
441443
442fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {444fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) anyerror!void {
443 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);445 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);
444 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;446 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
445 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });447 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
...@@ -454,25 +456,20 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {...@@ -454,25 +456,20 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
454 .plan9 => |dbg_out| {456 .plan9 => |dbg_out| {
455 if (delta_pc <= 0) return; // only do this when the pc changes457 if (delta_pc <= 0) return; // only do this when the pc changes
456458
459 var aw: std.io.AllocatingWriter = undefined;
460 const bw = aw.fromArrayList(emit.bin_file.comp.gpa, &dbg_out.dbg_line);
461 defer dbg_out.dbg_line = aw.toArrayList();
462
457 // increasing the line number463 // increasing the line number
458 try link.File.Plan9.changeLine(&dbg_out.dbg_line, @intCast(delta_line));464 try link.File.Plan9.changeLine(bw, @intCast(delta_line));
459 // increasing the pc465 // increasing the pc
460 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;466 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
461 if (d_pc_p9 > 0) {467 if (d_pc_p9 > 0) {
462 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta468 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta
463 var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;469 try bw.writeByte(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
464 while (diff > 0) {470 const dbg_line = aw.getWritten();
465 if (diff < 64) {471 if (dbg_out.pcop_change_index) |pci| dbg_line[pci] += 1;
466 try dbg_out.dbg_line.append(@intCast(diff + 128));472 dbg_out.pcop_change_index = @intCast(dbg_line.len - 1);
467 diff = 0;
468 } else {
469 try dbg_out.dbg_line.append(@intCast(64 + 128));
470 diff -= 64;
471 }
472 }
473 if (dbg_out.pcop_change_index) |pci|
474 dbg_out.dbg_line.items[pci] += 1;
475 dbg_out.pcop_change_index = @intCast(dbg_out.dbg_line.items.len - 1);
476 } else if (d_pc_p9 == 0) {473 } else if (d_pc_p9 == 0) {
477 // we don't need to do anything, because adding the pc quanta does it for us474 // we don't need to do anything, because adding the pc quanta does it for us
478 } else unreachable;475 } else unreachable;
src/arch/arm/CodeGen.zig+3-3
...@@ -997,7 +997,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -997,7 +997,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
997 }997 }
998998
999 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {999 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
1000 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});1000 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
1001 };1001 };
1002 // TODO swap this for inst.ty.ptrAlign1002 // TODO swap this for inst.ty.ptrAlign
1003 const abi_align = elem_ty.abiAlignment(zcu);1003 const abi_align = elem_ty.abiAlignment(zcu);
...@@ -1008,7 +1008,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -1008,7 +1008,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1008fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {1008fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {
1009 const pt = self.pt;1009 const pt = self.pt;
1010 const abi_size = math.cast(u32, elem_ty.abiSize(pt.zcu)) orelse {1010 const abi_size = math.cast(u32, elem_ty.abiSize(pt.zcu)) orelse {
1011 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});1011 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
1012 };1012 };
1013 const abi_align = elem_ty.abiAlignment(pt.zcu);1013 const abi_align = elem_ty.abiAlignment(pt.zcu);
10141014
...@@ -4609,7 +4609,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -4609,7 +4609,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4609 const mcv = try self.resolveInst(operand);4609 const mcv = try self.resolveInst(operand);
4610 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);4610 const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
46114611
4612 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });4612 log.debug("airDbgVar: %{f}: {f}, {}", .{ inst, ty.fmtDebug(), mcv });
46134613
4614 try self.dbg_info_relocs.append(self.gpa, .{4614 try self.dbg_info_relocs.append(self.gpa, .{
4615 .tag = tag,4615 .tag = tag,
src/arch/arm/Emit.zig+14-8
...@@ -67,9 +67,11 @@ const BranchType = enum {...@@ -67,9 +67,11 @@ const BranchType = enum {
67 }67 }
68};68};
6969
70pub fn emitMir(70pub fn emitMir(emit: *Emit) InnerError!void {
71 emit: *Emit,71 return @errorCast(emit.emitMirInner());
72) !void {72}
73
74fn emitMirInner(emit: *Emit) anyerror!void {
73 const mir_tags = emit.mir.instructions.items(.tag);75 const mir_tags = emit.mir.instructions.items(.tag);
7476
75 // Find smallest lowerings for branch instructions77 // Find smallest lowerings for branch instructions
...@@ -370,16 +372,20 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -370,16 +372,20 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
370 .plan9 => |dbg_out| {372 .plan9 => |dbg_out| {
371 if (delta_pc <= 0) return; // only do this when the pc changes373 if (delta_pc <= 0) return; // only do this when the pc changes
372374
375 var aw: std.io.AllocatingWriter = undefined;
376 const bw = aw.fromArrayList(self.bin_file.comp.gpa, &dbg_out.dbg_line);
377 defer dbg_out.dbg_line = aw.toArrayList();
378
373 // increasing the line number379 // increasing the line number
374 try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);380 try link.File.Plan9.changeLine(bw, delta_line);
375 // increasing the pc381 // increasing the pc
376 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;382 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
377 if (d_pc_p9 > 0) {383 if (d_pc_p9 > 0) {
378 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta384 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta
379 try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);385 try bw.writeByte(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
380 if (dbg_out.pcop_change_index) |pci|386 const dbg_line = aw.getWritten();
381 dbg_out.dbg_line.items[pci] += 1;387 if (dbg_out.pcop_change_index) |pci| dbg_line[pci] += 1;
382 dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));388 dbg_out.pcop_change_index = @intCast(dbg_line.len - 1);
383 } else if (d_pc_p9 == 0) {389 } else if (d_pc_p9 == 0) {
384 // we don't need to do anything, because adding the pc quanta does it for us390 // we don't need to do anything, because adding the pc quanta does it for us
385 } else unreachable;391 } else unreachable;
src/arch/riscv64/CodeGen.zig+50-75
...@@ -401,7 +401,7 @@ const InstTracking = struct {...@@ -401,7 +401,7 @@ const InstTracking = struct {
401 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },401 .reserved_frame => |index| inst_tracking.long = .{ .load_frame = .{ .index = index } },
402 else => unreachable,402 else => unreachable,
403 }403 }
404 tracking_log.debug("spill %{d} from {} to {}", .{ inst, inst_tracking.short, inst_tracking.long });404 tracking_log.debug("spill %{f} from {} to {}", .{ inst, inst_tracking.short, inst_tracking.long });
405 try function.genCopy(function.typeOfIndex(inst), inst_tracking.long, inst_tracking.short);405 try function.genCopy(function.typeOfIndex(inst), inst_tracking.long, inst_tracking.short);
406 }406 }
407407
...@@ -435,7 +435,7 @@ const InstTracking = struct {...@@ -435,7 +435,7 @@ const InstTracking = struct {
435 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {435 fn trackSpill(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) !void {
436 try function.freeValue(inst_tracking.short);436 try function.freeValue(inst_tracking.short);
437 inst_tracking.reuseFrame();437 inst_tracking.reuseFrame();
438 tracking_log.debug("%{d} => {} (spilled)", .{ inst, inst_tracking.* });438 tracking_log.debug("%{f} => {f} (spilled)", .{ inst, inst_tracking.* });
439 }439 }
440440
441 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {441 fn verifyMaterialize(inst_tracking: InstTracking, target: InstTracking) void {
...@@ -499,14 +499,14 @@ const InstTracking = struct {...@@ -499,14 +499,14 @@ const InstTracking = struct {
499 else => target.long,499 else => target.long,
500 } else target.long;500 } else target.long;
501 inst_tracking.short = target.short;501 inst_tracking.short = target.short;
502 tracking_log.debug("%{d} => {} (materialize)", .{ inst, inst_tracking.* });502 tracking_log.debug("%{f} => {f} (materialize)", .{ inst, inst_tracking.* });
503 }503 }
504504
505 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {505 fn resurrect(inst_tracking: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
506 switch (inst_tracking.short) {506 switch (inst_tracking.short) {
507 .dead => |die_generation| if (die_generation >= scope_generation) {507 .dead => |die_generation| if (die_generation >= scope_generation) {
508 inst_tracking.reuseFrame();508 inst_tracking.reuseFrame();
509 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, inst_tracking.* });509 tracking_log.debug("%{f} => {f} (resurrect)", .{ inst, inst_tracking.* });
510 },510 },
511 else => {},511 else => {},
512 }512 }
...@@ -516,7 +516,7 @@ const InstTracking = struct {...@@ -516,7 +516,7 @@ const InstTracking = struct {
516 if (inst_tracking.short == .dead) return;516 if (inst_tracking.short == .dead) return;
517 try function.freeValue(inst_tracking.short);517 try function.freeValue(inst_tracking.short);
518 inst_tracking.short = .{ .dead = function.scope_generation };518 inst_tracking.short = .{ .dead = function.scope_generation };
519 tracking_log.debug("%{d} => {} (death)", .{ inst, inst_tracking.* });519 tracking_log.debug("%{f} => {f} (death)", .{ inst, inst_tracking.* });
520 }520 }
521521
522 fn reuse(522 fn reuse(
...@@ -527,15 +527,15 @@ const InstTracking = struct {...@@ -527,15 +527,15 @@ const InstTracking = struct {
527 ) void {527 ) void {
528 inst_tracking.short = .{ .dead = function.scope_generation };528 inst_tracking.short = .{ .dead = function.scope_generation };
529 if (new_inst) |inst|529 if (new_inst) |inst|
530 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, inst_tracking.*, old_inst })530 tracking_log.debug("%{f} => {f} (reuse %{f})", .{ inst, inst_tracking.*, old_inst })
531 else531 else
532 tracking_log.debug("tmp => {} (reuse %{d})", .{ inst_tracking.*, old_inst });532 tracking_log.debug("tmp => {f} (reuse %{f})", .{ inst_tracking.*, old_inst });
533 }533 }
534534
535 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {535 fn liveOut(inst_tracking: *InstTracking, function: *Func, inst: Air.Inst.Index) void {
536 for (inst_tracking.getRegs()) |reg| {536 for (inst_tracking.getRegs()) |reg| {
537 if (function.register_manager.isRegFree(reg)) {537 if (function.register_manager.isRegFree(reg)) {
538 tracking_log.debug("%{d} => {} (live-out)", .{ inst, inst_tracking.* });538 tracking_log.debug("%{f} => {f} (live-out)", .{ inst, inst_tracking.* });
539 continue;539 continue;
540 }540 }
541541
...@@ -562,18 +562,13 @@ const InstTracking = struct {...@@ -562,18 +562,13 @@ const InstTracking = struct {
562 // Perform side-effects of freeValue manually.562 // Perform side-effects of freeValue manually.
563 function.register_manager.freeReg(reg);563 function.register_manager.freeReg(reg);
564564
565 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, inst_tracking.*, tracked_inst });565 tracking_log.debug("%{f} => {f} (live-out %{f})", .{ inst, inst_tracking.*, tracked_inst });
566 }566 }
567 }567 }
568568
569 pub fn format(569 pub fn format(inst_tracking: InstTracking, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
570 inst_tracking: InstTracking,570 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try bw.print("|{}| ", .{inst_tracking.long});
571 comptime _: []const u8,571 try bw.print("{}", .{inst_tracking.short});
572 _: std.fmt.FormatOptions,
573 writer: anytype,
574 ) @TypeOf(writer).Error!void {
575 if (!std.meta.eql(inst_tracking.long, inst_tracking.short)) try writer.print("|{}| ", .{inst_tracking.long});
576 try writer.print("{}", .{inst_tracking.short});
577 }572 }
578};573};
579574
...@@ -802,7 +797,7 @@ pub fn generate(...@@ -802,7 +797,7 @@ pub fn generate(
802 function.mir_instructions.deinit(gpa);797 function.mir_instructions.deinit(gpa);
803 }798 }
804799
805 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});800 wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)});
806801
807 try function.frame_allocs.resize(gpa, FrameIndex.named_count);802 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
808 function.frame_allocs.set(803 function.frame_allocs.set(
...@@ -937,12 +932,7 @@ const FormatWipMirData = struct {...@@ -937,12 +932,7 @@ const FormatWipMirData = struct {
937 func: *Func,932 func: *Func,
938 inst: Mir.Inst.Index,933 inst: Mir.Inst.Index,
939};934};
940fn formatWipMir(935fn formatWipMir(data: FormatWipMirData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
941 data: FormatWipMirData,
942 comptime _: []const u8,
943 _: std.fmt.FormatOptions,
944 writer: anytype,
945) @TypeOf(writer).Error!void {
946 const pt = data.func.pt;936 const pt = data.func.pt;
947 const comp = pt.zcu.comp;937 const comp = pt.zcu.comp;
948 var lower: Lower = .{938 var lower: Lower = .{
...@@ -965,11 +955,11 @@ fn formatWipMir(...@@ -965,11 +955,11 @@ fn formatWipMir(
965 lower.err_msg.?.deinit(data.func.gpa);955 lower.err_msg.?.deinit(data.func.gpa);
966 lower.err_msg = null;956 lower.err_msg = null;
967 }957 }
968 try writer.writeAll(lower.err_msg.?.msg);958 try bw.writeAll(lower.err_msg.?.msg);
969 return;959 return;
970 },960 },
971 error.OutOfMemory, error.InvalidInstruction => |e| {961 error.OutOfMemory, error.InvalidInstruction => |e| {
972 try writer.writeAll(switch (e) {962 try bw.writeAll(switch (e) {
973 error.OutOfMemory => "Out of memory",963 error.OutOfMemory => "Out of memory",
974 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",964 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
975 });965 });
...@@ -977,8 +967,8 @@ fn formatWipMir(...@@ -977,8 +967,8 @@ fn formatWipMir(
977 },967 },
978 else => |e| return e,968 else => |e| return e,
979 }).insts) |lowered_inst| {969 }).insts) |lowered_inst| {
980 if (!first) try writer.writeAll("\ndebug(wip_mir): ");970 if (!first) try bw.writeAll("\ndebug(wip_mir): ");
981 try writer.print(" | {}", .{lowered_inst});971 try bw.print(" | {}", .{lowered_inst});
982 first = false;972 first = false;
983 }973 }
984}974}
...@@ -990,13 +980,8 @@ const FormatNavData = struct {...@@ -990,13 +980,8 @@ const FormatNavData = struct {
990 ip: *const InternPool,980 ip: *const InternPool,
991 nav_index: InternPool.Nav.Index,981 nav_index: InternPool.Nav.Index,
992};982};
993fn formatNav(983fn formatNav(data: FormatNavData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
994 data: FormatNavData,984 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
995 comptime _: []const u8,
996 _: std.fmt.FormatOptions,
997 writer: anytype,
998) @TypeOf(writer).Error!void {
999 try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1000}985}
1001fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {986fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {
1002 return .{ .data = .{987 return .{ .data = .{
...@@ -1009,12 +994,7 @@ const FormatAirData = struct {...@@ -1009,12 +994,7 @@ const FormatAirData = struct {
1009 func: *Func,994 func: *Func,
1010 inst: Air.Inst.Index,995 inst: Air.Inst.Index,
1011};996};
1012fn formatAir(997fn formatAir(data: FormatAirData, _: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1013 data: FormatAirData,
1014 comptime _: []const u8,
1015 _: std.fmt.FormatOptions,
1016 writer: anytype,
1017) @TypeOf(writer).Error!void {
1018 data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);998 data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness);
1019}999}
1020fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {1000fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
...@@ -1024,14 +1004,9 @@ fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {...@@ -1024,14 +1004,9 @@ fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
1024const FormatTrackingData = struct {1004const FormatTrackingData = struct {
1025 func: *Func,1005 func: *Func,
1026};1006};
1027fn formatTracking(1007fn formatTracking(data: FormatTrackingData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1028 data: FormatTrackingData,
1029 comptime _: []const u8,
1030 _: std.fmt.FormatOptions,
1031 writer: anytype,
1032) @TypeOf(writer).Error!void {
1033 var it = data.func.inst_tracking.iterator();1008 var it = data.func.inst_tracking.iterator();
1034 while (it.next()) |entry| try writer.print("\n%{d} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });1009 while (it.next()) |entry| try bw.print("\n%{d} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1035}1010}
1036fn fmtTracking(func: *Func) std.fmt.Formatter(formatTracking) {1011fn fmtTracking(func: *Func) std.fmt.Formatter(formatTracking) {
1037 return .{ .data = .{ .func = func } };1012 return .{ .data = .{ .func = func } };
...@@ -1049,7 +1024,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1049,7 +1024,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1049 .pseudo_dbg_epilogue_begin,1024 .pseudo_dbg_epilogue_begin,
1050 .pseudo_dead,1025 .pseudo_dead,
1051 => false,1026 => false,
1052 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)});1027 }) wip_mir_log.debug("{f}", .{func.fmtWipMir(result_index)});
1053 return result_index;1028 return result_index;
1054}1029}
10551030
...@@ -1172,7 +1147,7 @@ fn gen(func: *Func) !void {...@@ -1172,7 +1147,7 @@ fn gen(func: *Func) !void {
1172 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),1147 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
1173 );1148 );
1174 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };1149 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
1175 tracking_log.debug("spill {} to {}", .{ func.ret_mcv.long, frame_index });1150 tracking_log.debug("spill {} to {f}", .{ func.ret_mcv.long, frame_index });
1176 },1151 },
1177 else => unreachable,1152 else => unreachable,
1178 }1153 }
...@@ -1303,7 +1278,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -1303,7 +1278,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1303 switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {1278 switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {
1304 .@"enum" => {1279 .@"enum" => {
1305 const enum_ty = Type.fromInterned(lazy_sym.ty);1280 const enum_ty = Type.fromInterned(lazy_sym.ty);
1306 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});1281 wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
13071282
1308 const param_regs = abi.Registers.Integer.function_arg_regs;1283 const param_regs = abi.Registers.Integer.function_arg_regs;
1309 const ret_reg = param_regs[0];1284 const ret_reg = param_regs[0];
...@@ -1385,7 +1360,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -1385,7 +1360,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1385 });1360 });
1386 },1361 },
1387 else => return func.fail(1362 else => return func.fail(
1388 "TODO implement {s} for {}",1363 "TODO implement {s} for {f}",
1389 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },1364 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
1390 ),1365 ),
1391 }1366 }
...@@ -1399,8 +1374,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1399,8 +1374,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
13991374
1400 for (body) |inst| {1375 for (body) |inst| {
1401 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;1376 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) continue;
1402 wip_mir_log.debug("{}", .{func.fmtAir(inst)});1377 wip_mir_log.debug("{f}", .{func.fmtAir(inst)});
1403 verbose_tracking_log.debug("{}", .{func.fmtTracking()});1378 verbose_tracking_log.debug("{f}", .{func.fmtTracking()});
14041379
1405 const old_air_bookkeeping = func.air_bookkeeping;1380 const old_air_bookkeeping = func.air_bookkeeping;
1406 try func.ensureProcessDeathCapacity(Air.Liveness.bpi);1381 try func.ensureProcessDeathCapacity(Air.Liveness.bpi);
...@@ -1679,18 +1654,18 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1679,18 +1654,18 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1679 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });1654 var it = func.register_manager.free_registers.iterator(.{ .kind = .unset });
1680 while (it.next()) |index| {1655 while (it.next()) |index| {
1681 const tracked_inst = func.register_manager.registers[index];1656 const tracked_inst = func.register_manager.registers[index];
1682 tracking_log.debug("tracked inst: {}", .{tracked_inst});1657 tracking_log.debug("tracked inst: {f}", .{tracked_inst});
1683 const tracking = func.getResolvedInstValue(tracked_inst);1658 const tracking = func.getResolvedInstValue(tracked_inst);
1684 for (tracking.getRegs()) |reg| {1659 for (tracking.getRegs()) |reg| {
1685 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1660 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1686 } else return std.debug.panic(1661 } else return std.debug.panic(
1687 \\%{} takes up these regs: {any}, however this regs {any}, don't use it1662 \\%{f} takes up these regs: {any}, however this regs {any}, don't use it
1688 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });1663 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
1689 }1664 }
1690 }1665 }
1691 }1666 }
1692 }1667 }
1693 verbose_tracking_log.debug("{}", .{func.fmtTracking()});1668 verbose_tracking_log.debug("{f}", .{func.fmtTracking()});
1694}1669}
16951670
1696fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {1671fn getValue(func: *Func, value: MCValue, inst: ?Air.Inst.Index) !void {
...@@ -1713,7 +1688,7 @@ fn freeValue(func: *Func, value: MCValue) !void {...@@ -1713,7 +1688,7 @@ fn freeValue(func: *Func, value: MCValue) !void {
17131688
1714fn feed(func: *Func, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) !void {1689fn feed(func: *Func, bt: *Air.Liveness.BigTomb, operand: Air.Inst.Ref) !void {
1715 if (bt.feed()) if (operand.toIndex()) |inst| {1690 if (bt.feed()) if (operand.toIndex()) |inst| {
1716 log.debug("feed inst: %{}", .{inst});1691 log.debug("feed inst: %{f}", .{inst});
1717 try func.processDeath(inst);1692 try func.processDeath(inst);
1718 };1693 };
1719}1694}
...@@ -1907,7 +1882,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type {...@@ -1907,7 +1882,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type {
1907 else => return func.fail("TODO: splitType class {}", .{class}),1882 else => return func.fail("TODO: splitType class {}", .{class}),
1908 };1883 };
1909 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;1884 } else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;
1910 return func.fail("TODO implement splitType for {}", .{ty.fmt(func.pt)});1885 return func.fail("TODO implement splitType for {f}", .{ty.fmt(func.pt)});
1911}1886}
19121887
1913/// Truncates the value in the register in place.1888/// Truncates the value in the register in place.
...@@ -2008,7 +1983,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {...@@ -2008,7 +1983,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
2008 }1983 }
2009 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);1984 const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len);
2010 try func.frame_allocs.append(func.gpa, alloc);1985 try func.frame_allocs.append(func.gpa, alloc);
2011 log.debug("allocated frame {}", .{frame_index});1986 log.debug("allocated frame {f}", .{frame_index});
2012 return frame_index;1987 return frame_index;
2013}1988}
20141989
...@@ -2020,7 +1995,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {...@@ -2020,7 +1995,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {
2020 const val_ty = ptr_ty.childType(zcu);1995 const val_ty = ptr_ty.childType(zcu);
2021 return func.allocFrameIndex(FrameAlloc.init(.{1996 return func.allocFrameIndex(FrameAlloc.init(.{
2022 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {1997 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
2023 return func.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});1998 return func.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
2024 },1999 },
2025 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),2000 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
2026 }));2001 }));
...@@ -2160,7 +2135,7 @@ pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {...@@ -2160,7 +2135,7 @@ pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {
2160/// allocated. A second call to `copyToTmpRegister` may return the same register.2135/// allocated. A second call to `copyToTmpRegister` may return the same register.
2161/// This can have a side effect of spilling instructions to the stack to free up a register.2136/// This can have a side effect of spilling instructions to the stack to free up a register.
2162fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {2137fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {
2163 log.debug("copyToTmpRegister ty: {}", .{ty.fmt(func.pt)});2138 log.debug("copyToTmpRegister ty: {f}", .{ty.fmt(func.pt)});
2164 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));2139 const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));
2165 try func.genSetReg(ty, reg, mcv);2140 try func.genSetReg(ty, reg, mcv);
2166 return reg;2141 return reg;
...@@ -2245,7 +2220,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -2245,7 +2220,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
2245 break :result null; // TODO2220 break :result null; // TODO
22462221
2247 break :result dst_mcv;2222 break :result dst_mcv;
2248 } orelse return func.fail("TODO: implement airIntCast from {} to {}", .{2223 } orelse return func.fail("TODO: implement airIntCast from {f} to {f}", .{
2249 src_ty.fmt(pt), dst_ty.fmt(pt),2224 src_ty.fmt(pt), dst_ty.fmt(pt),
2250 });2225 });
22512226
...@@ -2633,7 +2608,7 @@ fn genBinOp(...@@ -2633,7 +2608,7 @@ fn genBinOp(
2633 .add_sat,2608 .add_sat,
2634 => {2609 => {
2635 if (bit_size != 64 or !is_unsigned)2610 if (bit_size != 64 or !is_unsigned)
2636 return func.fail("TODO: genBinOp ty: {}", .{lhs_ty.fmt(pt)});2611 return func.fail("TODO: genBinOp ty: {f}", .{lhs_ty.fmt(pt)});
26372612
2638 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });2613 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
2639 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);2614 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
...@@ -4065,7 +4040,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {...@@ -4065,7 +4040,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
4065 );4040 );
4066 } else {4041 } else {
4067 return func.fail(4042 return func.fail(
4068 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}, tag {}",4043 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}, tag {f}",
4069 .{ frame_mcv, tag_ty.fmt(pt) },4044 .{ frame_mcv, tag_ty.fmt(pt) },
4070 );4045 );
4071 }4046 }
...@@ -4186,7 +4161,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -4186,7 +4161,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
41864161
4187 switch (scalar_ty.zigTypeTag(zcu)) {4162 switch (scalar_ty.zigTypeTag(zcu)) {
4188 .int => if (ty.zigTypeTag(zcu) == .vector) {4163 .int => if (ty.zigTypeTag(zcu) == .vector) {
4189 return func.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});4164 return func.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
4190 } else {4165 } else {
4191 const int_info = scalar_ty.intInfo(zcu);4166 const int_info = scalar_ty.intInfo(zcu);
4192 const int_bits = int_info.bits;4167 const int_bits = int_info.bits;
...@@ -4267,7 +4242,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -4267,7 +4242,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
42674242
4268 break :result return_mcv;4243 break :result return_mcv;
4269 },4244 },
4270 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(pt)}),4245 else => return func.fail("TODO: implement airAbs {f}", .{scalar_ty.fmt(pt)}),
4271 }4246 }
42724247
4273 break :result .unreach;4248 break :result .unreach;
...@@ -4331,7 +4306,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {...@@ -4331,7 +4306,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
43314306
4332 break :result dest_mcv;4307 break :result dest_mcv;
4333 },4308 },
4334 else => return func.fail("TODO: airByteSwap {}", .{ty.fmt(pt)}),4309 else => return func.fail("TODO: airByteSwap {f}", .{ty.fmt(pt)}),
4335 }4310 }
4336 };4311 };
4337 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });4312 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -4397,7 +4372,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -4397,7 +4372,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
4397 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),4372 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
4398 }4373 }
4399 },4374 },
4400 else => return func.fail("TODO: airUnaryMath ty: {}", .{ty.fmt(pt)}),4375 else => return func.fail("TODO: airUnaryMath ty: {f}", .{ty.fmt(pt)}),
4401 }4376 }
44024377
4403 break :result MCValue{ .register = dst_reg };4378 break :result MCValue{ .register = dst_reg };
...@@ -4497,7 +4472,7 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro...@@ -4497,7 +4472,7 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
4497 const zcu = pt.zcu;4472 const zcu = pt.zcu;
4498 const dst_ty = ptr_ty.childType(zcu);4473 const dst_ty = ptr_ty.childType(zcu);
44994474
4500 log.debug("loading {}:{} into {}", .{ ptr_mcv, ptr_ty.fmt(pt), dst_mcv });4475 log.debug("loading {}:{f} into {}", .{ ptr_mcv, ptr_ty.fmt(pt), dst_mcv });
45014476
4502 switch (ptr_mcv) {4477 switch (ptr_mcv) {
4503 .none,4478 .none,
...@@ -4550,7 +4525,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4550,7 +4525,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4550fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {4525fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {
4551 const zcu = func.pt.zcu;4526 const zcu = func.pt.zcu;
4552 const src_ty = ptr_ty.childType(zcu);4527 const src_ty = ptr_ty.childType(zcu);
4553 log.debug("storing {}:{} in {}:{}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });4528 log.debug("storing {}:{f} in {}:{f}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });
45544529
4555 switch (ptr_mcv) {4530 switch (ptr_mcv) {
4556 .none => unreachable,4531 .none => unreachable,
...@@ -7305,7 +7280,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -7305,7 +7280,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
7305 const bit_size = dst_ty.bitSize(zcu);7280 const bit_size = dst_ty.bitSize(zcu);
7306 if (abi_size * 8 <= bit_size) break :result dst_mcv;7281 if (abi_size * 8 <= bit_size) break :result dst_mcv;
73077282
7308 return func.fail("TODO: airBitCast {} to {}", .{ src_ty.fmt(pt), dst_ty.fmt(pt) });7283 return func.fail("TODO: airBitCast {f} to {f}", .{ src_ty.fmt(pt), dst_ty.fmt(pt) });
7309 };7284 };
7310 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });7285 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
7311}7286}
...@@ -8121,7 +8096,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {...@@ -8121,7 +8096,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
8121 );8096 );
8122 break :result .{ .load_frame = .{ .index = frame_index } };8097 break :result .{ .load_frame = .{ .index = frame_index } };
8123 },8098 },
8124 else => return func.fail("TODO: airAggregate {}", .{result_ty.fmt(pt)}),8099 else => return func.fail("TODO: airAggregate {f}", .{result_ty.fmt(pt)}),
8125 }8100 }
8126 };8101 };
81278102
...@@ -8322,7 +8297,7 @@ fn resolveCallingConventionValues(...@@ -8322,7 +8297,7 @@ fn resolveCallingConventionValues(
8322 };8297 };
83238298
8324 result.return_value = switch (ret_tracking_i) {8299 result.return_value = switch (ret_tracking_i) {
8325 else => return func.fail("ty {} took {} tracking return indices", .{ ret_ty.fmt(pt), ret_tracking_i }),8300 else => return func.fail("ty {f} took {} tracking return indices", .{ ret_ty.fmt(pt), ret_tracking_i }),
8326 1 => ret_tracking[0],8301 1 => ret_tracking[0],
8327 2 => InstTracking.init(.{ .register_pair = .{8302 2 => InstTracking.init(.{ .register_pair = .{
8328 ret_tracking[0].short.register, ret_tracking[1].short.register,8303 ret_tracking[0].short.register, ret_tracking[1].short.register,
...@@ -8377,7 +8352,7 @@ fn resolveCallingConventionValues(...@@ -8377,7 +8352,7 @@ fn resolveCallingConventionValues(
8377 else => return func.fail("TODO: C calling convention arg class {}", .{class}),8352 else => return func.fail("TODO: C calling convention arg class {}", .{class}),
8378 } else {8353 } else {
8379 arg.* = switch (arg_mcv_i) {8354 arg.* = switch (arg_mcv_i) {
8380 else => return func.fail("ty {} took {} tracking arg indices", .{ ty.fmt(pt), arg_mcv_i }),8355 else => return func.fail("ty {f} took {} tracking arg indices", .{ ty.fmt(pt), arg_mcv_i }),
8381 1 => arg_mcv[0],8356 1 => arg_mcv[0],
8382 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },8357 2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },
8383 };8358 };
src/arch/riscv64/Emit.zig+20-11
...@@ -18,20 +18,28 @@ pub const Error = Lower.Error || error{...@@ -18,20 +18,28 @@ pub const Error = Lower.Error || error{
18};18};
1919
20pub fn emitMir(emit: *Emit) Error!void {20pub fn emitMir(emit: *Emit) Error!void {
21 return @errorCast(emit.emitMirInner());
22}
23
24fn emitMirInner(emit: *Emit) anyerror!void {
21 const gpa = emit.bin_file.comp.gpa;25 const gpa = emit.bin_file.comp.gpa;
26 var aw: std.io.AllocatingWriter = undefined;
27 const bw = aw.fromArrayList(gpa, emit.code);
28 defer emit.code.* = aw.toArrayList();
29
22 log.debug("mir instruction len: {}", .{emit.lower.mir.instructions.len});30 log.debug("mir instruction len: {}", .{emit.lower.mir.instructions.len});
23 for (0..emit.lower.mir.instructions.len) |mir_i| {31 for (0..emit.lower.mir.instructions.len) |mir_i| {
24 const mir_index: Mir.Inst.Index = @intCast(mir_i);32 const mir_index: Mir.Inst.Index = @intCast(mir_i);
25 try emit.code_offset_mapping.putNoClobber(33 try emit.code_offset_mapping.putNoClobber(
26 emit.lower.allocator,34 emit.lower.allocator,
27 mir_index,35 mir_index,
28 @intCast(emit.code.items.len),36 @intCast(bw.count),
29 );37 );
30 const lowered = try emit.lower.lowerMir(mir_index, .{ .allow_frame_locs = true });38 const lowered = try emit.lower.lowerMir(mir_index, .{ .allow_frame_locs = true });
31 var lowered_relocs = lowered.relocs;39 var lowered_relocs = lowered.relocs;
32 for (lowered.insts, 0..) |lowered_inst, lowered_index| {40 for (lowered.insts, 0..) |lowered_inst, lowered_index| {
33 const start_offset: u32 = @intCast(emit.code.items.len);41 const start_offset: u32 = @intCast(bw.count);
34 try lowered_inst.encode(emit.code.writer(gpa));42 try lowered_inst.encode(bw);
3543
36 while (lowered_relocs.len > 0 and44 while (lowered_relocs.len > 0 and
37 lowered_relocs[0].lowered_inst_index == lowered_index) : ({45 lowered_relocs[0].lowered_inst_index == lowered_index) : ({
...@@ -123,7 +131,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -123,7 +131,7 @@ pub fn emitMir(emit: *Emit) Error!void {
123 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{131 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
124 emit.prev_di_line, emit.prev_di_column,132 emit.prev_di_line, emit.prev_di_column,
125 });133 });
126 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);134 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column, bw.count);
127 },135 },
128 .plan9 => {},136 .plan9 => {},
129 .none => {},137 .none => {},
...@@ -132,6 +140,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -132,6 +140,7 @@ pub fn emitMir(emit: *Emit) Error!void {
132 .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine(140 .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine(
133 mir_inst.data.pseudo_dbg_line_column.line,141 mir_inst.data.pseudo_dbg_line_column.line,
134 mir_inst.data.pseudo_dbg_line_column.column,142 mir_inst.data.pseudo_dbg_line_column.column,
143 bw.count,
135 ),144 ),
136 .pseudo_dbg_epilogue_begin => {145 .pseudo_dbg_epilogue_begin => {
137 switch (emit.debug_output) {146 switch (emit.debug_output) {
...@@ -140,7 +149,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -140,7 +149,7 @@ pub fn emitMir(emit: *Emit) Error!void {
140 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{149 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
141 emit.prev_di_line, emit.prev_di_column,150 emit.prev_di_line, emit.prev_di_column,
142 });151 });
143 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);152 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column, bw.count);
144 },153 },
145 .plan9 => {},154 .plan9 => {},
146 .none => {},155 .none => {},
...@@ -150,7 +159,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -150,7 +159,7 @@ pub fn emitMir(emit: *Emit) Error!void {
150 }159 }
151 }160 }
152 }161 }
153 try emit.fixupRelocs();162 try emit.fixupRelocs(aw.getWritten());
154}163}
155164
156pub fn deinit(emit: *Emit) void {165pub fn deinit(emit: *Emit) void {
...@@ -170,14 +179,14 @@ const Reloc = struct {...@@ -170,14 +179,14 @@ const Reloc = struct {
170 fmt: encoding.Lir.Format,179 fmt: encoding.Lir.Format,
171};180};
172181
173fn fixupRelocs(emit: *Emit) Error!void {182fn fixupRelocs(emit: *Emit, written: []u8) Error!void {
174 for (emit.relocs.items) |reloc| {183 for (emit.relocs.items) |reloc| {
175 log.debug("target inst: {}", .{emit.lower.mir.instructions.get(reloc.target)});184 log.debug("target inst: {f}", .{emit.lower.mir.instructions.get(reloc.target)});
176 const target = emit.code_offset_mapping.get(reloc.target) orelse185 const target = emit.code_offset_mapping.get(reloc.target) orelse
177 return emit.fail("relocation target not found!", .{});186 return emit.fail("relocation target not found!", .{});
178187
179 const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source));188 const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source));
180 const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4];189 const code: *[4]u8 = written[reloc.source + reloc.offset ..][0..4];
181190
182 switch (reloc.fmt) {191 switch (reloc.fmt) {
183 .J => riscv_util.writeInstJ(code, @bitCast(disp)),192 .J => riscv_util.writeInstJ(code, @bitCast(disp)),
...@@ -187,9 +196,9 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -187,9 +196,9 @@ fn fixupRelocs(emit: *Emit) Error!void {
187 }196 }
188}197}
189198
190fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {199fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32, pc: usize) Error!void {
191 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);200 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);
192 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;201 const delta_pc = pc - emit.prev_di_pc;
193 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });202 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
194 switch (emit.debug_output) {203 switch (emit.debug_output) {
195 .dwarf => |dw| {204 .dwarf => |dw| {
src/arch/riscv64/Lower.zig+1-1
...@@ -61,7 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -61,7 +61,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
61 defer lower.result_relocs_len = undefined;61 defer lower.result_relocs_len = undefined;
6262
63 const inst = lower.mir.instructions.get(index);63 const inst = lower.mir.instructions.get(index);
64 log.debug("lowerMir {}", .{inst});64 log.debug("lowerMir {f}", .{inst});
65 switch (inst.tag) {65 switch (inst.tag) {
66 else => try lower.generic(inst),66 else => try lower.generic(inst),
67 .pseudo_dbg_line_column,67 .pseudo_dbg_line_column,
src/arch/riscv64/Mir.zig+2-7
...@@ -92,14 +92,9 @@ pub const Inst = struct {...@@ -92,14 +92,9 @@ pub const Inst = struct {
92 },92 },
93 };93 };
9494
95 pub fn format(95 pub fn format(inst: Inst, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
96 inst: Inst,
97 comptime fmt: []const u8,
98 _: std.fmt.FormatOptions,
99 writer: anytype,
100 ) !void {
101 assert(fmt.len == 0);96 assert(fmt.len == 0);
102 try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });97 try bw.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) });
103 }98 }
104};99};
105100
src/arch/riscv64/bits.zig+6-15
...@@ -256,21 +256,12 @@ pub const FrameIndex = enum(u32) {...@@ -256,21 +256,12 @@ pub const FrameIndex = enum(u32) {
256 return @intFromEnum(fi) < named_count;256 return @intFromEnum(fi) < named_count;
257 }257 }
258258
259 pub fn format(259 pub fn format(fi: FrameIndex, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
260 fi: FrameIndex,260 try bw.writeAll("FrameIndex");
261 comptime fmt: []const u8,261 if (fi.isNamed())
262 options: std.fmt.FormatOptions,262 try bw.print(".{s}", .{@tagName(fi)})
263 writer: anytype,263 else
264 ) @TypeOf(writer).Error!void {264 try bw.print("({d})", .{@intFromEnum(fi)});
265 try writer.writeAll("FrameIndex");
266 if (fi.isNamed()) {
267 try writer.writeByte('.');
268 try writer.writeAll(@tagName(fi));
269 } else {
270 try writer.writeByte('(');
271 try std.fmt.formatType(@intFromEnum(fi), fmt, options, writer, 0);
272 try writer.writeByte(')');
273 }
274 }265 }
275};266};
276267
src/arch/sparc64/CodeGen.zig+5-5
...@@ -1001,7 +1001,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -1001,7 +1001,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
1001 switch (self.args[arg_index]) {1001 switch (self.args[arg_index]) {
1002 .stack_offset => |off| {1002 .stack_offset => |off| {
1003 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {1003 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
1004 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});1004 return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
1005 };1005 };
1006 const offset = off + abi_size;1006 const offset = off + abi_size;
1007 break :blk .{ .stack_offset = offset };1007 break :blk .{ .stack_offset = offset };
...@@ -2748,7 +2748,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -2748,7 +2748,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
2748 }2748 }
27492749
2750 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {2750 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
2751 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});2751 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
2752 };2752 };
2753 // TODO swap this for inst.ty.ptrAlign2753 // TODO swap this for inst.ty.ptrAlign
2754 const abi_align = elem_ty.abiAlignment(zcu);2754 const abi_align = elem_ty.abiAlignment(zcu);
...@@ -2760,7 +2760,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -2760,7 +2760,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
2760 const zcu = pt.zcu;2760 const zcu = pt.zcu;
2761 const elem_ty = self.typeOfIndex(inst);2761 const elem_ty = self.typeOfIndex(inst);
2762 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {2762 const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
2763 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(pt)});2763 return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
2764 };2764 };
2765 const abi_align = elem_ty.abiAlignment(zcu);2765 const abi_align = elem_ty.abiAlignment(zcu);
2766 self.stack_align = self.stack_align.max(abi_align);2766 self.stack_align = self.stack_align.max(abi_align);
...@@ -4111,7 +4111,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -4111,7 +4111,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
4111 while (true) {4111 while (true) {
4112 i -= 1;4112 i -= 1;
4113 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {4113 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {
4114 log.debug("getResolvedInstValue %{} => {}", .{ inst, mcv });4114 log.debug("getResolvedInstValue %{f} => {}", .{ inst, mcv });
4115 assert(mcv != .dead);4115 assert(mcv != .dead);
4116 return mcv;4116 return mcv;
4117 }4117 }
...@@ -4382,7 +4382,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -4382,7 +4382,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4382 const prev_value = self.getResolvedInstValue(inst);4382 const prev_value = self.getResolvedInstValue(inst);
4383 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4383 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4384 branch.inst_table.putAssumeCapacity(inst, .dead);4384 branch.inst_table.putAssumeCapacity(inst, .dead);
4385 log.debug("%{} death: {} -> .dead", .{ inst, prev_value });4385 log.debug("%{f} death: {} -> .dead", .{ inst, prev_value });
4386 switch (prev_value) {4386 switch (prev_value) {
4387 .register => |reg| {4387 .register => |reg| {
4388 self.register_manager.freeReg(reg);4388 self.register_manager.freeReg(reg);
src/arch/wasm/CodeGen.zig+16-16
...@@ -1463,7 +1463,7 @@ fn allocStack(cg: *CodeGen, ty: Type) !WValue {...@@ -1463,7 +1463,7 @@ fn allocStack(cg: *CodeGen, ty: Type) !WValue {
1463 }1463 }
14641464
1465 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {1465 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
1466 return cg.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1466 return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
1467 ty.fmt(pt), ty.abiSize(zcu),1467 ty.fmt(pt), ty.abiSize(zcu),
1468 });1468 });
1469 };1469 };
...@@ -1497,7 +1497,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue {...@@ -1497,7 +1497,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue {
14971497
1498 const abi_alignment = ptr_ty.ptrAlignment(zcu);1498 const abi_alignment = ptr_ty.ptrAlignment(zcu);
1499 const abi_size = std.math.cast(u32, pointee_ty.abiSize(zcu)) orelse {1499 const abi_size = std.math.cast(u32, pointee_ty.abiSize(zcu)) orelse {
1500 return cg.fail("Type {} with ABI size of {d} exceeds stack frame size", .{1500 return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
1501 pointee_ty.fmt(pt), pointee_ty.abiSize(zcu),1501 pointee_ty.fmt(pt), pointee_ty.abiSize(zcu),
1502 });1502 });
1503 };1503 };
...@@ -2404,7 +2404,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr...@@ -2404,7 +2404,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
2404 try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) });2404 try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) });
2405 },2405 },
2406 else => if (abi_size > 8) {2406 else => if (abi_size > 8) {
2407 return cg.fail("TODO: `store` for type `{}` with abisize `{d}`", .{2407 return cg.fail("TODO: `store` for type `{f}` with abisize `{d}`", .{
2408 ty.fmt(pt),2408 ty.fmt(pt),
2409 abi_size,2409 abi_size,
2410 });2410 });
...@@ -2597,7 +2597,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV...@@ -2597,7 +2597,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV
2597 return cg.binOpBigInt(lhs, rhs, ty, op);2597 return cg.binOpBigInt(lhs, rhs, ty, op);
2598 } else {2598 } else {
2599 return cg.fail(2599 return cg.fail(
2600 "TODO: Implement binary operation for type: {}",2600 "TODO: Implement binary operation for type: {f}",
2601 .{ty.fmt(pt)},2601 .{ty.fmt(pt)},
2602 );2602 );
2603 }2603 }
...@@ -2817,7 +2817,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2817,7 +2817,7 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
28172817
2818 switch (scalar_ty.zigTypeTag(zcu)) {2818 switch (scalar_ty.zigTypeTag(zcu)) {
2819 .int => if (ty.zigTypeTag(zcu) == .vector) {2819 .int => if (ty.zigTypeTag(zcu) == .vector) {
2820 return cg.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});2820 return cg.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
2821 } else {2821 } else {
2822 const int_bits = ty.intInfo(zcu).bits;2822 const int_bits = ty.intInfo(zcu).bits;
2823 const wasm_bits = toWasmBits(int_bits) orelse {2823 const wasm_bits = toWasmBits(int_bits) orelse {
...@@ -3244,7 +3244,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3244,7 +3244,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3244 return .{ .imm32 = @intFromBool(!val.isNull(zcu)) };3244 return .{ .imm32 = @intFromBool(!val.isNull(zcu)) };
3245 },3245 },
3246 .aggregate => switch (ip.indexToKey(ty.ip_index)) {3246 .aggregate => switch (ip.indexToKey(ty.ip_index)) {
3247 .array_type => return cg.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(pt)}),3247 .array_type => return cg.fail("Wasm TODO: LowerConstant for {f}", .{ty.fmt(pt)}),
3248 .vector_type => {3248 .vector_type => {
3249 assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct);3249 assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct);
3250 var buf: [16]u8 = undefined;3250 var buf: [16]u8 = undefined;
...@@ -3608,7 +3608,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3608,7 +3608,7 @@ fn airNot(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3608 } else {3608 } else {
3609 const int_info = operand_ty.intInfo(zcu);3609 const int_info = operand_ty.intInfo(zcu);
3610 const wasm_bits = toWasmBits(int_info.bits) orelse {3610 const wasm_bits = toWasmBits(int_info.bits) orelse {
3611 return cg.fail("TODO: Implement binary NOT for {}", .{operand_ty.fmt(pt)});3611 return cg.fail("TODO: Implement binary NOT for {f}", .{operand_ty.fmt(pt)});
3612 };3612 };
36133613
3614 switch (wasm_bits) {3614 switch (wasm_bits) {
...@@ -3874,7 +3874,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3874,7 +3874,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3874 },3874 },
3875 else => result: {3875 else => result: {
3876 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse {3876 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse {
3877 return cg.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(pt)});3877 return cg.fail("Field type '{f}' too big to fit into stack frame", .{field_ty.fmt(pt)});
3878 };3878 };
3879 if (isByRef(field_ty, zcu, cg.target)) {3879 if (isByRef(field_ty, zcu, cg.target)) {
3880 switch (operand) {3880 switch (operand) {
...@@ -4360,7 +4360,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc...@@ -4360,7 +4360,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc
4360 // a pointer to the stack value4360 // a pointer to the stack value
4361 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {4361 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
4362 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4362 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4363 return cg.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(pt)});4363 return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)});
4364 };4364 };
4365 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });4365 try cg.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
4366 }4366 }
...@@ -4430,7 +4430,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void...@@ -4430,7 +4430,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
4430 }4430 }
44314431
4432 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4432 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4433 return cg.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(pt)});4433 return cg.fail("Optional type {f} too big to fit into stack frame", .{opt_ty.fmt(pt)});
4434 };4434 };
44354435
4436 try cg.emitWValue(operand);4436 try cg.emitWValue(operand);
...@@ -4462,7 +4462,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4462,7 +4462,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4462 break :result cg.reuseOperand(ty_op.operand, operand);4462 break :result cg.reuseOperand(ty_op.operand, operand);
4463 }4463 }
4464 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {4464 const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
4465 return cg.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(pt)});4465 return cg.fail("Optional type {f} too big to fit into stack frame", .{op_ty.fmt(pt)});
4466 };4466 };
44674467
4468 // Create optional type, set the non-null bit, and store the operand inside the optional type4468 // Create optional type, set the non-null bit, and store the operand inside the optional type
...@@ -6196,7 +6196,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6196,7 +6196,7 @@ fn airMulWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6196 _ = try cg.load(overflow_ret, Type.i32, 0);6196 _ = try cg.load(overflow_ret, Type.i32, 0);
6197 try cg.addLocal(.local_set, overflow_bit.local.value);6197 try cg.addLocal(.local_set, overflow_bit.local.value);
6198 break :blk res;6198 break :blk res;
6199 } else return cg.fail("TODO: @mulWithOverflow for {}", .{ty.fmt(pt)});6199 } else return cg.fail("TODO: @mulWithOverflow for {f}", .{ty.fmt(pt)});
6200 var bin_op_local = try mul.toLocal(cg, ty);6200 var bin_op_local = try mul.toLocal(cg, ty);
6201 defer bin_op_local.free(cg);6201 defer bin_op_local.free(cg);
62026202
...@@ -6749,7 +6749,7 @@ fn airMod(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6749,7 +6749,7 @@ fn airMod(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6749 const add = try cg.binOp(rem, rhs, ty, .add);6749 const add = try cg.binOp(rem, rhs, ty, .add);
6750 break :result try cg.binOp(add, rhs, ty, .rem);6750 break :result try cg.binOp(add, rhs, ty, .rem);
6751 }6751 }
6752 return cg.fail("TODO: @mod for {}", .{ty.fmt(pt)});6752 return cg.fail("TODO: @mod for {f}", .{ty.fmt(pt)});
6753 };6753 };
67546754
6755 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });6755 return cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
...@@ -6767,7 +6767,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6767,7 +6767,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6767 const lhs = try cg.resolveInst(bin_op.lhs);6767 const lhs = try cg.resolveInst(bin_op.lhs);
6768 const rhs = try cg.resolveInst(bin_op.rhs);6768 const rhs = try cg.resolveInst(bin_op.rhs);
6769 const wasm_bits = toWasmBits(int_info.bits) orelse {6769 const wasm_bits = toWasmBits(int_info.bits) orelse {
6770 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6770 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6771 };6771 };
67726772
6773 switch (wasm_bits) {6773 switch (wasm_bits) {
...@@ -6804,7 +6804,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6804,7 +6804,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6804 },6804 },
6805 64 => {6805 64 => {
6806 if (!(int_info.bits == 64 and int_info.signedness == .signed)) {6806 if (!(int_info.bits == 64 and int_info.signedness == .signed)) {
6807 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6807 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6808 }6808 }
6809 const overflow_ret = try cg.allocStack(Type.i32);6809 const overflow_ret = try cg.allocStack(Type.i32);
6810 _ = try cg.callIntrinsic(6810 _ = try cg.callIntrinsic(
...@@ -6822,7 +6822,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6822,7 +6822,7 @@ fn airSatMul(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6822 },6822 },
6823 128 => {6823 128 => {
6824 if (!(int_info.bits == 128 and int_info.signedness == .signed)) {6824 if (!(int_info.bits == 128 and int_info.signedness == .signed)) {
6825 return cg.fail("TODO: mul_sat for {}", .{ty.fmt(pt)});6825 return cg.fail("TODO: mul_sat for {f}", .{ty.fmt(pt)});
6826 }6826 }
6827 const overflow_ret = try cg.allocStack(Type.i32);6827 const overflow_ret = try cg.allocStack(Type.i32);
6828 const ret = try cg.callIntrinsic(6828 const ret = try cg.callIntrinsic(
src/arch/wasm/Emit.zig+105-133
...@@ -14,16 +14,20 @@ const codegen = @import("../../codegen.zig");...@@ -14,16 +14,20 @@ const codegen = @import("../../codegen.zig");
1414
15mir: Mir,15mir: Mir,
16wasm: *Wasm,16wasm: *Wasm,
17/// The binary representation that will be emitted by this module.17/// The binary representation of this module is written here.
18code: *std.ArrayListUnmanaged(u8),18bw: *std.io.BufferedWriter,
1919
20pub const Error = error{20pub const Error = error{
21 OutOfMemory,21 OutOfMemory,
22};22};
2323
24pub fn lowerToCode(emit: *Emit) Error!void {24pub fn lowerToCode(emit: *Emit) Error!void {
25 return @errorCast(emit.lowerToCodeInner());
26}
27
28fn lowerToCodeInner(emit: *Emit) anyerror!void {
25 const mir = &emit.mir;29 const mir = &emit.mir;
26 const code = emit.code;30 const bw = emit.bw;
27 const wasm = emit.wasm;31 const wasm = emit.wasm;
28 const comp = wasm.base.comp;32 const comp = wasm.base.comp;
29 const gpa = comp.gpa;33 const gpa = comp.gpa;
...@@ -41,18 +45,19 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -41,18 +45,19 @@ pub fn lowerToCode(emit: *Emit) Error!void {
41 },45 },
42 .block, .loop => {46 .block, .loop => {
43 const block_type = datas[inst].block_type;47 const block_type = datas[inst].block_type;
44 try code.ensureUnusedCapacity(gpa, 2);48 try bw.writeAll(&.{
45 code.appendAssumeCapacity(@intFromEnum(tags[inst]));49 @intFromEnum(tags[inst]),
46 code.appendAssumeCapacity(@intFromEnum(block_type));50 @intFromEnum(block_type),
51 });
4752
48 inst += 1;53 inst += 1;
49 continue :loop tags[inst];54 continue :loop tags[inst];
50 },55 },
51 .uav_ref => {56 .uav_ref => {
52 if (is_obj) {57 if (is_obj) {
53 try uavRefObj(wasm, code, datas[inst].ip_index, 0, is_wasm32);58 try uavRefObj(wasm, bw, datas[inst].ip_index, 0, is_wasm32);
54 } else {59 } else {
55 try uavRefExe(wasm, code, datas[inst].ip_index, 0, is_wasm32);60 try uavRefExe(wasm, bw, datas[inst].ip_index, 0, is_wasm32);
56 }61 }
57 inst += 1;62 inst += 1;
58 continue :loop tags[inst];63 continue :loop tags[inst];
...@@ -60,20 +65,20 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -60,20 +65,20 @@ pub fn lowerToCode(emit: *Emit) Error!void {
60 .uav_ref_off => {65 .uav_ref_off => {
61 const extra = mir.extraData(Mir.UavRefOff, datas[inst].payload).data;66 const extra = mir.extraData(Mir.UavRefOff, datas[inst].payload).data;
62 if (is_obj) {67 if (is_obj) {
63 try uavRefObj(wasm, code, extra.value, extra.offset, is_wasm32);68 try uavRefObj(wasm, bw, extra.value, extra.offset, is_wasm32);
64 } else {69 } else {
65 try uavRefExe(wasm, code, extra.value, extra.offset, is_wasm32);70 try uavRefExe(wasm, bw, extra.value, extra.offset, is_wasm32);
66 }71 }
67 inst += 1;72 inst += 1;
68 continue :loop tags[inst];73 continue :loop tags[inst];
69 },74 },
70 .nav_ref => {75 .nav_ref => {
71 try navRefOff(wasm, code, .{ .nav_index = datas[inst].nav_index, .offset = 0 }, is_wasm32);76 try navRefOff(wasm, bw, .{ .nav_index = datas[inst].nav_index, .offset = 0 }, is_wasm32);
72 inst += 1;77 inst += 1;
73 continue :loop tags[inst];78 continue :loop tags[inst];
74 },79 },
75 .nav_ref_off => {80 .nav_ref_off => {
76 try navRefOff(wasm, code, mir.extraData(Mir.NavRefOff, datas[inst].payload).data, is_wasm32);81 try navRefOff(wasm, bw, mir.extraData(Mir.NavRefOff, datas[inst].payload).data, is_wasm32);
77 inst += 1;82 inst += 1;
78 continue :loop tags[inst];83 continue :loop tags[inst];
79 },84 },
...@@ -81,11 +86,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -81,11 +86,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {
81 const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @enumFromInt(86 const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @enumFromInt(
82 wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,87 wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?,
83 );88 );
84 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));89 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
85 if (is_obj) {90 if (is_obj) {
86 @panic("TODO");91 @panic("TODO");
87 } else {92 } else {
88 leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(indirect_func_idx)) catch unreachable;93 try bw.writeLeb128(1 + @intFromEnum(indirect_func_idx));
89 }94 }
90 inst += 1;95 inst += 1;
91 continue :loop tags[inst];96 continue :loop tags[inst];
...@@ -95,52 +100,48 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -95,52 +100,48 @@ pub fn lowerToCode(emit: *Emit) Error!void {
95 continue :loop tags[inst];100 continue :loop tags[inst];
96 },101 },
97 .errors_len => {102 .errors_len => {
98 try code.ensureUnusedCapacity(gpa, 6);103 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
99 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
100 // MIR is lowered during flush, so there is indeed only one thread at this time.104 // MIR is lowered during flush, so there is indeed only one thread at this time.
101 const errors_len = 1 + comp.zcu.?.intern_pool.global_error_set.getNamesFromMainThread().len;105 const errors_len: u32 = @intCast(1 + comp.zcu.?.intern_pool.global_error_set.getNamesFromMainThread().len);
102 leb.writeIleb128(code.fixedWriter(), errors_len) catch unreachable;106 try bw.writeLeb128(@as(i32, @bitCast(errors_len)));
103107
104 inst += 1;108 inst += 1;
105 continue :loop tags[inst];109 continue :loop tags[inst];
106 },110 },
107 .error_name_table_ref => {111 .error_name_table_ref => {
108 wasm.error_name_table_ref_count += 1;112 wasm.error_name_table_ref_count += 1;
109 try code.ensureUnusedCapacity(gpa, 11);
110 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;113 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
111 code.appendAssumeCapacity(@intFromEnum(opcode));114 try bw.writeByte(@intFromEnum(opcode));
112 if (is_obj) {115 if (is_obj) {
113 try wasm.out_relocs.append(gpa, .{116 try wasm.out_relocs.append(gpa, .{
114 .offset = @intCast(code.items.len),117 .offset = @intCast(bw.count),
115 .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() },118 .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() },
116 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,119 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
117 .addend = 0,120 .addend = 0,
118 });121 });
119 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);122 try bw.splatByteAll(0, if (is_wasm32) 5 else 10);
120123
121 inst += 1;124 inst += 1;
122 continue :loop tags[inst];125 continue :loop tags[inst];
123 } else {126 } else {
124 const addr: u32 = wasm.errorNameTableAddr();127 const addr: u32 = wasm.errorNameTableAddr();
125 leb.writeIleb128(code.fixedWriter(), addr) catch unreachable;128 try bw.writeLeb128(@as(i32, @bitCast(addr)));
126129
127 inst += 1;130 inst += 1;
128 continue :loop tags[inst];131 continue :loop tags[inst];
129 }132 }
130 },133 },
131 .br_if, .br, .memory_grow, .memory_size => {134 .br_if, .br, .memory_grow, .memory_size => {
132 try code.ensureUnusedCapacity(gpa, 11);135 try bw.writeByte(@intFromEnum(tags[inst]));
133 code.appendAssumeCapacity(@intFromEnum(tags[inst]));136 try bw.writeLeb128(datas[inst].label);
134 leb.writeUleb128(code.fixedWriter(), datas[inst].label) catch unreachable;
135137
136 inst += 1;138 inst += 1;
137 continue :loop tags[inst];139 continue :loop tags[inst];
138 },140 },
139141
140 .local_get, .local_set, .local_tee => {142 .local_get, .local_set, .local_tee => {
141 try code.ensureUnusedCapacity(gpa, 11);143 try bw.writeByte(@intFromEnum(tags[inst]));
142 code.appendAssumeCapacity(@intFromEnum(tags[inst]));144 try bw.writeLeb128(datas[inst].local);
143 leb.writeUleb128(code.fixedWriter(), datas[inst].local) catch unreachable;
144145
145 inst += 1;146 inst += 1;
146 continue :loop tags[inst];147 continue :loop tags[inst];
...@@ -150,29 +151,27 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -150,29 +151,27 @@ pub fn lowerToCode(emit: *Emit) Error!void {
150 const extra_index = datas[inst].payload;151 const extra_index = datas[inst].payload;
151 const extra = mir.extraData(Mir.JumpTable, extra_index);152 const extra = mir.extraData(Mir.JumpTable, extra_index);
152 const labels = mir.extra[extra.end..][0..extra.data.length];153 const labels = mir.extra[extra.end..][0..extra.data.length];
153 try code.ensureUnusedCapacity(gpa, 11 + 10 * labels.len);154 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br_table));
154 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_table));
155 // -1 because default label is not part of length/depth.155 // -1 because default label is not part of length/depth.
156 leb.writeUleb128(code.fixedWriter(), extra.data.length - 1) catch unreachable;156 try bw.writeLeb128(extra.data.length - 1);
157 for (labels) |label| leb.writeUleb128(code.fixedWriter(), label) catch unreachable;157 for (labels) |label| try bw.writeLeb128(label);
158158
159 inst += 1;159 inst += 1;
160 continue :loop tags[inst];160 continue :loop tags[inst];
161 },161 },
162162
163 .call_nav => {163 .call_nav => {
164 try code.ensureUnusedCapacity(gpa, 6);164 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));
165 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));
166 if (is_obj) {165 if (is_obj) {
167 try wasm.out_relocs.append(gpa, .{166 try wasm.out_relocs.append(gpa, .{
168 .offset = @intCast(code.items.len),167 .offset = @intCast(bw.count),
169 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) },168 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(datas[inst].nav_index) },
170 .tag = .function_index_leb,169 .tag = .function_index_leb,
171 .addend = 0,170 .addend = 0,
172 });171 });
173 code.appendNTimesAssumeCapacity(0, 5);172 try bw.splatByteAll(0, 5);
174 } else {173 } else {
175 appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index));174 try appendOutputFunctionIndex(bw, .fromIpNav(wasm, datas[inst].nav_index));
176 }175 }
177176
178 inst += 1;177 inst += 1;
...@@ -180,7 +179,6 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -180,7 +179,6 @@ pub fn lowerToCode(emit: *Emit) Error!void {
180 },179 },
181180
182 .call_indirect => {181 .call_indirect => {
183 try code.ensureUnusedCapacity(gpa, 11);
184 const fn_info = comp.zcu.?.typeToFunc(.fromInterned(datas[inst].ip_index)).?;182 const fn_info = comp.zcu.?.typeToFunc(.fromInterned(datas[inst].ip_index)).?;
185 const func_ty_index = wasm.getExistingFunctionType(183 const func_ty_index = wasm.getExistingFunctionType(
186 fn_info.cc,184 fn_info.cc,
...@@ -188,38 +186,37 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -188,38 +186,37 @@ pub fn lowerToCode(emit: *Emit) Error!void {
188 .fromInterned(fn_info.return_type),186 .fromInterned(fn_info.return_type),
189 target,187 target,
190 ).?;188 ).?;
191 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call_indirect));189 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call_indirect));
192 if (is_obj) {190 if (is_obj) {
193 try wasm.out_relocs.append(gpa, .{191 try wasm.out_relocs.append(gpa, .{
194 .offset = @intCast(code.items.len),192 .offset = @intCast(bw.count),
195 .pointee = .{ .type_index = func_ty_index },193 .pointee = .{ .type_index = func_ty_index },
196 .tag = .type_index_leb,194 .tag = .type_index_leb,
197 .addend = 0,195 .addend = 0,
198 });196 });
199 code.appendNTimesAssumeCapacity(0, 5);197 try bw.splatByteAll(0, 5);
200 } else {198 } else {
201 const index: Wasm.Flush.FuncTypeIndex = .fromTypeIndex(func_ty_index, &wasm.flush_buffer);199 const index: Wasm.Flush.FuncTypeIndex = .fromTypeIndex(func_ty_index, &wasm.flush_buffer);
202 leb.writeUleb128(code.fixedWriter(), @intFromEnum(index)) catch unreachable;200 try bw.writeLeb128(@intFromEnum(index));
203 }201 }
204 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // table index202 try bw.writeUleb128(0); // table index
205203
206 inst += 1;204 inst += 1;
207 continue :loop tags[inst];205 continue :loop tags[inst];
208 },206 },
209207
210 .call_tag_name => {208 .call_tag_name => {
211 try code.ensureUnusedCapacity(gpa, 6);209 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));
212 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));
213 if (is_obj) {210 if (is_obj) {
214 try wasm.out_relocs.append(gpa, .{211 try wasm.out_relocs.append(gpa, .{
215 .offset = @intCast(code.items.len),212 .offset = @intCast(bw.count),
216 .pointee = .{ .symbol_index = try wasm.tagNameSymbolIndex(datas[inst].ip_index) },213 .pointee = .{ .symbol_index = try wasm.tagNameSymbolIndex(datas[inst].ip_index) },
217 .tag = .function_index_leb,214 .tag = .function_index_leb,
218 .addend = 0,215 .addend = 0,
219 });216 });
220 code.appendNTimesAssumeCapacity(0, 5);217 try bw.splatByteAll(0, 5);
221 } else {218 } else {
222 appendOutputFunctionIndex(code, .fromTagNameType(wasm, datas[inst].ip_index));219 try appendOutputFunctionIndex(bw, .fromTagNameType(wasm, datas[inst].ip_index));
223 }220 }
224221
225 inst += 1;222 inst += 1;
...@@ -232,18 +229,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -232,18 +229,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {
232 // table initialized based on the `Mir.Intrinsic` enum.229 // table initialized based on the `Mir.Intrinsic` enum.
233 const symbol_name = try wasm.internString(@tagName(datas[inst].intrinsic));230 const symbol_name = try wasm.internString(@tagName(datas[inst].intrinsic));
234231
235 try code.ensureUnusedCapacity(gpa, 6);232 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));
236 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));
237 if (is_obj) {233 if (is_obj) {
238 try wasm.out_relocs.append(gpa, .{234 try wasm.out_relocs.append(gpa, .{
239 .offset = @intCast(code.items.len),235 .offset = @intCast(bw.count),
240 .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) },236 .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) },
241 .tag = .function_index_leb,237 .tag = .function_index_leb,
242 .addend = 0,238 .addend = 0,
243 });239 });
244 code.appendNTimesAssumeCapacity(0, 5);240 try bw.splatByteAll(0, 5);
245 } else {241 } else {
246 appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name));242 try appendOutputFunctionIndex(bw, .fromSymbolName(wasm, symbol_name));
247 }243 }
248244
249 inst += 1;245 inst += 1;
...@@ -251,19 +247,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -251,19 +247,17 @@ pub fn lowerToCode(emit: *Emit) Error!void {
251 },247 },
252248
253 .global_set_sp => {249 .global_set_sp => {
254 try code.ensureUnusedCapacity(gpa, 6);250 try bw.writeByte(@intFromEnum(std.wasm.Opcode.global_set));
255 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));
256 if (is_obj) {251 if (is_obj) {
257 try wasm.out_relocs.append(gpa, .{252 try wasm.out_relocs.append(gpa, .{
258 .offset = @intCast(code.items.len),253 .offset = @intCast(bw.count),
259 .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() },254 .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() },
260 .tag = .global_index_leb,255 .tag = .global_index_leb,
261 .addend = 0,256 .addend = 0,
262 });257 });
263 code.appendNTimesAssumeCapacity(0, 5);258 try bw.splatByteAll(0, 5);
264 } else {259 } else {
265 const sp_global: Wasm.GlobalIndex = .stack_pointer;260 try bw.writeLeb128(@intFromEnum(Wasm.GlobalIndex.stack_pointer));
266 std.leb.writeULEB128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable;
267 }261 }
268262
269 inst += 1;263 inst += 1;
...@@ -271,36 +265,32 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -271,36 +265,32 @@ pub fn lowerToCode(emit: *Emit) Error!void {
271 },265 },
272266
273 .f32_const => {267 .f32_const => {
274 try code.ensureUnusedCapacity(gpa, 5);268 try bw.writeByte(@intFromEnum(std.wasm.Opcode.f32_const));
275 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.f32_const));269 try bw.writeInt(u32, @bitCast(datas[inst].float32), .little);
276 std.mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @bitCast(datas[inst].float32), .little);
277270
278 inst += 1;271 inst += 1;
279 continue :loop tags[inst];272 continue :loop tags[inst];
280 },273 },
281274
282 .f64_const => {275 .f64_const => {
283 try code.ensureUnusedCapacity(gpa, 9);276 try bw.writeByte(@intFromEnum(std.wasm.Opcode.f64_const));
284 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.f64_const));
285 const float64 = mir.extraData(Mir.Float64, datas[inst].payload).data;277 const float64 = mir.extraData(Mir.Float64, datas[inst].payload).data;
286 std.mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), float64.toInt(), .little);278 try bw.writeInt(u64, float64.toInt(), .little);
287279
288 inst += 1;280 inst += 1;
289 continue :loop tags[inst];281 continue :loop tags[inst];
290 },282 },
291 .i32_const => {283 .i32_const => {
292 try code.ensureUnusedCapacity(gpa, 6);284 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
293 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));285 try bw.writeLeb128(datas[inst].imm32);
294 leb.writeIleb128(code.fixedWriter(), datas[inst].imm32) catch unreachable;
295286
296 inst += 1;287 inst += 1;
297 continue :loop tags[inst];288 continue :loop tags[inst];
298 },289 },
299 .i64_const => {290 .i64_const => {
300 try code.ensureUnusedCapacity(gpa, 11);291 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));
301 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const));
302 const int64: i64 = @bitCast(mir.extraData(Mir.Imm64, datas[inst].payload).data.toInt());292 const int64: i64 = @bitCast(mir.extraData(Mir.Imm64, datas[inst].payload).data.toInt());
303 leb.writeIleb128(code.fixedWriter(), int64) catch unreachable;293 try bw.writeLeb128(int64);
304294
305 inst += 1;295 inst += 1;
306 continue :loop tags[inst];296 continue :loop tags[inst];
...@@ -330,9 +320,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -330,9 +320,8 @@ pub fn lowerToCode(emit: *Emit) Error!void {
330 .i64_store16,320 .i64_store16,
331 .i64_store32,321 .i64_store32,
332 => {322 => {
333 try code.ensureUnusedCapacity(gpa, 1 + 20);323 try bw.writeByte(@intFromEnum(tags[inst]));
334 code.appendAssumeCapacity(@intFromEnum(tags[inst]));324 try encodeMemArg(bw, mir.extraData(Mir.MemArg, datas[inst].payload).data);
335 encodeMemArg(code, mir.extraData(Mir.MemArg, datas[inst].payload).data);
336 inst += 1;325 inst += 1;
337 continue :loop tags[inst];326 continue :loop tags[inst];
338 },327 },
...@@ -466,43 +455,42 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -466,43 +455,42 @@ pub fn lowerToCode(emit: *Emit) Error!void {
466 .i64_clz,455 .i64_clz,
467 .i64_ctz,456 .i64_ctz,
468 => {457 => {
469 try code.append(gpa, @intFromEnum(tags[inst]));458 try bw.writeByte(@intFromEnum(tags[inst]));
470 inst += 1;459 inst += 1;
471 continue :loop tags[inst];460 continue :loop tags[inst];
472 },461 },
473462
474 .misc_prefix => {463 .misc_prefix => {
475 try code.ensureUnusedCapacity(gpa, 6 + 6);
476 const extra_index = datas[inst].payload;464 const extra_index = datas[inst].payload;
477 const opcode = mir.extra[extra_index];465 const opcode: std.wasm.MiscOpcode = @enumFromInt(mir.extra[extra_index]);
478 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.misc_prefix));466 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
479 leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable;467 try bw.writeLeb128(@intFromEnum(opcode));
480 switch (@as(std.wasm.MiscOpcode, @enumFromInt(opcode))) {468 switch (opcode) {
481 // bulk-memory opcodes469 // bulk-memory opcodes
482 .data_drop => {470 .data_drop => {
483 const segment = mir.extra[extra_index + 1];471 const segment = mir.extra[extra_index + 1];
484 leb.writeUleb128(code.fixedWriter(), segment) catch unreachable;472 try bw.writeLeb128(segment);
485473
486 inst += 1;474 inst += 1;
487 continue :loop tags[inst];475 continue :loop tags[inst];
488 },476 },
489 .memory_init => {477 .memory_init => {
490 const segment = mir.extra[extra_index + 1];478 const segment = mir.extra[extra_index + 1];
491 leb.writeUleb128(code.fixedWriter(), segment) catch unreachable;479 try bw.writeLeb128(segment);
492 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // memory index480 try bw.writeByte(0); // memory index
493481
494 inst += 1;482 inst += 1;
495 continue :loop tags[inst];483 continue :loop tags[inst];
496 },484 },
497 .memory_fill => {485 .memory_fill => {
498 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // memory index486 try bw.writeByte(0); // memory index
499487
500 inst += 1;488 inst += 1;
501 continue :loop tags[inst];489 continue :loop tags[inst];
502 },490 },
503 .memory_copy => {491 .memory_copy => {
504 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // dst memory index492 try bw.writeByte(0); // dst memory index
505 leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // src memory index493 try bw.writeByte(0); // src memory index
506494
507 inst += 1;495 inst += 1;
508 continue :loop tags[inst];496 continue :loop tags[inst];
...@@ -534,12 +522,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -534,12 +522,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {
534 comptime unreachable;522 comptime unreachable;
535 },523 },
536 .simd_prefix => {524 .simd_prefix => {
537 try code.ensureUnusedCapacity(gpa, 6 + 20);
538 const extra_index = datas[inst].payload;525 const extra_index = datas[inst].payload;
539 const opcode = mir.extra[extra_index];526 const opcode: std.wasm.SimdOpcode = @enumFromInt(mir.extra[extra_index]);
540 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.simd_prefix));527 try bw.writeByte(@intFromEnum(std.wasm.Opcode.simd_prefix));
541 leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable;528 try bw.writeLeb128(@intFromEnum(opcode));
542 switch (@as(std.wasm.SimdOpcode, @enumFromInt(opcode))) {529 switch (opcode) {
543 .v128_store,530 .v128_store,
544 .v128_load,531 .v128_load,
545 .v128_load8_splat,532 .v128_load8_splat,
...@@ -547,12 +534,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -547,12 +534,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {
547 .v128_load32_splat,534 .v128_load32_splat,
548 .v128_load64_splat,535 .v128_load64_splat,
549 => {536 => {
550 encodeMemArg(code, mir.extraData(Mir.MemArg, extra_index + 1).data);537 try encodeMemArg(bw, mir.extraData(Mir.MemArg, extra_index + 1).data);
551 inst += 1;538 inst += 1;
552 continue :loop tags[inst];539 continue :loop tags[inst];
553 },540 },
554 .v128_const, .i8x16_shuffle => {541 .v128_const, .i8x16_shuffle => {
555 code.appendSliceAssumeCapacity(std.mem.asBytes(mir.extra[extra_index + 1 ..][0..4]));542 try bw.writeAll(std.mem.asBytes(mir.extra[extra_index + 1 ..][0..4]));
556 inst += 1;543 inst += 1;
557 continue :loop tags[inst];544 continue :loop tags[inst];
558 },545 },
...@@ -571,7 +558,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -571,7 +558,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
571 .f64x2_extract_lane,558 .f64x2_extract_lane,
572 .f64x2_replace_lane,559 .f64x2_replace_lane,
573 => {560 => {
574 code.appendAssumeCapacity(@intCast(mir.extra[extra_index + 1]));561 try bw.writeByte(@intCast(mir.extra[extra_index + 1]));
575 inst += 1;562 inst += 1;
576 continue :loop tags[inst];563 continue :loop tags[inst];
577 },564 },
...@@ -819,13 +806,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -819,13 +806,11 @@ pub fn lowerToCode(emit: *Emit) Error!void {
819 comptime unreachable;806 comptime unreachable;
820 },807 },
821 .atomics_prefix => {808 .atomics_prefix => {
822 try code.ensureUnusedCapacity(gpa, 6 + 20);
823
824 const extra_index = datas[inst].payload;809 const extra_index = datas[inst].payload;
825 const opcode = mir.extra[extra_index];810 const opcode: std.wasm.AtomicsOpcode = @enumFromInt(mir.extra[extra_index]);
826 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix));811 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
827 leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable;812 try bw.writeLeb128(@intFromEnum(opcode));
828 switch (@as(std.wasm.AtomicsOpcode, @enumFromInt(opcode))) {813 switch (opcode) {
829 .i32_atomic_load,814 .i32_atomic_load,
830 .i64_atomic_load,815 .i64_atomic_load,
831 .i32_atomic_load8_u,816 .i32_atomic_load8_u,
...@@ -892,15 +877,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -892,15 +877,12 @@ pub fn lowerToCode(emit: *Emit) Error!void {
892 .i64_atomic_rmw32_cmpxchg_u,877 .i64_atomic_rmw32_cmpxchg_u,
893 => {878 => {
894 const mem_arg = mir.extraData(Mir.MemArg, extra_index + 1).data;879 const mem_arg = mir.extraData(Mir.MemArg, extra_index + 1).data;
895 encodeMemArg(code, mem_arg);880 try encodeMemArg(bw, mem_arg);
896 inst += 1;881 inst += 1;
897 continue :loop tags[inst];882 continue :loop tags[inst];
898 },883 },
899 .atomic_fence => {884 .atomic_fence => {
900 // Hard-codes memory index 0 since multi-memory proposal is885 try bw.writeByte(0); // memory index
901 // not yet accepted nor implemented.
902 const memory_index: u32 = 0;
903 leb.writeUleb128(code.fixedWriter(), memory_index) catch unreachable;
904 inst += 1;886 inst += 1;
905 continue :loop tags[inst];887 continue :loop tags[inst];
906 },888 },
...@@ -915,44 +897,36 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -915,44 +897,36 @@ pub fn lowerToCode(emit: *Emit) Error!void {
915}897}
916898
917/// Asserts 20 unused capacity.899/// Asserts 20 unused capacity.
918fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void {900fn encodeMemArg(bw: *std.io.BufferedWriter, mem_arg: Mir.MemArg) anyerror!void {
919 assert(code.unusedCapacitySlice().len >= 20);901 try bw.writeLeb128(Wasm.Alignment.fromNonzeroByteUnits(mem_arg.alignment).toLog2Units());
920 // Wasm encodes alignment as power of 2, rather than natural alignment.902 try bw.writeLeb128(mem_arg.offset);
921 const encoded_alignment = @ctz(mem_arg.alignment);
922 leb.writeUleb128(code.fixedWriter(), encoded_alignment) catch unreachable;
923 leb.writeUleb128(code.fixedWriter(), mem_arg.offset) catch unreachable;
924}903}
925904
926fn uavRefObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {905fn uavRefObj(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
927 const comp = wasm.base.comp;906 const comp = wasm.base.comp;
928 const gpa = comp.gpa;907 const gpa = comp.gpa;
929 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;908 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
930909
931 try code.ensureUnusedCapacity(gpa, 11);910 try bw.writeByte(@intFromEnum(opcode));
932 code.appendAssumeCapacity(@intFromEnum(opcode));
933911
934 try wasm.out_relocs.append(gpa, .{912 try wasm.out_relocs.append(gpa, .{
935 .offset = @intCast(code.items.len),913 .offset = @intCast(bw.count),
936 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },914 .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) },
937 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,915 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
938 .addend = offset,916 .addend = offset,
939 });917 });
940 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);918 try bw.splatByteAll(0, if (is_wasm32) 5 else 10);
941}919}
942920
943fn uavRefExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void {921fn uavRefExe(wasm: *Wasm, bw: *std.io.BufferedWriter, value: InternPool.Index, offset: i32, is_wasm32: bool) !void {
944 const comp = wasm.base.comp;
945 const gpa = comp.gpa;
946 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;922 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
947923 try bw.writeByte(@intFromEnum(opcode));
948 try code.ensureUnusedCapacity(gpa, 11);
949 code.appendAssumeCapacity(@intFromEnum(opcode));
950924
951 const addr = wasm.uavAddr(value);925 const addr = wasm.uavAddr(value);
952 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + offset))) catch unreachable;926 try bw.writeLeb128(@as(u32, @intCast(@as(i64, addr) + offset)));
953}927}
954928
955fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff, is_wasm32: bool) !void {929fn navRefOff(wasm: *Wasm, bw: *std.io.BufferedWriter, data: Mir.NavRefOff, is_wasm32: bool) !void {
956 const comp = wasm.base.comp;930 const comp = wasm.base.comp;
957 const zcu = comp.zcu.?;931 const zcu = comp.zcu.?;
958 const ip = &zcu.intern_pool;932 const ip = &zcu.intern_pool;
...@@ -961,24 +935,22 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff...@@ -961,24 +935,22 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff
961 const nav_ty = ip.getNav(data.nav_index).typeOf(ip);935 const nav_ty = ip.getNav(data.nav_index).typeOf(ip);
962 assert(!ip.isFunctionType(nav_ty));936 assert(!ip.isFunctionType(nav_ty));
963937
964 try code.ensureUnusedCapacity(gpa, 11);
965
966 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;938 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
967 code.appendAssumeCapacity(@intFromEnum(opcode));939 try bw.writeByte(@intFromEnum(opcode));
968 if (is_obj) {940 if (is_obj) {
969 try wasm.out_relocs.append(gpa, .{941 try wasm.out_relocs.append(gpa, .{
970 .offset = @intCast(code.items.len),942 .offset = @intCast(bw.count),
971 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) },943 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) },
972 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,944 .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64,
973 .addend = data.offset,945 .addend = data.offset,
974 });946 });
975 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);947 try bw.splatByteAll(0, if (is_wasm32) 5 else 10);
976 } else {948 } else {
977 const addr = wasm.navAddr(data.nav_index);949 const addr = wasm.navAddr(data.nav_index);
978 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;950 try bw.writeLeb128(@as(i32, @bitCast(@as(u32, @intCast(@as(i64, addr) + data.offset)))));
979 }951 }
980}952}
981953
982fn appendOutputFunctionIndex(code: *std.ArrayListUnmanaged(u8), i: Wasm.OutputFunctionIndex) void {954fn appendOutputFunctionIndex(bw: *std.io.BufferedWriter, i: Wasm.OutputFunctionIndex) anyerror!void {
983 leb.writeUleb128(code.fixedWriter(), @intFromEnum(i)) catch unreachable;955 return bw.writeLeb128(@intFromEnum(i));
984}956}
src/arch/x86_64/CodeGen.zig+198-228
...@@ -524,52 +524,47 @@ pub const MCValue = union(enum) {...@@ -524,52 +524,47 @@ pub const MCValue = union(enum) {
524 };524 };
525 }525 }
526526
527 pub fn format(527 pub fn format(mcv: MCValue, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
528 mcv: MCValue,
529 comptime _: []const u8,
530 _: std.fmt.FormatOptions,
531 writer: anytype,
532 ) @TypeOf(writer).Error!void {
533 switch (mcv) {528 switch (mcv) {
534 .none, .unreach, .dead, .undef => try writer.print("({s})", .{@tagName(mcv)}),529 .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}),
535 .immediate => |pl| try writer.print("0x{x}", .{pl}),530 .immediate => |pl| try bw.print("0x{x}", .{pl}),
536 .memory => |pl| try writer.print("[ds:0x{x}]", .{pl}),531 .memory => |pl| try bw.print("[ds:0x{x}]", .{pl}),
537 inline .eflags, .register => |pl| try writer.print("{s}", .{@tagName(pl)}),532 inline .eflags, .register => |pl| try bw.print("{s}", .{@tagName(pl)}),
538 .register_pair => |pl| try writer.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),533 .register_pair => |pl| try bw.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
539 .register_triple => |pl| try writer.print("{s}:{s}:{s}", .{534 .register_triple => |pl| try bw.print("{s}:{s}:{s}", .{
540 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),535 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
541 }),536 }),
542 .register_quadruple => |pl| try writer.print("{s}:{s}:{s}:{s}", .{537 .register_quadruple => |pl| try bw.print("{s}:{s}:{s}:{s}", .{
543 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),538 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
544 }),539 }),
545 .register_offset => |pl| try writer.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),540 .register_offset => |pl| try bw.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
546 .register_overflow => |pl| try writer.print("{s}:{s}", .{541 .register_overflow => |pl| try bw.print("{s}:{s}", .{
547 @tagName(pl.eflags),542 @tagName(pl.eflags),
548 @tagName(pl.reg),543 @tagName(pl.reg),
549 }),544 }),
550 .register_mask => |pl| try writer.print("mask({s},{}):{c}{s}", .{545 .register_mask => |pl| try bw.print("mask({s},{f}):{c}{s}", .{
551 @tagName(pl.info.kind),546 @tagName(pl.info.kind),
552 pl.info.scalar,547 pl.info.scalar,
553 @as(u8, if (pl.info.inverted) '!' else ' '),548 @as(u8, if (pl.info.inverted) '!' else ' '),
554 @tagName(pl.reg),549 @tagName(pl.reg),
555 }),550 }),
556 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),551 .indirect => |pl| try bw.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
557 .indirect_load_frame => |pl| try writer.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }),552 .indirect_load_frame => |pl| try bw.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }),
558 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),553 .load_frame => |pl| try bw.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
559 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),554 .lea_frame => |pl| try bw.print("{} + 0x{x}", .{ pl.index, pl.off }),
560 .load_nav => |pl| try writer.print("[nav:{d}]", .{@intFromEnum(pl)}),555 .load_nav => |pl| try bw.print("[nav:{d}]", .{@intFromEnum(pl)}),
561 .lea_nav => |pl| try writer.print("nav:{d}", .{@intFromEnum(pl)}),556 .lea_nav => |pl| try bw.print("nav:{d}", .{@intFromEnum(pl)}),
562 .load_uav => |pl| try writer.print("[uav:{d}]", .{@intFromEnum(pl.val)}),557 .load_uav => |pl| try bw.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
563 .lea_uav => |pl| try writer.print("uav:{d}", .{@intFromEnum(pl.val)}),558 .lea_uav => |pl| try bw.print("uav:{d}", .{@intFromEnum(pl.val)}),
564 .load_lazy_sym => |pl| try writer.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),559 .load_lazy_sym => |pl| try bw.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
565 .lea_lazy_sym => |pl| try writer.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),560 .lea_lazy_sym => |pl| try bw.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
566 .load_extern_func => |pl| try writer.print("[extern:{d}]", .{@intFromEnum(pl)}),561 .load_extern_func => |pl| try bw.print("[extern:{d}]", .{@intFromEnum(pl)}),
567 .lea_extern_func => |pl| try writer.print("extern:{d}", .{@intFromEnum(pl)}),562 .lea_extern_func => |pl| try bw.print("extern:{d}", .{@intFromEnum(pl)}),
568 .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{563 .elementwise_args => |pl| try bw.print("elementwise:{d}:[{} + 0x{x}]", .{
569 pl.regs, pl.frame_index, pl.frame_off,564 pl.regs, pl.frame_index, pl.frame_off,
570 }),565 }),
571 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),566 .reserved_frame => |pl| try bw.print("(dead:{})", .{pl}),
572 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),567 .air_ref => |pl| try bw.print("(air:0x{x})", .{@intFromEnum(pl)}),
573 }568 }
574 }569 }
575};570};
...@@ -639,7 +634,7 @@ const InstTracking = struct {...@@ -639,7 +634,7 @@ const InstTracking = struct {
639 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },634 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
640 else => unreachable,635 else => unreachable,
641 }636 }
642 tracking_log.debug("spill {} from {} to {}", .{ inst, self.short, self.long });637 tracking_log.debug("spill {f} from {f} to {f}", .{ inst, self.short, self.long });
643 try cg.genCopy(cg.typeOfIndex(inst), self.long, self.short, .{});638 try cg.genCopy(cg.typeOfIndex(inst), self.long, self.short, .{});
644 for (self.short.getRegs()) |reg| if (reg.isClass(.x87)) try cg.asmRegister(.{ .f_, .free }, reg);639 for (self.short.getRegs()) |reg| if (reg.isClass(.x87)) try cg.asmRegister(.{ .f_, .free }, reg);
645 }640 }
...@@ -672,7 +667,7 @@ const InstTracking = struct {...@@ -672,7 +667,7 @@ const InstTracking = struct {
672 else => {}, // TODO process stack allocation death667 else => {}, // TODO process stack allocation death
673 }668 }
674 self.reuseFrame();669 self.reuseFrame();
675 tracking_log.debug("{} => {} (spilled)", .{ inst, self.* });670 tracking_log.debug("{f} => {f} (spilled)", .{ inst, self.* });
676 }671 }
677672
678 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {673 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
...@@ -749,7 +744,7 @@ const InstTracking = struct {...@@ -749,7 +744,7 @@ const InstTracking = struct {
749 else => target.long,744 else => target.long,
750 } else target.long;745 } else target.long;
751 self.short = target.short;746 self.short = target.short;
752 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });747 tracking_log.debug("{f} => {f} (materialize)", .{ inst, self.* });
753 }748 }
754749
755 fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void {750 fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void {
...@@ -757,7 +752,7 @@ const InstTracking = struct {...@@ -757,7 +752,7 @@ const InstTracking = struct {
757 .dead => |die_generation| if (die_generation >= scope_generation) {752 .dead => |die_generation| if (die_generation >= scope_generation) {
758 self.reuseFrame();753 self.reuseFrame();
759 try function.getValue(self.short, inst);754 try function.getValue(self.short, inst);
760 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });755 tracking_log.debug("{f} => {f} (resurrect)", .{ inst, self.* });
761 },756 },
762 else => {},757 else => {},
763 }758 }
...@@ -768,7 +763,7 @@ const InstTracking = struct {...@@ -768,7 +763,7 @@ const InstTracking = struct {
768 try function.freeValue(self.short, opts);763 try function.freeValue(self.short, opts);
769 if (self.long == .none) self.long = self.short;764 if (self.long == .none) self.long = self.short;
770 self.short = .{ .dead = function.scope_generation };765 self.short = .{ .dead = function.scope_generation };
771 tracking_log.debug("{} => {} (death)", .{ inst, self.* });766 tracking_log.debug("{f} => {f} (death)", .{ inst, self.* });
772 }767 }
773768
774 fn reuse(769 fn reuse(
...@@ -778,13 +773,13 @@ const InstTracking = struct {...@@ -778,13 +773,13 @@ const InstTracking = struct {
778 old_inst: Air.Inst.Index,773 old_inst: Air.Inst.Index,
779 ) void {774 ) void {
780 self.short = .{ .dead = function.scope_generation };775 self.short = .{ .dead = function.scope_generation };
781 tracking_log.debug("{?} => {} (reuse {})", .{ new_inst, self.*, old_inst });776 tracking_log.debug("{?f} => {f} (reuse {f})", .{ new_inst, self.*, old_inst });
782 }777 }
783778
784 fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void {779 fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void {
785 for (self.getRegs()) |reg| {780 for (self.getRegs()) |reg| {
786 if (function.register_manager.isRegFree(reg)) {781 if (function.register_manager.isRegFree(reg)) {
787 tracking_log.debug("{} => {} (live-out)", .{ inst, self.* });782 tracking_log.debug("{f} => {f} (live-out)", .{ inst, self.* });
788 continue;783 continue;
789 }784 }
790785
...@@ -812,18 +807,13 @@ const InstTracking = struct {...@@ -812,18 +807,13 @@ const InstTracking = struct {
812 // Perform side-effects of freeValue manually.807 // Perform side-effects of freeValue manually.
813 function.register_manager.freeReg(reg);808 function.register_manager.freeReg(reg);
814809
815 tracking_log.debug("{} => {} (live-out {})", .{ inst, self.*, tracked_inst });810 tracking_log.debug("{f} => {f} (live-out {f})", .{ inst, self.*, tracked_inst });
816 }811 }
817 }812 }
818813
819 pub fn format(814 pub fn format(tracking: InstTracking, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
820 tracking: InstTracking,815 if (!std.meta.eql(tracking.long, tracking.short)) try bw.print("|{f}| ", .{tracking.long});
821 comptime _: []const u8,816 try bw.print("{f}", .{tracking.short});
822 _: std.fmt.FormatOptions,
823 writer: anytype,
824 ) @TypeOf(writer).Error!void {
825 if (!std.meta.eql(tracking.long, tracking.short)) try writer.print("|{}| ", .{tracking.long});
826 try writer.print("{}", .{tracking.short});
827 }817 }
828};818};
829819
...@@ -939,7 +929,7 @@ pub fn generate(...@@ -939,7 +929,7 @@ pub fn generate(
939 function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), .init(.none));929 function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), .init(.none));
940 }930 }
941931
942 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});932 wip_mir_log.debug("{f}:", .{fmtNav(func.owner_nav, ip)});
943933
944 try function.frame_allocs.resize(gpa, FrameIndex.named_count);934 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
945 function.frame_allocs.set(935 function.frame_allocs.set(
...@@ -1097,13 +1087,8 @@ const FormatNavData = struct {...@@ -1097,13 +1087,8 @@ const FormatNavData = struct {
1097 ip: *const InternPool,1087 ip: *const InternPool,
1098 nav_index: InternPool.Nav.Index,1088 nav_index: InternPool.Nav.Index,
1099};1089};
1100fn formatNav(1090fn formatNav(data: FormatNavData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1101 data: FormatNavData,1091 try bw.print("{f}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1102 comptime _: []const u8,
1103 _: std.fmt.FormatOptions,
1104 writer: anytype,
1105) @TypeOf(writer).Error!void {
1106 try writer.print("{}", .{data.ip.getNav(data.nav_index).fqn.fmt(data.ip)});
1107}1092}
1108fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {1093fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Formatter(formatNav) {
1109 return .{ .data = .{1094 return .{ .data = .{
...@@ -1116,12 +1101,7 @@ const FormatAirData = struct {...@@ -1116,12 +1101,7 @@ const FormatAirData = struct {
1116 self: *CodeGen,1101 self: *CodeGen,
1117 inst: Air.Inst.Index,1102 inst: Air.Inst.Index,
1118};1103};
1119fn formatAir(1104fn formatAir(data: FormatAirData, _: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1120 data: FormatAirData,
1121 comptime _: []const u8,
1122 _: std.fmt.FormatOptions,
1123 writer: anytype,
1124) @TypeOf(writer).Error!void {
1125 data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);1105 data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness);
1126}1106}
1127fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {1107fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) {
...@@ -1132,12 +1112,7 @@ const FormatWipMirData = struct {...@@ -1132,12 +1112,7 @@ const FormatWipMirData = struct {
1132 self: *CodeGen,1112 self: *CodeGen,
1133 inst: Mir.Inst.Index,1113 inst: Mir.Inst.Index,
1134};1114};
1135fn formatWipMir(1115fn formatWipMir(data: FormatWipMirData, bw: *std.io.BufferedWriter, comptime _: []const u8) !void {
1136 data: FormatWipMirData,
1137 comptime _: []const u8,
1138 _: std.fmt.FormatOptions,
1139 writer: anytype,
1140) @TypeOf(writer).Error!void {
1141 var lower: Lower = .{1116 var lower: Lower = .{
1142 .target = data.self.target,1117 .target = data.self.target,
1143 .allocator = data.self.gpa,1118 .allocator = data.self.gpa,
...@@ -1152,11 +1127,11 @@ fn formatWipMir(...@@ -1152,11 +1127,11 @@ fn formatWipMir(
1152 lower.err_msg.?.deinit(data.self.gpa);1127 lower.err_msg.?.deinit(data.self.gpa);
1153 lower.err_msg = null;1128 lower.err_msg = null;
1154 }1129 }
1155 try writer.writeAll(lower.err_msg.?.msg);1130 try bw.writeAll(lower.err_msg.?.msg);
1156 return;1131 return;
1157 },1132 },
1158 error.OutOfMemory, error.InvalidInstruction, error.CannotEncode => |e| {1133 error.OutOfMemory, error.InvalidInstruction, error.CannotEncode => |e| {
1159 try writer.writeAll(switch (e) {1134 try bw.writeAll(switch (e) {
1160 error.OutOfMemory => "Out of memory",1135 error.OutOfMemory => "Out of memory",
1161 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",1136 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
1162 error.CannotEncode => "CodeGen failed to encode the instruction.",1137 error.CannotEncode => "CodeGen failed to encode the instruction.",
...@@ -1165,14 +1140,14 @@ fn formatWipMir(...@@ -1165,14 +1140,14 @@ fn formatWipMir(
1165 },1140 },
1166 else => |e| return e,1141 else => |e| return e,
1167 }).insts) |lowered_inst| {1142 }).insts) |lowered_inst| {
1168 if (!first) try writer.writeAll("\ndebug(wip_mir): ");1143 if (!first) try bw.writeAll("\ndebug(wip_mir): ");
1169 try writer.print(" | {}", .{lowered_inst});1144 try bw.print(" | {f}", .{lowered_inst});
1170 first = false;1145 first = false;
1171 }1146 }
1172 if (first) {1147 if (first) {
1173 const ip = &data.self.pt.zcu.intern_pool;1148 const ip = &data.self.pt.zcu.intern_pool;
1174 const mir_inst = lower.mir.instructions.get(data.inst);1149 const mir_inst = lower.mir.instructions.get(data.inst);
1175 try writer.print(" | .{s}", .{@tagName(mir_inst.ops)});1150 try bw.print(" | .{s}", .{@tagName(mir_inst.ops)});
1176 switch (mir_inst.ops) {1151 switch (mir_inst.ops) {
1177 else => unreachable,1152 else => unreachable,
1178 .pseudo_dbg_prologue_end_none,1153 .pseudo_dbg_prologue_end_none,
...@@ -1184,20 +1159,20 @@ fn formatWipMir(...@@ -1184,20 +1159,20 @@ fn formatWipMir(
1184 .pseudo_dbg_var_none,1159 .pseudo_dbg_var_none,
1185 .pseudo_dead_none,1160 .pseudo_dead_none,
1186 => {},1161 => {},
1187 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(1162 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try bw.print(
1188 " {[line]d}, {[column]d}",1163 " {[line]d}, {[column]d}",
1189 mir_inst.data.line_column,1164 mir_inst.data.line_column,
1190 ),1165 ),
1191 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{1166 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try bw.print(" {f}", .{
1192 ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),1167 ip.getNav(ip.indexToKey(mir_inst.data.ip_index).func.owner_nav).name.fmt(ip),
1193 }),1168 }),
1194 .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try writer.print(" {d}", .{1169 .pseudo_dbg_arg_i_s, .pseudo_dbg_var_i_s => try bw.print(" {d}", .{
1195 @as(i32, @bitCast(mir_inst.data.i.i)),1170 @as(i32, @bitCast(mir_inst.data.i.i)),
1196 }),1171 }),
1197 .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try writer.print(" {d}", .{1172 .pseudo_dbg_arg_i_u, .pseudo_dbg_var_i_u => try bw.print(" {d}", .{
1198 mir_inst.data.i.i,1173 mir_inst.data.i.i,
1199 }),1174 }),
1200 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try writer.print(" {d}", .{1175 .pseudo_dbg_arg_i_64, .pseudo_dbg_var_i_64 => try bw.print(" {d}", .{
1201 mir_inst.data.i64,1176 mir_inst.data.i64,
1202 }),1177 }),
1203 .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {1178 .pseudo_dbg_arg_ro, .pseudo_dbg_var_ro => {
...@@ -1205,22 +1180,22 @@ fn formatWipMir(...@@ -1205,22 +1180,22 @@ fn formatWipMir(
1205 .base = .{ .reg = mir_inst.data.ro.reg },1180 .base = .{ .reg = mir_inst.data.ro.reg },
1206 .disp = mir_inst.data.ro.off,1181 .disp = mir_inst.data.ro.off,
1207 }) };1182 }) };
1208 try writer.print(" {}", .{mem_op.fmt(.m)});1183 try bw.print(" {f}", .{mem_op.fmt(.m)});
1209 },1184 },
1210 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {1185 .pseudo_dbg_arg_fa, .pseudo_dbg_var_fa => {
1211 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{1186 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
1212 .base = .{ .frame = mir_inst.data.fa.index },1187 .base = .{ .frame = mir_inst.data.fa.index },
1213 .disp = mir_inst.data.fa.off,1188 .disp = mir_inst.data.fa.off,
1214 }) };1189 }) };
1215 try writer.print(" {}", .{mem_op.fmt(.m)});1190 try bw.print(" {f}", .{mem_op.fmt(.m)});
1216 },1191 },
1217 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {1192 .pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
1218 const mem_op: encoder.Instruction.Operand = .{1193 const mem_op: encoder.Instruction.Operand = .{
1219 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),1194 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.x.payload).data.decode(),
1220 };1195 };
1221 try writer.print(" {}", .{mem_op.fmt(.m)});1196 try bw.print(" {f}", .{mem_op.fmt(.m)});
1222 },1197 },
1223 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try writer.print(" {}", .{1198 .pseudo_dbg_arg_val, .pseudo_dbg_var_val => try bw.print(" {}", .{
1224 Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),1199 Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),
1225 }),1200 }),
1226 }1201 }
...@@ -1233,14 +1208,9 @@ fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMi...@@ -1233,14 +1208,9 @@ fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMi
1233const FormatTrackingData = struct {1208const FormatTrackingData = struct {
1234 self: *CodeGen,1209 self: *CodeGen,
1235};1210};
1236fn formatTracking(1211fn formatTracking(data: FormatTrackingData, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
1237 data: FormatTrackingData,
1238 comptime _: []const u8,
1239 _: std.fmt.FormatOptions,
1240 writer: anytype,
1241) @TypeOf(writer).Error!void {
1242 var it = data.self.inst_tracking.iterator();1212 var it = data.self.inst_tracking.iterator();
1243 while (it.next()) |entry| try writer.print("\n{} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });1213 while (it.next()) |entry| try bw.print("\n{f} = {f}", .{ entry.key_ptr.*, entry.value_ptr.* });
1244}1214}
1245fn fmtTracking(self: *CodeGen) std.fmt.Formatter(formatTracking) {1215fn fmtTracking(self: *CodeGen) std.fmt.Formatter(formatTracking) {
1246 return .{ .data = .{ .self = self } };1216 return .{ .data = .{ .self = self } };
...@@ -1251,7 +1221,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1251,7 +1221,7 @@ fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1251 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);1221 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
1252 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);1222 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);
1253 self.mir_instructions.appendAssumeCapacity(inst);1223 self.mir_instructions.appendAssumeCapacity(inst);
1254 if (inst.ops != .pseudo_dead_none) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});1224 if (inst.ops != .pseudo_dead_none) wip_mir_log.debug("{f}", .{self.fmtWipMir(result_index)});
1255 return result_index;1225 return result_index;
1256}1226}
12571227
...@@ -2056,7 +2026,7 @@ fn gen(...@@ -2056,7 +2026,7 @@ fn gen(
2056 .{},2026 .{},
2057 );2027 );
2058 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };2028 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
2059 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });2029 tracking_log.debug("spill {f} to {f}", .{ self.ret_mcv.long, frame_index });
2060 },2030 },
2061 else => unreachable,2031 else => unreachable,
2062 }2032 }
...@@ -2334,8 +2304,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2334,8 +2304,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
23342304
2335 for (body) |inst| {2305 for (body) |inst| {
2336 if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;2306 if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue;
2337 wip_mir_log.debug("{}", .{cg.fmtAir(inst)});2307 wip_mir_log.debug("{f}", .{cg.fmtAir(inst)});
2338 verbose_tracking_log.debug("{}", .{cg.fmtTracking()});2308 verbose_tracking_log.debug("{f}", .{cg.fmtTracking()});
23392309
2340 cg.reused_operands = .initEmpty();2310 cg.reused_operands = .initEmpty();
2341 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);2311 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);
...@@ -4339,7 +4309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4339,7 +4309,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4339 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },4309 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
4340 } },4310 } },
4341 } }) catch |err| switch (err) {4311 } }) catch |err| switch (err) {
4342 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{4312 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
4343 @tagName(air_tag),4313 @tagName(air_tag),
4344 cg.typeOf(bin_op.lhs).fmt(pt),4314 cg.typeOf(bin_op.lhs).fmt(pt),
4345 ops[0].tracking(cg),4315 ops[0].tracking(cg),
...@@ -4351,7 +4321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -4351,7 +4321,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4351 else => unreachable,4321 else => unreachable,
4352 .add, .add_optimized => {},4322 .add, .add_optimized => {},
4353 .add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {4323 .add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
4354 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{4324 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
4355 @tagName(air_tag),4325 @tagName(air_tag),
4356 cg.typeOf(bin_op.lhs).fmt(pt),4326 cg.typeOf(bin_op.lhs).fmt(pt),
4357 res[0].tracking(cg),4327 res[0].tracking(cg),
...@@ -14947,7 +14917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -14947,7 +14917,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
14947 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },14917 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
14948 } },14918 } },
14949 } }) catch |err| switch (err) {14919 } }) catch |err| switch (err) {
14950 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{14920 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
14951 @tagName(air_tag),14921 @tagName(air_tag),
14952 cg.typeOf(bin_op.lhs).fmt(pt),14922 cg.typeOf(bin_op.lhs).fmt(pt),
14953 ops[0].tracking(cg),14923 ops[0].tracking(cg),
...@@ -14959,7 +14929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -14959,7 +14929,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
14959 else => unreachable,14929 else => unreachable,
14960 .sub, .sub_optimized => {},14930 .sub, .sub_optimized => {},
14961 .sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {14931 .sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
14962 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{14932 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
14963 @tagName(air_tag),14933 @tagName(air_tag),
14964 cg.typeOf(bin_op.lhs).fmt(pt),14934 cg.typeOf(bin_op.lhs).fmt(pt),
14965 res[0].tracking(cg),14935 res[0].tracking(cg),
...@@ -24587,7 +24557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -24587,7 +24557,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24587 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },24557 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
24588 } },24558 } },
24589 } }) catch |err| switch (err) {24559 } }) catch |err| switch (err) {
24590 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{24560 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
24591 @tagName(air_tag),24561 @tagName(air_tag),
24592 ty.fmt(pt),24562 ty.fmt(pt),
24593 ops[0].tracking(cg),24563 ops[0].tracking(cg),
...@@ -27287,7 +27257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -27287,7 +27257,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27287 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },27257 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
27288 } },27258 } },
27289 } }) catch |err| switch (err) {27259 } }) catch |err| switch (err) {
27290 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{27260 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
27291 @tagName(air_tag),27261 @tagName(air_tag),
27292 ty.fmt(pt),27262 ty.fmt(pt),
27293 ops[0].tracking(cg),27263 ops[0].tracking(cg),
...@@ -27296,7 +27266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -27296,7 +27266,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27296 else => |e| return e,27266 else => |e| return e,
27297 };27267 };
27298 res[0].wrapInt(cg) catch |err| switch (err) {27268 res[0].wrapInt(cg) catch |err| switch (err) {
27299 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{27269 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
27300 @tagName(air_tag),27270 @tagName(air_tag),
27301 cg.typeOf(bin_op.lhs).fmt(pt),27271 cg.typeOf(bin_op.lhs).fmt(pt),
27302 res[0].tracking(cg),27272 res[0].tracking(cg),
...@@ -33606,7 +33576,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -33606,7 +33576,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
33606 assert(air_tag == .div_exact);33576 assert(air_tag == .div_exact);
33607 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;33577 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
33608 }) catch |err| switch (err) {33578 }) catch |err| switch (err) {
33609 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{33579 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
33610 @tagName(air_tag),33580 @tagName(air_tag),
33611 ty.fmt(pt),33581 ty.fmt(pt),
33612 ops[0].tracking(cg),33582 ops[0].tracking(cg),
...@@ -34837,7 +34807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -34837,7 +34807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
34837 } }) else err: {34807 } }) else err: {
34838 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;34808 res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
34839 }) catch |err| switch (err) {34809 }) catch |err| switch (err) {
34840 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{34810 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
34841 @tagName(air_tag),34811 @tagName(air_tag),
34842 ty.fmt(pt),34812 ty.fmt(pt),
34843 ops[0].tracking(cg),34813 ops[0].tracking(cg),
...@@ -36148,7 +36118,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -36148,7 +36118,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
36148 } },36118 } },
36149 } },36119 } },
36150 }) catch |err| switch (err) {36120 }) catch |err| switch (err) {
36151 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{36121 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
36152 @tagName(air_tag),36122 @tagName(air_tag),
36153 cg.typeOf(bin_op.lhs).fmt(pt),36123 cg.typeOf(bin_op.lhs).fmt(pt),
36154 ops[0].tracking(cg),36124 ops[0].tracking(cg),
...@@ -37614,7 +37584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37614,7 +37584,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37614 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },37584 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
37615 } },37585 } },
37616 } })) catch |err| switch (err) {37586 } })) catch |err| switch (err) {
37617 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{37587 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
37618 @tagName(air_tag),37588 @tagName(air_tag),
37619 ty.fmt(pt),37589 ty.fmt(pt),
37620 ops[0].tracking(cg),37590 ops[0].tracking(cg),
...@@ -39248,7 +39218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -39248,7 +39218,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
39248 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },39218 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
39249 } },39219 } },
39250 } }) catch |err| switch (err) {39220 } }) catch |err| switch (err) {
39251 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{39221 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
39252 @tagName(air_tag),39222 @tagName(air_tag),
39253 cg.typeOf(bin_op.lhs).fmt(pt),39223 cg.typeOf(bin_op.lhs).fmt(pt),
39254 ops[0].tracking(cg),39224 ops[0].tracking(cg),
...@@ -42077,7 +42047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42077,7 +42047,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42077 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },42047 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
42078 } },42048 } },
42079 } }) catch |err| switch (err) {42049 } }) catch |err| switch (err) {
42080 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42050 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42081 @tagName(air_tag),42051 @tagName(air_tag),
42082 cg.typeOf(bin_op.lhs).fmt(pt),42052 cg.typeOf(bin_op.lhs).fmt(pt),
42083 ops[0].tracking(cg),42053 ops[0].tracking(cg),
...@@ -42191,7 +42161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42191,7 +42161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42191 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },42161 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
42192 } },42162 } },
42193 } }) catch |err| switch (err) {42163 } }) catch |err| switch (err) {
42194 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42164 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42195 @tagName(air_tag),42165 @tagName(air_tag),
42196 cg.typeOf(bin_op.lhs).fmt(pt),42166 cg.typeOf(bin_op.lhs).fmt(pt),
42197 ops[0].tracking(cg),42167 ops[0].tracking(cg),
...@@ -42320,7 +42290,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -42320,7 +42290,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42320 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },42290 .{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
42321 } },42291 } },
42322 } }) catch |err| switch (err) {42292 } }) catch |err| switch (err) {
42323 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{42293 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
42324 @tagName(air_tag),42294 @tagName(air_tag),
42325 cg.typeOf(bin_op.lhs).fmt(pt),42295 cg.typeOf(bin_op.lhs).fmt(pt),
42326 ops[0].tracking(cg),42296 ops[0].tracking(cg),
...@@ -46485,7 +46455,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -46485,7 +46455,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
46485 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },46455 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
46486 } },46456 } },
46487 } }) catch |err| switch (err) {46457 } }) catch |err| switch (err) {
46488 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{46458 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
46489 @tagName(air_tag),46459 @tagName(air_tag),
46490 cg.typeOf(bin_op.lhs).fmt(pt),46460 cg.typeOf(bin_op.lhs).fmt(pt),
46491 ops[0].tracking(cg),46461 ops[0].tracking(cg),
...@@ -50644,7 +50614,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -50644,7 +50614,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
50644 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },50614 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
50645 } },50615 } },
50646 } }) catch |err| switch (err) {50616 } }) catch |err| switch (err) {
50647 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{50617 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
50648 @tagName(air_tag),50618 @tagName(air_tag),
50649 cg.typeOf(bin_op.lhs).fmt(pt),50619 cg.typeOf(bin_op.lhs).fmt(pt),
50650 ops[0].tracking(cg),50620 ops[0].tracking(cg),
...@@ -51493,7 +51463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -51493,7 +51463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
51493 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },51463 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
51494 } },51464 } },
51495 } }) catch |err| switch (err) {51465 } }) catch |err| switch (err) {
51496 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{51466 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
51497 @tagName(air_tag),51467 @tagName(air_tag),
51498 ty_pl.ty.toType().fmt(pt),51468 ty_pl.ty.toType().fmt(pt),
51499 ops[0].tracking(cg),51469 ops[0].tracking(cg),
...@@ -52398,7 +52368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -52398,7 +52368,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
52398 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },52368 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
52399 } },52369 } },
52400 } }) catch |err| switch (err) {52370 } }) catch |err| switch (err) {
52401 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{52371 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
52402 @tagName(air_tag),52372 @tagName(air_tag),
52403 ty_pl.ty.toType().fmt(pt),52373 ty_pl.ty.toType().fmt(pt),
52404 ops[0].tracking(cg),52374 ops[0].tracking(cg),
...@@ -55995,7 +55965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -55995,7 +55965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
55995 .{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },55965 .{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },
55996 } },55966 } },
55997 } }) catch |err| switch (err) {55967 } }) catch |err| switch (err) {
55998 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{55968 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
55999 @tagName(air_tag),55969 @tagName(air_tag),
56000 ty_pl.ty.toType().fmt(pt),55970 ty_pl.ty.toType().fmt(pt),
56001 ops[0].tracking(cg),55971 ops[0].tracking(cg),
...@@ -59735,7 +59705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -59735,7 +59705,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
59735 } },59705 } },
59736 } },59706 } },
59737 }) catch |err| switch (err) {59707 }) catch |err| switch (err) {
59738 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{59708 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
59739 @tagName(air_tag),59709 @tagName(air_tag),
59740 cg.typeOf(bin_op.lhs).fmt(pt),59710 cg.typeOf(bin_op.lhs).fmt(pt),
59741 ops[0].tracking(cg),59711 ops[0].tracking(cg),
...@@ -60298,7 +60268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60298,7 +60268,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60298 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },60268 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
60299 } },60269 } },
60300 } }) catch |err| switch (err) {60270 } }) catch |err| switch (err) {
60301 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{60271 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
60302 @tagName(air_tag),60272 @tagName(air_tag),
60303 cg.typeOf(bin_op.lhs).fmt(pt),60273 cg.typeOf(bin_op.lhs).fmt(pt),
60304 cg.typeOf(bin_op.rhs).fmt(pt),60274 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -60660,7 +60630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60660,7 +60630,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60660 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },60630 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
60661 } },60631 } },
60662 } }) catch |err| switch (err) {60632 } }) catch |err| switch (err) {
60663 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{60633 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
60664 @tagName(air_tag),60634 @tagName(air_tag),
60665 cg.typeOf(bin_op.lhs).fmt(pt),60635 cg.typeOf(bin_op.lhs).fmt(pt),
60666 cg.typeOf(bin_op.rhs).fmt(pt),60636 cg.typeOf(bin_op.rhs).fmt(pt),
...@@ -60672,7 +60642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -60672,7 +60642,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
60672 switch (air_tag) {60642 switch (air_tag) {
60673 else => unreachable,60643 else => unreachable,
60674 .shl => res[0].wrapInt(cg) catch |err| switch (err) {60644 .shl => res[0].wrapInt(cg) catch |err| switch (err) {
60675 error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{60645 error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
60676 @tagName(air_tag),60646 @tagName(air_tag),
60677 cg.typeOf(bin_op.lhs).fmt(pt),60647 cg.typeOf(bin_op.lhs).fmt(pt),
60678 res[0].tracking(cg),60648 res[0].tracking(cg),
...@@ -65329,7 +65299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -65329,7 +65299,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
65329 .{ ._, ._b, .j, .@"0b", ._, ._, ._ },65299 .{ ._, ._b, .j, .@"0b", ._, ._, ._ },
65330 } },65300 } },
65331 } }) catch |err| switch (err) {65301 } }) catch |err| switch (err) {
65332 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{65302 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
65333 @tagName(air_tag),65303 @tagName(air_tag),
65334 ty_op.ty.toType().fmt(pt),65304 ty_op.ty.toType().fmt(pt),
65335 ops[0].tracking(cg),65305 ops[0].tracking(cg),
...@@ -68483,7 +68453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -68483,7 +68453,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
68483 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },68453 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
68484 } },68454 } },
68485 } }) catch |err| switch (err) {68455 } }) catch |err| switch (err) {
68486 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{68456 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
68487 @tagName(air_tag),68457 @tagName(air_tag),
68488 cg.typeOf(ty_op.operand).fmt(pt),68458 cg.typeOf(ty_op.operand).fmt(pt),
68489 ops[0].tracking(cg),68459 ops[0].tracking(cg),
...@@ -68880,7 +68850,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -68880,7 +68850,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
68880 .{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },68850 .{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },
68881 } },68851 } },
68882 } }) catch |err| switch (err) {68852 } }) catch |err| switch (err) {
68883 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{68853 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
68884 @tagName(air_tag),68854 @tagName(air_tag),
68885 cg.typeOf(ty_op.operand).fmt(pt),68855 cg.typeOf(ty_op.operand).fmt(pt),
68886 ops[0].tracking(cg),68856 ops[0].tracking(cg),
...@@ -69768,7 +69738,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -69768,7 +69738,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
69768 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },69738 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
69769 } },69739 } },
69770 } }) catch |err| switch (err) {69740 } }) catch |err| switch (err) {
69771 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{69741 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
69772 @tagName(air_tag),69742 @tagName(air_tag),
69773 cg.typeOf(ty_op.operand).fmt(pt),69743 cg.typeOf(ty_op.operand).fmt(pt),
69774 ops[0].tracking(cg),69744 ops[0].tracking(cg),
...@@ -70417,7 +70387,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -70417,7 +70387,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
70417 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },70387 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
70418 } },70388 } },
70419 } }) catch |err| switch (err) {70389 } }) catch |err| switch (err) {
70420 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{70390 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
70421 @tagName(air_tag),70391 @tagName(air_tag),
70422 ty_op.ty.toType().fmt(pt),70392 ty_op.ty.toType().fmt(pt),
70423 ops[0].tracking(cg),70393 ops[0].tracking(cg),
...@@ -73519,7 +73489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -73519,7 +73489,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
73519 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },73489 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
73520 } },73490 } },
73521 } }) catch |err| switch (err) {73491 } }) catch |err| switch (err) {
73522 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{73492 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
73523 @tagName(air_tag),73493 @tagName(air_tag),
73524 ty_op.ty.toType().fmt(pt),73494 ty_op.ty.toType().fmt(pt),
73525 ops[0].tracking(cg),73495 ops[0].tracking(cg),
...@@ -74457,7 +74427,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -74457,7 +74427,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
74457 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },74427 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
74458 } },74428 } },
74459 } }) catch |err| switch (err) {74429 } }) catch |err| switch (err) {
74460 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{74430 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
74461 @tagName(air_tag),74431 @tagName(air_tag),
74462 cg.typeOf(un_op).fmt(pt),74432 cg.typeOf(un_op).fmt(pt),
74463 ops[0].tracking(cg),74433 ops[0].tracking(cg),
...@@ -75183,7 +75153,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -75183,7 +75153,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
75183 } },75153 } },
75184 } },75154 } },
75185 }) catch |err| switch (err) {75155 }) catch |err| switch (err) {
75186 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{75156 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
75187 @tagName(air_tag),75157 @tagName(air_tag),
75188 cg.typeOf(un_op).fmt(pt),75158 cg.typeOf(un_op).fmt(pt),
75189 ops[0].tracking(cg),75159 ops[0].tracking(cg),
...@@ -76734,7 +76704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -76734,7 +76704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
76734 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },76704 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
76735 } },76705 } },
76736 } }) catch |err| switch (err) {76706 } }) catch |err| switch (err) {
76737 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{76707 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
76738 @tagName(air_tag),76708 @tagName(air_tag),
76739 cg.typeOf(ty_op.operand).fmt(pt),76709 cg.typeOf(ty_op.operand).fmt(pt),
76740 ops[0].tracking(cg),76710 ops[0].tracking(cg),
...@@ -77926,7 +77896,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -77926,7 +77896,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
77926 } },77896 } },
77927 } },77897 } },
77928 }) catch |err| switch (err) {77898 }) catch |err| switch (err) {
77929 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{77899 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
77930 @tagName(air_tag),77900 @tagName(air_tag),
77931 cg.typeOf(un_op).fmt(pt),77901 cg.typeOf(un_op).fmt(pt),
77932 ops[0].tracking(cg),77902 ops[0].tracking(cg),
...@@ -78466,7 +78436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -78466,7 +78436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
78466 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },78436 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
78467 } },78437 } },
78468 } }) catch |err| switch (err) {78438 } }) catch |err| switch (err) {
78469 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{78439 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
78470 @tagName(air_tag),78440 @tagName(air_tag),
78471 cg.typeOf(un_op).fmt(pt),78441 cg.typeOf(un_op).fmt(pt),
78472 ops[0].tracking(cg),78442 ops[0].tracking(cg),
...@@ -78913,7 +78883,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -78913,7 +78883,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
78913 } else err: {78883 } else err: {
78914 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;78884 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
78915 }) catch |err| switch (err) {78885 }) catch |err| switch (err) {
78916 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{78886 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
78917 @tagName(air_tag),78887 @tagName(air_tag),
78918 cg.typeOf(bin_op.lhs).fmt(pt),78888 cg.typeOf(bin_op.lhs).fmt(pt),
78919 ops[0].tracking(cg),78889 ops[0].tracking(cg),
...@@ -79470,7 +79440,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -79470,7 +79440,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
79470 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;79440 res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
79471 },79441 },
79472 }) catch |err| switch (err) {79442 }) catch |err| switch (err) {
79473 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{79443 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
79474 @tagName(air_tag),79444 @tagName(air_tag),
79475 ty.fmt(pt),79445 ty.fmt(pt),
79476 ops[0].tracking(cg),79446 ops[0].tracking(cg),
...@@ -88546,7 +88516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -88546,7 +88516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
88546 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },88516 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
88547 } },88517 } },
88548 } }) catch |err| switch (err) {88518 } }) catch |err| switch (err) {
88549 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{88519 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
88550 @tagName(air_tag),88520 @tagName(air_tag),
88551 ty_op.ty.toType().fmt(pt),88521 ty_op.ty.toType().fmt(pt),
88552 cg.typeOf(ty_op.operand).fmt(pt),88522 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -90221,7 +90191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -90221,7 +90191,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
90221 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },90191 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
90222 } },90192 } },
90223 } }) catch |err| switch (err) {90193 } }) catch |err| switch (err) {
90224 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{90194 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
90225 @tagName(air_tag),90195 @tagName(air_tag),
90226 ty_op.ty.toType().fmt(pt),90196 ty_op.ty.toType().fmt(pt),
90227 cg.typeOf(ty_op.operand).fmt(pt),90197 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -94899,7 +94869,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -94899,7 +94869,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
94899 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },94869 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
94900 } },94870 } },
94901 } }) catch |err| switch (err) {94871 } }) catch |err| switch (err) {
94902 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{94872 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
94903 @tagName(air_tag),94873 @tagName(air_tag),
94904 dst_ty.fmt(pt),94874 dst_ty.fmt(pt),
94905 src_ty.fmt(pt),94875 src_ty.fmt(pt),
...@@ -100565,7 +100535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -100565,7 +100535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100565 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },100535 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
100566 } },100536 } },
100567 } }) catch |err| switch (err) {100537 } }) catch |err| switch (err) {
100568 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{100538 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
100569 @tagName(air_tag),100539 @tagName(air_tag),
100570 ty_op.ty.toType().fmt(pt),100540 ty_op.ty.toType().fmt(pt),
100571 cg.typeOf(ty_op.operand).fmt(pt),100541 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -111427,7 +111397,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -111427,7 +111397,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
111427 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },111397 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
111428 } },111398 } },
111429 } }) catch |err| switch (err) {111399 } }) catch |err| switch (err) {
111430 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{111400 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
111431 @tagName(air_tag),111401 @tagName(air_tag),
111432 ty_op.ty.toType().fmt(pt),111402 ty_op.ty.toType().fmt(pt),
111433 cg.typeOf(ty_op.operand).fmt(pt),111403 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -123446,7 +123416,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -123446,7 +123416,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
123446 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },123416 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
123447 } },123417 } },
123448 } }) catch |err| switch (err) {123418 } }) catch |err| switch (err) {
123449 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{123419 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
123450 @tagName(air_tag),123420 @tagName(air_tag),
123451 ty_op.ty.toType().fmt(pt),123421 ty_op.ty.toType().fmt(pt),
123452 cg.typeOf(ty_op.operand).fmt(pt),123422 cg.typeOf(ty_op.operand).fmt(pt),
...@@ -166464,7 +166434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166464,7 +166434,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166464 .{ ._, ._, .@"test", .src0p, .src0p, ._, ._ },166434 .{ ._, ._, .@"test", .src0p, .src0p, ._, ._ },
166465 } },166435 } },
166466 } }) catch |err| switch (err) {166436 } }) catch |err| switch (err) {
166467 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166437 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166468 @tagName(air_tag),166438 @tagName(air_tag),
166469 cg.typeOf(un_op).fmt(pt),166439 cg.typeOf(un_op).fmt(pt),
166470 ops[0].tracking(cg),166440 ops[0].tracking(cg),
...@@ -166552,7 +166522,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166552,7 +166522,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166552 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },166522 .{ ._, ._, .call, .tmp0d, ._, ._, ._ },
166553 } },166523 } },
166554 } }) catch |err| switch (err) {166524 } }) catch |err| switch (err) {
166555 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166525 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166556 @tagName(air_tag),166526 @tagName(air_tag),
166557 cg.typeOf(un_op).fmt(pt),166527 cg.typeOf(un_op).fmt(pt),
166558 ops[0].tracking(cg),166528 ops[0].tracking(cg),
...@@ -166654,7 +166624,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166654,7 +166624,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166654 .{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },166624 .{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },
166655 } },166625 } },
166656 } }) catch |err| switch (err) {166626 } }) catch |err| switch (err) {
166657 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166627 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166658 @tagName(air_tag),166628 @tagName(air_tag),
166659 cg.typeOf(un_op).fmt(pt),166629 cg.typeOf(un_op).fmt(pt),
166660 ops[0].tracking(cg),166630 ops[0].tracking(cg),
...@@ -166752,7 +166722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166752,7 +166722,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166752 .{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },166722 .{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },
166753 } },166723 } },
166754 } }) catch |err| switch (err) {166724 } }) catch |err| switch (err) {
166755 error.SelectFailed => return cg.fail("failed to select {s} {} {}", .{166725 error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
166756 @tagName(air_tag),166726 @tagName(air_tag),
166757 ty_op.ty.toType().fmt(pt),166727 ty_op.ty.toType().fmt(pt),
166758 ops[0].tracking(cg),166728 ops[0].tracking(cg),
...@@ -166804,7 +166774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166804,7 +166774,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166804 }166774 }
166805 }166775 }
166806 },166776 },
166807 .@"packed" => return cg.fail("failed to select {s} {}", .{166777 .@"packed" => return cg.fail("failed to select {s} {f}", .{
166808 @tagName(air_tag),166778 @tagName(air_tag),
166809 agg_ty.fmt(pt),166779 agg_ty.fmt(pt),
166810 }),166780 }),
...@@ -166825,7 +166795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -166825,7 +166795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
166825 elem_disp += @intCast(field_type.abiSize(zcu));166795 elem_disp += @intCast(field_type.abiSize(zcu));
166826 }166796 }
166827 },166797 },
166828 else => return cg.fail("failed to select {s} {}", .{166798 else => return cg.fail("failed to select {s} {f}", .{
166829 @tagName(air_tag),166799 @tagName(air_tag),
166830 agg_ty.fmt(pt),166800 agg_ty.fmt(pt),
166831 }),166801 }),
...@@ -168123,7 +168093,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168123,7 +168093,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168123 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },168093 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
168124 } },168094 } },
168125 } }) catch |err| switch (err) {168095 } }) catch |err| switch (err) {
168126 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{168096 error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
168127 @tagName(air_tag),168097 @tagName(air_tag),
168128 cg.typeOf(bin_op.lhs).fmt(pt),168098 cg.typeOf(bin_op.lhs).fmt(pt),
168129 ops[0].tracking(cg),168099 ops[0].tracking(cg),
...@@ -168223,7 +168193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168223,7 +168193,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168223 .{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },168193 .{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },
168224 } },168194 } },
168225 } }) catch |err| switch (err) {168195 } }) catch |err| switch (err) {
168226 error.SelectFailed => return cg.fail("failed to select {s} {}", .{168196 error.SelectFailed => return cg.fail("failed to select {s} {f}", .{
168227 @tagName(air_tag),168197 @tagName(air_tag),
168228 ops[0].tracking(cg),168198 ops[0].tracking(cg),
168229 }),168199 }),
...@@ -168242,12 +168212,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168242,12 +168212,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168242 .ref => {168212 .ref => {
168243 const result = try cg.allocRegOrMem(err_ret_trace_index, true);168213 const result = try cg.allocRegOrMem(err_ret_trace_index, true);
168244 try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});168214 try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});
168245 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, result });168215 tracking_log.debug("{f} => {f} (birth)", .{ err_ret_trace_index, result });
168246 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result));168216 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result));
168247 },168217 },
168248 .temp => |temp_index| {168218 .temp => |temp_index| {
168249 const temp_tracking = temp_index.tracking(cg);168219 const temp_tracking = temp_index.tracking(cg);
168250 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, temp_tracking.short });168220 tracking_log.debug("{f} => {f} (birth)", .{ err_ret_trace_index, temp_tracking.short });
168251 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*);168221 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*);
168252 assert(cg.reuseTemp(err_ret_trace_index, temp_index.toIndex(), temp_tracking));168222 assert(cg.reuseTemp(err_ret_trace_index, temp_index.toIndex(), temp_tracking));
168253 },168223 },
...@@ -168917,7 +168887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168917,7 +168887,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168917 try cg.resetTemps(@enumFromInt(0));168887 try cg.resetTemps(@enumFromInt(0));
168918 cg.checkInvariantsAfterAirInst();168888 cg.checkInvariantsAfterAirInst();
168919 }168889 }
168920 verbose_tracking_log.debug("{}", .{cg.fmtTracking()});168890 verbose_tracking_log.debug("{f}", .{cg.fmtTracking()});
168921}168891}
168922168892
168923fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {168893fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
...@@ -168927,7 +168897,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -168927,7 +168897,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
168927 switch (ip.indexToKey(lazy_sym.ty)) {168897 switch (ip.indexToKey(lazy_sym.ty)) {
168928 .enum_type => {168898 .enum_type => {
168929 const enum_ty: Type = .fromInterned(lazy_sym.ty);168899 const enum_ty: Type = .fromInterned(lazy_sym.ty);
168930 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});168900 wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
168931168901
168932 const param_regs = abi.getCAbiIntParamRegs(.auto);168902 const param_regs = abi.getCAbiIntParamRegs(.auto);
168933 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);168903 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
...@@ -168976,7 +168946,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -168976,7 +168946,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
168976 },168946 },
168977 .error_set_type => |error_set_type| {168947 .error_set_type => |error_set_type| {
168978 const err_ty: Type = .fromInterned(lazy_sym.ty);168948 const err_ty: Type = .fromInterned(lazy_sym.ty);
168979 wip_mir_log.debug("{}.@errorCast:", .{err_ty.fmt(pt)});168949 wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(pt)});
168980168950
168981 const param_regs = abi.getCAbiIntParamRegs(.auto);168951 const param_regs = abi.getCAbiIntParamRegs(.auto);
168982 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);168952 const param_locks = cg.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
...@@ -169016,7 +168986,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -169016,7 +168986,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
169016 try cg.asmOpOnly(.{ ._, .ret });168986 try cg.asmOpOnly(.{ ._, .ret });
169017 },168987 },
169018 else => return cg.fail(168988 else => return cg.fail(
169019 "TODO implement {s} for {}",168989 "TODO implement {s} for {f}",
169020 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },168990 .{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
169021 ),168991 ),
169022 }168992 }
...@@ -169076,7 +169046,7 @@ fn finishAirResult(self: *CodeGen, inst: Air.Inst.Index, result: MCValue) void {...@@ -169076,7 +169046,7 @@ fn finishAirResult(self: *CodeGen, inst: Air.Inst.Index, result: MCValue) void {
169076 .none, .dead, .unreach => {},169046 .none, .dead, .unreach => {},
169077 else => unreachable, // Why didn't the result die?169047 else => unreachable, // Why didn't the result die?
169078 } else {169048 } else {
169079 tracking_log.debug("{} => {} (birth)", .{ inst, result });169049 tracking_log.debug("{f} => {f} (birth)", .{ inst, result });
169080 self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));169050 self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
169081 // In some cases, an operand may be reused as the result.169051 // In some cases, an operand may be reused as the result.
169082 // If that operand died and was a register, it was freed by169052 // If that operand died and was a register, it was freed by
...@@ -169226,7 +169196,7 @@ fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex {...@@ -169226,7 +169196,7 @@ fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex {
169226 const val_ty = ptr_ty.childType(zcu);169196 const val_ty = ptr_ty.childType(zcu);
169227 return self.allocFrameIndex(.init(.{169197 return self.allocFrameIndex(.init(.{
169228 .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {169198 .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {
169229 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});169199 return self.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
169230 },169200 },
169231 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),169201 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
169232 }));169202 }));
...@@ -169244,7 +169214,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok...@@ -169244,7 +169214,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok
169244 const pt = self.pt;169214 const pt = self.pt;
169245 const zcu = pt.zcu;169215 const zcu = pt.zcu;
169246 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {169216 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
169247 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});169217 return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
169248 };169218 };
169249169219
169250 if (reg_ok) need_mem: {169220 if (reg_ok) need_mem: {
...@@ -169749,7 +169719,7 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -169749,7 +169719,7 @@ fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void {
169749 );169719 );
169750 }169720 }
169751 break :result dst_mcv;169721 break :result dst_mcv;
169752 } orelse return self.fail("TODO implement airFpext from {} to {}", .{169722 } orelse return self.fail("TODO implement airFpext from {f} to {f}", .{
169753 src_ty.fmt(pt), dst_ty.fmt(pt),169723 src_ty.fmt(pt), dst_ty.fmt(pt),
169754 });169724 });
169755 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });169725 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -170004,7 +169974,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170004,7 +169974,7 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
170004 );169974 );
170005169975
170006 break :result dst_mcv;169976 break :result dst_mcv;
170007 }) orelse return self.fail("TODO implement airIntCast from {} to {}", .{169977 }) orelse return self.fail("TODO implement airIntCast from {f} to {f}", .{
170008 src_ty.fmt(pt), dst_ty.fmt(pt),169978 src_ty.fmt(pt), dst_ty.fmt(pt),
170009 });169979 });
170010 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });169980 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -170076,7 +170046,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170076,7 +170046,7 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
170076 else => null,170046 else => null,
170077 },170047 },
170078 else => null,170048 else => null,
170079 }) orelse return self.fail("TODO implement airTrunc for {}", .{dst_ty.fmt(pt)});170049 }) orelse return self.fail("TODO implement airTrunc for {f}", .{dst_ty.fmt(pt)});
170080170050
170081 const dst_info = dst_elem_ty.intInfo(zcu);170051 const dst_info = dst_elem_ty.intInfo(zcu);
170082 const src_info = src_elem_ty.intInfo(zcu);170052 const src_info = src_elem_ty.intInfo(zcu);
...@@ -170497,7 +170467,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170497,7 +170467,7 @@ fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170497 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;170467 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
170498 const ty = self.typeOf(bin_op.lhs);170468 const ty = self.typeOf(bin_op.lhs);
170499 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170469 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170500 "TODO implement airAddSat for {}",170470 "TODO implement airAddSat for {f}",
170501 .{ty.fmt(pt)},170471 .{ty.fmt(pt)},
170502 );170472 );
170503170473
...@@ -170575,7 +170545,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170575,7 +170545,7 @@ fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170575 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;170545 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
170576 const ty = self.typeOf(bin_op.lhs);170546 const ty = self.typeOf(bin_op.lhs);
170577 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170547 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170578 "TODO implement airSubSat for {}",170548 "TODO implement airSubSat for {f}",
170579 .{ty.fmt(pt)},170549 .{ty.fmt(pt)},
170580 );170550 );
170581170551
...@@ -170726,7 +170696,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -170726,7 +170696,7 @@ fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void {
170726 }170696 }
170727170697
170728 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(170698 if (ty.zigTypeTag(zcu) == .vector or ty.abiSize(zcu) > 8) return self.fail(
170729 "TODO implement airMulSat for {}",170699 "TODO implement airMulSat for {f}",
170730 .{ty.fmt(pt)},170700 .{ty.fmt(pt)},
170731 );170701 );
170732170702
...@@ -171020,7 +170990,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171020,7 +170990,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
171020 const tuple_ty = self.typeOfIndex(inst);170990 const tuple_ty = self.typeOfIndex(inst);
171021 const dst_ty = self.typeOf(bin_op.lhs);170991 const dst_ty = self.typeOf(bin_op.lhs);
171022 const result: MCValue = switch (dst_ty.zigTypeTag(zcu)) {170992 const result: MCValue = switch (dst_ty.zigTypeTag(zcu)) {
171023 .vector => return self.fail("TODO implement airMulWithOverflow for {}", .{dst_ty.fmt(pt)}),170993 .vector => return self.fail("TODO implement airMulWithOverflow for {f}", .{dst_ty.fmt(pt)}),
171024 .int => result: {170994 .int => result: {
171025 const dst_info = dst_ty.intInfo(zcu);170995 const dst_info = dst_ty.intInfo(zcu);
171026 if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {170996 if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {
...@@ -171373,7 +171343,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171373,7 +171343,7 @@ fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
171373 else => {171343 else => {
171374 // For now, this is the only supported multiply that doesn't fit in a register.171344 // For now, this is the only supported multiply that doesn't fit in a register.
171375 if (dst_info.bits > 128 or src_bits != 64)171345 if (dst_info.bits > 128 or src_bits != 64)
171376 return self.fail("TODO implement airWithOverflow from {} to {}", .{171346 return self.fail("TODO implement airWithOverflow from {f} to {f}", .{
171377 src_ty.fmt(pt), dst_ty.fmt(pt),171347 src_ty.fmt(pt), dst_ty.fmt(pt),
171378 });171348 });
171379171349
...@@ -171774,7 +171744,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -171774,7 +171744,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void {
171774 },171744 },
171775 else => {},171745 else => {},
171776 }171746 }
171777 return self.fail("TODO implement airShlShrBinOp for {}", .{lhs_ty.fmt(pt)});171747 return self.fail("TODO implement airShlShrBinOp for {f}", .{lhs_ty.fmt(pt)});
171778 };171748 };
171779 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });171749 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
171780}171750}
...@@ -172034,7 +172004,7 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172034,7 +172004,7 @@ fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void {
172034 .index = frame_addr.index,172004 .index = frame_addr.index,
172035 .off = frame_addr.off + @as(i32, @intCast(err_off)),172005 .off = frame_addr.off + @as(i32, @intCast(err_off)),
172036 } },172006 } },
172037 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),172007 else => return self.fail("TODO implement unwrap_err_err for {f}", .{operand}),
172038 }172008 }
172039 };172009 };
172040 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });172010 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -172196,7 +172166,7 @@ fn genUnwrapErrUnionPayloadMir(...@@ -172196,7 +172166,7 @@ fn genUnwrapErrUnionPayloadMir(
172196 else172166 else
172197 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };172167 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };
172198 },172168 },
172199 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),172169 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {f}", .{err_union}),
172200 }172170 }
172201 };172171 };
172202172172
...@@ -172362,7 +172332,7 @@ fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172362,7 +172332,7 @@ fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void {
172362 .index = frame_addr.index,172332 .index = frame_addr.index,
172363 .off = frame_addr.off + 8,172333 .off = frame_addr.off + 8,
172364 } },172334 } },
172365 else => return self.fail("TODO implement slice_len for {}", .{src_mcv}),172335 else => return self.fail("TODO implement slice_len for {f}", .{src_mcv}),
172366 };172336 };
172367 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {172337 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
172368 switch (src_mcv) {172338 switch (src_mcv) {
...@@ -172645,7 +172615,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172645,7 +172615,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
172645 }.to64(),172615 }.to64(),
172646 ),172616 ),
172647 },172617 },
172648 else => return self.fail("TODO airArrayElemVal for {s} of {}", .{172618 else => return self.fail("TODO airArrayElemVal for {s} of {f}", .{
172649 @tagName(array_mat_mcv), array_ty.fmt(pt),172619 @tagName(array_mat_mcv), array_ty.fmt(pt),
172650 }),172620 }),
172651 }172621 }
...@@ -172688,7 +172658,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172688,7 +172658,7 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
172688 .load_extern_func,172658 .load_extern_func,
172689 .lea_extern_func,172659 .lea_extern_func,
172690 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),172660 => try self.genSetReg(addr_reg, .usize, array_mcv.address(), .{}),
172691 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{172661 else => return self.fail("TODO airArrayElemVal_val for {s} of {f}", .{
172692 @tagName(array_mcv), array_ty.fmt(pt),172662 @tagName(array_mcv), array_ty.fmt(pt),
172693 }),172663 }),
172694 }172664 }
...@@ -172881,7 +172851,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172881,7 +172851,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {
172881 }172851 }
172882172852
172883 return self.fail(172853 return self.fail(
172884 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {}",172854 "TODO implement get_union_tag for ABI larger than 8 bytes and operand {f}",
172885 .{operand},172855 .{operand},
172886 );172856 );
172887 },172857 },
...@@ -172893,7 +172863,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172893,7 +172863,7 @@ fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void {
172893 .register = registerAlias(result.register, @intCast(layout.tag_size)),172863 .register = registerAlias(result.register, @intCast(layout.tag_size)),
172894 };172864 };
172895 },172865 },
172896 else => return self.fail("TODO implement get_union_tag for {}", .{operand}),172866 else => return self.fail("TODO implement get_union_tag for {f}", .{operand}),
172897 }172867 }
172898 };172868 };
172899172869
...@@ -172909,7 +172879,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -172909,7 +172879,7 @@ fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void {
172909172879
172910 const dst_ty = self.typeOfIndex(inst);172880 const dst_ty = self.typeOfIndex(inst);
172911 const src_ty = self.typeOf(ty_op.operand);172881 const src_ty = self.typeOf(ty_op.operand);
172912 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airClz for {}", .{172882 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airClz for {f}", .{
172913 src_ty.fmt(pt),172883 src_ty.fmt(pt),
172914 });172884 });
172915172885
...@@ -173105,7 +173075,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -173105,7 +173075,7 @@ fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void {
173105173075
173106 const dst_ty = self.typeOfIndex(inst);173076 const dst_ty = self.typeOfIndex(inst);
173107 const src_ty = self.typeOf(ty_op.operand);173077 const src_ty = self.typeOf(ty_op.operand);
173108 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airCtz for {}", .{173078 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail("TODO implement airCtz for {f}", .{
173109 src_ty.fmt(pt),173079 src_ty.fmt(pt),
173110 });173080 });
173111173081
...@@ -173277,7 +173247,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -173277,7 +173247,7 @@ fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void {
173277 const src_ty = self.typeOf(ty_op.operand);173247 const src_ty = self.typeOf(ty_op.operand);
173278 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));173248 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));
173279 if (src_ty.zigTypeTag(zcu) == .vector or src_abi_size > 16)173249 if (src_ty.zigTypeTag(zcu) == .vector or src_abi_size > 16)
173280 return self.fail("TODO implement airPopCount for {}", .{src_ty.fmt(pt)});173250 return self.fail("TODO implement airPopCount for {f}", .{src_ty.fmt(pt)});
173281 const src_mcv = try self.resolveInst(ty_op.operand);173251 const src_mcv = try self.resolveInst(ty_op.operand);
173282173252
173283 const mat_src_mcv = switch (src_mcv) {173253 const mat_src_mcv = switch (src_mcv) {
...@@ -173430,7 +173400,7 @@ fn genByteSwap(...@@ -173430,7 +173400,7 @@ fn genByteSwap(
173430 const has_movbe = self.hasFeature(.movbe);173400 const has_movbe = self.hasFeature(.movbe);
173431173401
173432 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail(173402 if (src_ty.zigTypeTag(zcu) == .vector) return self.fail(
173433 "TODO implement genByteSwap for {}",173403 "TODO implement genByteSwap for {f}",
173434 .{src_ty.fmt(pt)},173404 .{src_ty.fmt(pt)},
173435 );173405 );
173436173406
...@@ -173739,7 +173709,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173739,7 +173709,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173739 const result = result: {173709 const result = result: {
173740 const scalar_bits = ty.scalarType(zcu).floatBits(self.target);173710 const scalar_bits = ty.scalarType(zcu).floatBits(self.target);
173741 if (scalar_bits == 80) {173711 if (scalar_bits == 80) {
173742 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement floatSign for {}", .{173712 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement floatSign for {f}", .{
173743 ty.fmt(pt),173713 ty.fmt(pt),
173744 });173714 });
173745173715
...@@ -173763,7 +173733,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173763,7 +173733,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173763 const abi_size: u32 = switch (ty.abiSize(zcu)) {173733 const abi_size: u32 = switch (ty.abiSize(zcu)) {
173764 1...16 => 16,173734 1...16 => 16,
173765 17...32 => 32,173735 17...32 => 32,
173766 else => return self.fail("TODO implement floatSign for {}", .{173736 else => return self.fail("TODO implement floatSign for {f}", .{
173767 ty.fmt(pt),173737 ty.fmt(pt),
173768 }),173738 }),
173769 };173739 };
...@@ -173822,7 +173792,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173822,7 +173792,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173822 .abs => .{ .v_pd, .@"and" },173792 .abs => .{ .v_pd, .@"and" },
173823 else => unreachable,173793 else => unreachable,
173824 },173794 },
173825 80 => return self.fail("TODO implement floatSign for {}", .{ty.fmt(pt)}),173795 80 => return self.fail("TODO implement floatSign for {f}", .{ty.fmt(pt)}),
173826 else => unreachable,173796 else => unreachable,
173827 },173797 },
173828 registerAlias(dst_reg, abi_size),173798 registerAlias(dst_reg, abi_size),
...@@ -173848,7 +173818,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A...@@ -173848,7 +173818,7 @@ fn floatSign(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag, operand: A
173848 .abs => .{ ._pd, .@"and" },173818 .abs => .{ ._pd, .@"and" },
173849 else => unreachable,173819 else => unreachable,
173850 },173820 },
173851 80 => return self.fail("TODO implement floatSign for {}", .{ty.fmt(pt)}),173821 80 => return self.fail("TODO implement floatSign for {f}", .{ty.fmt(pt)}),
173852 else => unreachable,173822 else => unreachable,
173853 },173823 },
173854 registerAlias(dst_reg, abi_size),173824 registerAlias(dst_reg, abi_size),
...@@ -173928,7 +173898,7 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM...@@ -173928,7 +173898,7 @@ fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: bits.RoundM
173928 if (self.getRoundTag(ty)) |_| return .none;173898 if (self.getRoundTag(ty)) |_| return .none;
173929173899
173930 if (ty.zigTypeTag(zcu) != .float)173900 if (ty.zigTypeTag(zcu) != .float)
173931 return self.fail("TODO implement genRound for {}", .{ty.fmt(pt)});173901 return self.fail("TODO implement genRound for {f}", .{ty.fmt(pt)});
173932173902
173933 var sym_buf: ["__trunc?".len]u8 = undefined;173903 var sym_buf: ["__trunc?".len]u8 = undefined;
173934 return try self.genCall(.{ .extern_func = .{173904 return try self.genCall(.{ .extern_func = .{
...@@ -174164,7 +174134,7 @@ fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -174164,7 +174134,7 @@ fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void {
174164 },174134 },
174165 .float => return self.floatSign(inst, .abs, ty_op.operand, ty),174135 .float => return self.floatSign(inst, .abs, ty_op.operand, ty),
174166 },174136 },
174167 }) orelse return self.fail("TODO implement airAbs for {}", .{ty.fmt(pt)});174137 }) orelse return self.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
174168174138
174169 const abi_size: u32 = @intCast(ty.abiSize(zcu));174139 const abi_size: u32 = @intCast(ty.abiSize(zcu));
174170 const src_mcv = try self.resolveInst(ty_op.operand);174140 const src_mcv = try self.resolveInst(ty_op.operand);
...@@ -174323,7 +174293,7 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -174323,7 +174293,7 @@ fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void {
174323 else => unreachable,174293 else => unreachable,
174324 },174294 },
174325 else => unreachable,174295 else => unreachable,
174326 }) orelse return self.fail("TODO implement airSqrt for {}", .{ty.fmt(pt)});174296 }) orelse return self.fail("TODO implement airSqrt for {f}", .{ty.fmt(pt)});
174327 switch (mir_tag[0]) {174297 switch (mir_tag[0]) {
174328 .v_ss, .v_sd => if (src_mcv.isBase()) try self.asmRegisterRegisterMemory(174298 .v_ss, .v_sd => if (src_mcv.isBase()) try self.asmRegisterRegisterMemory(
174329 mir_tag,174299 mir_tag,
...@@ -174481,7 +174451,7 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)...@@ -174481,7 +174451,7 @@ fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue)
174481 return;174451 return;
174482 }174452 }
174483174453
174484 if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(pt)});174454 if (val_abi_size > 8) return self.fail("TODO implement packed load of {f}", .{val_ty.fmt(pt)});
174485174455
174486 const limb_abi_size: u31 = @min(val_abi_size, 8);174456 const limb_abi_size: u31 = @min(val_abi_size, 8);
174487 const limb_abi_bits = limb_abi_size * 8;174457 const limb_abi_bits = limb_abi_size * 8;
...@@ -174753,7 +174723,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)...@@ -174753,7 +174723,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
174753 limb_mem,174723 limb_mem,
174754 registerAlias(tmp_reg, limb_abi_size),174724 registerAlias(tmp_reg, limb_abi_size),
174755 );174725 );
174756 } else return self.fail("TODO: implement packed store of {}", .{src_ty.fmt(pt)});174726 } else return self.fail("TODO: implement packed store of {f}", .{src_ty.fmt(pt)});
174757 }174727 }
174758}174728}
174759174729
...@@ -174856,7 +174826,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -174856,7 +174826,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
174856 const zcu = pt.zcu;174826 const zcu = pt.zcu;
174857 const src_ty = self.typeOf(src_air);174827 const src_ty = self.typeOf(src_air);
174858 if (src_ty.zigTypeTag(zcu) == .vector)174828 if (src_ty.zigTypeTag(zcu) == .vector)
174859 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(pt)});174829 return self.fail("TODO implement genUnOp for {f}", .{src_ty.fmt(pt)});
174860174830
174861 var src_mcv = try self.resolveInst(src_air);174831 var src_mcv = try self.resolveInst(src_air);
174862 switch (src_mcv) {174832 switch (src_mcv) {
...@@ -174943,7 +174913,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a...@@ -174943,7 +174913,7 @@ fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_a
174943fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {174913fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {
174944 const pt = self.pt;174914 const pt = self.pt;
174945 const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu));174915 const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu));
174946 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ mir_tag, dst_ty.fmt(pt) });174916 if (abi_size > 8) return self.fail("TODO implement {} for {f}", .{ mir_tag, dst_ty.fmt(pt) });
174947 switch (dst_mcv) {174917 switch (dst_mcv) {
174948 .none,174918 .none,
174949 .unreach,174919 .unreach,
...@@ -175672,7 +175642,7 @@ fn genBinOp(...@@ -175672,7 +175642,7 @@ fn genBinOp(
175672 },175642 },
175673 floatLibcAbiSuffix(lhs_ty),175643 floatLibcAbiSuffix(lhs_ty),
175674 }),175644 }),
175675 else => return self.fail("TODO implement genBinOp for {s} {}", .{175645 else => return self.fail("TODO implement genBinOp for {s} {f}", .{
175676 @tagName(air_tag), lhs_ty.fmt(pt),175646 @tagName(air_tag), lhs_ty.fmt(pt),
175677 }),175647 }),
175678 } catch unreachable;175648 } catch unreachable;
...@@ -175785,7 +175755,7 @@ fn genBinOp(...@@ -175785,7 +175755,7 @@ fn genBinOp(
175785 );175755 );
175786 break :adjusted .{ .register = dst_reg };175756 break :adjusted .{ .register = dst_reg };
175787 },175757 },
175788 80, 128 => return self.fail("TODO implement genBinOp for {s} of {}", .{175758 80, 128 => return self.fail("TODO implement genBinOp for {s} of {f}", .{
175789 @tagName(air_tag), lhs_ty.fmt(pt),175759 @tagName(air_tag), lhs_ty.fmt(pt),
175790 }),175760 }),
175791 else => unreachable,175761 else => unreachable,
...@@ -175819,7 +175789,7 @@ fn genBinOp(...@@ -175819,7 +175789,7 @@ fn genBinOp(
175819 if (sse_op and ((lhs_ty.scalarType(zcu).isRuntimeFloat() and175789 if (sse_op and ((lhs_ty.scalarType(zcu).isRuntimeFloat() and
175820 lhs_ty.scalarType(zcu).floatBits(self.target) == 80) or175790 lhs_ty.scalarType(zcu).floatBits(self.target) == 80) or
175821 lhs_ty.abiSize(zcu) > self.vectorSize(.float)))175791 lhs_ty.abiSize(zcu) > self.vectorSize(.float)))
175822 return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(air_tag), lhs_ty.fmt(pt) });175792 return self.fail("TODO implement genBinOp for {s} {f}", .{ @tagName(air_tag), lhs_ty.fmt(pt) });
175823175793
175824 const maybe_mask_reg = switch (air_tag) {175794 const maybe_mask_reg = switch (air_tag) {
175825 else => null,175795 else => null,
...@@ -176199,7 +176169,7 @@ fn genBinOp(...@@ -176199,7 +176169,7 @@ fn genBinOp(
176199 }176169 }
176200 },176170 },
176201176171
176202 else => return self.fail("TODO implement genBinOp for {s} {}", .{176172 else => return self.fail("TODO implement genBinOp for {s} {f}", .{
176203 @tagName(air_tag), lhs_ty.fmt(pt),176173 @tagName(air_tag), lhs_ty.fmt(pt),
176204 }),176174 }),
176205 }176175 }
...@@ -176953,7 +176923,7 @@ fn genBinOp(...@@ -176953,7 +176923,7 @@ fn genBinOp(
176953 else => unreachable,176923 else => unreachable,
176954 },176924 },
176955 },176925 },
176956 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{176926 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
176957 @tagName(air_tag), lhs_ty.fmt(pt),176927 @tagName(air_tag), lhs_ty.fmt(pt),
176958 });176928 });
176959176929
...@@ -177086,7 +177056,7 @@ fn genBinOp(...@@ -177086,7 +177056,7 @@ fn genBinOp(
177086 else => unreachable,177056 else => unreachable,
177087 },177057 },
177088 else => unreachable,177058 else => unreachable,
177089 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177059 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177090 @tagName(air_tag), lhs_ty.fmt(pt),177060 @tagName(air_tag), lhs_ty.fmt(pt),
177091 }),177061 }),
177092 mask_reg,177062 mask_reg,
...@@ -177118,7 +177088,7 @@ fn genBinOp(...@@ -177118,7 +177088,7 @@ fn genBinOp(
177118 else => unreachable,177088 else => unreachable,
177119 },177089 },
177120 else => unreachable,177090 else => unreachable,
177121 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177091 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177122 @tagName(air_tag), lhs_ty.fmt(pt),177092 @tagName(air_tag), lhs_ty.fmt(pt),
177123 }),177093 }),
177124 dst_reg,177094 dst_reg,
...@@ -177154,7 +177124,7 @@ fn genBinOp(...@@ -177154,7 +177124,7 @@ fn genBinOp(
177154 else => unreachable,177124 else => unreachable,
177155 },177125 },
177156 else => unreachable,177126 else => unreachable,
177157 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177127 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177158 @tagName(air_tag), lhs_ty.fmt(pt),177128 @tagName(air_tag), lhs_ty.fmt(pt),
177159 }),177129 }),
177160 mask_reg,177130 mask_reg,
...@@ -177185,7 +177155,7 @@ fn genBinOp(...@@ -177185,7 +177155,7 @@ fn genBinOp(
177185 else => unreachable,177155 else => unreachable,
177186 },177156 },
177187 else => unreachable,177157 else => unreachable,
177188 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177158 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177189 @tagName(air_tag), lhs_ty.fmt(pt),177159 @tagName(air_tag), lhs_ty.fmt(pt),
177190 }),177160 }),
177191 dst_reg,177161 dst_reg,
...@@ -177215,7 +177185,7 @@ fn genBinOp(...@@ -177215,7 +177185,7 @@ fn genBinOp(
177215 else => unreachable,177185 else => unreachable,
177216 },177186 },
177217 else => unreachable,177187 else => unreachable,
177218 }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{177188 }) orelse return self.fail("TODO implement genBinOp for {s} {f}", .{
177219 @tagName(air_tag), lhs_ty.fmt(pt),177189 @tagName(air_tag), lhs_ty.fmt(pt),
177220 });177190 });
177221 try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_reg, mask_reg);177191 try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_reg, mask_reg);
...@@ -178022,7 +177992,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -178022,7 +177992,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void {
178022177992
178023 break :result dst_mcv;177993 break :result dst_mcv;
178024 },177994 },
178025 else => return self.fail("TODO implement arg for {}", .{src_mcv}),177995 else => return self.fail("TODO implement arg for {f}", .{src_mcv}),
178026 }177996 }
178027 };177997 };
178028 return self.finishAir(inst, result, .{ .none, .none, .none });177998 return self.finishAir(inst, result, .{ .none, .none, .none });
...@@ -179079,7 +179049,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {...@@ -179079,7 +179049,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {
179079 const reg = try self.copyToTmpRegister(ty, mcv);179049 const reg = try self.copyToTmpRegister(ty, mcv);
179080 return self.genCondBrMir(ty, .{ .register = reg });179050 return self.genCondBrMir(ty, .{ .register = reg });
179081 }179051 }
179082 return self.fail("TODO implement condbr when condition is {} with abi larger than 8 bytes", .{mcv});179052 return self.fail("TODO implement condbr when condition is {f} with abi larger than 8 bytes", .{mcv});
179083 },179053 },
179084 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),179054 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
179085 }179055 }
...@@ -179166,7 +179136,7 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal...@@ -179166,7 +179136,7 @@ fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCVal
179166 } },179136 } },
179167 .{ .immediate = 0 },179137 .{ .immediate = 0 },
179168 ),179138 ),
179169 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),179139 else => return self.fail("TODO implement isErr for {f}", .{eu_mcv}),
179170 }179140 }
179171179141
179172 if (maybe_inst) |inst| self.eflags_inst = inst;179142 if (maybe_inst) |inst| self.eflags_inst = inst;
...@@ -180916,7 +180886,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M...@@ -180916,7 +180886,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
180916 },180886 },
180917 .ip, .cr, .dr => {},180887 .ip, .cr, .dr => {},
180918 }180888 }
180919 return cg.fail("TODO moveStrategy for {}", .{ty.fmt(pt)});180889 return cg.fail("TODO moveStrategy for {f}", .{ty.fmt(pt)});
180920}180890}
180921180891
180922const CopyOptions = struct {180892const CopyOptions = struct {
...@@ -181048,7 +181018,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C...@@ -181048,7 +181018,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
181048 break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };181018 break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
181049 },181019 },
181050 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),181020 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),
181051 else => return self.fail("TODO implement genCopy for {s} of {}", .{181021 else => return self.fail("TODO implement genCopy for {s} of {f}", .{
181052 @tagName(src_mcv), ty.fmt(pt),181022 @tagName(src_mcv), ty.fmt(pt),
181053 }),181023 }),
181054 };181024 };
...@@ -181424,7 +181394,7 @@ fn genSetReg(...@@ -181424,7 +181394,7 @@ fn genSetReg(
181424 80 => null,181394 80 => null,
181425 else => unreachable,181395 else => unreachable,
181426 },181396 },
181427 }) orelse return self.fail("TODO implement genSetReg for {}", .{ty.fmt(pt)}),181397 }) orelse return self.fail("TODO implement genSetReg for {f}", .{ty.fmt(pt)}),
181428 dst_alias,181398 dst_alias,
181429 registerAlias(src_reg, abi_size),181399 registerAlias(src_reg, abi_size),
181430 ),181400 ),
...@@ -181854,7 +181824,7 @@ fn genSetMem(...@@ -181854,7 +181824,7 @@ fn genSetMem(
181854 opts,181824 opts,
181855 );181825 );
181856 },181826 },
181857 else => return self.fail("TODO implement genSetMem for {s} of {}", .{181827 else => return self.fail("TODO implement genSetMem for {s} of {f}", .{
181858 @tagName(src_mcv), ty.fmt(pt),181828 @tagName(src_mcv), ty.fmt(pt),
181859 }),181829 }),
181860 },181830 },
...@@ -182167,7 +182137,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182167,7 +182137,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
182167 32, 64 => src_size > 8,182137 32, 64 => src_size > 8,
182168 else => unreachable,182138 else => unreachable,
182169 }) {182139 }) {
182170 if (src_bits > 128) return self.fail("TODO implement airFloatFromInt from {} to {}", .{182140 if (src_bits > 128) return self.fail("TODO implement airFloatFromInt from {f} to {f}", .{
182171 src_ty.fmt(pt), dst_ty.fmt(pt),182141 src_ty.fmt(pt), dst_ty.fmt(pt),
182172 });182142 });
182173182143
...@@ -182209,7 +182179,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182209,7 +182179,7 @@ fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void {
182209 else => unreachable,182179 else => unreachable,
182210 },182180 },
182211 else => null,182181 else => null,
182212 }) orelse return self.fail("TODO implement airFloatFromInt from {} to {}", .{182182 }) orelse return self.fail("TODO implement airFloatFromInt from {f} to {f}", .{
182213 src_ty.fmt(pt), dst_ty.fmt(pt),182183 src_ty.fmt(pt), dst_ty.fmt(pt),
182214 });182184 });
182215 const dst_alias = dst_reg.to128();182185 const dst_alias = dst_reg.to128();
...@@ -182247,7 +182217,7 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -182247,7 +182217,7 @@ fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void {
182247 32, 64 => dst_size > 8,182217 32, 64 => dst_size > 8,
182248 else => unreachable,182218 else => unreachable,
182249 }) {182219 }) {
182250 if (dst_bits > 128) return self.fail("TODO implement airIntFromFloat from {} to {}", .{182220 if (dst_bits > 128) return self.fail("TODO implement airIntFromFloat from {f} to {f}", .{
182251 src_ty.fmt(pt), dst_ty.fmt(pt),182221 src_ty.fmt(pt), dst_ty.fmt(pt),
182252 });182222 });
182253182223
...@@ -182531,7 +182501,7 @@ fn atomicOp(...@@ -182531,7 +182501,7 @@ fn atomicOp(
182531 else => null,182501 else => null,
182532 },182502 },
182533 else => unreachable,182503 else => unreachable,
182534 }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{182504 }) orelse return self.fail("TODO implement atomicOp of {s} for {f}", .{
182535 @tagName(op), val_ty.fmt(pt),182505 @tagName(op), val_ty.fmt(pt),
182536 });182506 });
182537 try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});182507 try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});
...@@ -183286,7 +183256,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183286,7 +183256,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {
183286 else => unreachable,183256 else => unreachable,
183287 },183257 },
183288 }183258 }
183289 return self.fail("TODO implement airSplat for {}", .{vector_ty.fmt(pt)});183259 return self.fail("TODO implement airSplat for {f}", .{vector_ty.fmt(pt)});
183290 };183260 };
183291 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });183261 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
183292}183262}
...@@ -183322,12 +183292,12 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183322,12 +183292,12 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183322 else183292 else
183323 try self.copyToTmpRegister(pred_ty, pred_mcv)183293 try self.copyToTmpRegister(pred_ty, pred_mcv)
183324 else183294 else
183325 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),183295 return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)}),
183326 else => unreachable,183296 else => unreachable,
183327 },183297 },
183328 .register_mask => |pred_reg_mask| {183298 .register_mask => |pred_reg_mask| {
183329 if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)183299 if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
183330 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183300 return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183331183301
183332 const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {183302 const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
183333 try self.register_manager.getKnownReg(.xmm0, null);183303 try self.register_manager.getKnownReg(.xmm0, null);
...@@ -183401,7 +183371,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183401,7 +183371,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183401 else183371 else
183402 null183372 null
183403 else183373 else
183404 null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183374 null) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183405 if (has_avx) {183375 if (has_avx) {
183406 const rhs_alias = if (reuse_mcv.isRegister())183376 const rhs_alias = if (reuse_mcv.isRegister())
183407 registerAlias(reuse_mcv.getReg().?, abi_size)183377 registerAlias(reuse_mcv.getReg().?, abi_size)
...@@ -183554,7 +183524,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183554,7 +183524,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183554 else => unreachable,183524 else => unreachable,
183555 }),183525 }),
183556 );183526 );
183557 } else return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183527 } else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183558 const elem_bits: u16 = @intCast(elem_abi_size * 8);183528 const elem_bits: u16 = @intCast(elem_abi_size * 8);
183559 if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) {183529 if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) {
183560 const mask_len = elem_abi_size * vec_len;183530 const mask_len = elem_abi_size * vec_len;
...@@ -183583,7 +183553,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183583,7 +183553,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183583 mask_alias,183553 mask_alias,
183584 mask_mem,183554 mask_mem,
183585 );183555 );
183586 } else return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183556 } else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183587 {183557 {
183588 const mask_elem_ty = try pt.intType(.unsigned, elem_bits);183558 const mask_elem_ty = try pt.intType(.unsigned, elem_bits);
183589 const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() });183559 const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() });
...@@ -183706,7 +183676,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -183706,7 +183676,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
183706 else => null,183676 else => null,
183707 },183677 },
183708 },183678 },
183709 }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});183679 }) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
183710 if (has_avx) {183680 if (has_avx) {
183711 const rhs_alias = if (rhs_mcv.isRegister())183681 const rhs_alias = if (rhs_mcv.isRegister())
183712 registerAlias(rhs_mcv.getReg().?, abi_size)183682 registerAlias(rhs_mcv.getReg().?, abi_size)
...@@ -184551,7 +184521,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184551,7 +184521,7 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void {
184551 }184521 }
184552184522
184553 break :result null;184523 break :result null;
184554 }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{184524 }) orelse return self.fail("TODO implement airShuffle from {f} and {f} to {f} with {f}", .{
184555 lhs_ty.fmt(pt),184525 lhs_ty.fmt(pt),
184556 rhs_ty.fmt(pt),184526 rhs_ty.fmt(pt),
184557 dst_ty.fmt(pt),184527 dst_ty.fmt(pt),
...@@ -184800,7 +184770,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184800,7 +184770,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
184800 32, 64 => !self.hasFeature(.fma),184770 32, 64 => !self.hasFeature(.fma),
184801 else => unreachable,184771 else => unreachable,
184802 }) {184772 }) {
184803 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement airMulAdd for {}", .{184773 if (ty.zigTypeTag(zcu) != .float) return self.fail("TODO implement airMulAdd for {f}", .{
184804 ty.fmt(pt),184774 ty.fmt(pt),
184805 });184775 });
184806184776
...@@ -184930,7 +184900,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184930,7 +184900,7 @@ fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void {
184930 else => unreachable,184900 else => unreachable,
184931 }184901 }
184932 else184902 else
184933 unreachable) orelse return self.fail("TODO implement airMulAdd for {}", .{ty.fmt(pt)});184903 unreachable) orelse return self.fail("TODO implement airMulAdd for {f}", .{ty.fmt(pt)});
184934184904
184935 var mops: [3]MCValue = undefined;184905 var mops: [3]MCValue = undefined;
184936 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;184906 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;
...@@ -185130,7 +185100,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -185130,7 +185100,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
185130 assert(classes.len == 1);185100 assert(classes.len == 1);
185131 unreachable;185101 unreachable;
185132 },185102 },
185133 else => return self.fail("TODO implement c_va_arg for {} on SysV", .{promote_ty.fmt(pt)}),185103 else => return self.fail("TODO implement c_va_arg for {f} on SysV", .{promote_ty.fmt(pt)}),
185134 }185104 }
185135185105
185136 if (unused) break :result .unreach;185106 if (unused) break :result .unreach;
...@@ -185779,7 +185749,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty...@@ -185779,7 +185749,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
185779 for (parts) |part| part_sizes += part.abiSize(zcu);185749 for (parts) |part| part_sizes += part.abiSize(zcu);
185780 if (part_sizes == ty.abiSize(zcu)) return parts;185750 if (part_sizes == ty.abiSize(zcu)) return parts;
185781 };185751 };
185782 return self.fail("TODO implement splitType({d}, {})", .{ parts_len, ty.fmt(pt) });185752 return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) });
185783}185753}
185784185754
185785/// Truncates the value in the register in place.185755/// Truncates the value in the register in place.
...@@ -186153,7 +186123,7 @@ const Temp = struct {...@@ -186153,7 +186123,7 @@ const Temp = struct {
186153 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);186123 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
186154 const mcv = temp.tracking(cg).short;186124 const mcv = temp.tracking(cg).short;
186155 switch (mcv) {186125 switch (mcv) {
186156 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186126 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186157 .register => |reg| {186127 .register => |reg| {
186158 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);186128 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
186159 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });186129 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
...@@ -186227,7 +186197,7 @@ const Temp = struct {...@@ -186227,7 +186197,7 @@ const Temp = struct {
186227 const new_temp_index = cg.next_temp_index;186197 const new_temp_index = cg.next_temp_index;
186228 cg.temp_type[@intFromEnum(new_temp_index)] = limb_ty;186198 cg.temp_type[@intFromEnum(new_temp_index)] = limb_ty;
186229 switch (temp.tracking(cg).short) {186199 switch (temp.tracking(cg).short) {
186230 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186200 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186231 .immediate => |imm| {186201 .immediate => |imm| {
186232 assert(limb_index == 0);186202 assert(limb_index == 0);
186233 new_temp_index.tracking(cg).* = .init(.{ .immediate = imm });186203 new_temp_index.tracking(cg).* = .init(.{ .immediate = imm });
...@@ -186568,7 +186538,7 @@ const Temp = struct {...@@ -186568,7 +186538,7 @@ const Temp = struct {
186568 },186538 },
186569 else => {},186539 else => {},
186570 }186540 }
186571 std.debug.panic("{s}: {} {}\n", .{ @src().fn_name, temp_tracking, overflow_temp_tracking });186541 std.debug.panic("{s}: {f} {f}\n", .{ @src().fn_name, temp_tracking, overflow_temp_tracking });
186572 }186542 }
186573186543
186574 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {186544 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {
...@@ -186658,7 +186628,7 @@ const Temp = struct {...@@ -186658,7 +186628,7 @@ const Temp = struct {
186658 while (try ptr.toLea(cg)) {}186628 while (try ptr.toLea(cg)) {}
186659 const val_mcv = val.tracking(cg).short;186629 const val_mcv = val.tracking(cg).short;
186660 switch (val_mcv) {186630 switch (val_mcv) {
186661 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186631 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186662 .register => |val_reg| try ptr.loadReg(val_ty, registerAlias(186632 .register => |val_reg| try ptr.loadReg(val_ty, registerAlias(
186663 val_reg,186633 val_reg,
186664 @intCast(val_ty.abiSize(cg.pt.zcu)),186634 @intCast(val_ty.abiSize(cg.pt.zcu)),
...@@ -186698,7 +186668,7 @@ const Temp = struct {...@@ -186698,7 +186668,7 @@ const Temp = struct {
186698 {}) {186668 {}) {
186699 const val_mcv = val.tracking(cg).short;186669 const val_mcv = val.tracking(cg).short;
186700 switch (val_mcv) {186670 switch (val_mcv) {
186701 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186671 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186702 .undef => if (opts.safe) {186672 .undef => if (opts.safe) {
186703 var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });186673 var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });
186704 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });186674 var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
...@@ -186772,7 +186742,7 @@ const Temp = struct {...@@ -186772,7 +186742,7 @@ const Temp = struct {
186772 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));186742 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
186773 break :first_ty opt_child;186743 break :first_ty opt_child;
186774 },186744 },
186775 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),186745 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
186776 });186746 });
186777 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));186747 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
186778 try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);186748 try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);
...@@ -186804,7 +186774,7 @@ const Temp = struct {...@@ -186804,7 +186774,7 @@ const Temp = struct {
186804186774
186805 fn readTo(src: *Temp, val_ty: Type, val_mcv: MCValue, opts: AccessOptions, cg: *CodeGen) InnerError!void {186775 fn readTo(src: *Temp, val_ty: Type, val_mcv: MCValue, opts: AccessOptions, cg: *CodeGen) InnerError!void {
186806 switch (val_mcv) {186776 switch (val_mcv) {
186807 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186777 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186808 .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias(186778 .register => |val_reg| try src.readReg(opts.disp, val_ty, registerAlias(
186809 val_reg,186779 val_reg,
186810 @intCast(cg.unalignedSize(val_ty)),186780 @intCast(cg.unalignedSize(val_ty)),
...@@ -186844,7 +186814,7 @@ const Temp = struct {...@@ -186844,7 +186814,7 @@ const Temp = struct {
186844 {}) {186814 {}) {
186845 const val_mcv = val.tracking(cg).short;186815 const val_mcv = val.tracking(cg).short;
186846 switch (val_mcv) {186816 switch (val_mcv) {
186847 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),186817 else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
186848 .none => {},186818 .none => {},
186849 .undef => if (opts.safe) {186819 .undef => if (opts.safe) {
186850 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));186820 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
...@@ -186905,7 +186875,7 @@ const Temp = struct {...@@ -186905,7 +186875,7 @@ const Temp = struct {
186905 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));186875 assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
186906 break :first_ty opt_child;186876 break :first_ty opt_child;
186907 },186877 },
186908 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),186878 else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
186909 });186879 });
186910 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));186880 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
186911 try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);186881 try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);
...@@ -191677,12 +191647,12 @@ const Temp = struct {...@@ -191677,12 +191647,12 @@ const Temp = struct {
191677 break :result result;191647 break :result result;
191678 },191648 },
191679 };191649 };
191680 tracking_log.debug("{} => {} (birth)", .{ inst, result });191650 tracking_log.debug("{f} => {f} (birth)", .{ inst, result });
191681 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));191651 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result));
191682 },191652 },
191683 .temp => |temp_index| {191653 .temp => |temp_index| {
191684 const temp_tracking = temp_index.tracking(cg);191654 const temp_tracking = temp_index.tracking(cg);
191685 tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });191655 tracking_log.debug("{f} => {f} (birth)", .{ inst, temp_tracking.short });
191686 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));191656 cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short));
191687 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));191657 assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
191688 },191658 },
...@@ -191757,7 +191727,7 @@ fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {...@@ -191757,7 +191727,7 @@ fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {
191757 const temp: Temp.Index = @enumFromInt(temp_index);191727 const temp: Temp.Index = @enumFromInt(temp_index);
191758 if (temp.isValid(cg)) {191728 if (temp.isValid(cg)) {
191759 any_valid = true;191729 any_valid = true;
191760 tracking_log.err("failed to kill {}: {}", .{191730 tracking_log.err("failed to kill {f}: {f}", .{
191761 temp.toIndex(),191731 temp.toIndex(),
191762 cg.temp_type[temp_index].fmt(cg.pt),191732 cg.temp_type[temp_index].fmt(cg.pt),
191763 });191733 });
src/arch/x86_64/Disassembler.zig+73-92
...@@ -31,10 +31,11 @@ pub fn init(code: []const u8) Disassembler {...@@ -31,10 +31,11 @@ pub fn init(code: []const u8) Disassembler {
31}31}
3232
33pub fn next(dis: *Disassembler) Error!?Instruction {33pub fn next(dis: *Disassembler) Error!?Instruction {
34 const prefixes = dis.parsePrefixes() catch |err| switch (err) {34 return @errorCast(dis.nextInner());
35 error.EndOfStream => return null,35}
36 else => |e| return e,36
37 };37fn nextInner(dis: *Disassembler) anyerror!?Instruction {
38 const prefixes = try dis.parsePrefixes();
3839
39 const enc = try dis.parseEncoding(prefixes) orelse return error.UnknownOpcode;40 const enc = try dis.parseEncoding(prefixes) orelse return error.UnknownOpcode;
40 switch (enc.data.op_en) {41 switch (enc.data.op_en) {
...@@ -283,66 +284,53 @@ const Prefixes = struct {...@@ -283,66 +284,53 @@ const Prefixes = struct {
283284
284fn parsePrefixes(dis: *Disassembler) !Prefixes {285fn parsePrefixes(dis: *Disassembler) !Prefixes {
285 const rex_prefix_mask: u4 = 0b0100;286 const rex_prefix_mask: u4 = 0b0100;
286 var stream = std.io.fixedBufferStream(dis.code[dis.pos..]);
287 const reader = stream.reader();
288
289 var res: Prefixes = .{};287 var res: Prefixes = .{};
288 for (dis.code[dis.pos..], dis.pos..) |byte, pos| switch (byte) {
289 0xf0, 0xf2, 0xf3, 0x2e, 0x36, 0x26, 0x64, 0x65, 0x3e, 0x66, 0x67 => {
290 // Legacy prefix
291 if (res.rex.present) return error.LegacyPrefixAfterRex;
292 switch (byte) {
293 0xf0 => res.legacy.prefix_f0 = true,
294 0xf2 => res.legacy.prefix_f2 = true,
295 0xf3 => res.legacy.prefix_f3 = true,
296 0x2e => res.legacy.prefix_2e = true,
297 0x36 => res.legacy.prefix_36 = true,
298 0x26 => res.legacy.prefix_26 = true,
299 0x64 => res.legacy.prefix_64 = true,
300 0x65 => res.legacy.prefix_65 = true,
301 0x3e => res.legacy.prefix_3e = true,
302 0x66 => res.legacy.prefix_66 = true,
303 0x67 => res.legacy.prefix_67 = true,
304 else => unreachable,
305 }
306 },
307 else => {
308 if (rex_prefix_mask == @as(u4, @truncate(byte >> 4))) {
309 // REX prefix
310 res.rex.w = byte & 0b1000 != 0;
311 res.rex.r = byte & 0b100 != 0;
312 res.rex.x = byte & 0b10 != 0;
313 res.rex.b = byte & 0b1 != 0;
314 res.rex.present = true;
315 continue;
316 }
290317
291 while (true) {318 // TODO VEX prefix
292 const next_byte = try reader.readByte();
293 dis.pos += 1;
294
295 switch (next_byte) {
296 0xf0, 0xf2, 0xf3, 0x2e, 0x36, 0x26, 0x64, 0x65, 0x3e, 0x66, 0x67 => {
297 // Legacy prefix
298 if (res.rex.present) return error.LegacyPrefixAfterRex;
299 switch (next_byte) {
300 0xf0 => res.legacy.prefix_f0 = true,
301 0xf2 => res.legacy.prefix_f2 = true,
302 0xf3 => res.legacy.prefix_f3 = true,
303 0x2e => res.legacy.prefix_2e = true,
304 0x36 => res.legacy.prefix_36 = true,
305 0x26 => res.legacy.prefix_26 = true,
306 0x64 => res.legacy.prefix_64 = true,
307 0x65 => res.legacy.prefix_65 = true,
308 0x3e => res.legacy.prefix_3e = true,
309 0x66 => res.legacy.prefix_66 = true,
310 0x67 => res.legacy.prefix_67 = true,
311 else => unreachable,
312 }
313 },
314 else => {
315 if (rex_prefix_mask == @as(u4, @truncate(next_byte >> 4))) {
316 // REX prefix
317 res.rex.w = next_byte & 0b1000 != 0;
318 res.rex.r = next_byte & 0b100 != 0;
319 res.rex.x = next_byte & 0b10 != 0;
320 res.rex.b = next_byte & 0b1 != 0;
321 res.rex.present = true;
322 continue;
323 }
324
325 // TODO VEX prefix
326
327 dis.pos -= 1;
328 break;
329 },
330 }
331 }
332319
320 dis.pos = pos;
321 break;
322 },
323 };
333 return res;324 return res;
334}325}
335326
336fn parseEncoding(dis: *Disassembler, prefixes: Prefixes) !?Encoding {327fn parseEncoding(dis: *Disassembler, prefixes: Prefixes) !?Encoding {
337 const o_mask: u8 = 0b1111_1000;328 const o_mask: u8 = 0b1111_1000;
338
339 var opcode: [3]u8 = .{ 0, 0, 0 };329 var opcode: [3]u8 = .{ 0, 0, 0 };
340 var stream = std.io.fixedBufferStream(dis.code[dis.pos..]);
341 const reader = stream.reader();
342330
343 comptime var opc_count = 0;331 comptime var opc_count = 0;
344 inline while (opc_count < 3) : (opc_count += 1) {332 inline while (opc_count < 3) : (opc_count += 1) {
345 const byte = try reader.readByte();333 const byte = dis.code[dis.pos];
346 opcode[opc_count] = byte;334 opcode[opc_count] = byte;
347 dis.pos += 1;335 dis.pos += 1;
348336
...@@ -387,30 +375,27 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi...@@ -387,30 +375,27 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi
387 };375 };
388}376}
389377
390fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate {378fn parseImm(dis: *Disassembler, kind: Encoding.Op) anyerror!Immediate {
391 var stream = std.io.fixedBufferStream(dis.code[dis.pos..]);379 var br: std.io.BufferedReader = undefined;
392 var creader = std.io.countingReader(stream.reader());380 br.initFixed(dis.code[dis.pos..]);
393 const reader = creader.reader();381 defer dis.pos += br.seek;
394 const imm = switch (kind) {382 return switch (kind) {
395 .imm8s, .rel8 => Immediate.s(try reader.readInt(i8, .little)),383 .imm8s, .rel8 => .s(try br.takeInt(i8, .little)),
396 .imm16s, .rel16 => Immediate.s(try reader.readInt(i16, .little)),384 .imm16s, .rel16 => .s(try br.takeInt(i16, .little)),
397 .imm32s, .rel32 => Immediate.s(try reader.readInt(i32, .little)),385 .imm32s, .rel32 => .s(try br.takeInt(i32, .little)),
398 .imm8 => Immediate.u(try reader.readInt(u8, .little)),386 .imm8 => .u(try br.takeInt(u8, .little)),
399 .imm16 => Immediate.u(try reader.readInt(u16, .little)),387 .imm16 => .u(try br.takeInt(u16, .little)),
400 .imm32 => Immediate.u(try reader.readInt(u32, .little)),388 .imm32 => .u(try br.takeInt(u32, .little)),
401 .imm64 => Immediate.u(try reader.readInt(u64, .little)),389 .imm64 => .u(try br.takeInt(u64, .little)),
402 else => unreachable,390 else => unreachable,
403 };391 };
404 dis.pos += std.math.cast(usize, creader.bytes_read) orelse return error.Overflow;
405 return imm;
406}392}
407393
408fn parseOffset(dis: *Disassembler) !u64 {394fn parseOffset(dis: *Disassembler) anyerror!u64 {
409 var stream = std.io.fixedBufferStream(dis.code[dis.pos..]);395 var br: std.io.BufferedReader = undefined;
410 const reader = stream.reader();396 br.initFixed(dis.code[dis.pos..]);
411 const offset = try reader.readInt(u64, .little);397 defer dis.pos += br.seek;
412 dis.pos += 8;398 return br.takeInt(u64, .little);
413 return offset;
414}399}
415400
416const ModRm = packed struct {401const ModRm = packed struct {
...@@ -482,26 +467,22 @@ fn parseSibByte(dis: *Disassembler) !Sib {...@@ -482,26 +467,22 @@ fn parseSibByte(dis: *Disassembler) !Sib {
482 return Sib{ .scale = scale, .index = index, .base = base };467 return Sib{ .scale = scale, .index = index, .base = base };
483}468}
484469
485fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 {470fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) anyerror!i32 {
486 var stream = std.io.fixedBufferStream(dis.code[dis.pos..]);471 var br: std.io.BufferedReader = undefined;
487 var creader = std.io.countingReader(stream.reader());472 br.initFixed(dis.code[dis.pos..]);
488 const reader = creader.reader();473 defer dis.pos += br.seek;
489 const disp = disp: {474 if (sib) |info| {
490 if (sib) |info| {475 if (info.base == 0b101 and modrm.mod == 0) {
491 if (info.base == 0b101 and modrm.mod == 0) {476 return br.takeInt(i32, .little);
492 break :disp try reader.readInt(i32, .little);
493 }
494 }
495 if (modrm.rip()) {
496 break :disp try reader.readInt(i32, .little);
497 }477 }
498 break :disp switch (modrm.mod) {478 }
499 0b00 => 0,479 if (modrm.rip()) {
500 0b01 => try reader.readInt(i8, .little),480 return br.takeInt(i32, .little);
501 0b10 => try reader.readInt(i32, .little),481 }
502 0b11 => unreachable,482 return switch (modrm.mod) {
503 };483 0b00 => 0,
484 0b01 => try br.takeInt(i8, .little),
485 0b10 => try br.takeInt(i32, .little),
486 0b11 => unreachable,
504 };487 };
505 dis.pos += std.math.cast(usize, creader.bytes_read) orelse return error.Overflow;
506 return disp;
507}488}
src/arch/x86_64/Emit.zig+16-21
...@@ -424,19 +424,19 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -424,19 +424,19 @@ pub fn emitMir(emit: *Emit) Error!void {
424 .line = mir_inst.data.line_column.line,424 .line = mir_inst.data.line_column.line,
425 .column = mir_inst.data.line_column.column,425 .column = mir_inst.data.line_column.column,
426 .is_stmt = true,426 .is_stmt = true,
427 }),427 }, emit.code.items.len),
428 .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{428 .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{
429 .line = mir_inst.data.line_column.line,429 .line = mir_inst.data.line_column.line,
430 .column = mir_inst.data.line_column.column,430 .column = mir_inst.data.line_column.column,
431 .is_stmt = false,431 .is_stmt = false,
432 }),432 }, emit.code.items.len),
433 .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {433 .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {
434 .dwarf => |dwarf| {434 .dwarf => |dwarf| {
435 try dwarf.setEpilogueBegin();435 try dwarf.setEpilogueBegin();
436 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{436 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
437 emit.prev_di_loc.line, emit.prev_di_loc.column,437 emit.prev_di_loc.line, emit.prev_di_loc.column,
438 });438 });
439 try emit.dbgAdvancePCAndLine(emit.prev_di_loc);439 try emit.dbgAdvancePCAndLine(emit.prev_di_loc, emit.code.items.len);
440 },440 },
441 .plan9 => {},441 .plan9 => {},
442 .none => {},442 .none => {},
...@@ -909,9 +909,9 @@ const Loc = struct {...@@ -909,9 +909,9 @@ const Loc = struct {
909 is_stmt: bool,909 is_stmt: bool,
910};910};
911911
912fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {912fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc, pc: usize) anyerror!void {
913 const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);913 const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);
914 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;914 const delta_pc = pc - emit.prev_di_pc;
915 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });915 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
916 switch (emit.debug_output) {916 switch (emit.debug_output) {
917 .dwarf => |dwarf| {917 .dwarf => |dwarf| {
...@@ -919,30 +919,25 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {...@@ -919,30 +919,25 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
919 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);919 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);
920 try dwarf.advancePCAndLine(delta_line, delta_pc);920 try dwarf.advancePCAndLine(delta_line, delta_pc);
921 emit.prev_di_loc = loc;921 emit.prev_di_loc = loc;
922 emit.prev_di_pc = emit.code.items.len;922 emit.prev_di_pc = pc;
923 },923 },
924 .plan9 => |dbg_out| {924 .plan9 => |dbg_out| {
925 if (delta_pc <= 0) return; // only do this when the pc changes925 if (delta_pc <= 0) return; // only do this when the pc changes
926926
927 var aw: std.io.AllocatingWriter = undefined;
928 const bw = aw.fromArrayList(emit.lower.bin_file.comp.gpa, &dbg_out.dbg_line);
929 defer dbg_out.dbg_line = aw.toArrayList();
930
927 // increasing the line number931 // increasing the line number
928 try link.File.Plan9.changeLine(&dbg_out.dbg_line, @intCast(delta_line));932 try link.File.Plan9.changeLine(bw, @intCast(delta_line));
929 // increasing the pc933 // increasing the pc
930 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;934 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
931 if (d_pc_p9 > 0) {935 if (d_pc_p9 > 0) {
932 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta936 // minus one because if its the last one, we want to leave space to change the line which is one pc quanta
933 var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;937 try bw.writeByte(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
934 while (diff > 0) {938 const dbg_line = aw.getWritten();
935 if (diff < 64) {939 if (dbg_out.pcop_change_index) |pci| dbg_line[pci] += 1;
936 try dbg_out.dbg_line.append(@intCast(diff + 128));940 dbg_out.pcop_change_index = @intCast(dbg_line.len - 1);
937 diff = 0;
938 } else {
939 try dbg_out.dbg_line.append(@intCast(64 + 128));
940 diff -= 64;
941 }
942 }
943 if (dbg_out.pcop_change_index) |pci|
944 dbg_out.dbg_line.items[pci] += 1;
945 dbg_out.pcop_change_index = @intCast(dbg_out.dbg_line.items.len - 1);
946 } else if (d_pc_p9 == 0) {941 } else if (d_pc_p9 == 0) {
947 // we don't need to do anything, because adding the pc quanta does it for us942 // we don't need to do anything, because adding the pc quanta does it for us
948 } else unreachable;943 } else unreachable;
...@@ -951,7 +946,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {...@@ -951,7 +946,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
951 dbg_out.end_line = loc.line;946 dbg_out.end_line = loc.line;
952 // only do this if the pc changed947 // only do this if the pc changed
953 emit.prev_di_loc = loc;948 emit.prev_di_loc = loc;
954 emit.prev_di_pc = emit.code.items.len;949 emit.prev_di_pc = pc;
955 },950 },
956 .none => {},951 .none => {},
957 }952 }
src/arch/x86_64/Encoding.zig+25-29
...@@ -158,20 +158,14 @@ pub fn modRmExt(encoding: Encoding) u3 {...@@ -158,20 +158,14 @@ pub fn modRmExt(encoding: Encoding) u3 {
158 };158 };
159}159}
160160
161pub fn format(161pub fn format(encoding: Encoding, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
162 encoding: Encoding,
163 comptime fmt: []const u8,
164 options: std.fmt.FormatOptions,
165 writer: anytype,
166) !void {
167 _ = options;
168 _ = fmt;162 _ = fmt;
169163
170 var opc = encoding.opcode();164 var opc = encoding.opcode();
171 if (encoding.data.mode.isVex()) {165 if (encoding.data.mode.isVex()) {
172 try writer.writeAll("VEX.");166 try bw.writeAll("VEX.");
173167
174 try writer.writeAll(switch (encoding.data.mode) {168 try bw.writeAll(switch (encoding.data.mode) {
175 .vex_128_w0, .vex_128_w1, .vex_128_wig => "128",169 .vex_128_w0, .vex_128_w1, .vex_128_wig => "128",
176 .vex_256_w0, .vex_256_w1, .vex_256_wig => "256",170 .vex_256_w0, .vex_256_w1, .vex_256_wig => "256",
177 .vex_lig_w0, .vex_lig_w1, .vex_lig_wig => "LIG",171 .vex_lig_w0, .vex_lig_w1, .vex_lig_wig => "LIG",
...@@ -182,25 +176,25 @@ pub fn format(...@@ -182,25 +176,25 @@ pub fn format(
182 switch (opc[0]) {176 switch (opc[0]) {
183 else => {},177 else => {},
184 0x66, 0xf3, 0xf2 => {178 0x66, 0xf3, 0xf2 => {
185 try writer.print(".{X:0>2}", .{opc[0]});179 try bw.print(".{X:0>2}", .{opc[0]});
186 opc = opc[1..];180 opc = opc[1..];
187 },181 },
188 }182 }
189183
190 try writer.print(".{}", .{std.fmt.fmtSliceHexUpper(opc[0 .. opc.len - 1])});184 try bw.print(".{X}", .{opc[0 .. opc.len - 1]});
191 opc = opc[opc.len - 1 ..];185 opc = opc[opc.len - 1 ..];
192186
193 try writer.writeAll(".W");187 try bw.writeAll(".W");
194 try writer.writeAll(switch (encoding.data.mode) {188 try bw.writeAll(switch (encoding.data.mode) {
195 .vex_128_w0, .vex_256_w0, .vex_lig_w0, .vex_lz_w0 => "0",189 .vex_128_w0, .vex_256_w0, .vex_lig_w0, .vex_lz_w0 => "0",
196 .vex_128_w1, .vex_256_w1, .vex_lig_w1, .vex_lz_w1 => "1",190 .vex_128_w1, .vex_256_w1, .vex_lig_w1, .vex_lz_w1 => "1",
197 .vex_128_wig, .vex_256_wig, .vex_lig_wig, .vex_lz_wig => "IG",191 .vex_128_wig, .vex_256_wig, .vex_lig_wig, .vex_lz_wig => "IG",
198 else => unreachable,192 else => unreachable,
199 });193 });
200194
201 try writer.writeByte(' ');195 try bw.writeByte(' ');
202 } else if (encoding.data.mode.isLong()) try writer.writeAll("REX.W + ");196 } else if (encoding.data.mode.isLong()) try bw.writeAll("REX.W + ");
203 for (opc) |byte| try writer.print("{x:0>2} ", .{byte});197 for (opc) |byte| try bw.print("{x:0>2} ", .{byte});
204198
205 switch (encoding.data.op_en) {199 switch (encoding.data.op_en) {
206 .z, .fd, .td, .i, .zi, .ii, .d => {},200 .z, .fd, .td, .i, .zi, .ii, .d => {},
...@@ -217,10 +211,10 @@ pub fn format(...@@ -217,10 +211,10 @@ pub fn format(
217 .r64 => "rd",211 .r64 => "rd",
218 else => unreachable,212 else => unreachable,
219 };213 };
220 try writer.print("+{s} ", .{tag});214 try bw.print("+{s} ", .{tag});
221 },215 },
222 .ia, .m, .mi, .m1, .mc, .vm, .vmi => try writer.print("/{d} ", .{encoding.modRmExt()}),216 .ia, .m, .mi, .m1, .mc, .vm, .vmi => try bw.print("/{d} ", .{encoding.modRmExt()}),
223 .mr, .rm, .rmi, .mri, .mrc, .rm0, .rvm, .rvmr, .rvmi, .mvr, .rmv => try writer.writeAll("/r "),217 .mr, .rm, .rmi, .mri, .mrc, .rm0, .rvm, .rvmr, .rvmi, .mvr, .rmv => try bw.writeAll("/r "),
224 }218 }
225219
226 switch (encoding.data.op_en) {220 switch (encoding.data.op_en) {
...@@ -249,24 +243,24 @@ pub fn format(...@@ -249,24 +243,24 @@ pub fn format(
249 .rel32 => "cd",243 .rel32 => "cd",
250 else => unreachable,244 else => unreachable,
251 };245 };
252 try writer.print("{s} ", .{tag});246 try bw.print("{s} ", .{tag});
253 },247 },
254 .rvmr => try writer.writeAll("/is4 "),248 .rvmr => try bw.writeAll("/is4 "),
255 .z, .fd, .td, .o, .zo, .oz, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .vm, .rvm, .mvr, .rmv => {},249 .z, .fd, .td, .o, .zo, .oz, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .vm, .rvm, .mvr, .rmv => {},
256 }250 }
257251
258 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});252 try bw.print("{s} ", .{@tagName(encoding.mnemonic)});
259253
260 for (encoding.data.ops) |op| switch (op) {254 for (encoding.data.ops) |op| switch (op) {
261 .none => break,255 .none => break,
262 else => try writer.print("{s} ", .{@tagName(op)}),256 else => try bw.print("{s} ", .{@tagName(op)}),
263 };257 };
264258
265 const op_en = switch (encoding.data.op_en) {259 const op_en = switch (encoding.data.op_en) {
266 .zi => .i,260 .zi => .i,
267 else => |op_en| op_en,261 else => |op_en| op_en,
268 };262 };
269 try writer.print("{s}", .{@tagName(op_en)});263 try bw.print("{s}", .{@tagName(op_en)});
270}264}
271265
272pub const Mnemonic = enum {266pub const Mnemonic = enum {
...@@ -1014,19 +1008,21 @@ pub const Feature = enum {...@@ -1014,19 +1008,21 @@ pub const Feature = enum {
1014};1008};
10151009
1016fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {1010fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {
1017 var inst = Instruction{1011 var inst: Instruction = .{
1018 .prefix = prefix,1012 .prefix = prefix,
1019 .encoding = encoding,1013 .encoding = encoding,
1020 .ops = @splat(.none),1014 .ops = @splat(.none),
1021 };1015 };
1022 @memcpy(inst.ops[0..ops.len], ops);1016 @memcpy(inst.ops[0..ops.len], ops);
10231017
1024 var cwriter = std.io.countingWriter(std.io.null_writer);1018 var buf: [15]u8 = undefined;
1025 inst.encode(cwriter.writer(), .{1019 var bw: std.io.BufferedWriter = undefined;
1020 bw.initFixed(&buf);
1021 inst.encode(&bw, .{
1026 .allow_frame_locs = true,1022 .allow_frame_locs = true,
1027 .allow_symbols = true,1023 .allow_symbols = true,
1028 }) catch unreachable; // Not allowed to fail here unless OOM.1024 }) catch unreachable;
1029 return @as(usize, @intCast(cwriter.bytes_written));1025 return @intCast(bw.end);
1030}1026}
10311027
1032const mnemonic_to_encodings_map = init: {1028const mnemonic_to_encodings_map = init: {
src/arch/x86_64/bits.zig+9-26
...@@ -728,21 +728,12 @@ pub const FrameIndex = enum(u32) {...@@ -728,21 +728,12 @@ pub const FrameIndex = enum(u32) {
728 return @intFromEnum(fi) < named_count;728 return @intFromEnum(fi) < named_count;
729 }729 }
730730
731 pub fn format(731 pub fn format(fi: FrameIndex, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
732 fi: FrameIndex,732 try bw.writeAll("FrameIndex");
733 comptime fmt: []const u8,733 if (fi.isNamed())
734 options: std.fmt.FormatOptions,734 try bw.print(".{s}", .{@tagName(fi)})
735 writer: anytype,735 else
736 ) @TypeOf(writer).Error!void {736 try bw.print("({d})", .{@intFromEnum(fi)});
737 try writer.writeAll("FrameIndex");
738 if (fi.isNamed()) {
739 try writer.writeByte('.');
740 try writer.writeAll(@tagName(fi));
741 } else {
742 try writer.writeByte('(');
743 try std.fmt.formatType(@intFromEnum(fi), fmt, options, writer, 0);
744 try writer.writeByte(')');
745 }
746 }737 }
747};738};
748739
...@@ -844,21 +835,13 @@ pub const Memory = struct {...@@ -844,21 +835,13 @@ pub const Memory = struct {
844 };835 };
845 }836 }
846837
847 pub fn format(838 pub fn format(s: Size, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
848 s: Size,
849 comptime _: []const u8,
850 _: std.fmt.FormatOptions,
851 writer: anytype,
852 ) @TypeOf(writer).Error!void {
853 if (s == .none) return;839 if (s == .none) return;
854 try writer.writeAll(@tagName(s));840 try bw.writeAll(@tagName(s));
855 switch (s) {841 switch (s) {
856 .none => unreachable,842 .none => unreachable,
857 .ptr, .gpr => {},843 .ptr, .gpr => {},
858 else => {844 else => try bw.writeAll(" ptr"),
859 try writer.writeByte(' ');
860 try writer.writeAll("ptr");
861 },
862 }845 }
863 }846 }
864 };847 };
src/arch/x86_64/encoder.zig+102-121
...@@ -226,16 +226,10 @@ pub const Instruction = struct {...@@ -226,16 +226,10 @@ pub const Instruction = struct {
226 };226 };
227 }227 }
228228
229 fn format(229 fn format(op: Operand, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
230 op: Operand,
231 comptime unused_format_string: []const u8,
232 options: std.fmt.FormatOptions,
233 writer: anytype,
234 ) !void {
235 _ = op;230 _ = op;
231 _ = bw;
236 _ = unused_format_string;232 _ = unused_format_string;
237 _ = options;
238 _ = writer;
239 @compileError("do not format Operand directly; use fmt() instead");233 @compileError("do not format Operand directly; use fmt() instead");
240 }234 }
241235
...@@ -244,78 +238,72 @@ pub const Instruction = struct {...@@ -244,78 +238,72 @@ pub const Instruction = struct {
244 enc_op: Encoding.Op,238 enc_op: Encoding.Op,
245 };239 };
246240
247 fn fmtContext(241 fn fmtContext(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
248 ctx: FormatContext,
249 comptime unused_format_string: []const u8,
250 options: std.fmt.FormatOptions,
251 writer: anytype,
252 ) @TypeOf(writer).Error!void {
253 _ = unused_format_string;242 _ = unused_format_string;
254 _ = options;
255 const op = ctx.op;243 const op = ctx.op;
256 const enc_op = ctx.enc_op;244 const enc_op = ctx.enc_op;
257 switch (op) {245 switch (op) {
258 .none => {},246 .none => {},
259 .reg => |reg| try writer.writeAll(@tagName(reg)),247 .reg => |reg| try bw.writeAll(@tagName(reg)),
260 .mem => |mem| switch (mem) {248 .mem => |mem| switch (mem) {
261 .rip => |rip| {249 .rip => |rip| {
262 try writer.print("{} [rip", .{rip.ptr_size});250 try bw.print("{f} [rip", .{rip.ptr_size});
263 if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{251 if (rip.disp != 0) try bw.print(" {c} 0x{x}", .{
264 @as(u8, if (rip.disp < 0) '-' else '+'),252 @as(u8, if (rip.disp < 0) '-' else '+'),
265 @abs(rip.disp),253 @abs(rip.disp),
266 });254 });
267 try writer.writeByte(']');255 try bw.writeByte(']');
268 },256 },
269 .sib => |sib| {257 .sib => |sib| {
270 try writer.print("{} ", .{sib.ptr_size});258 try bw.print("{f} ", .{sib.ptr_size});
271259
272 if (mem.isSegmentRegister()) {260 if (mem.isSegmentRegister()) {
273 return writer.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });261 return bw.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });
274 }262 }
275263
276 try writer.writeByte('[');264 try bw.writeByte('[');
277265
278 var any = true;266 var any = true;
279 switch (sib.base) {267 switch (sib.base) {
280 .none => any = false,268 .none => any = false,
281 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),269 .reg => |reg| try bw.print("{s}", .{@tagName(reg)}),
282 .frame => |frame_index| try writer.print("{}", .{frame_index}),270 .frame => |frame_index| try bw.print("{}", .{frame_index}),
283 .table => try writer.print("Table", .{}),271 .table => try bw.print("Table", .{}),
284 .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}),272 .rip_inst => |inst_index| try bw.print("RipInst({d})", .{inst_index}),
285 .nav => |nav| try writer.print("Nav({d})", .{@intFromEnum(nav)}),273 .nav => |nav| try bw.print("Nav({d})", .{@intFromEnum(nav)}),
286 .uav => |uav| try writer.print("Uav({d})", .{@intFromEnum(uav.val)}),274 .uav => |uav| try bw.print("Uav({d})", .{@intFromEnum(uav.val)}),
287 .lazy_sym => |lazy_sym| try writer.print("LazySym({s}, {d})", .{275 .lazy_sym => |lazy_sym| try bw.print("LazySym({s}, {d})", .{
288 @tagName(lazy_sym.kind),276 @tagName(lazy_sym.kind),
289 @intFromEnum(lazy_sym.ty),277 @intFromEnum(lazy_sym.ty),
290 }),278 }),
291 .extern_func => |extern_func| try writer.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),279 .extern_func => |extern_func| try bw.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
292 }280 }
293 if (mem.scaleIndex()) |si| {281 if (mem.scaleIndex()) |si| {
294 if (any) try writer.writeAll(" + ");282 if (any) try bw.writeAll(" + ");
295 try writer.print("{s} * {d}", .{ @tagName(si.index), si.scale });283 try bw.print("{s} * {d}", .{ @tagName(si.index), si.scale });
296 any = true;284 any = true;
297 }285 }
298 if (sib.disp != 0 or !any) {286 if (sib.disp != 0 or !any) {
299 if (any)287 if (any)
300 try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})288 try bw.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')})
301 else if (sib.disp < 0)289 else if (sib.disp < 0)
302 try writer.writeByte('-');290 try bw.writeByte('-');
303 try writer.print("0x{x}", .{@abs(sib.disp)});291 try bw.print("0x{x}", .{@abs(sib.disp)});
304 any = true;292 any = true;
305 }293 }
306294
307 try writer.writeByte(']');295 try bw.writeByte(']');
308 },296 },
309 .moffs => |moffs| try writer.print("{s}:0x{x}", .{297 .moffs => |moffs| try bw.print("{s}:0x{x}", .{
310 @tagName(moffs.seg),298 @tagName(moffs.seg),
311 moffs.offset,299 moffs.offset,
312 }),300 }),
313 },301 },
314 .imm => |imm| if (enc_op.isSigned()) {302 .imm => |imm| if (enc_op.isSigned()) {
315 const imms = imm.asSigned(enc_op.immBitSize());303 const imms = imm.asSigned(enc_op.immBitSize());
316 if (imms < 0) try writer.writeByte('-');304 if (imms < 0) try bw.writeByte('-');
317 try writer.print("0x{x}", .{@abs(imms)});305 try bw.print("0x{x}", .{@abs(imms)});
318 } else try writer.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}),306 } else try bw.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}),
319 .bytes => unreachable,307 .bytes => unreachable,
320 }308 }
321 }309 }
...@@ -361,7 +349,7 @@ pub const Instruction = struct {...@@ -361,7 +349,7 @@ pub const Instruction = struct {
361 },349 },
362 },350 },
363 };351 };
364 log.debug("selected encoding: {}", .{encoding});352 log.debug("selected encoding: {f}", .{encoding});
365353
366 var inst: Instruction = .{354 var inst: Instruction = .{
367 .prefix = prefix,355 .prefix = prefix,
...@@ -372,30 +360,23 @@ pub const Instruction = struct {...@@ -372,30 +360,23 @@ pub const Instruction = struct {
372 return inst;360 return inst;
373 }361 }
374362
375 pub fn format(363 pub fn format(inst: Instruction, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
376 inst: Instruction,
377 comptime unused_format_string: []const u8,
378 options: std.fmt.FormatOptions,
379 writer: anytype,
380 ) @TypeOf(writer).Error!void {
381 _ = unused_format_string;364 _ = unused_format_string;
382 _ = options;
383 switch (inst.prefix) {365 switch (inst.prefix) {
384 .none, .directive => {},366 .none, .directive => {},
385 else => try writer.print("{s} ", .{@tagName(inst.prefix)}),367 else => try bw.print("{s} ", .{@tagName(inst.prefix)}),
386 }368 }
387 try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)});369 try bw.print("{s}", .{@tagName(inst.encoding.mnemonic)});
388 for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {370 for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {
389 if (op == .none) break;371 if (op == .none) break;
390 if (i > 0) try writer.writeByte(',');372 if (i > 0) try bw.writeByte(',');
391 try writer.writeByte(' ');373 try bw.print(" {f}", .{op.fmt(enc)});
392 try writer.print("{}", .{op.fmt(enc)});
393 }374 }
394 }375 }
395376
396 pub fn encode(inst: Instruction, writer: anytype, comptime opts: Options) !void {377 pub fn encode(inst: Instruction, bw: *std.io.BufferedWriter, comptime opts: Options) !void {
397 assert(inst.prefix != .directive);378 assert(inst.prefix != .directive);
398 const encoder = Encoder(@TypeOf(writer), opts){ .writer = writer };379 const encoder: Encoder(opts) = .{ .bw = bw };
399 const enc = inst.encoding;380 const enc = inst.encoding;
400 const data = enc.data;381 const data = enc.data;
401382
...@@ -801,9 +782,9 @@ pub const LegacyPrefixes = packed struct {...@@ -801,9 +782,9 @@ pub const LegacyPrefixes = packed struct {
801782
802pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool = false };783pub const Options = struct { allow_frame_locs: bool = false, allow_symbols: bool = false };
803784
804fn Encoder(comptime T: type, comptime opts: Options) type {785fn Encoder(comptime opts: Options) type {
805 return struct {786 return struct {
806 writer: T,787 bw: *std.io.BufferedWriter,
807788
808 const Self = @This();789 const Self = @This();
809 pub const options = opts;790 pub const options = opts;
...@@ -813,44 +794,44 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -813,44 +794,44 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
813 // --------794 // --------
814795
815 /// Encodes legacy prefixes796 /// Encodes legacy prefixes
816 pub fn legacyPrefixes(self: Self, prefixes: LegacyPrefixes) !void {797 pub fn legacyPrefixes(self: Self, prefixes: LegacyPrefixes) anyerror!void {
817 if (@as(u16, @bitCast(prefixes)) != 0) {798 if (@as(u16, @bitCast(prefixes)) != 0) {
818 // Hopefully this path isn't taken very often, so we'll do it the slow way for now799 // Hopefully this path isn't taken very often, so we'll do it the slow way for now
819800
820 // LOCK801 // LOCK
821 if (prefixes.prefix_f0) try self.writer.writeByte(0xf0);802 if (prefixes.prefix_f0) try self.bw.writeByte(0xf0);
822 // REPNZ, REPNE, REP, Scalar Double-precision803 // REPNZ, REPNE, REP, Scalar Double-precision
823 if (prefixes.prefix_f2) try self.writer.writeByte(0xf2);804 if (prefixes.prefix_f2) try self.bw.writeByte(0xf2);
824 // REPZ, REPE, REP, Scalar Single-precision805 // REPZ, REPE, REP, Scalar Single-precision
825 if (prefixes.prefix_f3) try self.writer.writeByte(0xf3);806 if (prefixes.prefix_f3) try self.bw.writeByte(0xf3);
826807
827 // CS segment override or Branch not taken808 // CS segment override or Branch not taken
828 if (prefixes.prefix_2e) try self.writer.writeByte(0x2e);809 if (prefixes.prefix_2e) try self.bw.writeByte(0x2e);
829 // DS segment override810 // DS segment override
830 if (prefixes.prefix_36) try self.writer.writeByte(0x36);811 if (prefixes.prefix_36) try self.bw.writeByte(0x36);
831 // ES segment override812 // ES segment override
832 if (prefixes.prefix_26) try self.writer.writeByte(0x26);813 if (prefixes.prefix_26) try self.bw.writeByte(0x26);
833 // FS segment override814 // FS segment override
834 if (prefixes.prefix_64) try self.writer.writeByte(0x64);815 if (prefixes.prefix_64) try self.bw.writeByte(0x64);
835 // GS segment override816 // GS segment override
836 if (prefixes.prefix_65) try self.writer.writeByte(0x65);817 if (prefixes.prefix_65) try self.bw.writeByte(0x65);
837818
838 // Branch taken819 // Branch taken
839 if (prefixes.prefix_3e) try self.writer.writeByte(0x3e);820 if (prefixes.prefix_3e) try self.bw.writeByte(0x3e);
840821
841 // Operand size override822 // Operand size override
842 if (prefixes.prefix_66) try self.writer.writeByte(0x66);823 if (prefixes.prefix_66) try self.bw.writeByte(0x66);
843824
844 // Address size override825 // Address size override
845 if (prefixes.prefix_67) try self.writer.writeByte(0x67);826 if (prefixes.prefix_67) try self.bw.writeByte(0x67);
846 }827 }
847 }828 }
848829
849 /// Use 16 bit operand size830 /// Use 16 bit operand size
850 ///831 ///
851 /// Note that this flag is overridden by REX.W, if both are present.832 /// Note that this flag is overridden by REX.W, if both are present.
852 pub fn prefix16BitMode(self: Self) !void {833 pub fn prefix16BitMode(self: Self) anyerror!void {
853 try self.writer.writeByte(0x66);834 try self.bw.writeByte(0x66);
854 }835 }
855836
856 /// Encodes a REX prefix byte given all the fields837 /// Encodes a REX prefix byte given all the fields
...@@ -859,7 +840,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -859,7 +840,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
859 /// or one of reg, index, r/m, base, or opcode-reg might be extended.840 /// or one of reg, index, r/m, base, or opcode-reg might be extended.
860 ///841 ///
861 /// See struct `Rex` for a description of each field.842 /// See struct `Rex` for a description of each field.
862 pub fn rex(self: Self, fields: Rex) !void {843 pub fn rex(self: Self, fields: Rex) anyerror!void {
863 if (!fields.present and !fields.isSet()) return;844 if (!fields.present and !fields.isSet()) return;
864845
865 var byte: u8 = 0b0100_0000;846 var byte: u8 = 0b0100_0000;
...@@ -869,32 +850,32 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -869,32 +850,32 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
869 if (fields.x) byte |= 0b0010;850 if (fields.x) byte |= 0b0010;
870 if (fields.b) byte |= 0b0001;851 if (fields.b) byte |= 0b0001;
871852
872 try self.writer.writeByte(byte);853 try self.bw.writeByte(byte);
873 }854 }
874855
875 /// Encodes a VEX prefix given all the fields856 /// Encodes a VEX prefix given all the fields
876 ///857 ///
877 /// See struct `Vex` for a description of each field.858 /// See struct `Vex` for a description of each field.
878 pub fn vex(self: Self, fields: Vex) !void {859 pub fn vex(self: Self, fields: Vex) anyerror!void {
879 if (fields.is3Byte()) {860 if (fields.is3Byte()) {
880 try self.writer.writeByte(0b1100_0100);861 try self.bw.writeByte(0b1100_0100);
881862
882 try self.writer.writeByte(863 try self.bw.writeByte(
883 @as(u8, ~@intFromBool(fields.r)) << 7 |864 @as(u8, ~@intFromBool(fields.r)) << 7 |
884 @as(u8, ~@intFromBool(fields.x)) << 6 |865 @as(u8, ~@intFromBool(fields.x)) << 6 |
885 @as(u8, ~@intFromBool(fields.b)) << 5 |866 @as(u8, ~@intFromBool(fields.b)) << 5 |
886 @as(u8, @intFromEnum(fields.m)) << 0,867 @as(u8, @intFromEnum(fields.m)) << 0,
887 );868 );
888869
889 try self.writer.writeByte(870 try self.bw.writeByte(
890 @as(u8, @intFromBool(fields.w)) << 7 |871 @as(u8, @intFromBool(fields.w)) << 7 |
891 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |872 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
892 @as(u8, @intFromBool(fields.l)) << 2 |873 @as(u8, @intFromBool(fields.l)) << 2 |
893 @as(u8, @intFromEnum(fields.p)) << 0,874 @as(u8, @intFromEnum(fields.p)) << 0,
894 );875 );
895 } else {876 } else {
896 try self.writer.writeByte(0b1100_0101);877 try self.bw.writeByte(0b1100_0101);
897 try self.writer.writeByte(878 try self.bw.writeByte(
898 @as(u8, ~@intFromBool(fields.r)) << 7 |879 @as(u8, ~@intFromBool(fields.r)) << 7 |
899 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |880 @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 |
900 @as(u8, @intFromBool(fields.l)) << 2 |881 @as(u8, @intFromBool(fields.l)) << 2 |
...@@ -908,8 +889,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -908,8 +889,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
908 // ------889 // ------
909890
910 /// Encodes a 1 byte opcode891 /// Encodes a 1 byte opcode
911 pub fn opcode_1byte(self: Self, opcode: u8) !void {892 pub fn opcode_1byte(self: Self, opcode: u8) anyerror!void {
912 try self.writer.writeByte(opcode);893 try self.bw.writeByte(opcode);
913 }894 }
914895
915 /// Encodes a 2 byte opcode896 /// Encodes a 2 byte opcode
...@@ -917,8 +898,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -917,8 +898,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
917 /// e.g. IMUL has the opcode 0x0f 0xaf, so you use898 /// e.g. IMUL has the opcode 0x0f 0xaf, so you use
918 ///899 ///
919 /// encoder.opcode_2byte(0x0f, 0xaf);900 /// encoder.opcode_2byte(0x0f, 0xaf);
920 pub fn opcode_2byte(self: Self, prefix: u8, opcode: u8) !void {901 pub fn opcode_2byte(self: Self, prefix: u8, opcode: u8) anyerror!void {
921 try self.writer.writeAll(&.{ prefix, opcode });902 try self.bw.writeAll(&.{ prefix, opcode });
922 }903 }
923904
924 /// Encodes a 3 byte opcode905 /// Encodes a 3 byte opcode
...@@ -926,16 +907,16 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -926,16 +907,16 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
926 /// e.g. MOVSD has the opcode 0xf2 0x0f 0x10907 /// e.g. MOVSD has the opcode 0xf2 0x0f 0x10
927 ///908 ///
928 /// encoder.opcode_3byte(0xf2, 0x0f, 0x10);909 /// encoder.opcode_3byte(0xf2, 0x0f, 0x10);
929 pub fn opcode_3byte(self: Self, prefix_1: u8, prefix_2: u8, opcode: u8) !void {910 pub fn opcode_3byte(self: Self, prefix_1: u8, prefix_2: u8, opcode: u8) anyerror!void {
930 try self.writer.writeAll(&.{ prefix_1, prefix_2, opcode });911 try self.bw.writeAll(&.{ prefix_1, prefix_2, opcode });
931 }912 }
932913
933 /// Encodes a 1 byte opcode with a reg field914 /// Encodes a 1 byte opcode with a reg field
934 ///915 ///
935 /// Remember to add a REX prefix byte if reg is extended!916 /// Remember to add a REX prefix byte if reg is extended!
936 pub fn opcode_withReg(self: Self, opcode: u8, reg: u3) !void {917 pub fn opcode_withReg(self: Self, opcode: u8, reg: u3) anyerror!void {
937 assert(opcode & 0b111 == 0);918 assert(opcode & 0b111 == 0);
938 try self.writer.writeByte(opcode | reg);919 try self.bw.writeByte(opcode | reg);
939 }920 }
940921
941 // ------922 // ------
...@@ -945,8 +926,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -945,8 +926,8 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
945 /// Construct a ModR/M byte given all the fields926 /// Construct a ModR/M byte given all the fields
946 ///927 ///
947 /// Remember to add a REX prefix byte if reg or rm are extended!928 /// Remember to add a REX prefix byte if reg or rm are extended!
948 pub fn modRm(self: Self, mod: u2, reg_or_opx: u3, rm: u3) !void {929 pub fn modRm(self: Self, mod: u2, reg_or_opx: u3, rm: u3) anyerror!void {
949 try self.writer.writeByte(@as(u8, mod) << 6 | @as(u8, reg_or_opx) << 3 | rm);930 try self.bw.writeByte(@as(u8, mod) << 6 | @as(u8, reg_or_opx) << 3 | rm);
950 }931 }
951932
952 /// Construct a ModR/M byte using direct r/m addressing933 /// Construct a ModR/M byte using direct r/m addressing
...@@ -954,7 +935,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -954,7 +935,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
954 ///935 ///
955 /// Note reg's effective address is always just reg for the ModR/M byte.936 /// Note reg's effective address is always just reg for the ModR/M byte.
956 /// Remember to add a REX prefix byte if reg or rm are extended!937 /// Remember to add a REX prefix byte if reg or rm are extended!
957 pub fn modRm_direct(self: Self, reg_or_opx: u3, rm: u3) !void {938 pub fn modRm_direct(self: Self, reg_or_opx: u3, rm: u3) anyerror!void {
958 try self.modRm(0b11, reg_or_opx, rm);939 try self.modRm(0b11, reg_or_opx, rm);
959 }940 }
960941
...@@ -963,7 +944,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -963,7 +944,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
963 ///944 ///
964 /// Note reg's effective address is always just reg for the ModR/M byte.945 /// Note reg's effective address is always just reg for the ModR/M byte.
965 /// Remember to add a REX prefix byte if reg or rm are extended!946 /// Remember to add a REX prefix byte if reg or rm are extended!
966 pub fn modRm_indirectDisp0(self: Self, reg_or_opx: u3, rm: u3) !void {947 pub fn modRm_indirectDisp0(self: Self, reg_or_opx: u3, rm: u3) anyerror!void {
967 assert(rm != 4 and rm != 5);948 assert(rm != 4 and rm != 5);
968 try self.modRm(0b00, reg_or_opx, rm);949 try self.modRm(0b00, reg_or_opx, rm);
969 }950 }
...@@ -973,7 +954,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -973,7 +954,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
973 ///954 ///
974 /// Note reg's effective address is always just reg for the ModR/M byte.955 /// Note reg's effective address is always just reg for the ModR/M byte.
975 /// Remember to add a REX prefix byte if reg or rm are extended!956 /// Remember to add a REX prefix byte if reg or rm are extended!
976 pub fn modRm_SIBDisp0(self: Self, reg_or_opx: u3) !void {957 pub fn modRm_SIBDisp0(self: Self, reg_or_opx: u3) anyerror!void {
977 try self.modRm(0b00, reg_or_opx, 0b100);958 try self.modRm(0b00, reg_or_opx, 0b100);
978 }959 }
979960
...@@ -982,7 +963,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -982,7 +963,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
982 ///963 ///
983 /// Note reg's effective address is always just reg for the ModR/M byte.964 /// Note reg's effective address is always just reg for the ModR/M byte.
984 /// Remember to add a REX prefix byte if reg or rm are extended!965 /// Remember to add a REX prefix byte if reg or rm are extended!
985 pub fn modRm_RIPDisp32(self: Self, reg_or_opx: u3) !void {966 pub fn modRm_RIPDisp32(self: Self, reg_or_opx: u3) anyerror!void {
986 try self.modRm(0b00, reg_or_opx, 0b101);967 try self.modRm(0b00, reg_or_opx, 0b101);
987 }968 }
988969
...@@ -991,7 +972,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -991,7 +972,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
991 ///972 ///
992 /// Note reg's effective address is always just reg for the ModR/M byte.973 /// Note reg's effective address is always just reg for the ModR/M byte.
993 /// Remember to add a REX prefix byte if reg or rm are extended!974 /// Remember to add a REX prefix byte if reg or rm are extended!
994 pub fn modRm_indirectDisp8(self: Self, reg_or_opx: u3, rm: u3) !void {975 pub fn modRm_indirectDisp8(self: Self, reg_or_opx: u3, rm: u3) anyerror!void {
995 assert(rm != 4);976 assert(rm != 4);
996 try self.modRm(0b01, reg_or_opx, rm);977 try self.modRm(0b01, reg_or_opx, rm);
997 }978 }
...@@ -1001,7 +982,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1001,7 +982,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1001 ///982 ///
1002 /// Note reg's effective address is always just reg for the ModR/M byte.983 /// Note reg's effective address is always just reg for the ModR/M byte.
1003 /// Remember to add a REX prefix byte if reg or rm are extended!984 /// Remember to add a REX prefix byte if reg or rm are extended!
1004 pub fn modRm_SIBDisp8(self: Self, reg_or_opx: u3) !void {985 pub fn modRm_SIBDisp8(self: Self, reg_or_opx: u3) anyerror!void {
1005 try self.modRm(0b01, reg_or_opx, 0b100);986 try self.modRm(0b01, reg_or_opx, 0b100);
1006 }987 }
1007988
...@@ -1010,7 +991,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1010,7 +991,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1010 ///991 ///
1011 /// Note reg's effective address is always just reg for the ModR/M byte.992 /// Note reg's effective address is always just reg for the ModR/M byte.
1012 /// Remember to add a REX prefix byte if reg or rm are extended!993 /// Remember to add a REX prefix byte if reg or rm are extended!
1013 pub fn modRm_indirectDisp32(self: Self, reg_or_opx: u3, rm: u3) !void {994 pub fn modRm_indirectDisp32(self: Self, reg_or_opx: u3, rm: u3) anyerror!void {
1014 assert(rm != 4);995 assert(rm != 4);
1015 try self.modRm(0b10, reg_or_opx, rm);996 try self.modRm(0b10, reg_or_opx, rm);
1016 }997 }
...@@ -1020,7 +1001,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1020,7 +1001,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1020 ///1001 ///
1021 /// Note reg's effective address is always just reg for the ModR/M byte.1002 /// Note reg's effective address is always just reg for the ModR/M byte.
1022 /// Remember to add a REX prefix byte if reg or rm are extended!1003 /// Remember to add a REX prefix byte if reg or rm are extended!
1023 pub fn modRm_SIBDisp32(self: Self, reg_or_opx: u3) !void {1004 pub fn modRm_SIBDisp32(self: Self, reg_or_opx: u3) anyerror!void {
1024 try self.modRm(0b10, reg_or_opx, 0b100);1005 try self.modRm(0b10, reg_or_opx, 0b100);
1025 }1006 }
10261007
...@@ -1031,15 +1012,15 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1031,15 +1012,15 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1031 /// Construct a SIB byte given all the fields1012 /// Construct a SIB byte given all the fields
1032 ///1013 ///
1033 /// Remember to add a REX prefix byte if index or base are extended!1014 /// Remember to add a REX prefix byte if index or base are extended!
1034 pub fn sib(self: Self, scale: u2, index: u3, base: u3) !void {1015 pub fn sib(self: Self, scale: u2, index: u3, base: u3) anyerror!void {
1035 try self.writer.writeByte(@as(u8, scale) << 6 | @as(u8, index) << 3 | base);1016 try self.bw.writeByte(@as(u8, scale) << 6 | @as(u8, index) << 3 | base);
1036 }1017 }
10371018
1038 /// Construct a SIB byte with scale * index + base, no frills.1019 /// Construct a SIB byte with scale * index + base, no frills.
1039 /// r/m effective address: [base + scale * index]1020 /// r/m effective address: [base + scale * index]
1040 ///1021 ///
1041 /// Remember to add a REX prefix byte if index or base are extended!1022 /// Remember to add a REX prefix byte if index or base are extended!
1042 pub fn sib_scaleIndexBase(self: Self, scale: u2, index: u3, base: u3) !void {1023 pub fn sib_scaleIndexBase(self: Self, scale: u2, index: u3, base: u3) anyerror!void {
1043 assert(base != 5);1024 assert(base != 5);
10441025
1045 try self.sib(scale, index, base);1026 try self.sib(scale, index, base);
...@@ -1049,7 +1030,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1049,7 +1030,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1049 /// r/m effective address: [scale * index + disp32]1030 /// r/m effective address: [scale * index + disp32]
1050 ///1031 ///
1051 /// Remember to add a REX prefix byte if index or base are extended!1032 /// Remember to add a REX prefix byte if index or base are extended!
1052 pub fn sib_scaleIndexDisp32(self: Self, scale: u2, index: u3) !void {1033 pub fn sib_scaleIndexDisp32(self: Self, scale: u2, index: u3) anyerror!void {
1053 // scale is actually ignored1034 // scale is actually ignored
1054 // index = 4 means no index if and only if we haven't extended the register1035 // index = 4 means no index if and only if we haven't extended the register
1055 // TODO enforce this1036 // TODO enforce this
...@@ -1061,7 +1042,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1061,7 +1042,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1061 /// r/m effective address: [base]1042 /// r/m effective address: [base]
1062 ///1043 ///
1063 /// Remember to add a REX prefix byte if index or base are extended!1044 /// Remember to add a REX prefix byte if index or base are extended!
1064 pub fn sib_base(self: Self, base: u3) !void {1045 pub fn sib_base(self: Self, base: u3) anyerror!void {
1065 assert(base != 5);1046 assert(base != 5);
10661047
1067 // scale is actually ignored1048 // scale is actually ignored
...@@ -1073,7 +1054,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1073,7 +1054,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1073 /// r/m effective address: [disp32]1054 /// r/m effective address: [disp32]
1074 ///1055 ///
1075 /// Remember to add a REX prefix byte if index or base are extended!1056 /// Remember to add a REX prefix byte if index or base are extended!
1076 pub fn sib_disp32(self: Self) !void {1057 pub fn sib_disp32(self: Self) anyerror!void {
1077 // scale is actually ignored1058 // scale is actually ignored
1078 // index = 4 means no index1059 // index = 4 means no index
1079 // base = 5 means no base, if mod == 0.1060 // base = 5 means no base, if mod == 0.
...@@ -1084,7 +1065,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1084,7 +1065,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1084 /// r/m effective address: [base + scale * index + disp8]1065 /// r/m effective address: [base + scale * index + disp8]
1085 ///1066 ///
1086 /// Remember to add a REX prefix byte if index or base are extended!1067 /// Remember to add a REX prefix byte if index or base are extended!
1087 pub fn sib_scaleIndexBaseDisp8(self: Self, scale: u2, index: u3, base: u3) !void {1068 pub fn sib_scaleIndexBaseDisp8(self: Self, scale: u2, index: u3, base: u3) anyerror!void {
1088 try self.sib(scale, index, base);1069 try self.sib(scale, index, base);
1089 }1070 }
10901071
...@@ -1092,7 +1073,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1092,7 +1073,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1092 /// r/m effective address: [base + disp8]1073 /// r/m effective address: [base + disp8]
1093 ///1074 ///
1094 /// Remember to add a REX prefix byte if index or base are extended!1075 /// Remember to add a REX prefix byte if index or base are extended!
1095 pub fn sib_baseDisp8(self: Self, base: u3) !void {1076 pub fn sib_baseDisp8(self: Self, base: u3) anyerror!void {
1096 // scale is ignored1077 // scale is ignored
1097 // index = 4 means no index1078 // index = 4 means no index
1098 try self.sib(0, 4, base);1079 try self.sib(0, 4, base);
...@@ -1102,7 +1083,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1102,7 +1083,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1102 /// r/m effective address: [base + scale * index + disp32]1083 /// r/m effective address: [base + scale * index + disp32]
1103 ///1084 ///
1104 /// Remember to add a REX prefix byte if index or base are extended!1085 /// Remember to add a REX prefix byte if index or base are extended!
1105 pub fn sib_scaleIndexBaseDisp32(self: Self, scale: u2, index: u3, base: u3) !void {1086 pub fn sib_scaleIndexBaseDisp32(self: Self, scale: u2, index: u3, base: u3) anyerror!void {
1106 try self.sib(scale, index, base);1087 try self.sib(scale, index, base);
1107 }1088 }
11081089
...@@ -1110,7 +1091,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1110,7 +1091,7 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1110 /// r/m effective address: [base + disp32]1091 /// r/m effective address: [base + disp32]
1111 ///1092 ///
1112 /// Remember to add a REX prefix byte if index or base are extended!1093 /// Remember to add a REX prefix byte if index or base are extended!
1113 pub fn sib_baseDisp32(self: Self, base: u3) !void {1094 pub fn sib_baseDisp32(self: Self, base: u3) anyerror!void {
1114 // scale is ignored1095 // scale is ignored
1115 // index = 4 means no index1096 // index = 4 means no index
1116 try self.sib(0, 4, base);1097 try self.sib(0, 4, base);
...@@ -1123,43 +1104,43 @@ fn Encoder(comptime T: type, comptime opts: Options) type {...@@ -1123,43 +1104,43 @@ fn Encoder(comptime T: type, comptime opts: Options) type {
1123 /// Encode an 8 bit displacement1104 /// Encode an 8 bit displacement
1124 ///1105 ///
1125 /// It is sign-extended to 64 bits by the cpu.1106 /// It is sign-extended to 64 bits by the cpu.
1126 pub fn disp8(self: Self, disp: i8) !void {1107 pub fn disp8(self: Self, disp: i8) anyerror!void {
1127 try self.writer.writeByte(@as(u8, @bitCast(disp)));1108 try self.bw.writeByte(@as(u8, @bitCast(disp)));
1128 }1109 }
11291110
1130 /// Encode an 32 bit displacement1111 /// Encode an 32 bit displacement
1131 ///1112 ///
1132 /// It is sign-extended to 64 bits by the cpu.1113 /// It is sign-extended to 64 bits by the cpu.
1133 pub fn disp32(self: Self, disp: i32) !void {1114 pub fn disp32(self: Self, disp: i32) anyerror!void {
1134 try self.writer.writeInt(i32, disp, .little);1115 try self.bw.writeInt(i32, disp, .little);
1135 }1116 }
11361117
1137 /// Encode an 8 bit immediate1118 /// Encode an 8 bit immediate
1138 ///1119 ///
1139 /// It is sign-extended to 64 bits by the cpu.1120 /// It is sign-extended to 64 bits by the cpu.
1140 pub fn imm8(self: Self, imm: u8) !void {1121 pub fn imm8(self: Self, imm: u8) anyerror!void {
1141 try self.writer.writeByte(imm);1122 try self.bw.writeByte(imm);
1142 }1123 }
11431124
1144 /// Encode an 16 bit immediate1125 /// Encode an 16 bit immediate
1145 ///1126 ///
1146 /// It is sign-extended to 64 bits by the cpu.1127 /// It is sign-extended to 64 bits by the cpu.
1147 pub fn imm16(self: Self, imm: u16) !void {1128 pub fn imm16(self: Self, imm: u16) anyerror!void {
1148 try self.writer.writeInt(u16, imm, .little);1129 try self.bw.writeInt(u16, imm, .little);
1149 }1130 }
11501131
1151 /// Encode an 32 bit immediate1132 /// Encode an 32 bit immediate
1152 ///1133 ///
1153 /// It is sign-extended to 64 bits by the cpu.1134 /// It is sign-extended to 64 bits by the cpu.
1154 pub fn imm32(self: Self, imm: u32) !void {1135 pub fn imm32(self: Self, imm: u32) anyerror!void {
1155 try self.writer.writeInt(u32, imm, .little);1136 try self.bw.writeInt(u32, imm, .little);
1156 }1137 }
11571138
1158 /// Encode an 64 bit immediate1139 /// Encode an 64 bit immediate
1159 ///1140 ///
1160 /// It is sign-extended to 64 bits by the cpu.1141 /// It is sign-extended to 64 bits by the cpu.
1161 pub fn imm64(self: Self, imm: u64) !void {1142 pub fn imm64(self: Self, imm: u64) anyerror!void {
1162 try self.writer.writeInt(u64, imm, .little);1143 try self.bw.writeInt(u64, imm, .little);
1163 }1144 }
1164 };1145 };
1165}1146}
...@@ -2217,10 +2198,10 @@ const Assembler = struct {...@@ -2217,10 +2198,10 @@ const Assembler = struct {
2217 };2198 };
2218 }2199 }
22192200
2220 pub fn assemble(as: *Assembler, writer: anytype) !void {2201 pub fn assemble(as: *Assembler, bw: *std.io.BufferedWriter) !void {
2221 while (try as.next()) |parsed_inst| {2202 while (try as.next()) |parsed_inst| {
2222 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);2203 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
2223 try inst.encode(writer, .{});2204 try inst.encode(bw, .{});
2224 }2205 }
2225 }2206 }
22262207
src/codegen.zig+127-149
...@@ -225,14 +225,6 @@ pub fn generateLazyFunction(...@@ -225,14 +225,6 @@ pub fn generateLazyFunction(
225 }225 }
226}226}
227227
228fn writeFloat(comptime F: type, f: F, target: *const std.Target, endian: std.builtin.Endian, code: []u8) void {
229 _ = target;
230 const bits = @typeInfo(F).float.bits;
231 const Int = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } });
232 const int: Int = @bitCast(f);
233 mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian);
234}
235
236pub fn generateLazySymbol(228pub fn generateLazySymbol(
237 bin_file: *link.File,229 bin_file: *link.File,
238 pt: Zcu.PerThread,230 pt: Zcu.PerThread,
...@@ -256,7 +248,7 @@ pub fn generateLazySymbol(...@@ -256,7 +248,7 @@ pub fn generateLazySymbol(
256 const target = &comp.root_mod.resolved_target.result;248 const target = &comp.root_mod.resolved_target.result;
257 const endian = target.cpu.arch.endian();249 const endian = target.cpu.arch.endian();
258250
259 log.debug("generateLazySymbol: kind = {s}, ty = {}", .{251 log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{
260 @tagName(lazy_sym.kind),252 @tagName(lazy_sym.kind),
261 Type.fromInterned(lazy_sym.ty).fmt(pt),253 Type.fromInterned(lazy_sym.ty).fmt(pt),
262 });254 });
...@@ -296,7 +288,7 @@ pub fn generateLazySymbol(...@@ -296,7 +288,7 @@ pub fn generateLazySymbol(
296 code.appendAssumeCapacity(0);288 code.appendAssumeCapacity(0);
297 }289 }
298 } else {290 } else {
299 return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {}", .{291 return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
300 @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),292 @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
301 });293 });
302 }294 }
...@@ -321,19 +313,31 @@ pub fn generateSymbol(...@@ -321,19 +313,31 @@ pub fn generateSymbol(
321 const tracy = trace(@src());313 const tracy = trace(@src());
322 defer tracy.end();314 defer tracy.end();
323315
316 var aw: std.io.AllocatingWriter = undefined;
317 const bw = aw.fromArrayList(pt.zcu.gpa, code);
318 defer code.* = aw.toArrayList();
319 return @errorCast(generateSymbolInner(bin_file, pt, src_loc, val, bw, reloc_parent));
320}
321pub fn generateSymbolInner(
322 bin_file: *link.File,
323 pt: Zcu.PerThread,
324 src_loc: Zcu.LazySrcLoc,
325 val: Value,
326 bw: *std.io.BufferedWriter,
327 reloc_parent: link.File.RelocInfo.Parent,
328) anyerror!void {
324 const zcu = pt.zcu;329 const zcu = pt.zcu;
325 const gpa = zcu.gpa;
326 const ip = &zcu.intern_pool;330 const ip = &zcu.intern_pool;
327 const ty = val.typeOf(zcu);331 const ty = val.typeOf(zcu);
328332
329 const target = zcu.getTarget();333 const target = zcu.getTarget();
330 const endian = target.cpu.arch.endian();334 const endian = target.cpu.arch.endian();
331335
332 log.debug("generateSymbol: val = {}", .{val.fmtValue(pt)});336 log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});
333337
334 if (val.isUndefDeep(zcu)) {338 if (val.isUndefDeep(zcu)) {
335 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;339 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
336 try code.appendNTimes(gpa, 0xaa, abi_size);340 try bw.splatByteAll(0xaa, abi_size);
337 return;341 return;
338 }342 }
339343
...@@ -363,7 +367,7 @@ pub fn generateSymbol(...@@ -363,7 +367,7 @@ pub fn generateSymbol(
363 .null => unreachable, // non-runtime value367 .null => unreachable, // non-runtime value
364 .@"unreachable" => unreachable, // non-runtime value368 .@"unreachable" => unreachable, // non-runtime value
365 .empty_tuple => return,369 .empty_tuple => return,
366 .false, .true => try code.append(gpa, switch (simple_value) {370 .false, .true => try bw.writeByte(switch (simple_value) {
367 .false => 0,371 .false => 0,
368 .true => 1,372 .true => 1,
369 else => unreachable,373 else => unreachable,
...@@ -379,11 +383,12 @@ pub fn generateSymbol(...@@ -379,11 +383,12 @@ pub fn generateSymbol(
379 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;383 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
380 var space: Value.BigIntSpace = undefined;384 var space: Value.BigIntSpace = undefined;
381 const int_val = val.toBigInt(&space, zcu);385 const int_val = val.toBigInt(&space, zcu);
382 int_val.writeTwosComplement(try code.addManyAsSlice(gpa, abi_size), endian);386 int_val.writeTwosComplement((try bw.writableSlice(abi_size))[0..abi_size], endian);
387 bw.advance(abi_size);
383 },388 },
384 .err => |err| {389 .err => |err| {
385 const int = try pt.getErrorValue(err.name);390 const int = try pt.getErrorValue(err.name);
386 try code.writer(gpa).writeInt(u16, @intCast(int), endian);391 try bw.writeInt(u16, @intCast(int), endian);
387 },392 },
388 .error_union => |error_union| {393 .error_union => |error_union| {
389 const payload_ty = ty.errorUnionPayload(zcu);394 const payload_ty = ty.errorUnionPayload(zcu);
...@@ -393,7 +398,7 @@ pub fn generateSymbol(...@@ -393,7 +398,7 @@ pub fn generateSymbol(
393 };398 };
394399
395 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {400 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
396 try code.writer(gpa).writeInt(u16, err_val, endian);401 try bw.writeInt(u16, err_val, endian);
397 return;402 return;
398 }403 }
399404
...@@ -403,57 +408,49 @@ pub fn generateSymbol(...@@ -403,57 +408,49 @@ pub fn generateSymbol(
403408
404 // error value first when its type is larger than the error union's payload409 // error value first when its type is larger than the error union's payload
405 if (error_align.order(payload_align) == .gt) {410 if (error_align.order(payload_align) == .gt) {
406 try code.writer(gpa).writeInt(u16, err_val, endian);411 try bw.writeInt(u16, err_val, endian);
407 }412 }
408413
409 // emit payload part of the error union414 // emit payload part of the error union
410 {415 {
411 const begin = code.items.len;416 const begin = bw.count;
412 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) {417 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(switch (error_union.val) {
413 .err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),418 .err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }),
414 .payload => |payload| payload,419 .payload => |payload| payload,
415 }), code, reloc_parent);420 }), bw, reloc_parent);
416 const unpadded_end = code.items.len - begin;421 const unpadded_end = bw.count - begin;
417 const padded_end = abi_align.forward(unpadded_end);422 const padded_end = abi_align.forward(unpadded_end);
418 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;423 try bw.splatByteAll(0, math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow);
419
420 if (padding > 0) {
421 try code.appendNTimes(gpa, 0, padding);
422 }
423 }424 }
424425
425 // Payload size is larger than error set, so emit our error set last426 // Payload size is larger than error set, so emit our error set last
426 if (error_align.compare(.lte, payload_align)) {427 if (error_align.compare(.lte, payload_align)) {
427 const begin = code.items.len;428 const begin = bw.count;
428 try code.writer(gpa).writeInt(u16, err_val, endian);429 try bw.writeInt(u16, err_val, endian);
429 const unpadded_end = code.items.len - begin;430 const unpadded_end = bw.count - begin;
430 const padded_end = abi_align.forward(unpadded_end);431 const padded_end = abi_align.forward(unpadded_end);
431 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;432 try bw.splatByteAll(0, math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow);
432
433 if (padding > 0) {
434 try code.appendNTimes(gpa, 0, padding);
435 }
436 }433 }
437 },434 },
438 .enum_tag => |enum_tag| {435 .enum_tag => |enum_tag| {
439 const int_tag_ty = ty.intTagType(zcu);436 const int_tag_ty = ty.intTagType(zcu);
440 try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, reloc_parent);437 try generateSymbolInner(bin_file, pt, src_loc, try pt.getCoerced(.fromInterned(enum_tag.int), int_tag_ty), bw, reloc_parent);
441 },438 },
442 .float => |float| switch (float.storage) {439 .float => |float| switch (float.storage) {
443 .f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(gpa, 2)),440 .f16 => |f16_val| try bw.writeInt(u16, @bitCast(f16_val), endian),
444 .f32 => |f32_val| writeFloat(f32, f32_val, target, endian, try code.addManyAsArray(gpa, 4)),441 .f32 => |f32_val| try bw.writeInt(u32, @bitCast(f32_val), endian),
445 .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(gpa, 8)),442 .f64 => |f64_val| try bw.writeInt(u64, @bitCast(f64_val), endian),
446 .f80 => |f80_val| {443 .f80 => |f80_val| {
447 writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(gpa, 10));444 try bw.writeInt(u80, @bitCast(f80_val), endian);
448 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;445 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
449 try code.appendNTimes(gpa, 0, abi_size - 10);446 try bw.splatByteAll(0, abi_size - 10);
450 },447 },
451 .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(gpa, 16)),448 .f128 => |f128_val| try bw.writeInt(u128, @bitCast(f128_val), endian),
452 },449 },
453 .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), code, reloc_parent, 0),450 .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), bw, reloc_parent, 0),
454 .slice => |slice| {451 .slice => |slice| {
455 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), code, reloc_parent);452 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(slice.ptr), bw, reloc_parent);
456 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), code, reloc_parent);453 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(slice.len), bw, reloc_parent);
457 },454 },
458 .opt => {455 .opt => {
459 const payload_type = ty.optionalChild(zcu);456 const payload_type = ty.optionalChild(zcu);
...@@ -462,44 +459,44 @@ pub fn generateSymbol(...@@ -462,44 +459,44 @@ pub fn generateSymbol(
462459
463 if (ty.optionalReprIsPayload(zcu)) {460 if (ty.optionalReprIsPayload(zcu)) {
464 if (payload_val) |value| {461 if (payload_val) |value| {
465 try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);462 try generateSymbolInner(bin_file, pt, src_loc, value, bw, reloc_parent);
466 } else {463 } else {
467 try code.appendNTimes(gpa, 0, abi_size);464 try bw.splatByteAll(0, abi_size);
468 }465 }
469 } else {466 } else {
470 const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1;467 const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1;
471 if (payload_type.hasRuntimeBits(zcu)) {468 if (payload_type.hasRuntimeBits(zcu)) {
472 const value = payload_val orelse Value.fromInterned(try pt.intern(.{469 const value: Value = payload_val orelse .fromInterned(try pt.intern(.{
473 .undef = payload_type.toIntern(),470 .undef = payload_type.toIntern(),
474 }));471 }));
475 try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent);472 try generateSymbolInner(bin_file, pt, src_loc, value, bw, reloc_parent);
476 }473 }
477 try code.writer(gpa).writeByte(@intFromBool(payload_val != null));474 try bw.writeByte(@intFromBool(payload_val != null));
478 try code.appendNTimes(gpa, 0, padding);475 try bw.splatByteAll(0, padding);
479 }476 }
480 },477 },
481 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {478 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
482 .array_type => |array_type| switch (aggregate.storage) {479 .array_type => |array_type| switch (aggregate.storage) {
483 .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(array_type.lenIncludingSentinel(), ip)),480 .bytes => |bytes| try bw.writeAll(bytes.toSlice(array_type.lenIncludingSentinel(), ip)),
484 .elems, .repeated_elem => {481 .elems, .repeated_elem => {
485 var index: u64 = 0;482 var index: u64 = 0;
486 while (index < array_type.lenIncludingSentinel()) : (index += 1) {483 while (index < array_type.lenIncludingSentinel()) : (index += 1) {
487 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {484 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(switch (aggregate.storage) {
488 .bytes => unreachable,485 .bytes => unreachable,
489 .elems => |elems| elems[@intCast(index)],486 .elems => |elems| elems[@intCast(index)],
490 .repeated_elem => |elem| if (index < array_type.len)487 .repeated_elem => |elem| if (index < array_type.len)
491 elem488 elem
492 else489 else
493 array_type.sentinel,490 array_type.sentinel,
494 }), code, reloc_parent);491 }), bw, reloc_parent);
495 }492 }
496 },493 },
497 },494 },
498 .vector_type => |vector_type| {495 .vector_type => |vector_type| {
499 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;496 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
500 if (vector_type.child == .bool_type) {497 if (vector_type.child == .bool_type) {
501 const bytes = try code.addManyAsSlice(gpa, abi_size);498 const buffer = (try bw.writableSlice(abi_size))[0..abi_size];
502 @memset(bytes, 0xaa);499 @memset(buffer, 0xaa);
503 var index: usize = 0;500 var index: usize = 0;
504 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;501 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;
505 while (index < len) : (index += 1) {502 while (index < len) : (index += 1) {
...@@ -507,7 +504,7 @@ pub fn generateSymbol(...@@ -507,7 +504,7 @@ pub fn generateSymbol(
507 .big => len - 1 - index,504 .big => len - 1 - index,
508 .little => index,505 .little => index,
509 };506 };
510 const byte = &bytes[bit_index / 8];507 const byte = &buffer[bit_index / 8];
511 const mask = @as(u8, 1) << @truncate(bit_index);508 const mask = @as(u8, 1) << @truncate(bit_index);
512 if (switch (switch (aggregate.storage) {509 if (switch (switch (aggregate.storage) {
513 .bytes => unreachable,510 .bytes => unreachable,
...@@ -535,31 +532,31 @@ pub fn generateSymbol(...@@ -535,31 +532,31 @@ pub fn generateSymbol(
535 },532 },
536 }) byte.* |= mask else byte.* &= ~mask;533 }) byte.* |= mask else byte.* &= ~mask;
537 }534 }
535 bw.advance(abi_size);
538 } else {536 } else {
539 switch (aggregate.storage) {537 switch (aggregate.storage) {
540 .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(vector_type.len, ip)),538 .bytes => |bytes| try bw.writeAll(bytes.toSlice(vector_type.len, ip)),
541 .elems, .repeated_elem => {539 .elems, .repeated_elem => {
542 var index: u64 = 0;540 var index: u64 = 0;
543 while (index < vector_type.len) : (index += 1) {541 while (index < vector_type.len) : (index += 1) {
544 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (aggregate.storage) {542 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(switch (aggregate.storage) {
545 .bytes => unreachable,543 .bytes => unreachable,
546 .elems => |elems| elems[544 .elems => |elems| elems[
547 math.cast(usize, index) orelse return error.Overflow545 math.cast(usize, index) orelse return error.Overflow
548 ],546 ],
549 .repeated_elem => |elem| elem,547 .repeated_elem => |elem| elem,
550 }), code, reloc_parent);548 }), bw, reloc_parent);
551 }549 }
552 },550 },
553 }551 }
554552
555 const padding = abi_size -553 try bw.splatByteAll(0, abi_size -
556 (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse554 (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse
557 return error.Overflow);555 return error.Overflow));
558 if (padding > 0) try code.appendNTimes(gpa, 0, padding);
559 }556 }
560 },557 },
561 .tuple_type => |tuple| {558 .tuple_type => |tuple| {
562 const struct_begin = code.items.len;559 const struct_begin = bw.count;
563 for (560 for (
564 tuple.types.get(ip),561 tuple.types.get(ip),
565 tuple.values.get(ip),562 tuple.values.get(ip),
...@@ -577,17 +574,13 @@ pub fn generateSymbol(...@@ -577,17 +574,13 @@ pub fn generateSymbol(
577 .repeated_elem => |elem| elem,574 .repeated_elem => |elem| elem,
578 };575 };
579576
580 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);577 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(field_val), bw, reloc_parent);
581 const unpadded_field_end = code.items.len - struct_begin;578 const unpadded_field_end = bw.count - struct_begin;
582579
583 // Pad struct members if required580 // Pad struct members if required
584 const padded_field_end = ty.structFieldOffset(index + 1, zcu);581 const padded_field_end = ty.structFieldOffset(index + 1, zcu);
585 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse582 try bw.splatByteAll(0, math.cast(usize, padded_field_end - unpadded_field_end) orelse
586 return error.Overflow;583 return error.Overflow);
587
588 if (padding > 0) {
589 try code.appendNTimes(gpa, 0, padding);
590 }
591 }584 }
592 },585 },
593 .struct_type => {586 .struct_type => {
...@@ -595,8 +588,9 @@ pub fn generateSymbol(...@@ -595,8 +588,9 @@ pub fn generateSymbol(
595 switch (struct_type.layout) {588 switch (struct_type.layout) {
596 .@"packed" => {589 .@"packed" => {
597 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;590 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
598 const current_pos = code.items.len;591 const current_end, const current_count = .{ bw.end, bw.count };
599 try code.appendNTimes(gpa, 0, abi_size);592 const buffer = (try bw.writableSlice(abi_size))[0..abi_size];
593 @memset(buffer, 0);
600 var bits: u16 = 0;594 var bits: u16 = 0;
601595
602 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {596 for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
...@@ -616,22 +610,25 @@ pub fn generateSymbol(...@@ -616,22 +610,25 @@ pub fn generateSymbol(
616 error.DivisionByZero => unreachable,610 error.DivisionByZero => unreachable,
617 error.UnexpectedRemainder => return error.RelocationNotByteAligned,611 error.UnexpectedRemainder => return error.RelocationNotByteAligned,
618 };612 };
619 code.items.len = current_pos + field_offset;613 bw.end = current_end + field_offset;
620 // TODO: code.lockPointers();614 bw.count = current_count + field_offset;
621 defer {615 defer {
622 assert(code.items.len == current_pos + field_offset + @divExact(target.ptrBitWidth(), 8));616 const field_size = @divExact(target.ptrBitWidth(), 8);
623 // TODO: code.unlockPointers();617 assert(bw.end == current_end + field_offset + field_size);
624 code.items.len = current_pos + abi_size;618 assert(bw.count == current_count + field_offset + field_size);
619 bw.end = current_end;
620 bw.count = current_count;
625 }621 }
626 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);622 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(field_val), bw, reloc_parent);
627 } else {623 } else {
628 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable;624 Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, buffer, bits) catch unreachable;
629 }625 }
630 bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu));626 bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu));
631 }627 }
628 bw.advance(abi_size);
632 },629 },
633 .auto, .@"extern" => {630 .auto, .@"extern" => {
634 const struct_begin = code.items.len;631 const struct_begin = bw.count;
635 const field_types = struct_type.field_types.get(ip);632 const field_types = struct_type.field_types.get(ip);
636 const offsets = struct_type.offsets.get(ip);633 const offsets = struct_type.offsets.get(ip);
637634
...@@ -649,24 +646,22 @@ pub fn generateSymbol(...@@ -649,24 +646,22 @@ pub fn generateSymbol(
649 .repeated_elem => |elem| elem,646 .repeated_elem => |elem| elem,
650 };647 };
651648
652 const padding = math.cast(649 try bw.splatByteAll(0, math.cast(
653 usize,650 usize,
654 offsets[field_index] - (code.items.len - struct_begin),651 offsets[field_index] - (bw.count - struct_begin),
655 ) orelse return error.Overflow;652 ) orelse return error.Overflow);
656 if (padding > 0) try code.appendNTimes(gpa, 0, padding);
657653
658 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent);654 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(field_val), bw, reloc_parent);
659 }655 }
660656
661 const size = struct_type.sizeUnordered(ip);657 const size = struct_type.sizeUnordered(ip);
662 const alignment = struct_type.flagsUnordered(ip).alignment.toByteUnits().?;658 const alignment = struct_type.flagsUnordered(ip).alignment.toByteUnits().?;
663659
664 const padding = math.cast(660 try bw.splatByteAll(0, math.cast(
665 usize,661 usize,
666 std.mem.alignForward(u64, size, @max(alignment, 1)) -662 std.mem.alignForward(u64, size, @max(alignment, 1)) -
667 (code.items.len - struct_begin),663 (bw.count - struct_begin),
668 ) orelse return error.Overflow;664 ) orelse return error.Overflow);
669 if (padding > 0) try code.appendNTimes(gpa, 0, padding);
670 },665 },
671 }666 }
672 },667 },
...@@ -676,38 +671,31 @@ pub fn generateSymbol(...@@ -676,38 +671,31 @@ pub fn generateSymbol(
676 const layout = ty.unionGetLayout(zcu);671 const layout = ty.unionGetLayout(zcu);
677672
678 if (layout.payload_size == 0) {673 if (layout.payload_size == 0) {
679 return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);674 return generateSymbolInner(bin_file, pt, src_loc, .fromInterned(un.tag), bw, reloc_parent);
680 }675 }
681676
682 // Check if we should store the tag first.677 // Check if we should store the tag first.
683 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {678 if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) {
684 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);679 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(un.tag), bw, reloc_parent);
685 }680 }
686681
687 const union_obj = zcu.typeToUnion(ty).?;682 const union_obj = zcu.typeToUnion(ty).?;
688 if (un.tag != .none) {683 if (un.tag != .none) {
689 const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;684 const field_index = ty.unionTagFieldIndex(.fromInterned(un.tag), zcu).?;
690 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);685 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
691 if (!field_ty.hasRuntimeBits(zcu)) {686 if (!field_ty.hasRuntimeBits(zcu)) {
692 try code.appendNTimes(gpa, 0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);687 try bw.splatByteAll(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
693 } else {688 } else {
694 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);689 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(un.val), bw, reloc_parent);
695690 try bw.splatByteAll(0, math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow);
696 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow;
697 if (padding > 0) {
698 try code.appendNTimes(gpa, 0, padding);
699 }
700 }691 }
701 } else {692 } else {
702 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent);693 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(un.val), bw, reloc_parent);
703 }694 }
704695
705 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {696 if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) {
706 try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent);697 try generateSymbolInner(bin_file, pt, src_loc, .fromInterned(un.tag), bw, reloc_parent);
707698 try bw.splatByteAll(0, layout.padding);
708 if (layout.padding > 0) {
709 try code.appendNTimes(gpa, 0, layout.padding);
710 }
711 }699 }
712 },700 },
713 .memoized_call => unreachable,701 .memoized_call => unreachable,
...@@ -719,32 +707,32 @@ fn lowerPtr(...@@ -719,32 +707,32 @@ fn lowerPtr(
719 pt: Zcu.PerThread,707 pt: Zcu.PerThread,
720 src_loc: Zcu.LazySrcLoc,708 src_loc: Zcu.LazySrcLoc,
721 ptr_val: InternPool.Index,709 ptr_val: InternPool.Index,
722 code: *std.ArrayListUnmanaged(u8),710 bw: *std.io.BufferedWriter,
723 reloc_parent: link.File.RelocInfo.Parent,711 reloc_parent: link.File.RelocInfo.Parent,
724 prev_offset: u64,712 prev_offset: u64,
725) GenerateSymbolError!void {713) anyerror!void {
726 const zcu = pt.zcu;714 const zcu = pt.zcu;
727 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;715 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
728 const offset: u64 = prev_offset + ptr.byte_offset;716 const offset: u64 = prev_offset + ptr.byte_offset;
729 return switch (ptr.base_addr) {717 return switch (ptr.base_addr) {
730 .nav => |nav| try lowerNavRef(bin_file, pt, nav, code, reloc_parent, offset),718 .nav => |nav| try lowerNavRef(bin_file, pt, nav, bw, reloc_parent, offset),
731 .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, code, reloc_parent, offset),719 .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, bw, reloc_parent, offset),
732 .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), code, reloc_parent),720 .int => try generateSymbolInner(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), bw, reloc_parent),
733 .eu_payload => |eu_ptr| try lowerPtr(721 .eu_payload => |eu_ptr| try lowerPtr(
734 bin_file,722 bin_file,
735 pt,723 pt,
736 src_loc,724 src_loc,
737 eu_ptr,725 eu_ptr,
738 code,726 bw,
739 reloc_parent,727 reloc_parent,
740 offset + errUnionPayloadOffset(728 offset + errUnionPayloadOffset(
741 Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu).errorUnionPayload(zcu),729 Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu).errorUnionPayload(zcu),
742 zcu,730 zcu,
743 ),731 ),
744 ),732 ),
745 .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, code, reloc_parent, offset),733 .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, bw, reloc_parent, offset),
746 .field => |field| {734 .field => |field| {
747 const base_ptr = Value.fromInterned(field.base);735 const base_ptr: Value = .fromInterned(field.base);
748 const base_ty = base_ptr.typeOf(zcu).childType(zcu);736 const base_ty = base_ptr.typeOf(zcu).childType(zcu);
749 const field_off: u64 = switch (base_ty.zigTypeTag(zcu)) {737 const field_off: u64 = switch (base_ty.zigTypeTag(zcu)) {
750 .pointer => off: {738 .pointer => off: {
...@@ -761,7 +749,7 @@ fn lowerPtr(...@@ -761,7 +749,7 @@ fn lowerPtr(
761 },749 },
762 else => unreachable,750 else => unreachable,
763 };751 };
764 return lowerPtr(bin_file, pt, src_loc, field.base, code, reloc_parent, offset + field_off);752 return lowerPtr(bin_file, pt, src_loc, field.base, bw, reloc_parent, offset + field_off);
765 },753 },
766 .arr_elem, .comptime_field, .comptime_alloc => unreachable,754 .arr_elem, .comptime_field, .comptime_alloc => unreachable,
767 };755 };
...@@ -772,12 +760,11 @@ fn lowerUavRef(...@@ -772,12 +760,11 @@ fn lowerUavRef(
772 pt: Zcu.PerThread,760 pt: Zcu.PerThread,
773 src_loc: Zcu.LazySrcLoc,761 src_loc: Zcu.LazySrcLoc,
774 uav: InternPool.Key.Ptr.BaseAddr.Uav,762 uav: InternPool.Key.Ptr.BaseAddr.Uav,
775 code: *std.ArrayListUnmanaged(u8),763 bw: *std.io.BufferedWriter,
776 reloc_parent: link.File.RelocInfo.Parent,764 reloc_parent: link.File.RelocInfo.Parent,
777 offset: u64,765 offset: u64,
778) GenerateSymbolError!void {766) anyerror!void {
779 const zcu = pt.zcu;767 const zcu = pt.zcu;
780 const gpa = zcu.gpa;
781 const ip = &zcu.intern_pool;768 const ip = &zcu.intern_pool;
782 const comp = lf.comp;769 const comp = lf.comp;
783 const target = &comp.root_mod.resolved_target.result;770 const target = &comp.root_mod.resolved_target.result;
...@@ -786,13 +773,9 @@ fn lowerUavRef(...@@ -786,13 +773,9 @@ fn lowerUavRef(
786 const uav_ty = Type.fromInterned(ip.typeOf(uav_val));773 const uav_ty = Type.fromInterned(ip.typeOf(uav_val));
787 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";774 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
788775
789 log.debug("lowerUavRef: ty = {}", .{uav_ty.fmt(pt)});776 log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)});
790 try code.ensureUnusedCapacity(gpa, ptr_width_bytes);
791777
792 if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {778 if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) return bw.splatByteAll(0xaa, ptr_width_bytes);
793 code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes);
794 return;
795 }
796779
797 switch (lf.tag) {780 switch (lf.tag) {
798 .c => unreachable,781 .c => unreachable,
...@@ -801,9 +784,8 @@ fn lowerUavRef(...@@ -801,9 +784,8 @@ fn lowerUavRef(
801 dev.check(link.File.Tag.wasm.devFeature());784 dev.check(link.File.Tag.wasm.devFeature());
802 const wasm = lf.cast(.wasm).?;785 const wasm = lf.cast(.wasm).?;
803 assert(reloc_parent == .none);786 assert(reloc_parent == .none);
804 try wasm.addUavReloc(code.items.len, uav.val, uav.orig_ty, @intCast(offset));787 try wasm.addUavReloc(bw.count, uav.val, uav.orig_ty, @intCast(offset));
805 code.appendNTimesAssumeCapacity(0, ptr_width_bytes);788 return bw.splatByteAll(0, ptr_width_bytes);
806 return;
807 },789 },
808 else => {},790 else => {},
809 }791 }
...@@ -816,14 +798,14 @@ fn lowerUavRef(...@@ -816,14 +798,14 @@ fn lowerUavRef(
816798
817 const vaddr = try lf.getUavVAddr(uav_val, .{799 const vaddr = try lf.getUavVAddr(uav_val, .{
818 .parent = reloc_parent,800 .parent = reloc_parent,
819 .offset = code.items.len,801 .offset = bw.count,
820 .addend = @intCast(offset),802 .addend = @intCast(offset),
821 });803 });
822 const endian = target.cpu.arch.endian();804 const endian = target.cpu.arch.endian();
823 switch (ptr_width_bytes) {805 switch (ptr_width_bytes) {
824 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian),806 2 => try bw.writeInt(u16, @intCast(vaddr), endian),
825 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian),807 4 => try bw.writeInt(u32, @intCast(vaddr), endian),
826 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian),808 8 => try bw.writeInt(u64, vaddr, endian),
827 else => unreachable,809 else => unreachable,
828 }810 }
829}811}
...@@ -832,10 +814,10 @@ fn lowerNavRef(...@@ -832,10 +814,10 @@ fn lowerNavRef(
832 lf: *link.File,814 lf: *link.File,
833 pt: Zcu.PerThread,815 pt: Zcu.PerThread,
834 nav_index: InternPool.Nav.Index,816 nav_index: InternPool.Nav.Index,
835 code: *std.ArrayListUnmanaged(u8),817 bw: *std.io.BufferedWriter,
836 reloc_parent: link.File.RelocInfo.Parent,818 reloc_parent: link.File.RelocInfo.Parent,
837 offset: u64,819 offset: u64,
838) GenerateSymbolError!void {820) anyerror!void {
839 const zcu = pt.zcu;821 const zcu = pt.zcu;
840 const gpa = zcu.gpa;822 const gpa = zcu.gpa;
841 const ip = &zcu.intern_pool;823 const ip = &zcu.intern_pool;
...@@ -845,12 +827,9 @@ fn lowerNavRef(...@@ -845,12 +827,9 @@ fn lowerNavRef(
845 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));827 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));
846 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";828 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
847829
848 try code.ensureUnusedCapacity(gpa, ptr_width_bytes);830 log.debug("lowerNavRef: ty = {f}", .{nav_ty.fmt(pt)});
849831
850 if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) {832 if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) return bw.splatByteAll(0xaa, ptr_width_bytes);
851 code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes);
852 return;
853 }
854833
855 switch (lf.tag) {834 switch (lf.tag) {
856 .c => unreachable,835 .c => unreachable,
...@@ -867,13 +846,13 @@ fn lowerNavRef(...@@ -867,13 +846,13 @@ fn lowerNavRef(
867 } else {846 } else {
868 try wasm.func_table_fixups.append(gpa, .{847 try wasm.func_table_fixups.append(gpa, .{
869 .table_index = @enumFromInt(gop.index),848 .table_index = @enumFromInt(gop.index),
870 .offset = @intCast(code.items.len),849 .offset = @intCast(bw.count),
871 });850 });
872 }851 }
873 } else {852 } else {
874 if (is_obj) {853 if (is_obj) {
875 try wasm.out_relocs.append(gpa, .{854 try wasm.out_relocs.append(gpa, .{
876 .offset = @intCast(code.items.len),855 .offset = @intCast(bw.count),
877 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) },856 .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) },
878 .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,857 .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64,
879 .addend = @intCast(offset),858 .addend = @intCast(offset),
...@@ -882,27 +861,26 @@ fn lowerNavRef(...@@ -882,27 +861,26 @@ fn lowerNavRef(
882 try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);861 try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
883 wasm.nav_fixups.appendAssumeCapacity(.{862 wasm.nav_fixups.appendAssumeCapacity(.{
884 .navs_exe_index = try wasm.refNavExe(nav_index),863 .navs_exe_index = try wasm.refNavExe(nav_index),
885 .offset = @intCast(code.items.len),864 .offset = @intCast(bw.count),
886 .addend = @intCast(offset),865 .addend = @intCast(offset),
887 });866 });
888 }867 }
889 }868 }
890 code.appendNTimesAssumeCapacity(0, ptr_width_bytes);869 return bw.splatByteAll(0, ptr_width_bytes);
891 return;
892 },870 },
893 else => {},871 else => {},
894 }872 }
895873
896 const vaddr = lf.getNavVAddr(pt, nav_index, .{874 const vaddr = lf.getNavVAddr(pt, nav_index, .{
897 .parent = reloc_parent,875 .parent = reloc_parent,
898 .offset = code.items.len,876 .offset = bw.count,
899 .addend = @intCast(offset),877 .addend = @intCast(offset),
900 }) catch @panic("TODO rework getNavVAddr");878 }) catch @panic("TODO rework getNavVAddr");
901 const endian = target.cpu.arch.endian();879 const endian = target.cpu.arch.endian();
902 switch (ptr_width_bytes) {880 switch (ptr_width_bytes) {
903 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian),881 2 => try bw.writeInt(u16, @intCast(vaddr), endian),
904 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian),882 4 => try bw.writeInt(u32, @intCast(vaddr), endian),
905 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian),883 8 => try bw.writeInt(u64, vaddr, endian),
906 else => unreachable,884 else => unreachable,
907 }885 }
908}886}
...@@ -1084,7 +1062,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo...@@ -1084,7 +1062,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
1084 const ip = &zcu.intern_pool;1062 const ip = &zcu.intern_pool;
1085 const ty = val.typeOf(zcu);1063 const ty = val.typeOf(zcu);
10861064
1087 log.debug("lowerValue(@as({}, {}))", .{ ty.fmt(pt), val.fmtValue(pt) });1065 log.debug("lowerValue(@as({f}, {f}))", .{ ty.fmt(pt), val.fmtValue(pt) });
10881066
1089 if (val.isUndef(zcu)) return .undef;1067 if (val.isUndef(zcu)) return .undef;
10901068
src/codegen/llvm.zig+14-12
...@@ -746,12 +746,14 @@ pub const Object = struct {...@@ -746,12 +746,14 @@ pub const Object = struct {
746 try wip.finish();746 try wip.finish();
747 }747 }
748748
749 fn genModuleLevelAssembly(object: *Object) !void {749 fn genModuleLevelAssembly(object: *Object) Allocator.Error!void {
750 const writer = object.builder.setModuleAsm();750 var aw: std.io.AllocatingWriter = undefined;
751 const bw = object.builder.setModuleAsm(&aw);
752 errdefer aw.deinit();
751 for (object.pt.zcu.global_assembly.values()) |assembly| {753 for (object.pt.zcu.global_assembly.values()) |assembly| {
752 try writer.print("{s}\n", .{assembly});754 bw.print("{s}\n", .{assembly}) catch |err| return @errorCast(err);
753 }755 }
754 try object.builder.finishModuleAsm();756 try object.builder.finishModuleAsm(&aw);
755 }757 }
756758
757 pub const EmitOptions = struct {759 pub const EmitOptions = struct {
...@@ -939,7 +941,7 @@ pub const Object = struct {...@@ -939,7 +941,7 @@ pub const Object = struct {
939 if (std.mem.eql(u8, path, "-")) {941 if (std.mem.eql(u8, path, "-")) {
940 o.builder.dump();942 o.builder.dump();
941 } else {943 } else {
942 _ = try o.builder.printToFile(path);944 _ = o.builder.printToFile(path);
943 }945 }
944 }946 }
945947
...@@ -2677,9 +2679,9 @@ pub const Object = struct {...@@ -2677,9 +2679,9 @@ pub const Object = struct {
26772679
2678 fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 {2680 fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 {
2679 var aw: std.io.AllocatingWriter = undefined;2681 var aw: std.io.AllocatingWriter = undefined;
2680 const bw = aw.init(o.gpa);2682 aw.init(o.gpa);
2681 defer aw.deinit();2683 defer aw.deinit();
2682 try ty.print(bw, o.pt);2684 ty.print(&aw.buffered_writer, o.pt) catch |err| return @errorCast(err);
2683 return aw.toOwnedSliceSentinel(0);2685 return aw.toOwnedSliceSentinel(0);
2684 }2686 }
26852687
...@@ -4479,7 +4481,7 @@ pub const Object = struct {...@@ -4479,7 +4481,7 @@ pub const Object = struct {
4479 const target = &zcu.root_mod.resolved_target.result;4481 const target = &zcu.root_mod.resolved_target.result;
4480 const function_index = try o.builder.addFunction(4482 const function_index = try o.builder.addFunction(
4481 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),4483 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
4482 try o.builder.strtabStringFmt("__zig_tag_name_{}", .{enum_type.name.fmt(ip)}),4484 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),
4483 toLlvmAddressSpace(.generic, target),4485 toLlvmAddressSpace(.generic, target),
4484 );4486 );
44854487
...@@ -4630,7 +4632,7 @@ pub const NavGen = struct {...@@ -4630,7 +4632,7 @@ pub const NavGen = struct {
4630 if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") {4632 if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") {
4631 if (lib_name.toSlice(ip)) |lib_name_slice| {4633 if (lib_name.toSlice(ip)) |lib_name_slice| {
4632 if (!std.mem.eql(u8, lib_name_slice, "c")) {4634 if (!std.mem.eql(u8, lib_name_slice, "c")) {
4633 break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice });4635 break :decl_name try o.builder.strtabStringFmt("{f}|{s}", .{ nav.name.fmt(ip), lib_name_slice });
4634 }4636 }
4635 }4637 }
4636 }4638 }
...@@ -7469,7 +7471,7 @@ pub const FuncGen = struct {...@@ -7469,7 +7471,7 @@ pub const FuncGen = struct {
7469 llvm_param_types[llvm_param_i] = llvm_elem_ty;7471 llvm_param_types[llvm_param_i] = llvm_elem_ty;
7470 }7472 }
74717473
7472 try llvm_constraints.writer(self.gpa).print(",{d}", .{output_index});7474 try llvm_constraints.print(self.gpa, ",{d}", .{output_index});
74737475
7474 // In the case of indirect inputs, LLVM requires the callsite to have7476 // In the case of indirect inputs, LLVM requires the callsite to have
7475 // an elementtype(<ty>) attribute.7477 // an elementtype(<ty>) attribute.
...@@ -7570,7 +7572,7 @@ pub const FuncGen = struct {...@@ -7570,7 +7572,7 @@ pub const FuncGen = struct {
7570 // we should validate the assembly in Sema; by now it is too late7572 // we should validate the assembly in Sema; by now it is too late
7571 return self.todo("unknown input or output name: '{s}'", .{name});7573 return self.todo("unknown input or output name: '{s}'", .{name});
7572 };7574 };
7573 try rendered_template.writer().print("{d}", .{index});7575 try rendered_template.print("{d}", .{index});
7574 if (byte == ':') {7576 if (byte == ':') {
7575 try rendered_template.append(':');7577 try rendered_template.append(':');
7576 modifier_start = i + 1;7578 modifier_start = i + 1;
...@@ -10377,7 +10379,7 @@ pub const FuncGen = struct {...@@ -10377,7 +10379,7 @@ pub const FuncGen = struct {
10377 const target = &zcu.root_mod.resolved_target.result;10379 const target = &zcu.root_mod.resolved_target.result;
10378 const function_index = try o.builder.addFunction(10380 const function_index = try o.builder.addFunction(
10379 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),10381 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
10380 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{enum_type.name.fmt(ip)}),10382 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),
10381 toLlvmAddressSpace(.generic, target),10383 toLlvmAddressSpace(.generic, target),
10382 );10384 );
1038310385
src/codegen/spirv.zig+9-9
...@@ -817,7 +817,7 @@ const NavGen = struct {...@@ -817,7 +817,7 @@ const NavGen = struct {
817 const result_ty_id = try self.resolveType(ty, repr);817 const result_ty_id = try self.resolveType(ty, repr);
818 const ip = &zcu.intern_pool;818 const ip = &zcu.intern_pool;
819819
820 log.debug("lowering constant: ty = {}, val = {}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });820 log.debug("lowering constant: ty = {f}, val = {f}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
821 if (val.isUndefDeep(zcu)) {821 if (val.isUndefDeep(zcu)) {
822 return self.spv.constUndef(result_ty_id);822 return self.spv.constUndef(result_ty_id);
823 }823 }
...@@ -1147,7 +1147,7 @@ const NavGen = struct {...@@ -1147,7 +1147,7 @@ const NavGen = struct {
1147 return result_ptr_id;1147 return result_ptr_id;
1148 }1148 }
11491149
1150 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{1150 return self.fail("cannot perform pointer cast: '{f}' to '{f}'", .{
1151 parent_ptr_ty.fmt(pt),1151 parent_ptr_ty.fmt(pt),
1152 oac.new_ptr_ty.fmt(pt),1152 oac.new_ptr_ty.fmt(pt),
1153 });1153 });
...@@ -1259,11 +1259,11 @@ const NavGen = struct {...@@ -1259,11 +1259,11 @@ const NavGen = struct {
1259 }1259 }
12601260
1261 // Turn a Zig type's name into a cache reference.1261 // Turn a Zig type's name into a cache reference.
1262 fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 {1262 fn resolveTypeName(self: *NavGen, ty: Type) Allocator.Error![]const u8 {
1263 var name = std.ArrayList(u8).init(self.gpa);1263 var aw: std.io.AllocatingWriter = undefined;
1264 defer name.deinit();1264 aw.init(self.gpa);
1265 try ty.print(name.writer(), self.pt);1265 ty.print(&aw.buffered_writer, self.pt) catch |err| return @errorCast(err);
1266 return try name.toOwnedSlice();1266 return aw.toOwnedSlice();
1267 }1267 }
12681268
1269 /// Create an integer type suitable for storing at least 'bits' bits.1269 /// Create an integer type suitable for storing at least 'bits' bits.
...@@ -1462,7 +1462,7 @@ const NavGen = struct {...@@ -1462,7 +1462,7 @@ const NavGen = struct {
1462 const pt = self.pt;1462 const pt = self.pt;
1463 const zcu = pt.zcu;1463 const zcu = pt.zcu;
1464 const ip = &zcu.intern_pool;1464 const ip = &zcu.intern_pool;
1465 log.debug("resolveType: ty = {}", .{ty.fmt(pt)});1465 log.debug("resolveType: ty = {f}", .{ty.fmt(pt)});
1466 const target = self.spv.target;1466 const target = self.spv.target;
14671467
1468 const section = &self.spv.sections.types_globals_constants;1468 const section = &self.spv.sections.types_globals_constants;
...@@ -3068,7 +3068,7 @@ const NavGen = struct {...@@ -3068,7 +3068,7 @@ const NavGen = struct {
3068 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});3068 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
3069 try self.spv.addFunction(spv_decl_index, self.func);3069 try self.spv.addFunction(spv_decl_index, self.func);
30703070
3071 try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{nav.fqn.fmt(ip)});3071 try self.spv.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
30723072
3073 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{3073 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
3074 .id_result_type = ptr_ty_id,3074 .id_result_type = ptr_ty_id,
src/codegen/spirv/spec.zig+3-8
...@@ -18,15 +18,10 @@ pub const IdResult = enum(Word) {...@@ -18,15 +18,10 @@ pub const IdResult = enum(Word) {
18 none,18 none,
19 _,19 _,
2020
21 pub fn format(21 pub fn format(self: IdResult, bw: *std.io.BufferedWriter, comptime _: []const u8) anyerror!void {
22 self: IdResult,
23 comptime _: []const u8,
24 _: std.fmt.FormatOptions,
25 writer: anytype,
26 ) @TypeOf(writer).Error!void {
27 switch (self) {22 switch (self) {
28 .none => try writer.writeAll("(none)"),23 .none => try bw.writeAll("(none)"),
29 else => try writer.print("%{}", .{@intFromEnum(self)}),24 else => try bw.print("%{}", .{@intFromEnum(self)}),
30 }25 }
31 }26 }
32};27};
src/crash_report.zig+13-12
...@@ -80,18 +80,18 @@ fn dumpStatusReport() !void {...@@ -80,18 +80,18 @@ fn dumpStatusReport() !void {
80 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);80 var fba = std.heap.FixedBufferAllocator.init(&crash_heap);
81 const allocator = fba.allocator();81 const allocator = fba.allocator();
8282
83 const stderr = std.fs.File.stderr.writer().unbuffered();83 var stderr = std.fs.File.stderr().writer().unbuffered();
84 const block: *Sema.Block = anal.block;84 const block: *Sema.Block = anal.block;
85 const zcu = anal.sema.pt.zcu;85 const zcu = anal.sema.pt.zcu;
8686
87 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {87 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {
88 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));88 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));
89 try stderr.print("Analyzing lost instruction in file '{}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});89 try stderr.print("Analyzing lost instruction in file '{f}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});
90 return;90 return;
91 };91 };
9292
93 try stderr.writeAll("Analyzing ");93 try stderr.writeAll("Analyzing ");
94 try stderr.print("Analyzing '{}'\n", .{file.path.fmt(zcu.comp)});94 try stderr.print("Analyzing '{f}'\n", .{file.path.fmt(zcu.comp)});
9595
96 print_zir.renderInstructionContext(96 print_zir.renderInstructionContext(
97 allocator,97 allocator,
...@@ -100,14 +100,14 @@ fn dumpStatusReport() !void {...@@ -100,14 +100,14 @@ fn dumpStatusReport() !void {
100 file,100 file,
101 src_base_node,101 src_base_node,
102 6, // indent102 6, // indent
103 stderr,103 &stderr,
104 ) catch |err| switch (err) {104 ) catch |err| switch (err) {
105 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),105 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),
106 else => |e| return e,106 else => |e| return e,
107 };107 };
108 try stderr.print(108 try stderr.print(
109 \\ For full context, use the command109 \\ For full context, use the command
110 \\ zig ast-check -t {}110 \\ zig ast-check -t {f}
111 \\111 \\
112 \\112 \\
113 , .{file.path.fmt(zcu.comp)});113 , .{file.path.fmt(zcu.comp)});
...@@ -116,7 +116,7 @@ fn dumpStatusReport() !void {...@@ -116,7 +116,7 @@ fn dumpStatusReport() !void {
116 while (parent) |curr| {116 while (parent) |curr| {
117 fba.reset();117 fba.reset();
118 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));118 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));
119 try stderr.print(" in {}\n", .{cur_block_file.path.fmt(zcu.comp)});119 try stderr.print(" in {f}\n", .{cur_block_file.path.fmt(zcu.comp)});
120 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {120 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {
121 try stderr.writeAll(" > [lost instruction; this should not happen]\n");121 try stderr.writeAll(" > [lost instruction; this should not happen]\n");
122 parent = curr.parent;122 parent = curr.parent;
...@@ -129,7 +129,7 @@ fn dumpStatusReport() !void {...@@ -129,7 +129,7 @@ fn dumpStatusReport() !void {
129 cur_block_file,129 cur_block_file,
130 cur_block_src_base_node,130 cur_block_src_base_node,
131 6, // indent131 6, // indent
132 stderr,132 &stderr,
133 ) catch |err| switch (err) {133 ) catch |err| switch (err) {
134 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),134 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),
135 else => |e| return e,135 else => |e| return e,
...@@ -139,7 +139,7 @@ fn dumpStatusReport() !void {...@@ -139,7 +139,7 @@ fn dumpStatusReport() !void {
139 parent = curr.parent;139 parent = curr.parent;
140 }140 }
141141
142 try stderr.writeAll("\n");142 try stderr.writeByte('\n');
143}143}
144144
145var crash_heap: [16 * 4096]u8 = undefined;145var crash_heap: [16 * 4096]u8 = undefined;
...@@ -268,7 +268,8 @@ const StackContext = union(enum) {...@@ -268,7 +268,8 @@ const StackContext = union(enum) {
268 debug.dumpCurrentStackTrace(ct.ret_addr);268 debug.dumpCurrentStackTrace(ct.ret_addr);
269 },269 },
270 .exception => |context| {270 .exception => |context| {
271 debug.dumpStackTraceFromBase(context);271 var stderr = std.fs.File.stderr().writer().unbuffered();
272 debug.dumpStackTraceFromBase(context, &stderr);
272 },273 },
273 .not_supported => {274 .not_supported => {
274 std.fs.File.stderr().writeAll("Stack trace not supported on this platform.\n") catch {};275 std.fs.File.stderr().writeAll("Stack trace not supported on this platform.\n") catch {};
...@@ -378,7 +379,7 @@ const PanicSwitch = struct {...@@ -378,7 +379,7 @@ const PanicSwitch = struct {
378379
379 state.recover_stage = .release_mutex;380 state.recover_stage = .release_mutex;
380381
381 const stderr = std.fs.File.stderr().writer().unbuffered();382 var stderr = std.fs.File.stderr().writer().unbuffered();
382 if (builtin.single_threaded) {383 if (builtin.single_threaded) {
383 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});384 stderr.print("panic: ", .{}) catch goTo(releaseMutex, .{state});
384 } else {385 } else {
...@@ -405,7 +406,7 @@ const PanicSwitch = struct {...@@ -405,7 +406,7 @@ const PanicSwitch = struct {
405 recover(state, trace, stack, msg);406 recover(state, trace, stack, msg);
406407
407 state.recover_stage = .release_mutex;408 state.recover_stage = .release_mutex;
408 const stderr = std.fs.File.stderr().writer().unbuffered();409 var stderr = std.fs.File.stderr().writer().unbuffered();
409 stderr.writeAll("\nOriginal Error:\n") catch {};410 stderr.writeAll("\nOriginal Error:\n") catch {};
410 goTo(reportStack, .{state});411 goTo(reportStack, .{state});
411 }412 }
...@@ -521,7 +522,7 @@ const PanicSwitch = struct {...@@ -521,7 +522,7 @@ const PanicSwitch = struct {
521 var stderr = std.fs.File.stderr().writer().unbuffered();522 var stderr = std.fs.File.stderr().writer().unbuffered();
522 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};523 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
523 stderr.writeAll(msg) catch {};524 stderr.writeAll(msg) catch {};
524 stderr.writeAll("\n") catch {};525 stderr.writeByte('\n') catch {};
525526
526 // If we succeed, restore all the way to dumping the stack.527 // If we succeed, restore all the way to dumping the stack.
527 state.recover_verbosity = .message_and_stack;528 state.recover_verbosity = .message_and_stack;
src/fmt.zig+3-3
...@@ -89,7 +89,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -89,7 +89,7 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
89 fatal("cannot use --stdin with positional arguments", .{});89 fatal("cannot use --stdin with positional arguments", .{});
90 }90 }
9191
92 const source_code = std.zig.readSourceFileToEndAlloc(gpa, .stdin(), null) catch |err| {92 const source_code = std.zig.readSourceFileToEndAlloc(gpa, .stdin(), 0) catch |err| {
93 fatal("unable to read stdin: {}", .{err});93 fatal("unable to read stdin: {}", .{err});
94 };94 };
95 defer gpa.free(source_code);95 defer gpa.free(source_code);
...@@ -134,9 +134,9 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -134,9 +134,9 @@ pub fn run(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
134 process.exit(2);134 process.exit(2);
135 }135 }
136 var aw: std.io.AllocatingWriter = undefined;136 var aw: std.io.AllocatingWriter = undefined;
137 const bw = aw.init(gpa);137 aw.init(gpa);
138 defer aw.deinit();138 defer aw.deinit();
139 try tree.render(gpa, bw, .{});139 try tree.render(gpa, &aw.buffered_writer, .{});
140 const formatted = aw.getWritten();140 const formatted = aw.getWritten();
141141
142 if (check_flag) {142 if (check_flag) {
src/libs/glibc.zig+24-33
...@@ -736,13 +736,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -736,13 +736,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
736 .lt => continue,736 .lt => continue,
737 .gt => {737 .gt => {
738 // TODO Expose via compile error mechanism instead of log.738 // TODO Expose via compile error mechanism instead of log.
739 log.warn("invalid target glibc version: {}", .{target_version});739 log.warn("invalid target glibc version: {f}", .{target_version});
740 return error.InvalidTargetGLibCVersion;740 return error.InvalidTargetGLibCVersion;
741 },741 },
742 }742 }
743 } else blk: {743 } else blk: {
744 const latest_index = metadata.all_versions.len - 1;744 const latest_index = metadata.all_versions.len - 1;
745 log.warn("zig cannot build new glibc version {}; providing instead {}", .{745 log.warn("zig cannot build new glibc version {f}; providing instead {f}", .{
746 target_version, metadata.all_versions[latest_index],746 target_version, metadata.all_versions[latest_index],
747 });747 });
748 break :blk latest_index;748 break :blk latest_index;
...@@ -752,9 +752,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -752,9 +752,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
752 var map_contents = std.ArrayList(u8).init(arena);752 var map_contents = std.ArrayList(u8).init(arena);
753 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {753 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {
754 if (ver.patch == 0) {754 if (ver.patch == 0) {
755 try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });755 try map_contents.print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });
756 } else {756 } else {
757 try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });757 try map_contents.print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });
758 }758 }
759 }759 }
760 try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items });760 try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items });
...@@ -773,7 +773,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -773,7 +773,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
773 try stubs_asm.appendSlice(".text\n");773 try stubs_asm.appendSlice(".text\n");
774774
775 var sym_i: usize = 0;775 var sym_i: usize = 0;
776 var sym_name_buf = std.ArrayList(u8).init(arena);
777 var opt_symbol_name: ?[]const u8 = null;776 var opt_symbol_name: ?[]const u8 = null;
778 var versions_buffer: [32]u8 = undefined;777 var versions_buffer: [32]u8 = undefined;
779 var versions_len: usize = undefined;778 var versions_len: usize = undefined;
...@@ -794,24 +793,20 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -794,24 +793,20 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
794 // twice, which causes a "duplicate symbol" assembler error.793 // twice, which causes a "duplicate symbol" assembler error.
795 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);794 var versions_written = std.AutoArrayHashMap(Version, void).init(arena);
796795
797 var inc_fbs = std.io.fixedBufferStream(metadata.inclusions);796 var inc_br: std.io.BufferedReader = undefined;
798 var inc_reader = inc_fbs.reader();797 inc_br.initFixed(metadata.inclusions);
799798
800 const fn_inclusions_len = try inc_reader.readInt(u16, .little);799 const fn_inclusions_len = try inc_br.takeInt(u16, .little);
801800
802 while (sym_i < fn_inclusions_len) : (sym_i += 1) {801 while (sym_i < fn_inclusions_len) : (sym_i += 1) {
803 const sym_name = opt_symbol_name orelse n: {802 const sym_name = opt_symbol_name orelse n: {
804 sym_name_buf.clearRetainingCapacity();803 opt_symbol_name = try inc_br.takeSentinel(0);
805 try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null);
806
807 opt_symbol_name = sym_name_buf.items;
808 versions_buffer = undefined;804 versions_buffer = undefined;
809 versions_len = 0;805 versions_len = 0;
810806 break :n opt_symbol_name.?;
811 break :n sym_name_buf.items;
812 };807 };
813 const targets = try std.leb.readUleb128(u64, inc_reader);808 const targets = try inc_br.takeLeb128(u64);
814 var lib_index = try inc_reader.readByte();809 var lib_index = try inc_br.takeByte();
815810
816 const is_terminal = (lib_index & (1 << 7)) != 0;811 const is_terminal = (lib_index & (1 << 7)) != 0;
817 if (is_terminal) {812 if (is_terminal) {
...@@ -825,7 +820,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -825,7 +820,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
825 ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0);820 ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0);
826821
827 while (true) {822 while (true) {
828 const byte = try inc_reader.readByte();823 const byte = try inc_br.takeByte();
829 const last = (byte & 0b1000_0000) != 0;824 const last = (byte & 0b1000_0000) != 0;
830 const ver_i = @as(u7, @truncate(byte));825 const ver_i = @as(u7, @truncate(byte));
831 if (ok_lib_and_target and ver_i <= target_ver_index) {826 if (ok_lib_and_target and ver_i <= target_ver_index) {
...@@ -880,7 +875,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -880,7 +875,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
880 "{s}_{d}_{d}",875 "{s}_{d}_{d}",
881 .{ sym_name, ver.major, ver.minor },876 .{ sym_name, ver.major, ver.minor },
882 );877 );
883 try stubs_asm.writer().print(878 try stubs_asm.print(
884 \\.balign {d}879 \\.balign {d}
885 \\.globl {s}880 \\.globl {s}
886 \\.type {s}, %function881 \\.type {s}, %function
...@@ -905,7 +900,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -905,7 +900,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
905 "{s}_{d}_{d}_{d}",900 "{s}_{d}_{d}_{d}",
906 .{ sym_name, ver.major, ver.minor, ver.patch },901 .{ sym_name, ver.major, ver.minor, ver.patch },
907 );902 );
908 try stubs_asm.writer().print(903 try stubs_asm.print(
909 \\.balign {d}904 \\.balign {d}
910 \\.globl {s}905 \\.globl {s}
911 \\.type {s}, %function906 \\.type {s}, %function
...@@ -950,7 +945,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -950,7 +945,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
950 // versions where the symbol didn't exist. We only care about modern glibc versions, so use945 // versions where the symbol didn't exist. We only care about modern glibc versions, so use
951 // a strong reference.946 // a strong reference.
952 if (std.mem.eql(u8, lib.name, "c")) {947 if (std.mem.eql(u8, lib.name, "c")) {
953 try stubs_asm.writer().print(948 try stubs_asm.print(
954 \\.balign {d}949 \\.balign {d}
955 \\.globl _IO_stdin_used950 \\.globl _IO_stdin_used
956 \\{s} _IO_stdin_used951 \\{s} _IO_stdin_used
...@@ -963,7 +958,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -963,7 +958,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
963958
964 try stubs_asm.appendSlice(".data\n");959 try stubs_asm.appendSlice(".data\n");
965960
966 const obj_inclusions_len = try inc_reader.readInt(u16, .little);961 const obj_inclusions_len = try inc_br.takeInt(u16, .little);
967962
968 var sizes = try arena.alloc(u16, metadata.all_versions.len);963 var sizes = try arena.alloc(u16, metadata.all_versions.len);
969964
...@@ -973,18 +968,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -973,18 +968,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
973 versions_len = undefined;968 versions_len = undefined;
974 while (sym_i < obj_inclusions_len) : (sym_i += 1) {969 while (sym_i < obj_inclusions_len) : (sym_i += 1) {
975 const sym_name = opt_symbol_name orelse n: {970 const sym_name = opt_symbol_name orelse n: {
976 sym_name_buf.clearRetainingCapacity();971 opt_symbol_name = try inc_br.takeSentinel(0);
977 try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null);
978
979 opt_symbol_name = sym_name_buf.items;
980 versions_buffer = undefined;972 versions_buffer = undefined;
981 versions_len = 0;973 versions_len = 0;
982974 break :n opt_symbol_name.?;
983 break :n sym_name_buf.items;
984 };975 };
985 const targets = try std.leb.readUleb128(u64, inc_reader);976 const targets = try inc_br.takeLeb128(u64);
986 const size = try std.leb.readUleb128(u16, inc_reader);977 const size = try inc_br.takeLeb128(u16);
987 var lib_index = try inc_reader.readByte();978 var lib_index = try inc_br.takeByte();
988979
989 const is_terminal = (lib_index & (1 << 7)) != 0;980 const is_terminal = (lib_index & (1 << 7)) != 0;
990 if (is_terminal) {981 if (is_terminal) {
...@@ -998,7 +989,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -998,7 +989,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
998 ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0);989 ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0);
999990
1000 while (true) {991 while (true) {
1001 const byte = try inc_reader.readByte();992 const byte = try inc_br.takeByte();
1002 const last = (byte & 0b1000_0000) != 0;993 const last = (byte & 0b1000_0000) != 0;
1003 const ver_i = @as(u7, @truncate(byte));994 const ver_i = @as(u7, @truncate(byte));
1004 if (ok_lib_and_target and ver_i <= target_ver_index) {995 if (ok_lib_and_target and ver_i <= target_ver_index) {
...@@ -1055,7 +1046,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1055,7 +1046,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1055 "{s}_{d}_{d}",1046 "{s}_{d}_{d}",
1056 .{ sym_name, ver.major, ver.minor },1047 .{ sym_name, ver.major, ver.minor },
1057 );1048 );
1058 try stubs_asm.writer().print(1049 try stubs_asm.print(
1059 \\.balign {d}1050 \\.balign {d}
1060 \\.globl {s}1051 \\.globl {s}
1061 \\.type {s}, %object1052 \\.type {s}, %object
...@@ -1083,7 +1074,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1083,7 +1074,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1083 "{s}_{d}_{d}_{d}",1074 "{s}_{d}_{d}_{d}",
1084 .{ sym_name, ver.major, ver.minor, ver.patch },1075 .{ sym_name, ver.major, ver.minor, ver.patch },
1085 );1076 );
1086 try stubs_asm.writer().print(1077 try stubs_asm.print(
1087 \\.balign {d}1078 \\.balign {d}
1088 \\.globl {s}1079 \\.globl {s}
1089 \\.type {s}, %object1080 \\.type {s}, %object
src/libs/mingw.zig+7-7
...@@ -401,7 +401,7 @@ fn findDef(...@@ -401,7 +401,7 @@ fn findDef(
401 };401 };
402402
403 var override_path: std.io.AllocatingWriter = undefined;403 var override_path: std.io.AllocatingWriter = undefined;
404 const override_path_writer = override_path.init(gpa);404 override_path.init(gpa);
405 defer override_path.deinit();405 defer override_path.deinit();
406406
407 const s = path.sep_str;407 const s = path.sep_str;
...@@ -410,9 +410,9 @@ fn findDef(...@@ -410,9 +410,9 @@ fn findDef(
410 // Try the archtecture-specific path first.410 // Try the archtecture-specific path first.
411 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";411 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";
412 if (zig_lib_directory.path) |p| {412 if (zig_lib_directory.path) |p| {
413 try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });413 try override_path.buffered_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });
414 } else {414 } else {
415 try override_path_writer.print(fmt_path, .{ lib_path, lib_name });415 try override_path.buffered_writer.print(fmt_path, .{ lib_path, lib_name });
416 }416 }
417 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {417 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
418 return override_path.toOwnedSlice();418 return override_path.toOwnedSlice();
...@@ -427,9 +427,9 @@ fn findDef(...@@ -427,9 +427,9 @@ fn findDef(
427 override_path.clearRetainingCapacity();427 override_path.clearRetainingCapacity();
428 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";428 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";
429 if (zig_lib_directory.path) |p| {429 if (zig_lib_directory.path) |p| {
430 try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });430 try override_path.buffered_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
431 } else {431 } else {
432 try override_path_writer.print(fmt_path, .{lib_name});432 try override_path.buffered_writer.print(fmt_path, .{lib_name});
433 }433 }
434 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {434 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
435 return override_path.toOwnedSlice();435 return override_path.toOwnedSlice();
...@@ -444,9 +444,9 @@ fn findDef(...@@ -444,9 +444,9 @@ fn findDef(
444 override_path.clearRetainingCapacity();444 override_path.clearRetainingCapacity();
445 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";445 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";
446 if (zig_lib_directory.path) |p| {446 if (zig_lib_directory.path) |p| {
447 try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });447 try override_path.buffered_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
448 } else {448 } else {
449 try override_path_writer.print(fmt_path, .{lib_name});449 try override_path.buffered_writer.print(fmt_path, .{lib_name});
450 }450 }
451 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {451 if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
452 return override_path.toOwnedSlice();452 return override_path.toOwnedSlice();
src/libs/musl.zig+11-13
...@@ -115,7 +115,8 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -115,7 +115,8 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
115 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(comp.gpa);115 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(comp.gpa);
116 defer c_source_files.deinit();116 defer c_source_files.deinit();
117117
118 var override_path = std.ArrayList(u8).init(comp.gpa);118 var override_path: std.io.AllocatingWriter = undefined;
119 override_path.init(comp.gpa);
119 defer override_path.deinit();120 defer override_path.deinit();
120121
121 const s = path.sep_str;122 const s = path.sep_str;
...@@ -139,26 +140,23 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -139,26 +140,23 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
139 }140 }
140 if (!is_arch_specific) {141 if (!is_arch_specific) {
141 // Look for an arch specific override.142 // Look for an arch specific override.
142 override_path.shrinkRetainingCapacity(0);143 override_path.clearRetainingCapacity();
143 try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.s", .{144 try override_path.buffered_writer.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.s", .{
144 dirname, arch_name, noextbasename,145 dirname, arch_name, noextbasename,
145 });146 });
146 if (source_table.contains(override_path.items))147 if (source_table.contains(override_path.getWritten())) continue;
147 continue;
148148
149 override_path.shrinkRetainingCapacity(0);149 override_path.clearRetainingCapacity();
150 try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.S", .{150 try override_path.buffered_writer.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.S", .{
151 dirname, arch_name, noextbasename,151 dirname, arch_name, noextbasename,
152 });152 });
153 if (source_table.contains(override_path.items))153 if (source_table.contains(override_path.getWritten())) continue;
154 continue;
155154
156 override_path.shrinkRetainingCapacity(0);155 override_path.clearRetainingCapacity();
157 try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.c", .{156 try override_path.buffered_writer.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.c", .{
158 dirname, arch_name, noextbasename,157 dirname, arch_name, noextbasename,
159 });158 });
160 if (source_table.contains(override_path.items))159 if (source_table.contains(override_path.getWritten())) continue;
161 continue;
162 }160 }
163161
164 var args = std.ArrayList([]const u8).init(arena);162 var args = std.ArrayList([]const u8).init(arena);
src/link.zig+25-25
...@@ -323,7 +323,7 @@ pub const Diags = struct {...@@ -323,7 +323,7 @@ pub const Diags = struct {
323 const main_msg = try m;323 const main_msg = try m;
324 errdefer gpa.free(main_msg);324 errdefer gpa.free(main_msg);
325 try diags.msgs.ensureUnusedCapacity(gpa, 1);325 try diags.msgs.ensureUnusedCapacity(gpa, 1);
326 const note = try std.fmt.allocPrint(gpa, "while parsing {}", .{path});326 const note = try std.fmt.allocPrint(gpa, "while parsing {f}", .{path});
327 errdefer gpa.free(note);327 errdefer gpa.free(note);
328 const notes = try gpa.create([1]Msg);328 const notes = try gpa.create([1]Msg);
329 errdefer gpa.destroy(notes);329 errdefer gpa.destroy(notes);
...@@ -838,7 +838,7 @@ pub const File = struct {...@@ -838,7 +838,7 @@ pub const File = struct {
838 const cached_pp_file_path = the_key.status.success.object_path;838 const cached_pp_file_path = the_key.status.success.object_path;
839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {839 cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| {
840 const diags = &base.comp.link_diags;840 const diags = &base.comp.link_diags;
841 return diags.fail("failed to copy '{'}' to '{'}': {s}", .{841 return diags.fail("failed to copy '{f'}' to '{f'}': {s}", .{
842 @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err),842 @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err),
843 });843 });
844 };844 };
...@@ -1351,7 +1351,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1351,7 +1351,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1351 .search_strategy = .paths_first,1351 .search_strategy = .paths_first,
1352 }) catch |archive_err| switch (archive_err) {1352 }) catch |archive_err| switch (archive_err) {
1353 error.LinkFailure => return, // error reported via diags1353 error.LinkFailure => return, // error reported via diags
1354 else => |e| diags.addParseError(dso_path, "failed to parse archive {}: {s}", .{ archive_path, @errorName(e) }),1354 else => |e| diags.addParseError(dso_path, "failed to parse archive {f}: {s}", .{ archive_path, @errorName(e) }),
1355 };1355 };
1356 },1356 },
1357 error.LinkFailure => return, // error reported via diags1357 error.LinkFailure => return, // error reported via diags
...@@ -1874,7 +1874,7 @@ pub fn resolveInputs(...@@ -1874,7 +1874,7 @@ pub fn resolveInputs(
1874 )) |lib_result| {1874 )) |lib_result| {
1875 switch (lib_result) {1875 switch (lib_result) {
1876 .ok => {},1876 .ok => {},
1877 .no_match => fatal("{}: file not found", .{pq.path}),1877 .no_match => fatal("{f}: file not found", .{pq.path}),
1878 }1878 }
1879 }1879 }
1880 continue;1880 continue;
...@@ -1928,10 +1928,10 @@ fn resolveLibInput(...@@ -1928,10 +1928,10 @@ fn resolveLibInput(
1928 .root_dir = lib_directory,1928 .root_dir = lib_directory,
1929 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}),1929 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}),
1930 };1930 };
1931 try checked_paths.print(gpa, "\n {}", .{test_path});1931 try checked_paths.print(gpa, "\n {f}", .{test_path});
1932 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1932 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1933 error.FileNotFound => break :tbd,1933 error.FileNotFound => break :tbd,
1934 else => |e| fatal("unable to search for tbd library '{}': {s}", .{ test_path, @errorName(e) }),1934 else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }),
1935 };1935 };
1936 errdefer file.close();1936 errdefer file.close();
1937 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);1937 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
...@@ -1947,7 +1947,7 @@ fn resolveLibInput(...@@ -1947,7 +1947,7 @@ fn resolveLibInput(
1947 },1947 },
1948 }),1948 }),
1949 };1949 };
1950 try checked_paths.print(gpa, "\n {}", .{test_path});1950 try checked_paths.print(gpa, "\n {f}", .{test_path});
1951 switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{1951 switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{
1952 .path = test_path,1952 .path = test_path,
1953 .query = name_query.query,1953 .query = name_query.query,
...@@ -1964,10 +1964,10 @@ fn resolveLibInput(...@@ -1964,10 +1964,10 @@ fn resolveLibInput(
1964 .root_dir = lib_directory,1964 .root_dir = lib_directory,
1965 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}),1965 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}),
1966 };1966 };
1967 try checked_paths.print(gpa, "\n {}", .{test_path});1967 try checked_paths.print(gpa, "\n {f}", .{test_path});
1968 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1968 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1969 error.FileNotFound => break :so,1969 error.FileNotFound => break :so,
1970 else => |e| fatal("unable to search for so library '{}': {s}", .{1970 else => |e| fatal("unable to search for so library '{f}': {s}", .{
1971 test_path, @errorName(e),1971 test_path, @errorName(e),
1972 }),1972 }),
1973 };1973 };
...@@ -1982,10 +1982,10 @@ fn resolveLibInput(...@@ -1982,10 +1982,10 @@ fn resolveLibInput(
1982 .root_dir = lib_directory,1982 .root_dir = lib_directory,
1983 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}),1983 .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}),
1984 };1984 };
1985 try checked_paths.print(gpa, "\n {}", .{test_path});1985 try checked_paths.print(gpa, "\n {f}", .{test_path});
1986 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {1986 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
1987 error.FileNotFound => break :mingw,1987 error.FileNotFound => break :mingw,
1988 else => |e| fatal("unable to search for static library '{}': {s}", .{ test_path, @errorName(e) }),1988 else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }),
1989 };1989 };
1990 errdefer file.close();1990 errdefer file.close();
1991 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);1991 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query);
...@@ -2037,7 +2037,7 @@ fn resolvePathInput(...@@ -2037,7 +2037,7 @@ fn resolvePathInput(
2037 .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color),2037 .shared_library => return try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color),
2038 .object => {2038 .object => {
2039 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|2039 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|
2040 fatal("failed to open object {}: {s}", .{ pq.path, @errorName(err) });2040 fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) });
2041 errdefer file.close();2041 errdefer file.close();
2042 try resolved_inputs.append(gpa, .{ .object = .{2042 try resolved_inputs.append(gpa, .{ .object = .{
2043 .path = pq.path,2043 .path = pq.path,
...@@ -2049,7 +2049,7 @@ fn resolvePathInput(...@@ -2049,7 +2049,7 @@ fn resolvePathInput(
2049 },2049 },
2050 .res => {2050 .res => {
2051 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|2051 var file = pq.path.root_dir.handle.openFile(pq.path.sub_path, .{}) catch |err|
2052 fatal("failed to open windows resource {}: {s}", .{ pq.path, @errorName(err) });2052 fatal("failed to open windows resource {f}: {s}", .{ pq.path, @errorName(err) });
2053 errdefer file.close();2053 errdefer file.close();
2054 try resolved_inputs.append(gpa, .{ .res = .{2054 try resolved_inputs.append(gpa, .{ .res = .{
2055 .path = pq.path,2055 .path = pq.path,
...@@ -2057,7 +2057,7 @@ fn resolvePathInput(...@@ -2057,7 +2057,7 @@ fn resolvePathInput(
2057 } });2057 } });
2058 return null;2058 return null;
2059 },2059 },
2060 else => fatal("{}: unrecognized file extension", .{pq.path}),2060 else => fatal("{f}: unrecognized file extension", .{pq.path}),
2061 }2061 }
2062}2062}
20632063
...@@ -2086,13 +2086,13 @@ fn resolvePathInputLib(...@@ -2086,13 +2086,13 @@ fn resolvePathInputLib(
2086 }) {2086 }) {
2087 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2087 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2088 error.FileNotFound => return .no_match,2088 error.FileNotFound => return .no_match,
2089 else => |e| fatal("unable to search for {s} library '{'}': {s}", .{2089 else => |e| fatal("unable to search for {s} library '{f'}': {s}", .{
2090 @tagName(link_mode), test_path, @errorName(e),2090 @tagName(link_mode), test_path, @errorName(e),
2091 }),2091 }),
2092 };2092 };
2093 errdefer file.close();2093 errdefer file.close();
2094 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));2094 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{'}': {s}", .{2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{
2096 test_path, @errorName(err),2096 test_path, @errorName(err),
2097 });2097 });
2098 const buf = ld_script_bytes.items[0..n];2098 const buf = ld_script_bytes.items[0..n];
...@@ -2101,14 +2101,14 @@ fn resolvePathInputLib(...@@ -2101,14 +2101,14 @@ fn resolvePathInputLib(
2101 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);2101 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2102 }2102 }
2103 const stat = file.stat() catch |err|2103 const stat = file.stat() catch |err|
2104 fatal("failed to stat {}: {s}", .{ test_path, @errorName(err) });2104 fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
2105 const size = std.math.cast(u32, stat.size) orelse2105 const size = std.math.cast(u32, stat.size) orelse
2106 fatal("{}: linker script too big", .{test_path});2106 fatal("{f}: linker script too big", .{test_path});
2107 try ld_script_bytes.resize(gpa, size);2107 try ld_script_bytes.resize(gpa, size);
2108 const buf2 = ld_script_bytes.items[n..];2108 const buf2 = ld_script_bytes.items[n..];
2109 const n2 = file.preadAll(buf2, n) catch |err|2109 const n2 = file.preadAll(buf2, n) catch |err|
2110 fatal("failed to read {}: {s}", .{ test_path, @errorName(err) });2110 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });
2111 if (n2 != buf2.len) fatal("failed to read {}: unexpected end of file", .{test_path});2111 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});
2112 var diags = Diags.init(gpa);2112 var diags = Diags.init(gpa);
2113 defer diags.deinit();2113 defer diags.deinit();
2114 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);2114 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
...@@ -2128,7 +2128,7 @@ fn resolvePathInputLib(...@@ -2128,7 +2128,7 @@ fn resolvePathInputLib(
2128 }2128 }
21292129
2130 var ld_script = ld_script_result catch |err|2130 var ld_script = ld_script_result catch |err|
2131 fatal("{}: failed to parse linker script: {s}", .{ test_path, @errorName(err) });2131 fatal("{f}: failed to parse linker script: {s}", .{ test_path, @errorName(err) });
2132 defer ld_script.deinit(gpa);2132 defer ld_script.deinit(gpa);
21332133
2134 try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len);2134 try unresolved_inputs.ensureUnusedCapacity(gpa, ld_script.args.len);
...@@ -2159,7 +2159,7 @@ fn resolvePathInputLib(...@@ -2159,7 +2159,7 @@ fn resolvePathInputLib(
21592159
2160 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2160 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2161 error.FileNotFound => return .no_match,2161 error.FileNotFound => return .no_match,
2162 else => |e| fatal("unable to search for {s} library {}: {s}", .{2162 else => |e| fatal("unable to search for {s} library {f}: {s}", .{
2163 @tagName(link_mode), test_path, @errorName(e),2163 @tagName(link_mode), test_path, @errorName(e),
2164 }),2164 }),
2165 };2165 };
...@@ -2192,19 +2192,19 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso...@@ -2192,19 +2192,19 @@ pub fn openDso(path: Path, needed: bool, weak: bool, reexport: bool) !Input.Dso
21922192
2193pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input {2193pub fn openObjectInput(diags: *Diags, path: Path) error{LinkFailure}!Input {
2194 return .{ .object = openObject(path, false, false) catch |err| {2194 return .{ .object = openObject(path, false, false) catch |err| {
2195 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2195 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2196 } };2196 } };
2197}2197}
21982198
2199pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {2199pub fn openArchiveInput(diags: *Diags, path: Path, must_link: bool, hidden: bool) error{LinkFailure}!Input {
2200 return .{ .archive = openObject(path, must_link, hidden) catch |err| {2200 return .{ .archive = openObject(path, must_link, hidden) catch |err| {
2201 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2201 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2202 } };2202 } };
2203}2203}
22042204
2205pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {2205pub fn openDsoInput(diags: *Diags, path: Path, needed: bool, weak: bool, reexport: bool) error{LinkFailure}!Input {
2206 return .{ .dso = openDso(path, needed, weak, reexport) catch |err| {2206 return .{ .dso = openDso(path, needed, weak, reexport) catch |err| {
2207 return diags.failParse(path, "failed to open {}: {s}", .{ path, @errorName(err) });2207 return diags.failParse(path, "failed to open {f}: {s}", .{ path, @errorName(err) });
2208 } };2208 } };
2209}2209}
22102210
src/link/Coff.zig+25-32
...@@ -1213,7 +1213,7 @@ fn updateLazySymbolAtom(...@@ -1213,7 +1213,7 @@ fn updateLazySymbolAtom(
1213 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;1213 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
1214 defer code_buffer.deinit(gpa);1214 defer code_buffer.deinit(gpa);
12151215
1216 const name = try allocPrint(gpa, "__lazy_{s}_{}", .{1216 const name = try allocPrint(gpa, "__lazy_{s}_{f}", .{
1217 @tagName(sym.kind),1217 @tagName(sym.kind),
1218 Type.fromInterned(sym.ty).fmt(pt),1218 Type.fromInterned(sym.ty).fmt(pt),
1219 });1219 });
...@@ -1333,7 +1333,7 @@ fn updateNavCode(...@@ -1333,7 +1333,7 @@ fn updateNavCode(
1333 const ip = &zcu.intern_pool;1333 const ip = &zcu.intern_pool;
1334 const nav = ip.getNav(nav_index);1334 const nav = ip.getNav(nav_index);
13351335
1336 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });1336 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13371337
1338 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1338 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1339 const required_alignment = switch (pt.navAlignment(nav_index)) {1339 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -1361,7 +1361,7 @@ fn updateNavCode(...@@ -1361,7 +1361,7 @@ fn updateNavCode(
1361 error.OutOfMemory => return error.OutOfMemory,1361 error.OutOfMemory => return error.OutOfMemory,
1362 else => |e| return coff.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(e)}),1362 else => |e| return coff.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(e)}),
1363 };1363 };
1364 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), sym.value, vaddr });1364 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), sym.value, vaddr });
1365 log.debug(" (required alignment 0x{x}", .{required_alignment});1365 log.debug(" (required alignment 0x{x}", .{required_alignment});
13661366
1367 if (vaddr != sym.value) {1367 if (vaddr != sym.value) {
...@@ -1389,7 +1389,7 @@ fn updateNavCode(...@@ -1389,7 +1389,7 @@ fn updateNavCode(
1389 else => |e| return coff.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(e)}),1389 else => |e| return coff.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(e)}),
1390 };1390 };
1391 errdefer coff.freeAtom(atom_index);1391 errdefer coff.freeAtom(atom_index);
1392 log.debug("allocated atom for {} at 0x{x}", .{ nav.fqn.fmt(ip), vaddr });1392 log.debug("allocated atom for {f} at 0x{x}", .{ nav.fqn.fmt(ip), vaddr });
1393 coff.getAtomPtr(atom_index).size = code_len;1393 coff.getAtomPtr(atom_index).size = code_len;
1394 sym.value = vaddr;1394 sym.value = vaddr;
13951395
...@@ -1454,7 +1454,7 @@ pub fn updateExports(...@@ -1454,7 +1454,7 @@ pub fn updateExports(
14541454
1455 for (export_indices) |export_idx| {1455 for (export_indices) |export_idx| {
1456 const exp = export_idx.ptr(zcu);1456 const exp = export_idx.ptr(zcu);
1457 log.debug("adding new export '{}'", .{exp.opts.name.fmt(&zcu.intern_pool)});1457 log.debug("adding new export '{f}'", .{exp.opts.name.fmt(&zcu.intern_pool)});
14581458
1459 if (exp.opts.section.toSlice(&zcu.intern_pool)) |section_name| {1459 if (exp.opts.section.toSlice(&zcu.intern_pool)) |section_name| {
1460 if (!mem.eql(u8, section_name, ".text")) {1460 if (!mem.eql(u8, section_name, ".text")) {
...@@ -1530,7 +1530,7 @@ pub fn deleteExport(...@@ -1530,7 +1530,7 @@ pub fn deleteExport(
1530 const gpa = coff.base.comp.gpa;1530 const gpa = coff.base.comp.gpa;
1531 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };1531 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };
1532 const sym = coff.getSymbolPtr(sym_loc);1532 const sym = coff.getSymbolPtr(sym_loc);
1533 log.debug("deleting export '{}'", .{name.fmt(&zcu.intern_pool)});1533 log.debug("deleting export '{f}'", .{name.fmt(&zcu.intern_pool)});
1534 assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED);1534 assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED);
1535 sym.* = .{1535 sym.* = .{
1536 .name = [_]u8{0} ** 8,1536 .name = [_]u8{0} ** 8,
...@@ -1748,7 +1748,7 @@ pub fn getNavVAddr(...@@ -1748,7 +1748,7 @@ pub fn getNavVAddr(
1748 const zcu = pt.zcu;1748 const zcu = pt.zcu;
1749 const ip = &zcu.intern_pool;1749 const ip = &zcu.intern_pool;
1750 const nav = ip.getNav(nav_index);1750 const nav = ip.getNav(nav_index);
1751 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });1751 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
1752 const sym_index = if (nav.getExtern(ip)) |e|1752 const sym_index = if (nav.getExtern(ip)) |e|
1753 try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip))1753 try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip))
1754 else1754 else
...@@ -2175,15 +2175,14 @@ fn writeDataDirectoriesHeaders(coff: *Coff) !void {...@@ -2175,15 +2175,14 @@ fn writeDataDirectoriesHeaders(coff: *Coff) !void {
2175fn writeHeader(coff: *Coff) !void {2175fn writeHeader(coff: *Coff) !void {
2176 const target = &coff.base.comp.root_mod.resolved_target.result;2176 const target = &coff.base.comp.root_mod.resolved_target.result;
2177 const gpa = coff.base.comp.gpa;2177 const gpa = coff.base.comp.gpa;
2178 var buffer = std.ArrayList(u8).init(gpa);2178 var bw: std.io.BufferedWriter = undefined;
2179 defer buffer.deinit();2179 bw.initFixed(try gpa.alloc(u8, coff.getSizeOfHeaders()));
2180 const writer = buffer.writer();2180 defer gpa.free(bw.buffer);
21812181
2182 try buffer.ensureTotalCapacity(coff.getSizeOfHeaders());2182 bw.writeAll(&msdos_stub) catch unreachable;
2183 writer.writeAll(&msdos_stub) catch unreachable;2183 mem.writeInt(u32, bw.buffer[0x3c..][0..4], msdos_stub.len, .little);
2184 mem.writeInt(u32, buffer.items[0x3c..][0..4], msdos_stub.len, .little);
21852184
2186 writer.writeAll("PE\x00\x00") catch unreachable;2185 bw.writeAll("PE\x00\x00") catch unreachable;
2187 var flags = coff_util.CoffHeaderFlags{2186 var flags = coff_util.CoffHeaderFlags{
2188 .EXECUTABLE_IMAGE = 1,2187 .EXECUTABLE_IMAGE = 1,
2189 .DEBUG_STRIPPED = 1, // TODO2188 .DEBUG_STRIPPED = 1, // TODO
...@@ -2208,7 +2207,7 @@ fn writeHeader(coff: *Coff) !void {...@@ -2208,7 +2207,7 @@ fn writeHeader(coff: *Coff) !void {
2208 .flags = flags,2207 .flags = flags,
2209 };2208 };
22102209
2211 writer.writeAll(mem.asBytes(&coff_header)) catch unreachable;2210 bw.writeAll(mem.asBytes(&coff_header)) catch unreachable;
22122211
2213 const dll_flags: coff_util.DllFlags = .{2212 const dll_flags: coff_util.DllFlags = .{
2214 .HIGH_ENTROPY_VA = 1, // TODO do we want to permit non-PIE builds at all?2213 .HIGH_ENTROPY_VA = 1, // TODO do we want to permit non-PIE builds at all?
...@@ -2271,7 +2270,7 @@ fn writeHeader(coff: *Coff) !void {...@@ -2271,7 +2270,7 @@ fn writeHeader(coff: *Coff) !void {
2271 .loader_flags = 0,2270 .loader_flags = 0,
2272 .number_of_rva_and_sizes = @intCast(coff.data_directories.len),2271 .number_of_rva_and_sizes = @intCast(coff.data_directories.len),
2273 };2272 };
2274 writer.writeAll(mem.asBytes(&opt_header)) catch unreachable;2273 bw.writeAll(mem.asBytes(&opt_header)) catch unreachable;
2275 },2274 },
2276 .p64 => {2275 .p64 => {
2277 var opt_header = coff_util.OptionalHeaderPE64{2276 var opt_header = coff_util.OptionalHeaderPE64{
...@@ -2305,11 +2304,12 @@ fn writeHeader(coff: *Coff) !void {...@@ -2305,11 +2304,12 @@ fn writeHeader(coff: *Coff) !void {
2305 .loader_flags = 0,2304 .loader_flags = 0,
2306 .number_of_rva_and_sizes = @intCast(coff.data_directories.len),2305 .number_of_rva_and_sizes = @intCast(coff.data_directories.len),
2307 };2306 };
2308 writer.writeAll(mem.asBytes(&opt_header)) catch unreachable;2307 bw.writeAll(mem.asBytes(&opt_header)) catch unreachable;
2309 },2308 },
2310 }2309 }
23112310
2312 try coff.pwriteAll(buffer.items, 0);2311 assert(bw.end == bw.buffer.len);
2312 try coff.pwriteAll(bw.buffer, 0);
2313}2313}
23142314
2315pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {2315pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
...@@ -2605,7 +2605,7 @@ fn logSymtab(coff: *Coff) void {...@@ -2605,7 +2605,7 @@ fn logSymtab(coff: *Coff) void {
2605 }2605 }
26062606
2607 log.debug("GOT entries:", .{});2607 log.debug("GOT entries:", .{});
2608 log.debug("{}", .{coff.got_table});2608 log.debug("{f}", .{coff.got_table});
2609}2609}
26102610
2611fn logSections(coff: *Coff) void {2611fn logSections(coff: *Coff) void {
...@@ -2625,7 +2625,7 @@ fn logImportTables(coff: *const Coff) void {...@@ -2625,7 +2625,7 @@ fn logImportTables(coff: *const Coff) void {
2625 log.debug("import tables:", .{});2625 log.debug("import tables:", .{});
2626 for (coff.import_tables.keys(), 0..) |off, i| {2626 for (coff.import_tables.keys(), 0..) |off, i| {
2627 const itable = coff.import_tables.values()[i];2627 const itable = coff.import_tables.values()[i];
2628 log.debug("{}", .{itable.fmtDebug(.{2628 log.debug("{f}", .{itable.fmtDebug(.{
2629 .coff = coff,2629 .coff = coff,
2630 .index = i,2630 .index = i,
2631 .name_off = off,2631 .name_off = off,
...@@ -3066,27 +3066,20 @@ const ImportTable = struct {...@@ -3066,27 +3066,20 @@ const ImportTable = struct {
3066 ctx: Context,3066 ctx: Context,
3067 };3067 };
30683068
3069 fn format(itab: ImportTable, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {3069 fn format(itab: ImportTable, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
3070 _ = itab;3070 _ = itab;
3071 _ = bw;
3071 _ = unused_format_string;3072 _ = unused_format_string;
3072 _ = options;
3073 _ = writer;
3074 @compileError("do not format ImportTable directly; use itab.fmtDebug()");3073 @compileError("do not format ImportTable directly; use itab.fmtDebug()");
3075 }3074 }
30763075
3077 fn format2(3076 fn format2(fmt_ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
3078 fmt_ctx: FormatContext,
3079 comptime unused_format_string: []const u8,
3080 options: fmt.FormatOptions,
3081 writer: anytype,
3082 ) @TypeOf(writer).Error!void {
3083 _ = options;
3084 comptime assert(unused_format_string.len == 0);3077 comptime assert(unused_format_string.len == 0);
3085 const lib_name = fmt_ctx.ctx.coff.temp_strtab.getAssumeExists(fmt_ctx.ctx.name_off);3078 const lib_name = fmt_ctx.ctx.coff.temp_strtab.getAssumeExists(fmt_ctx.ctx.name_off);
3086 const base_vaddr = getBaseAddress(fmt_ctx.ctx);3079 const base_vaddr = getBaseAddress(fmt_ctx.ctx);
3087 try writer.print("IAT({s}.dll) @{x}:", .{ lib_name, base_vaddr });3080 try bw.print("IAT({s}.dll) @{x}:", .{ lib_name, base_vaddr });
3088 for (fmt_ctx.itab.entries.items, 0..) |entry, i| {3081 for (fmt_ctx.itab.entries.items, 0..) |entry, i| {
3089 try writer.print("\n {d}@{?x} => {s}", .{3082 try bw.print("\n {d}@{?x} => {s}", .{
3090 i,3083 i,
3091 fmt_ctx.itab.getImportAddress(entry, fmt_ctx.ctx),3084 fmt_ctx.itab.getImportAddress(entry, fmt_ctx.ctx),
3092 fmt_ctx.ctx.coff.getSymbolName(entry),3085 fmt_ctx.ctx.coff.getSymbolName(entry),
src/link/Dwarf.zig+797-697
...@@ -132,7 +132,7 @@ const DebugInfo = struct {...@@ -132,7 +132,7 @@ const DebugInfo = struct {
132 return AbbrevCode.decl_bytes + dwarf.sectionOffsetBytes();132 return AbbrevCode.decl_bytes + dwarf.sectionOffsetBytes();
133 }133 }
134134
135 fn declAbbrevCode(debug_info: *DebugInfo, unit: Unit.Index, entry: Entry.Index) !AbbrevCode {135 fn declAbbrevCode(debug_info: *DebugInfo, unit: Unit.Index, entry: Entry.Index) anyerror!AbbrevCode {
136 const dwarf: *Dwarf = @fieldParentPtr("debug_info", debug_info);136 const dwarf: *Dwarf = @fieldParentPtr("debug_info", debug_info);
137 const unit_ptr = debug_info.section.getUnit(unit);137 const unit_ptr = debug_info.section.getUnit(unit);
138 const entry_ptr = unit_ptr.getEntry(entry);138 const entry_ptr = unit_ptr.getEntry(entry);
...@@ -142,8 +142,9 @@ const DebugInfo = struct {...@@ -142,8 +142,9 @@ const DebugInfo = struct {
142 &abbrev_code_buf,142 &abbrev_code_buf,
143 debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,143 debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,
144 ) != abbrev_code_buf.len) return error.InputOutput;144 ) != abbrev_code_buf.len) return error.InputOutput;
145 var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf);145 var abbrev_code_br: std.io.BufferedReader = undefined;
146 return @enumFromInt(std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable);146 abbrev_code_br.initFixed(&abbrev_code_buf);
147 return @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
147 }148 }
148149
149 const trailer_bytes = 1 + 1;150 const trailer_bytes = 1 + 1;
...@@ -226,7 +227,7 @@ const StringSection = struct {...@@ -226,7 +227,7 @@ const StringSection = struct {
226 str_sec.section.deinit(gpa);227 str_sec.section.deinit(gpa);
227 }228 }
228229
229 fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) UpdateError!Entry.Index {230 fn addString(str_sec: *StringSection, dwarf: *Dwarf, str: []const u8) anyerror!Entry.Index {
230 const gop = try str_sec.map.getOrPutAdapted(dwarf.gpa, str, Adapter{ .str_sec = str_sec });231 const gop = try str_sec.map.getOrPutAdapted(dwarf.gpa, str, Adapter{ .str_sec = str_sec });
231 const entry: Entry.Index = @enumFromInt(gop.index);232 const entry: Entry.Index = @enumFromInt(gop.index);
232 if (!gop.found_existing) {233 if (!gop.found_existing) {
...@@ -368,7 +369,7 @@ pub const Section = struct {...@@ -368,7 +369,7 @@ pub const Section = struct {
368 return &sec.units.items[@intFromEnum(unit)];369 return &sec.units.items[@intFromEnum(unit)];
369 }370 }
370371
371 fn resizeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, len: u32) UpdateError!void {372 fn resizeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, len: u32) anyerror!void {
372 const unit_ptr = sec.getUnit(unit);373 const unit_ptr = sec.getUnit(unit);
373 const entry_ptr = unit_ptr.getEntry(entry);374 const entry_ptr = unit_ptr.getEntry(entry);
374 if (len > 0) {375 if (len > 0) {
...@@ -389,13 +390,13 @@ pub const Section = struct {...@@ -389,13 +390,13 @@ pub const Section = struct {
389 assert(entry_ptr.len == len);390 assert(entry_ptr.len == len);
390 }391 }
391392
392 fn replaceEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, contents: []const u8) UpdateError!void {393 fn replaceEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, contents: []const u8) anyerror!void {
393 try sec.resizeEntry(unit, entry, dwarf, @intCast(contents.len));394 try sec.resizeEntry(unit, entry, dwarf, @intCast(contents.len));
394 const unit_ptr = sec.getUnit(unit);395 const unit_ptr = sec.getUnit(unit);
395 try unit_ptr.getEntry(entry).replace(unit_ptr, sec, dwarf, contents);396 try unit_ptr.getEntry(entry).replace(unit_ptr, sec, dwarf, contents);
396 }397 }
397398
398 fn freeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf) UpdateError!void {399 fn freeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf) anyerror!void {
399 const unit_ptr = sec.getUnit(unit);400 const unit_ptr = sec.getUnit(unit);
400 const entry_ptr = unit_ptr.getEntry(entry);401 const entry_ptr = unit_ptr.getEntry(entry);
401 if (entry_ptr.len > 0) {402 if (entry_ptr.len > 0) {
...@@ -648,35 +649,36 @@ const Unit = struct {...@@ -648,35 +649,36 @@ const Unit = struct {
648 assert(len >= unit.trailer_len);649 assert(len >= unit.trailer_len);
649 if (sec == &dwarf.debug_line.section) {650 if (sec == &dwarf.debug_line.section) {
650 var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined;651 var buf: [1 + uleb128Bytes(std.math.maxInt(u32)) + 1]u8 = undefined;
651 var fbs = std.io.fixedBufferStream(&buf);652 var bw: std.io.BufferedWriter = undefined;
652 const writer = fbs.writer();653 bw.initFixed(&buf);
653 writer.writeByte(DW.LNS.extended_op) catch unreachable;654 bw.writeByte(DW.LNS.extended_op) catch unreachable;
654 const extended_op_bytes = fbs.pos;655 const extended_op_bytes = bw.end;
655 var op_len_bytes: u5 = 1;656 var op_len_bytes: u5 = 1;
656 while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {657 while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {
657 .lt => break uleb128(writer, len - extended_op_bytes - op_len_bytes) catch unreachable,658 .lt => break bw.writeLeb128(len - extended_op_bytes - op_len_bytes) catch unreachable,
658 .eq => {659 .eq => {
659 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte660 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
660 op_len_bytes += 1;661 op_len_bytes += 1;
661 std.leb.writeUnsignedExtended(buf[fbs.pos..][0..op_len_bytes], len - extended_op_bytes - op_len_bytes);662 std.leb.writeUnsignedExtended((bw.writableSlice(op_len_bytes) catch unreachable)[0..op_len_bytes], len - extended_op_bytes - op_len_bytes);
662 fbs.pos += op_len_bytes;663 bw.advance(op_len_bytes);
663 break;664 break;
664 },665 },
665 .gt => op_len_bytes += 1,666 .gt => op_len_bytes += 1,
666 };667 };
667 assert(fbs.pos == extended_op_bytes + op_len_bytes);668 assert(bw.end == extended_op_bytes + op_len_bytes);
668 writer.writeByte(DW.LNE.padding) catch unreachable;669 bw.writeByte(DW.LNE.padding) catch unreachable;
669 assert(fbs.pos >= unit.trailer_len and fbs.pos <= len);670 assert(bw.end >= unit.trailer_len and bw.end <= len);
670 return dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + start);671 return dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + start);
671 }672 }
672 var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len);673 var trailer_bw: std.io.BufferedWriter = undefined;
673 defer trailer.deinit();674 trailer_bw.initFixed(try dwarf.gpa.alloc(u8, len));
675 defer dwarf.gpa.free(trailer_bw.buffer);
674 const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: {676 const fill_byte: u8 = if (sec == &dwarf.debug_abbrev.section) fill: {
675 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);677 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);
676 trailer.appendAssumeCapacity(@intFromEnum(AbbrevCode.null));678 trailer_bw.writeByte(@intFromEnum(AbbrevCode.null)) catch unreachable;
677 break :fill @intFromEnum(AbbrevCode.null);679 break :fill @intFromEnum(AbbrevCode.null);
678 } else if (sec == &dwarf.debug_aranges.section) fill: {680 } else if (sec == &dwarf.debug_aranges.section) fill: {
679 trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2);681 trailer_bw.splatByteAll(0, @intFromEnum(dwarf.address_size) * 2) catch unreachable;
680 break :fill 0;682 break :fill 0;
681 } else if (sec == &dwarf.debug_frame.section) fill: {683 } else if (sec == &dwarf.debug_frame.section) fill: {
682 switch (dwarf.debug_frame.header.format) {684 switch (dwarf.debug_frame.header.format) {
...@@ -684,49 +686,49 @@ const Unit = struct {...@@ -684,49 +686,49 @@ const Unit = struct {
684 .debug_frame, .eh_frame => |format| {686 .debug_frame, .eh_frame => |format| {
685 const unit_len = len - dwarf.unitLengthBytes();687 const unit_len = len - dwarf.unitLengthBytes();
686 switch (dwarf.format) {688 switch (dwarf.format) {
687 .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),689 .@"32" => trailer_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
688 .@"64" => {690 .@"64" => {
689 std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);691 trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
690 std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);692 trailer_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
691 },693 },
692 }694 }
693 switch (format) {695 switch (format) {
694 .none => unreachable,696 .none => unreachable,
695 .debug_frame => {697 .debug_frame => {
696 switch (dwarf.format) {698 switch (dwarf.format) {
697 .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian),699 .@"32" => trailer_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable,
698 .@"64" => std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), std.math.maxInt(u64), dwarf.endian),700 .@"64" => trailer_bw.writeInt(u64, std.math.maxInt(u64), dwarf.endian) catch unreachable,
699 }701 }
700 trailer.appendAssumeCapacity(4);702 trailer_bw.writeByte(4) catch unreachable;
701 trailer.appendSliceAssumeCapacity("\x00");703 trailer_bw.writeAll("\x00") catch unreachable;
702 trailer.appendAssumeCapacity(@intFromEnum(dwarf.address_size));704 trailer_bw.writeByte(@intFromEnum(dwarf.address_size)) catch unreachable;
703 trailer.appendAssumeCapacity(0);705 trailer_bw.writeByte(0) catch unreachable;
704 },706 },
705 .eh_frame => {707 .eh_frame => {
706 std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), 0, dwarf.endian);708 trailer_bw.writeInt(u32, 0, dwarf.endian) catch unreachable;
707 trailer.appendAssumeCapacity(1);709 trailer_bw.writeByte(1) catch unreachable;
708 trailer.appendSliceAssumeCapacity("\x00");710 trailer_bw.writeAll("\x00") catch unreachable;
709 },711 },
710 }712 }
711 uleb128(trailer.fixedWriter(), 1) catch unreachable;713 trailer_bw.writeUleb128(1) catch unreachable;
712 sleb128(trailer.fixedWriter(), 1) catch unreachable;714 trailer_bw.writeSleb128(1) catch unreachable;
713 uleb128(trailer.fixedWriter(), 0) catch unreachable;715 trailer_bw.writeUleb128(0) catch unreachable;
714 },716 },
715 }717 }
716 trailer.appendNTimesAssumeCapacity(DW.CFA.nop, unit.trailer_len - trailer.items.len);718 trailer_bw.splatByteAll(DW.CFA.nop, unit.trailer_len - trailer_bw.end) catch unreachable;
717 break :fill DW.CFA.nop;719 break :fill DW.CFA.nop;
718 } else if (sec == &dwarf.debug_info.section) fill: {720 } else if (sec == &dwarf.debug_info.section) fill: {
719 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);721 assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1);
720 trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2);722 trailer_bw.splatByteAll(@intFromEnum(AbbrevCode.null), 2) catch unreachable;
721 break :fill @intFromEnum(AbbrevCode.null);723 break :fill @intFromEnum(AbbrevCode.null);
722 } else if (sec == &dwarf.debug_rnglists.section) fill: {724 } else if (sec == &dwarf.debug_rnglists.section) fill: {
723 trailer.appendAssumeCapacity(DW.RLE.end_of_list);725 trailer_bw.writeByte(DW.RLE.end_of_list) catch unreachable;
724 break :fill DW.RLE.end_of_list;726 break :fill DW.RLE.end_of_list;
725 } else unreachable;727 } else unreachable;
726 assert(trailer.items.len == unit.trailer_len);728 assert(trailer_bw.end == unit.trailer_len);
727 trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len);729 trailer_bw.splatByteAll(fill_byte, len - unit.trailer_len) catch unreachable;
728 assert(trailer.items.len == len);730 assert(trailer_bw.end == len);
729 try dwarf.getFile().?.pwriteAll(trailer.items, sec.off(dwarf) + start);731 try dwarf.getFile().?.pwriteAll(trailer_bw.buffer, sec.off(dwarf) + start);
730 }732 }
731733
732 fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {734 fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
...@@ -805,7 +807,7 @@ const Entry = struct {...@@ -805,7 +807,7 @@ const Entry = struct {
805 }807 }
806 };808 };
807809
808 fn pad(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void {810 fn pad(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) anyerror!void {
809 assert(entry.len > 0);811 assert(entry.len > 0);
810 const start = entry.off + entry.len;812 const start = entry.off + entry.len;
811 if (sec == &dwarf.debug_frame.section) {813 if (sec == &dwarf.debug_frame.section) {
...@@ -833,55 +835,58 @@ const Entry = struct {...@@ -833,55 +835,58 @@ const Entry = struct {
833 1 + uleb128Bytes(std.math.maxInt(u32)) + 1,835 1 + uleb128Bytes(std.math.maxInt(u32)) + 1,
834 )836 )
835 ]u8 = undefined;837 ]u8 = undefined;
836 var fbs = std.io.fixedBufferStream(&buf);838 var bw: std.io.BufferedWriter = undefined;
837 const writer = fbs.writer();839 bw.initFixed(&buf);
838 if (sec == &dwarf.debug_info.section) switch (len) {840 if (sec == &dwarf.debug_info.section) switch (len) {
839 0 => {},841 0 => {},
840 1 => uleb128(writer, try dwarf.refAbbrevCode(.pad_1)) catch unreachable,842 1 => bw.writeLeb128(try dwarf.refAbbrevCode(.pad_1)) catch unreachable,
841 else => {843 else => {
842 uleb128(writer, try dwarf.refAbbrevCode(.pad_n)) catch unreachable;844 bw.writeLeb128(try dwarf.refAbbrevCode(.pad_n)) catch unreachable;
843 const abbrev_code_bytes = fbs.pos;845 const abbrev_code_bytes = bw.end;
844 var block_len_bytes: u5 = 1;846 var block_len_bytes: u5 = 1;
845 while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << 7 * block_len_bytes)) {847 while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << 7 * block_len_bytes)) {
846 .lt => break uleb128(writer, len - abbrev_code_bytes - block_len_bytes) catch unreachable,848 .lt => break bw.writeLeb128(len - abbrev_code_bytes - block_len_bytes) catch unreachable,
847 .eq => {849 .eq => {
848 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte850 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
849 block_len_bytes += 1;851 block_len_bytes += 1;
850 std.leb.writeUnsignedExtended(buf[fbs.pos..][0..block_len_bytes], len - abbrev_code_bytes - block_len_bytes);852 std.leb.writeUnsignedExtended((try bw.writableSlice(block_len_bytes))[0..block_len_bytes], len - abbrev_code_bytes - block_len_bytes);
851 fbs.pos += block_len_bytes;853 bw.advance(block_len_bytes);
852 break;854 break;
853 },855 },
854 .gt => block_len_bytes += 1,856 .gt => block_len_bytes += 1,
855 };857 };
856 assert(fbs.pos == abbrev_code_bytes + block_len_bytes);858 assert(bw.end == abbrev_code_bytes + block_len_bytes);
857 },859 },
858 } else if (sec == &dwarf.debug_line.section) switch (len) {860 } else if (sec == &dwarf.debug_line.section) switch (len) {
859 0 => {},861 0 => {},
860 1 => writer.writeByte(DW.LNS.const_add_pc) catch unreachable,862 1 => bw.writeByte(DW.LNS.const_add_pc) catch unreachable,
861 else => {863 else => {
862 writer.writeByte(DW.LNS.extended_op) catch unreachable;864 bw.writeByte(DW.LNS.extended_op) catch unreachable;
863 const extended_op_bytes = fbs.pos;865 const extended_op_bytes = bw.end;
864 var op_len_bytes: u5 = 1;866 var op_len_bytes: u5 = 1;
865 while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {867 while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) {
866 .lt => break uleb128(writer, len - extended_op_bytes - op_len_bytes) catch unreachable,868 .lt => break bw.writeLeb128(len - extended_op_bytes - op_len_bytes) catch unreachable,
867 .eq => {869 .eq => {
868 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte870 // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte
869 op_len_bytes += 1;871 op_len_bytes += 1;
870 std.leb.writeUnsignedExtended(buf[fbs.pos..][0..op_len_bytes], len - extended_op_bytes - op_len_bytes);872 std.leb.writeUnsignedExtended(
871 fbs.pos += op_len_bytes;873 (bw.writableSlice(op_len_bytes) catch unreachable)[0..op_len_bytes],
874 len - extended_op_bytes - op_len_bytes,
875 );
876 bw.advance(op_len_bytes);
872 break;877 break;
873 },878 },
874 .gt => op_len_bytes += 1,879 .gt => op_len_bytes += 1,
875 };880 };
876 assert(fbs.pos == extended_op_bytes + op_len_bytes);881 assert(bw.end == extended_op_bytes + op_len_bytes);
877 if (len > 2) writer.writeByte(DW.LNE.padding) catch unreachable;882 if (len > 2) bw.writeByte(DW.LNE.padding) catch unreachable;
878 },883 },
879 } else assert(!sec.pad_entries_to_ideal and len == 0);884 } else assert(!sec.pad_entries_to_ideal and len == 0);
880 assert(fbs.pos <= len);885 assert(bw.end <= len);
881 try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start);886 try dwarf.getFile().?.pwriteAll(bw.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start);
882 }887 }
883888
884 fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {889 fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) anyerror!void {
885 assert(len > 0);890 assert(len > 0);
886 assert(sec.alignment.check(len));891 assert(sec.alignment.check(len));
887 if (entry_ptr.len == len) return;892 if (entry_ptr.len == len) return;
...@@ -973,7 +978,7 @@ const Entry = struct {...@@ -973,7 +978,7 @@ const Entry = struct {
973 else978 else
974 .main;979 .main;
975 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)980 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)
976 log.err("missing Type({}({d}))", .{981 log.err("missing Type({f}({d}))", .{
977 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),982 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),
978 @intFromEnum(ty),983 @intFromEnum(ty),
979 });984 });
...@@ -981,7 +986,7 @@ const Entry = struct {...@@ -981,7 +986,7 @@ const Entry = struct {
981 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {986 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {
982 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable;987 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable;
983 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)988 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)
984 log.err("missing Nav({}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });989 log.err("missing Nav({f}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });
985 }990 }
986 }991 }
987 @panic("missing dwarf relocation target");992 @panic("missing dwarf relocation target");
...@@ -1133,150 +1138,149 @@ pub const Loc = union(enum) {...@@ -1133,150 +1138,149 @@ pub const Loc = union(enum) {
1133 };1138 };
1134 }1139 }
11351140
1136 fn writeReg(reg: u32, op0: u8, opx: u8, writer: anytype) @TypeOf(writer).Error!void {1141 fn writeReg(bw: *std.io.BufferedWriter, reg: u32, op0: u8, opx: u8) anyerror!void {
1137 if (std.math.cast(u5, reg)) |small_reg| {1142 if (std.math.cast(u5, reg)) |small_reg| {
1138 try writer.writeByte(op0 + small_reg);1143 try bw.writeByte(op0 + small_reg);
1139 } else {1144 } else {
1140 try writer.writeByte(opx);1145 try bw.writeByte(opx);
1141 try uleb128(writer, reg);1146 try bw.writeLeb128(reg);
1142 }1147 }
1143 }1148 }
11441149
1145 fn write(loc: Loc, adapter: anytype) UpdateError!void {1150 fn write(loc: Loc, bw: *std.io.BufferedWriter, adapter: anytype) anyerror!void {
1146 const writer = adapter.writer();
1147 switch (loc) {1151 switch (loc) {
1148 .empty => {},1152 .empty => {},
1149 .addr_reloc => |sym_index| {1153 .addr_reloc => |sym_index| {
1150 try writer.writeByte(DW.OP.addr);1154 try bw.writeByte(DW.OP.addr);
1151 try adapter.addrSym(sym_index);1155 try adapter.addrSym(sym_index);
1152 },1156 },
1153 .deref => |addr| {1157 .deref => |addr| {
1154 try addr.write(adapter);1158 try addr.write(adapter);
1155 try writer.writeByte(DW.OP.deref);1159 try bw.writeByte(DW.OP.deref);
1156 },1160 },
1157 .constu => |constu| if (std.math.cast(u5, constu)) |lit| {1161 .constu => |constu| if (std.math.cast(u5, constu)) |lit| {
1158 try writer.writeByte(@as(u8, DW.OP.lit0) + lit);1162 try bw.writeByte(@as(u8, DW.OP.lit0) + lit);
1159 } else if (std.math.cast(u8, constu)) |const1u| {1163 } else if (std.math.cast(u8, constu)) |const1u| {
1160 try writer.writeAll(&.{ DW.OP.const1u, const1u });1164 try bw.writeAll(&.{ DW.OP.const1u, const1u });
1161 } else if (std.math.cast(u16, constu)) |const2u| {1165 } else if (std.math.cast(u16, constu)) |const2u| {
1162 try writer.writeByte(DW.OP.const2u);1166 try bw.writeByte(DW.OP.const2u);
1163 try writer.writeInt(u16, const2u, adapter.endian());1167 try bw.writeInt(u16, const2u, adapter.endian());
1164 } else if (std.math.cast(u21, constu)) |const3u| {1168 } else if (std.math.cast(u21, constu)) |const3u| {
1165 try writer.writeByte(DW.OP.constu);1169 try bw.writeByte(DW.OP.constu);
1166 try uleb128(writer, const3u);1170 try bw.writeLeb128(const3u);
1167 } else if (std.math.cast(u32, constu)) |const4u| {1171 } else if (std.math.cast(u32, constu)) |const4u| {
1168 try writer.writeByte(DW.OP.const4u);1172 try bw.writeByte(DW.OP.const4u);
1169 try writer.writeInt(u32, const4u, adapter.endian());1173 try bw.writeInt(u32, const4u, adapter.endian());
1170 } else if (std.math.cast(u49, constu)) |const7u| {1174 } else if (std.math.cast(u49, constu)) |const7u| {
1171 try writer.writeByte(DW.OP.constu);1175 try bw.writeByte(DW.OP.constu);
1172 try uleb128(writer, const7u);1176 try bw.writeLeb128(const7u);
1173 } else {1177 } else {
1174 try writer.writeByte(DW.OP.const8u);1178 try bw.writeByte(DW.OP.const8u);
1175 try writer.writeInt(u64, constu, adapter.endian());1179 try bw.writeInt(u64, constu, adapter.endian());
1176 },1180 },
1177 .consts => |consts| if (std.math.cast(i8, consts)) |const1s| {1181 .consts => |consts| if (std.math.cast(i8, consts)) |const1s| {
1178 try writer.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) });1182 try bw.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) });
1179 } else if (std.math.cast(i16, consts)) |const2s| {1183 } else if (std.math.cast(i16, consts)) |const2s| {
1180 try writer.writeByte(DW.OP.const2s);1184 try bw.writeByte(DW.OP.const2s);
1181 try writer.writeInt(i16, const2s, adapter.endian());1185 try bw.writeInt(i16, const2s, adapter.endian());
1182 } else if (std.math.cast(i21, consts)) |const3s| {1186 } else if (std.math.cast(i21, consts)) |const3s| {
1183 try writer.writeByte(DW.OP.consts);1187 try bw.writeByte(DW.OP.consts);
1184 try sleb128(writer, const3s);1188 try bw.writeLeb128(const3s);
1185 } else if (std.math.cast(i32, consts)) |const4s| {1189 } else if (std.math.cast(i32, consts)) |const4s| {
1186 try writer.writeByte(DW.OP.const4s);1190 try bw.writeByte(DW.OP.const4s);
1187 try writer.writeInt(i32, const4s, adapter.endian());1191 try bw.writeInt(i32, const4s, adapter.endian());
1188 } else if (std.math.cast(i49, consts)) |const7s| {1192 } else if (std.math.cast(i49, consts)) |const7s| {
1189 try writer.writeByte(DW.OP.consts);1193 try bw.writeByte(DW.OP.consts);
1190 try sleb128(writer, const7s);1194 try bw.writeLeb128(const7s);
1191 } else {1195 } else {
1192 try writer.writeByte(DW.OP.const8s);1196 try bw.writeByte(DW.OP.const8s);
1193 try writer.writeInt(i64, consts, adapter.endian());1197 try bw.writeInt(i64, consts, adapter.endian());
1194 },1198 },
1195 .plus => |plus| done: {1199 .plus => |plus| done: {
1196 if (plus[0].getConst(u0)) |_| {1200 if (plus[0].getConst(u0)) |_| {
1197 try plus[1].write(adapter);1201 try plus[1].write(bw, adapter);
1198 break :done;1202 break :done;
1199 }1203 }
1200 if (plus[1].getConst(u0)) |_| {1204 if (plus[1].getConst(u0)) |_| {
1201 try plus[0].write(adapter);1205 try plus[0].write(bw, adapter);
1202 break :done;1206 break :done;
1203 }1207 }
1204 if (plus[0].getBaseReg()) |breg| {1208 if (plus[0].getBaseReg()) |breg| {
1205 if (plus[1].getConst(i65)) |offset| {1209 if (plus[1].getConst(i65)) |offset| {
1206 try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer);1210 try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx);
1207 try sleb128(writer, offset);1211 try bw.writeLeb128(offset);
1208 break :done;1212 break :done;
1209 }1213 }
1210 }1214 }
1211 if (plus[1].getBaseReg()) |breg| {1215 if (plus[1].getBaseReg()) |breg| {
1212 if (plus[0].getConst(i65)) |offset| {1216 if (plus[0].getConst(i65)) |offset| {
1213 try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer);1217 try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx);
1214 try sleb128(writer, offset);1218 try bw.writeLeb128(offset);
1215 break :done;1219 break :done;
1216 }1220 }
1217 }1221 }
1218 if (plus[0].getConst(u64)) |uconst| {1222 if (plus[0].getConst(u64)) |uconst| {
1219 try plus[1].write(adapter);1223 try plus[1].write(bw, adapter);
1220 try writer.writeByte(DW.OP.plus_uconst);1224 try bw.writeByte(DW.OP.plus_uconst);
1221 try uleb128(writer, uconst);1225 try bw.writeLeb128(uconst);
1222 break :done;1226 break :done;
1223 }1227 }
1224 if (plus[1].getConst(u64)) |uconst| {1228 if (plus[1].getConst(u64)) |uconst| {
1225 try plus[0].write(adapter);1229 try plus[0].write(bw, adapter);
1226 try writer.writeByte(DW.OP.plus_uconst);1230 try bw.writeByte(DW.OP.plus_uconst);
1227 try uleb128(writer, uconst);1231 try bw.writeLeb128(uconst);
1228 break :done;1232 break :done;
1229 }1233 }
1230 try plus[0].write(adapter);1234 try plus[0].write(bw, adapter);
1231 try plus[1].write(adapter);1235 try plus[1].write(bw, adapter);
1232 try writer.writeByte(DW.OP.plus);1236 try bw.writeByte(DW.OP.plus);
1233 },1237 },
1234 .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, writer),1238 .reg => |reg| try writeReg(bw, reg, DW.OP.reg0, DW.OP.regx),
1235 .breg => |breg| {1239 .breg => |breg| {
1236 try writeReg(breg, DW.OP.breg0, DW.OP.bregx, writer);1240 try writeReg(bw, breg, DW.OP.breg0, DW.OP.bregx);
1237 try sleb128(writer, 0);1241 try bw.writeSleb128(0);
1238 },1242 },
1239 .push_object_address => try writer.writeByte(DW.OP.push_object_address),1243 .push_object_address => try bw.writeByte(DW.OP.push_object_address),
1240 .call => |call| {1244 .call => |call| {
1241 for (call.args) |arg| try arg.write(adapter);1245 for (call.args) |arg| try arg.write(adapter);
1242 try writer.writeByte(DW.OP.call_ref);1246 try bw.writeByte(DW.OP.call_ref);
1243 try adapter.infoEntry(call.unit, call.entry);1247 try adapter.infoEntry(call.unit, call.entry);
1244 },1248 },
1245 .form_tls_address => |addr| {1249 .form_tls_address => |addr| {
1246 try addr.write(adapter);1250 try addr.write(bw, adapter);
1247 try writer.writeByte(DW.OP.form_tls_address);1251 try bw.writeByte(DW.OP.form_tls_address);
1248 },1252 },
1249 .implicit_value => |value| {1253 .implicit_value => |value| {
1250 try writer.writeByte(DW.OP.implicit_value);1254 try bw.writeByte(DW.OP.implicit_value);
1251 try uleb128(writer, value.len);1255 try bw.writeLeb128(value.len);
1252 try writer.writeAll(value);1256 try bw.writeAll(value);
1253 },1257 },
1254 .stack_value => |value| {1258 .stack_value => |value| {
1255 try value.write(adapter);1259 try value.write(bw, adapter);
1256 try writer.writeByte(DW.OP.stack_value);1260 try bw.writeByte(DW.OP.stack_value);
1257 },1261 },
1258 .implicit_pointer => |implicit_pointer| {1262 .implicit_pointer => |implicit_pointer| {
1259 try writer.writeByte(DW.OP.implicit_pointer);1263 try bw.writeByte(DW.OP.implicit_pointer);
1260 try adapter.infoEntry(implicit_pointer.unit, implicit_pointer.entry);1264 try adapter.infoEntry(bw, implicit_pointer.unit, implicit_pointer.entry);
1261 try sleb128(writer, implicit_pointer.offset);1265 try bw.writeLeb128(implicit_pointer.offset);
1262 },1266 },
1263 .wasm_ext => |wasm_ext| {1267 .wasm_ext => |wasm_ext| {
1264 try writer.writeByte(DW.OP.WASM_location);1268 try bw.writeByte(DW.OP.WASM_location);
1265 switch (wasm_ext) {1269 switch (wasm_ext) {
1266 .local => |local| {1270 .local => |local| {
1267 try writer.writeByte(DW.OP.WASM_local);1271 try bw.writeByte(DW.OP.WASM_local);
1268 try uleb128(writer, local);1272 try bw.writeLeb128(local);
1269 },1273 },
1270 .global => |global| if (std.math.cast(u21, global)) |global_u21| {1274 .global => |global| if (std.math.cast(u21, global)) |global_u21| {
1271 try writer.writeByte(DW.OP.WASM_global);1275 try bw.writeByte(DW.OP.WASM_global);
1272 try uleb128(writer, global_u21);1276 try bw.writeLeb128(global_u21);
1273 } else {1277 } else {
1274 try writer.writeByte(DW.OP.WASM_global_u32);1278 try bw.writeByte(DW.OP.WASM_global_u32);
1275 try writer.writeInt(u32, global, adapter.endian());1279 try bw.writeInt(u32, global, adapter.endian());
1276 },1280 },
1277 .operand_stack => |operand_stack| {1281 .operand_stack => |operand_stack| {
1278 try writer.writeByte(DW.OP.WASM_operand_stack);1282 try bw.writeByte(DW.OP.WASM_operand_stack);
1279 try uleb128(writer, operand_stack);1283 try bw.writeLeb128(operand_stack);
1280 },1284 },
1281 }1285 }
1282 },1286 },
...@@ -1308,22 +1312,22 @@ pub const Cfa = union(enum) {...@@ -1308,22 +1312,22 @@ pub const Cfa = union(enum) {
1308 const RegOff = struct { reg: u32, off: i64 };1312 const RegOff = struct { reg: u32, off: i64 };
1309 const RegExpr = struct { reg: u32, expr: Loc };1313 const RegExpr = struct { reg: u32, expr: Loc };
13101314
1311 fn write(cfa: Cfa, wip_nav: *WipNav) UpdateError!void {1315 fn write(cfa: Cfa, wip_nav: *WipNav) anyerror!void {
1312 const writer = wip_nav.debug_frame.writer(wip_nav.dwarf.gpa);1316 const bw = &wip_nav.debug_frame.buffered_writer;
1313 switch (cfa) {1317 switch (cfa) {
1314 .nop => try writer.writeByte(DW.CFA.nop),1318 .nop => try bw.writeByte(DW.CFA.nop),
1315 .advance_loc => |loc| {1319 .advance_loc => |loc| {
1316 const delta = @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.debug_frame.header.code_alignment_factor);1320 const delta = @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.debug_frame.header.code_alignment_factor);
1317 if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta|1321 if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta|
1318 try writer.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta)1322 try bw.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta)
1319 else if (std.math.cast(u8, delta)) |ubyte_delta|1323 else if (std.math.cast(u8, delta)) |ubyte_delta|
1320 try writer.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta })1324 try bw.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta })
1321 else if (std.math.cast(u16, delta)) |uhalf_delta| {1325 else if (std.math.cast(u16, delta)) |uhalf_delta| {
1322 try writer.writeByte(DW.CFA.advance_loc2);1326 try bw.writeByte(DW.CFA.advance_loc2);
1323 try writer.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian);1327 try bw.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian);
1324 } else if (std.math.cast(u32, delta)) |uword_delta| {1328 } else if (std.math.cast(u32, delta)) |uword_delta| {
1325 try writer.writeByte(DW.CFA.advance_loc4);1329 try bw.writeByte(DW.CFA.advance_loc4);
1326 try writer.writeInt(u32, uword_delta, wip_nav.dwarf.endian);1330 try bw.writeInt(u32, uword_delta, wip_nav.dwarf.endian);
1327 }1331 }
1328 wip_nav.cfi.loc = loc;1332 wip_nav.cfi.loc = loc;
1329 },1333 },
...@@ -1335,41 +1339,41 @@ pub const Cfa = union(enum) {...@@ -1335,41 +1339,41 @@ pub const Cfa = union(enum) {
1335 }, wip_nav.dwarf.debug_frame.header.data_alignment_factor);1339 }, wip_nav.dwarf.debug_frame.header.data_alignment_factor);
1336 if (std.math.cast(u63, factored_off)) |unsigned_off| {1340 if (std.math.cast(u63, factored_off)) |unsigned_off| {
1337 if (std.math.cast(u6, reg_off.reg)) |small_reg| {1341 if (std.math.cast(u6, reg_off.reg)) |small_reg| {
1338 try writer.writeByte(@as(u8, DW.CFA.offset) + small_reg);1342 try bw.writeByte(@as(u8, DW.CFA.offset) + small_reg);
1339 } else {1343 } else {
1340 try writer.writeByte(DW.CFA.offset_extended);1344 try bw.writeByte(DW.CFA.offset_extended);
1341 try uleb128(writer, reg_off.reg);1345 try bw.writeLeb128(reg_off.reg);
1342 }1346 }
1343 try uleb128(writer, unsigned_off);1347 try bw.writeLeb128(unsigned_off);
1344 } else {1348 } else {
1345 try writer.writeByte(DW.CFA.offset_extended_sf);1349 try bw.writeByte(DW.CFA.offset_extended_sf);
1346 try uleb128(writer, reg_off.reg);1350 try bw.writeLeb128(reg_off.reg);
1347 try sleb128(writer, factored_off);1351 try bw.writeLeb128(factored_off);
1348 }1352 }
1349 },1353 },
1350 .restore => |reg| if (std.math.cast(u6, reg)) |small_reg|1354 .restore => |reg| if (std.math.cast(u6, reg)) |small_reg|
1351 try writer.writeByte(@as(u8, DW.CFA.restore) + small_reg)1355 try bw.writeByte(@as(u8, DW.CFA.restore) + small_reg)
1352 else {1356 else {
1353 try writer.writeByte(DW.CFA.restore_extended);1357 try bw.writeByte(DW.CFA.restore_extended);
1354 try uleb128(writer, reg);1358 try bw.writeLeb128(reg);
1355 },1359 },
1356 .undefined => |reg| {1360 .undefined => |reg| {
1357 try writer.writeByte(DW.CFA.undefined);1361 try bw.writeByte(DW.CFA.undefined);
1358 try uleb128(writer, reg);1362 try bw.writeLeb128(reg);
1359 },1363 },
1360 .same_value => |reg| {1364 .same_value => |reg| {
1361 try writer.writeByte(DW.CFA.same_value);1365 try bw.writeByte(DW.CFA.same_value);
1362 try uleb128(writer, reg);1366 try bw.writeLeb128(reg);
1363 },1367 },
1364 .register => |regs| if (regs[0] != regs[1]) {1368 .register => |regs| if (regs[0] != regs[1]) {
1365 try writer.writeByte(DW.CFA.register);1369 try bw.writeByte(DW.CFA.register);
1366 for (regs) |reg| try uleb128(writer, reg);1370 for (regs) |reg| try bw.writeLeb128(reg);
1367 } else {1371 } else {
1368 try writer.writeByte(DW.CFA.same_value);1372 try bw.writeByte(DW.CFA.same_value);
1369 try uleb128(writer, regs[0]);1373 try bw.writeLeb128(regs[0]);
1370 },1374 },
1371 .remember_state => try writer.writeByte(DW.CFA.remember_state),1375 .remember_state => try bw.writeByte(DW.CFA.remember_state),
1372 .restore_state => try writer.writeByte(DW.CFA.restore_state),1376 .restore_state => try bw.writeByte(DW.CFA.restore_state),
1373 .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => {1377 .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => {
1374 const reg_off: RegOff = switch (cfa) {1378 const reg_off: RegOff = switch (cfa) {
1375 else => unreachable,1379 else => unreachable,
...@@ -1382,51 +1386,51 @@ pub const Cfa = union(enum) {...@@ -1382,51 +1386,51 @@ pub const Cfa = union(enum) {
1382 const unsigned_off = std.math.cast(u63, reg_off.off);1386 const unsigned_off = std.math.cast(u63, reg_off.off);
1383 if (reg_off.off == wip_nav.cfi.cfa.off) {1387 if (reg_off.off == wip_nav.cfi.cfa.off) {
1384 if (changed_reg) {1388 if (changed_reg) {
1385 try writer.writeByte(DW.CFA.def_cfa_register);1389 try bw.writeByte(DW.CFA.def_cfa_register);
1386 try uleb128(writer, reg_off.reg);1390 try bw.writeLeb128(reg_off.reg);
1387 }1391 }
1388 } else if (switch (wip_nav.dwarf.debug_frame.header.data_alignment_factor) {1392 } else if (switch (wip_nav.dwarf.debug_frame.header.data_alignment_factor) {
1389 0 => unreachable,1393 0 => unreachable,
1390 1 => unsigned_off != null,1394 1 => unsigned_off != null,
1391 else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0,1395 else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0,
1392 }) {1396 }) {
1393 try writer.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset);1397 try bw.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset);
1394 if (changed_reg) try uleb128(writer, reg_off.reg);1398 if (changed_reg) try bw.writeLeb128(reg_off.reg);
1395 try uleb128(writer, unsigned_off.?);1399 try bw.writeLeb128(unsigned_off.?);
1396 } else {1400 } else {
1397 try writer.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf);1401 try bw.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf);
1398 if (changed_reg) try uleb128(writer, reg_off.reg);1402 if (changed_reg) try bw.writeLeb128(reg_off.reg);
1399 try sleb128(writer, @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor));1403 try bw.writeLeb128(@divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor));
1400 }1404 }
1401 wip_nav.cfi.cfa = reg_off;1405 wip_nav.cfi.cfa = reg_off;
1402 },1406 },
1403 .def_cfa_expression => |expr| {1407 .def_cfa_expression => |expr| {
1404 try writer.writeByte(DW.CFA.def_cfa_expression);1408 try bw.writeByte(DW.CFA.def_cfa_expression);
1405 try wip_nav.frameExprLoc(expr);1409 try wip_nav.frameExprLoc(expr);
1406 },1410 },
1407 .expression => |reg_expr| {1411 .expression => |reg_expr| {
1408 try writer.writeByte(DW.CFA.expression);1412 try bw.writeByte(DW.CFA.expression);
1409 try uleb128(writer, reg_expr.reg);1413 try bw.writeLeb128(reg_expr.reg);
1410 try wip_nav.frameExprLoc(reg_expr.expr);1414 try wip_nav.frameExprLoc(reg_expr.expr);
1411 },1415 },
1412 .val_offset => |reg_off| {1416 .val_offset => |reg_off| {
1413 const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor);1417 const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor);
1414 if (std.math.cast(u63, factored_off)) |unsigned_off| {1418 if (std.math.cast(u63, factored_off)) |unsigned_off| {
1415 try writer.writeByte(DW.CFA.val_offset);1419 try bw.writeByte(DW.CFA.val_offset);
1416 try uleb128(writer, reg_off.reg);1420 try bw.writeLeb128(reg_off.reg);
1417 try uleb128(writer, unsigned_off);1421 try bw.writeLeb128(unsigned_off);
1418 } else {1422 } else {
1419 try writer.writeByte(DW.CFA.val_offset_sf);1423 try bw.writeByte(DW.CFA.val_offset_sf);
1420 try uleb128(writer, reg_off.reg);1424 try bw.writeLeb128(reg_off.reg);
1421 try sleb128(writer, factored_off);1425 try bw.writeLeb128(factored_off);
1422 }1426 }
1423 },1427 },
1424 .val_expression => |reg_expr| {1428 .val_expression => |reg_expr| {
1425 try writer.writeByte(DW.CFA.val_expression);1429 try bw.writeByte(DW.CFA.val_expression);
1426 try uleb128(writer, reg_expr.reg);1430 try bw.writeLeb128(reg_expr.reg);
1427 try wip_nav.frameExprLoc(reg_expr.expr);1431 try wip_nav.frameExprLoc(reg_expr.expr);
1428 },1432 },
1429 .escape => |bytes| try writer.writeAll(bytes),1433 .escape => |bytes| try bw.writeAll(bytes),
1430 }1434 }
1431 }1435 }
1432};1436};
...@@ -1449,19 +1453,27 @@ pub const WipNav = struct {...@@ -1449,19 +1453,27 @@ pub const WipNav = struct {
1449 loc: u32,1453 loc: u32,
1450 cfa: Cfa.RegOff,1454 cfa: Cfa.RegOff,
1451 },1455 },
1452 debug_frame: std.ArrayListUnmanaged(u8),1456 debug_frame: std.io.AllocatingWriter,
1453 debug_info: std.ArrayListUnmanaged(u8),1457 debug_info: std.io.AllocatingWriter,
1454 debug_line: std.ArrayListUnmanaged(u8),1458 debug_line: std.io.AllocatingWriter,
1455 debug_loclists: std.ArrayListUnmanaged(u8),1459 debug_loclists: std.io.AllocatingWriter,
1456 pending_lazy: PendingLazy,1460 pending_lazy: PendingLazy,
14571461
1462 pub fn init(wip_nav: *WipNav) void {
1463 const gpa = wip_nav.dwarf.gpa;
1464 wip_nav.debug_frame.init(gpa);
1465 wip_nav.debug_info.init(gpa);
1466 wip_nav.debug_line.init(gpa);
1467 wip_nav.debug_loclists.init(gpa);
1468 }
1469
1458 pub fn deinit(wip_nav: *WipNav) void {1470 pub fn deinit(wip_nav: *WipNav) void {
1459 const gpa = wip_nav.dwarf.gpa;1471 const gpa = wip_nav.dwarf.gpa;
1460 if (wip_nav.func != .none) wip_nav.blocks.deinit(gpa);1472 if (wip_nav.func != .none) wip_nav.blocks.deinit(gpa);
1461 wip_nav.debug_frame.deinit(gpa);1473 wip_nav.debug_frame.deinit();
1462 wip_nav.debug_info.deinit(gpa);1474 wip_nav.debug_info.deinit();
1463 wip_nav.debug_line.deinit(gpa);1475 wip_nav.debug_line.deinit();
1464 wip_nav.debug_loclists.deinit(gpa);1476 wip_nav.debug_loclists.deinit();
1465 wip_nav.pending_lazy.types.deinit(gpa);1477 wip_nav.pending_lazy.types.deinit(gpa);
1466 wip_nav.pending_lazy.values.deinit(gpa);1478 wip_nav.pending_lazy.values.deinit(gpa);
1467 }1479 }
...@@ -1470,8 +1482,8 @@ pub const WipNav = struct {...@@ -1470,8 +1482,8 @@ pub const WipNav = struct {
1470 assert(wip_nav.func != .none);1482 assert(wip_nav.func != .none);
1471 if (wip_nav.dwarf.debug_frame.header.format == .none) return;1483 if (wip_nav.dwarf.debug_frame.header.format == .none) return;
1472 const loc_cfa: Cfa = .{ .advance_loc = loc };1484 const loc_cfa: Cfa = .{ .advance_loc = loc };
1473 try loc_cfa.write(wip_nav);1485 loc_cfa.write(wip_nav) catch |err| return @errorCast(err);
1474 try cfa.write(wip_nav);1486 cfa.write(wip_nav) catch |err| return @errorCast(err);
1475 }1487 }
14761488
1477 pub const LocalVarTag = enum { arg, local_var };1489 pub const LocalVarTag = enum { arg, local_var };
...@@ -1529,7 +1541,7 @@ pub const WipNav = struct {...@@ -1529,7 +1541,7 @@ pub const WipNav = struct {
15291541
1530 pub fn genVarArgsDebugInfo(wip_nav: *WipNav) UpdateError!void {1542 pub fn genVarArgsDebugInfo(wip_nav: *WipNav) UpdateError!void {
1531 assert(wip_nav.func != .none);1543 assert(wip_nav.func != .none);
1532 try wip_nav.abbrevCode(.is_var_args);1544 wip_nav.abbrevCode(.is_var_args) catch |err| return @errorCast(err);
1533 wip_nav.any_children = true;1545 wip_nav.any_children = true;
1534 }1546 }
15351547
...@@ -1538,7 +1550,7 @@ pub const WipNav = struct {...@@ -1538,7 +1550,7 @@ pub const WipNav = struct {
1538 delta_line: i33,1550 delta_line: i33,
1539 delta_pc: u64,1551 delta_pc: u64,
1540 ) error{OutOfMemory}!void {1552 ) error{OutOfMemory}!void {
1541 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1553 const dlbw = &wip_nav.debug_line.buffered_writer;
15421554
1543 const header = wip_nav.dwarf.debug_line.header;1555 const header = wip_nav.dwarf.debug_line.header;
1544 assert(header.maximum_operations_per_instruction == 1);1556 assert(header.maximum_operations_per_instruction == 1);
...@@ -1548,8 +1560,8 @@ pub const WipNav = struct {...@@ -1548,8 +1560,8 @@ pub const WipNav = struct {
1548 delta_line - header.line_base >= header.line_range)1560 delta_line - header.line_base >= header.line_range)
1549 remaining: {1561 remaining: {
1550 assert(delta_line != 0);1562 assert(delta_line != 0);
1551 try dlw.writeByte(DW.LNS.advance_line);1563 dlbw.writeByte(DW.LNS.advance_line) catch |err| return @errorCast(err);
1552 try sleb128(dlw, delta_line);1564 dlbw.writeLeb128(delta_line) catch |err| return @errorCast(err);
1553 break :remaining 0;1565 break :remaining 0;
1554 } else delta_line);1566 } else delta_line);
15551567
...@@ -1557,68 +1569,68 @@ pub const WipNav = struct {...@@ -1557,68 +1569,68 @@ pub const WipNav = struct {
1557 header.maximum_operations_per_instruction + delta_op;1569 header.maximum_operations_per_instruction + delta_op;
1558 const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range;1570 const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range;
1559 const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: {1571 const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: {
1560 try dlw.writeByte(DW.LNS.advance_pc);1572 dlbw.writeByte(DW.LNS.advance_pc) catch |err| return @errorCast(err);
1561 try uleb128(dlw, op_advance);1573 dlbw.writeLeb128(op_advance) catch |err| return @errorCast(err);
1562 break :remaining 0;1574 break :remaining 0;
1563 } else if (op_advance >= max_op_advance) remaining: {1575 } else if (op_advance >= max_op_advance) remaining: {
1564 try dlw.writeByte(DW.LNS.const_add_pc);1576 dlbw.writeByte(DW.LNS.const_add_pc) catch |err| return @errorCast(err);
1565 break :remaining op_advance - max_op_advance;1577 break :remaining op_advance - max_op_advance;
1566 } else op_advance);1578 } else op_advance);
15671579
1568 if (remaining_delta_line == 0 and remaining_op_advance == 0)1580 dlbw.writeByte(
1569 try dlw.writeByte(DW.LNS.copy)1581 if (remaining_delta_line == 0 and remaining_op_advance == 0)
1570 else1582 DW.LNS.copy
1571 try dlw.writeByte(@intCast((remaining_delta_line - header.line_base) +1583 else
1572 (header.line_range * remaining_op_advance) + header.opcode_base));1584 @intCast((remaining_delta_line - header.line_base) +
1585 (header.line_range * remaining_op_advance) + header.opcode_base),
1586 ) catch |err| return @errorCast(err);
1573 }1587 }
15741588
1575 pub fn setColumn(wip_nav: *WipNav, column: u32) error{OutOfMemory}!void {1589 pub fn setColumn(wip_nav: *WipNav, column: u32) std.mem.Allocator.Error!void {
1576 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1590 const dlbw = &wip_nav.debug_line.buffered_writer;
1577 try dlw.writeByte(DW.LNS.set_column);1591 dlbw.writeByte(DW.LNS.set_column) catch |err| return @errorCast(err);
1578 try uleb128(dlw, column + 1);1592 dlbw.writeLeb128(column + 1) catch |err| return @errorCast(err);
1579 }1593 }
15801594
1581 pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void {1595 pub fn negateStmt(wip_nav: *WipNav) std.mem.Allocator.Error!void {
1582 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1596 return @errorCast(wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.negate_stmt));
1583 try dlw.writeByte(DW.LNS.negate_stmt);
1584 }1597 }
15851598
1586 pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void {1599 pub fn setPrologueEnd(wip_nav: *WipNav) std.mem.Allocator.Error!void {
1587 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1600 return @errorCast(wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_prologue_end));
1588 try dlw.writeByte(DW.LNS.set_prologue_end);
1589 }1601 }
15901602
1591 pub fn setEpilogueBegin(wip_nav: *WipNav) error{OutOfMemory}!void {1603 pub fn setEpilogueBegin(wip_nav: *WipNav) std.mem.Allocator.Error!void {
1592 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1604 return @errorCast(wip_nav.debug_line.buffered_writer.writeByte(DW.LNS.set_epilogue_begin));
1593 try dlw.writeByte(DW.LNS.set_epilogue_begin);
1594 }1605 }
15951606
1596 pub fn enterBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void {1607 pub fn enterBlock(wip_nav: *WipNav, code_off: u64) anyerror!void {
1597 const dwarf = wip_nav.dwarf;1608 const dwarf = wip_nav.dwarf;
1598 const diw = wip_nav.debug_info.writer(dwarf.gpa);1609 const dibw = &wip_nav.debug_info.buffered_writer;
1599 const block = try wip_nav.blocks.addOne(dwarf.gpa);1610 const block = try wip_nav.blocks.addOne(dwarf.gpa);
16001611
1601 block.abbrev_code = @intCast(wip_nav.debug_info.items.len);1612 block.abbrev_code = @intCast(dibw.count);
1602 try wip_nav.abbrevCode(.block);1613 try wip_nav.abbrevCode(.block);
1603 block.low_pc_off = code_off;1614 block.low_pc_off = code_off;
1604 try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off);1615 try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off);
1605 block.high_pc = @intCast(wip_nav.debug_info.items.len);1616 block.high_pc = @intCast(dibw.count);
1606 try diw.writeInt(u32, 0, dwarf.endian);1617 try dibw.writeInt(u32, 0, dwarf.endian);
1607 wip_nav.any_children = false;1618 wip_nav.any_children = false;
1608 }1619 }
16091620
1610 pub fn leaveBlock(wip_nav: *WipNav, code_off: u64) UpdateError!void {1621 pub fn leaveBlock(wip_nav: *WipNav, code_off: u64) anyerror!void {
1611 const block_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.block));1622 const block_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.block));
1612 const block = wip_nav.blocks.pop().?;1623 const block = wip_nav.blocks.pop().?;
1624 const dib = wip_nav.debug_info.getWritten();
1613 if (wip_nav.any_children)1625 if (wip_nav.any_children)
1614 try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null))1626 try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null))
1615 else1627 else
1616 std.leb.writeUnsignedFixed(1628 std.leb.writeUnsignedFixed(
1617 block_bytes,1629 block_bytes,
1618 wip_nav.debug_info.items[block.abbrev_code..][0..block_bytes],1630 dib[block.abbrev_code..][0..block_bytes],
1619 try wip_nav.dwarf.refAbbrevCode(.empty_block),1631 try wip_nav.dwarf.refAbbrevCode(.empty_block),
1620 );1632 );
1621 std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);1633 std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);
1622 wip_nav.any_children = true;1634 wip_nav.any_children = true;
1623 }1635 }
16241636
...@@ -1628,42 +1640,43 @@ pub const WipNav = struct {...@@ -1628,42 +1640,43 @@ pub const WipNav = struct {
1628 code_off: u64,1640 code_off: u64,
1629 line: u32,1641 line: u32,
1630 column: u32,1642 column: u32,
1631 ) UpdateError!void {1643 ) anyerror!void {
1632 const dwarf = wip_nav.dwarf;1644 const dwarf = wip_nav.dwarf;
1633 const zcu = wip_nav.pt.zcu;1645 const zcu = wip_nav.pt.zcu;
1634 const diw = wip_nav.debug_info.writer(dwarf.gpa);1646 const dibw = &wip_nav.debug_info.buffered_writer;
1635 const block = try wip_nav.blocks.addOne(dwarf.gpa);1647 const block = try wip_nav.blocks.addOne(dwarf.gpa);
16361648
1637 block.abbrev_code = @intCast(wip_nav.debug_info.items.len);1649 block.abbrev_code = @intCast(dibw.count);
1638 try wip_nav.abbrevCode(.inlined_func);1650 try wip_nav.abbrevCode(.inlined_func);
1639 try wip_nav.refNav(zcu.funcInfo(func).owner_nav);1651 try wip_nav.refNav(zcu.funcInfo(func).owner_nav);
1640 try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);1652 try dibw.writeLeb128(zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);
1641 try uleb128(diw, column + 1);1653 try dibw.writeLeb128(column + 1);
1642 block.low_pc_off = code_off;1654 block.low_pc_off = code_off;
1643 try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off);1655 try wip_nav.infoAddrSym(wip_nav.func_sym_index, code_off);
1644 block.high_pc = @intCast(wip_nav.debug_info.items.len);1656 block.high_pc = @intCast(dibw.count);
1645 try diw.writeInt(u32, 0, dwarf.endian);1657 try dibw.writeInt(u32, 0, dwarf.endian);
1646 try wip_nav.setInlineFunc(func);1658 try wip_nav.setInlineFunc(func);
1647 wip_nav.any_children = false;1659 wip_nav.any_children = false;
1648 }1660 }
16491661
1650 pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) UpdateError!void {1662 pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) anyerror!void {
1651 const inlined_func_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.inlined_func));1663 const inlined_func_bytes = comptime uleb128Bytes(@intFromEnum(AbbrevCode.inlined_func));
1652 const block = wip_nav.blocks.pop().?;1664 const block = wip_nav.blocks.pop().?;
1665 const dib = wip_nav.debug_info.getWritten();
1653 if (wip_nav.any_children)1666 if (wip_nav.any_children)
1654 try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null))1667 try wip_nav.debug_info.buffered_writer.writeLeb128(@intFromEnum(AbbrevCode.null))
1655 else1668 else
1656 std.leb.writeUnsignedFixed(1669 std.leb.writeUnsignedFixed(
1657 inlined_func_bytes,1670 inlined_func_bytes,
1658 wip_nav.debug_info.items[block.abbrev_code..][0..inlined_func_bytes],1671 dib[block.abbrev_code..][0..inlined_func_bytes],
1659 try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func),1672 try wip_nav.dwarf.refAbbrevCode(.empty_inlined_func),
1660 );1673 );
1661 std.mem.writeInt(u32, wip_nav.debug_info.items[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);1674 std.mem.writeInt(u32, dib[block.high_pc..][0..4], @intCast(code_off - block.low_pc_off), wip_nav.dwarf.endian);
1662 try wip_nav.setInlineFunc(func);1675 try wip_nav.setInlineFunc(func);
1663 wip_nav.any_children = true;1676 wip_nav.any_children = true;
1664 }1677 }
16651678
1666 pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {1679 pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) anyerror!void {
1667 const zcu = wip_nav.pt.zcu;1680 const zcu = wip_nav.pt.zcu;
1668 const dwarf = wip_nav.dwarf;1681 const dwarf = wip_nav.dwarf;
1669 if (wip_nav.func == func) return;1682 if (wip_nav.func == func) return;
...@@ -1672,22 +1685,22 @@ pub const WipNav = struct {...@@ -1672,22 +1685,22 @@ pub const WipNav = struct {
1672 const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav);1685 const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav);
1673 const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod.?);1686 const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod.?);
16741687
1675 const dlw = wip_nav.debug_line.writer(dwarf.gpa);1688 const dlbw = &wip_nav.debug_line.buffered_writer;
1676 if (dwarf.incremental()) {1689 if (dwarf.incremental()) {
1677 const new_nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, new_func_info.owner_nav);1690 const new_nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, new_func_info.owner_nav);
1678 errdefer _ = if (!new_nav_gop.found_existing) dwarf.navs.pop();1691 errdefer _ = if (!new_nav_gop.found_existing) dwarf.navs.pop();
1679 if (!new_nav_gop.found_existing) new_nav_gop.value_ptr.* = try dwarf.addCommonEntry(new_unit);1692 if (!new_nav_gop.found_existing) new_nav_gop.value_ptr.* = try dwarf.addCommonEntry(new_unit);
16801693
1681 try dlw.writeByte(DW.LNS.extended_op);1694 try dlbw.writeByte(DW.LNS.extended_op);
1682 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());1695 try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes());
1683 try dlw.writeByte(DW.LNE.ZIG_set_decl);1696 try dlbw.writeByte(DW.LNE.ZIG_set_decl);
1684 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{1697 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
1685 .source_off = @intCast(wip_nav.debug_line.items.len),1698 .source_off = @intCast(dlbw.count),
1686 .target_sec = .debug_info,1699 .target_sec = .debug_info,
1687 .target_unit = new_unit,1700 .target_unit = new_unit,
1688 .target_entry = new_nav_gop.value_ptr.toOptional(),1701 .target_entry = new_nav_gop.value_ptr.toOptional(),
1689 });1702 });
1690 try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes());1703 try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes());
1691 return;1704 return;
1692 }1705 }
16931706
...@@ -1698,15 +1711,15 @@ pub const WipNav = struct {...@@ -1698,15 +1711,15 @@ pub const WipNav = struct {
1698 try mod_info.dirs.put(dwarf.gpa, new_unit, {});1711 try mod_info.dirs.put(dwarf.gpa, new_unit, {});
1699 const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file);1712 const file_gop = try mod_info.files.getOrPut(dwarf.gpa, new_file);
17001713
1701 try dlw.writeByte(DW.LNS.set_file);1714 try dlbw.writeByte(DW.LNS.set_file);
1702 try uleb128(dlw, file_gop.index);1715 try dlbw.writeLeb128(file_gop.index);
1703 }1716 }
17041717
1705 const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav);1718 const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav);
1706 const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav);1719 const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav);
1707 if (new_src_line != old_src_line) {1720 if (new_src_line != old_src_line) {
1708 try dlw.writeByte(DW.LNS.advance_line);1721 try dlbw.writeByte(DW.LNS.advance_line);
1709 try sleb128(dlw, new_src_line - old_src_line);1722 try dlbw.writeLeb128(new_src_line - old_src_line);
1710 }1723 }
17111724
1712 wip_nav.func = func;1725 wip_nav.func = func;
...@@ -1724,16 +1737,23 @@ pub const WipNav = struct {...@@ -1724,16 +1737,23 @@ pub const WipNav = struct {
1724 try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc);1737 try wip_nav.externalReloc(&wip_nav.dwarf.debug_frame.section, reloc);
1725 }1738 }
17261739
1727 fn abbrevCode(wip_nav: *WipNav, abbrev_code: AbbrevCode) UpdateError!void {1740 fn abbrevCode(wip_nav: *WipNav, abbrev_code: AbbrevCode) anyerror!void {
1728 try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), try wip_nav.dwarf.refAbbrevCode(abbrev_code));1741 try wip_nav.debug_info.buffered_writer.writeLeb128(try wip_nav.dwarf.refAbbrevCode(abbrev_code));
1729 }1742 }
17301743
1731 fn sectionOffset(wip_nav: *WipNav, comptime sec: Section.Index, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void {1744 fn sectionOffset(
1745 wip_nav: *WipNav,
1746 comptime sec: Section.Index,
1747 target_sec: Section.Index,
1748 target_unit: Unit.Index,
1749 target_entry: Entry.Index,
1750 target_off: u32,
1751 ) anyerror!void {
1732 const dwarf = wip_nav.dwarf;1752 const dwarf = wip_nav.dwarf;
1733 const gpa = dwarf.gpa;1753 const gpa = dwarf.gpa;
1734 const entry_ptr = @field(dwarf, @tagName(sec)).section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);1754 const entry_ptr = @field(dwarf, @tagName(sec)).section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);
1735 const bytes = &@field(wip_nav, @tagName(sec));1755 const bw = &@field(wip_nav, @tagName(sec)).buffered_writer;
1736 const source_off: u32 = @intCast(bytes.items.len);1756 const source_off: u32 = @intCast(bw.count);
1737 if (target_sec != sec) {1757 if (target_sec != sec) {
1738 try entry_ptr.cross_section_relocs.append(gpa, .{1758 try entry_ptr.cross_section_relocs.append(gpa, .{
1739 .source_off = source_off,1759 .source_off = source_off,
...@@ -1756,112 +1776,108 @@ pub const WipNav = struct {...@@ -1756,112 +1776,108 @@ pub const WipNav = struct {
1756 .target_off = target_off,1776 .target_off = target_off,
1757 });1777 });
1758 }1778 }
1759 try bytes.appendNTimes(gpa, 0, dwarf.sectionOffsetBytes());1779 try bw.splatByteAll(0, dwarf.sectionOffsetBytes());
1760 }1780 }
17611781
1762 fn infoSectionOffset(wip_nav: *WipNav, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) UpdateError!void {1782 fn infoSectionOffset(wip_nav: *WipNav, target_sec: Section.Index, target_unit: Unit.Index, target_entry: Entry.Index, target_off: u32) anyerror!void {
1763 try wip_nav.sectionOffset(.debug_info, target_sec, target_unit, target_entry, target_off);1783 try wip_nav.sectionOffset(.debug_info, target_sec, target_unit, target_entry, target_off);
1764 }1784 }
17651785
1766 fn strp(wip_nav: *WipNav, str: []const u8) UpdateError!void {1786 fn strp(wip_nav: *WipNav, str: []const u8) anyerror!void {
1767 try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0);1787 try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0);
1768 }1788 }
17691789
1770 const ExprLocCounter = struct {1790 const ExprLocCounter = struct {
1771 stream: *std.io.BufferedWriter,
1772 section_offset_bytes: u32,1791 section_offset_bytes: u32,
1773 address_size: AddressSize,1792 address_size: AddressSize,
1774 counter: usize,1793 fn init(dwarf: *Dwarf) ExprLocCounter {
1775 fn init(dwarf: *Dwarf, stream: *std.io.BufferedWriter) ExprLocCounter {
1776 return .{1794 return .{
1777 .stream = stream,
1778 .section_offset_bytes = dwarf.sectionOffsetBytes(),1795 .section_offset_bytes = dwarf.sectionOffsetBytes(),
1779 .address_size = dwarf.address_size,1796 .address_size = dwarf.address_size,
1780 };1797 };
1781 }1798 }
1782 fn writer(counter: *ExprLocCounter) *std.io.BufferedWriter {
1783 return counter.stream;
1784 }
1785 fn endian(_: ExprLocCounter) std.builtin.Endian {1799 fn endian(_: ExprLocCounter) std.builtin.Endian {
1786 return @import("builtin").cpu.arch.endian();1800 return @import("builtin").cpu.arch.endian();
1787 }1801 }
1788 fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void {1802 fn addrSym(counter: ExprLocCounter, bw: *std.io.BufferedWriter, _: u32) error{}!void {
1789 counter.count += @intFromEnum(counter.address_size);1803 bw.count += @intFromEnum(counter.address_size);
1790 }1804 }
1791 fn infoEntry(counter: *ExprLocCounter, _: Unit.Index, _: Entry.Index) error{}!void {1805 fn infoEntry(counter: ExprLocCounter, bw: *std.io.BufferedWriter, _: Unit.Index, _: Entry.Index) error{}!void {
1792 counter.count += counter.section_offset_bytes;1806 bw.count += counter.section_offset_bytes;
1793 }1807 }
1794 };1808 };
17951809
1796 fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {1810 fn infoExprLoc(wip_nav: *WipNav, loc: Loc) anyerror!void {
1797 var buffer: [std.atomic.cache_line]u8 = undefined;1811 const bw = &wip_nav.debug_info.buffered_writer;
1798 var counter_bw = std.io.Writer.null.buffered(&buffer);1812 const counter: ExprLocCounter = .init(wip_nav.dwarf);
1799 var counter: ExprLocCounter = .init(wip_nav.dwarf, &counter_bw);1813 const start = bw.count;
1800 counter.count += try loc.write(&counter);1814 try loc.write(bw, counter);
1815 const len = bw.count - start;
1816 bw.count = start;
1817 wip_nav.debug_info.shrinkRetainingCapacity(start);
18011818
1802 const adapter: struct {1819 const adapter: struct {
1803 wip_nav: *WipNav,1820 wip_nav: *WipNav,
1804 fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer {
1805 return ctx.wip_nav.debug_info.writer(ctx.wip_nav.dwarf.gpa);
1806 }
1807 fn endian(ctx: @This()) std.builtin.Endian {1821 fn endian(ctx: @This()) std.builtin.Endian {
1808 return ctx.wip_nav.dwarf.endian;1822 return ctx.wip_nav.dwarf.endian;
1809 }1823 }
1810 fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void {1824 fn addrSym(ctx: @This(), _: *std.io.BufferedWriter, sym_index: u32) anyerror!void {
1811 try ctx.wip_nav.infoAddrSym(sym_index, 0);1825 try ctx.wip_nav.infoAddrSym(sym_index, 0);
1812 }1826 }
1813 fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void {1827 fn infoEntry(ctx: @This(), _: *std.io.BufferedWriter, unit: Unit.Index, entry: Entry.Index) anyerror!void {
1814 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1828 try ctx.wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1815 }1829 }
1816 } = .{ .wip_nav = wip_nav };1830 } = .{ .wip_nav = wip_nav };
1817 try uleb128(adapter.writer(), counter.count);1831 try bw.writeLeb128(len);
1818 _ = try loc.write(adapter);1832 try loc.write(bw, adapter);
1819 }1833 }
18201834
1821 fn infoAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void {1835 fn infoAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) anyerror!void {
1836 const dibw = &wip_nav.debug_info.buffered_writer;
1822 try wip_nav.infoExternalReloc(.{1837 try wip_nav.infoExternalReloc(.{
1823 .source_off = @intCast(wip_nav.debug_info.items.len),1838 .source_off = @intCast(dibw.count),
1824 .target_sym = sym_index,1839 .target_sym = sym_index,
1825 .target_off = sym_off,1840 .target_off = sym_off,
1826 });1841 });
1827 try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size));1842 try dibw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size));
1828 }1843 }
18291844
1830 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {1845 fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
1831 var buffer: [std.atomic.cache_line]u8 = undefined;1846 const bw = &wip_nav.debug_frame.buffered_writer;
1832 var counter_bw = std.io.Writer.null.buffered(&buffer);1847 const counter: ExprLocCounter = .init(wip_nav.dwarf);
1833 var counter: ExprLocCounter = .init(wip_nav.dwarf, &counter_bw);1848 const start = bw.count;
1834 counter.count += try loc.write(&counter);1849 try loc.write(bw, counter);
1850 const len = bw.count - start;
1851 bw.count = start;
1852 wip_nav.debug_frame.shrinkRetainingCapacity(start);
18351853
1836 const adapter: struct {1854 const adapter: struct {
1837 wip_nav: *WipNav,1855 wip_nav: *WipNav,
1838 fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer {
1839 return ctx.wip_nav.debug_frame.writer(ctx.wip_nav.dwarf.gpa);
1840 }
1841 fn endian(ctx: @This()) std.builtin.Endian {1856 fn endian(ctx: @This()) std.builtin.Endian {
1842 return ctx.wip_nav.dwarf.endian;1857 return ctx.wip_nav.dwarf.endian;
1843 }1858 }
1844 fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void {1859 fn addrSym(ctx: @This(), _: *std.io.BufferedWriter, sym_index: u32) anyerror!void {
1845 try ctx.wip_nav.frameAddrSym(sym_index, 0);1860 try ctx.wip_nav.frameAddrSym(sym_index, 0);
1846 }1861 }
1847 fn infoEntry(ctx: @This(), unit: Unit.Index, entry: Entry.Index) UpdateError!void {1862 fn infoEntry(ctx: @This(), _: *std.io.BufferedWriter, unit: Unit.Index, entry: Entry.Index) anyerror!void {
1848 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);1863 try ctx.wip_nav.sectionOffset(.debug_frame, .debug_info, unit, entry, 0);
1849 }1864 }
1850 } = .{ .wip_nav = wip_nav };1865 } = .{ .wip_nav = wip_nav };
1851 try uleb128(adapter.writer(), counter.count);1866 try bw.writeLeb128(len);
1852 _ = try loc.write(adapter);1867 try loc.write(bw, adapter);
1853 }1868 }
18541869
1855 fn frameAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) UpdateError!void {1870 fn frameAddrSym(wip_nav: *WipNav, sym_index: u32, sym_off: u64) anyerror!void {
1871 const dfbw = &wip_nav.debug_frame.buffered_writer;
1856 try wip_nav.frameExternalReloc(.{1872 try wip_nav.frameExternalReloc(.{
1857 .source_off = @intCast(wip_nav.debug_frame.items.len),1873 .source_off = @intCast(dfbw.count),
1858 .target_sym = sym_index,1874 .target_sym = sym_index,
1859 .target_off = sym_off,1875 .target_off = sym_off,
1860 });1876 });
1861 try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size));1877 try dfbw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size));
1862 }1878 }
18631879
1864 fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } {1880 fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) anyerror!struct { Unit.Index, Entry.Index } {
1865 const zcu = wip_nav.pt.zcu;1881 const zcu = wip_nav.pt.zcu;
1866 const ip = &zcu.intern_pool;1882 const ip = &zcu.intern_pool;
1867 const nav = ip.getNav(nav_index);1883 const nav = ip.getNav(nav_index);
...@@ -1873,12 +1889,12 @@ pub const WipNav = struct {...@@ -1873,12 +1889,12 @@ pub const WipNav = struct {
1873 return .{ unit, entry };1889 return .{ unit, entry };
1874 }1890 }
18751891
1876 fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!void {1892 fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) anyerror!void {
1877 const unit, const entry = try wip_nav.getNavEntry(nav_index);1893 const unit, const entry = try wip_nav.getNavEntry(nav_index);
1878 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1894 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1879 }1895 }
18801896
1881 fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } {1897 fn getTypeEntry(wip_nav: *WipNav, ty: Type) anyerror!struct { Unit.Index, Entry.Index } {
1882 const zcu = wip_nav.pt.zcu;1898 const zcu = wip_nav.pt.zcu;
1883 const ip = &zcu.intern_pool;1899 const ip = &zcu.intern_pool;
1884 const maybe_inst_index = ty.typeDeclInst(zcu);1900 const maybe_inst_index = ty.typeDeclInst(zcu);
...@@ -1900,12 +1916,12 @@ pub const WipNav = struct {...@@ -1900,12 +1916,12 @@ pub const WipNav = struct {
1900 return .{ unit, entry };1916 return .{ unit, entry };
1901 }1917 }
19021918
1903 fn refType(wip_nav: *WipNav, ty: Type) UpdateError!void {1919 fn refType(wip_nav: *WipNav, ty: Type) anyerror!void {
1904 const unit, const entry = try wip_nav.getTypeEntry(ty);1920 const unit, const entry = try wip_nav.getTypeEntry(ty);
1905 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1921 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1906 }1922 }
19071923
1908 fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } {1924 fn getValueEntry(wip_nav: *WipNav, value: Value) anyerror!struct { Unit.Index, Entry.Index } {
1909 const zcu = wip_nav.pt.zcu;1925 const zcu = wip_nav.pt.zcu;
1910 const ip = &zcu.intern_pool;1926 const ip = &zcu.intern_pool;
1911 const ty = value.typeOf(zcu);1927 const ty = value.typeOf(zcu);
...@@ -1921,47 +1937,50 @@ pub const WipNav = struct {...@@ -1921,47 +1937,50 @@ pub const WipNav = struct {
1921 return .{ unit, entry };1937 return .{ unit, entry };
1922 }1938 }
19231939
1924 fn refValue(wip_nav: *WipNav, value: Value) UpdateError!void {1940 fn refValue(wip_nav: *WipNav, value: Value) anyerror!void {
1925 const unit, const entry = try wip_nav.getValueEntry(value);1941 const unit, const entry = try wip_nav.getValueEntry(value);
1926 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);1942 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
1927 }1943 }
19281944
1929 fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {1945 fn refForward(wip_nav: *WipNav) anyerror!u32 {
1930 const dwarf = wip_nav.dwarf;1946 const dwarf = wip_nav.dwarf;
1947 const dibw = &wip_nav.debug_info.buffered_writer;
1931 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;1948 const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;
1932 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);1949 const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
1933 try cross_entry_relocs.append(dwarf.gpa, .{1950 try cross_entry_relocs.append(dwarf.gpa, .{
1934 .source_off = @intCast(wip_nav.debug_info.items.len),1951 .source_off = @intCast(dibw.count),
1935 .target_entry = undefined,1952 .target_entry = undefined,
1936 .target_off = undefined,1953 .target_off = undefined,
1937 });1954 });
1938 try wip_nav.debug_info.appendNTimes(dwarf.gpa, 0, dwarf.sectionOffsetBytes());1955 try dibw.splatByteAll(0, dwarf.sectionOffsetBytes());
1939 return reloc_index;1956 return reloc_index;
1940 }1957 }
19411958
1942 fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {1959 fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {
1943 const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index];1960 const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index];
1944 reloc.target_entry = wip_nav.entry.toOptional();1961 reloc.target_entry = wip_nav.entry.toOptional();
1945 reloc.target_off = @intCast(wip_nav.debug_info.items.len);1962 reloc.target_off = @intCast(wip_nav.debug_info.buffered_writer.count);
1946 }1963 }
19471964
1948 fn blockValue(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc, val: Value) UpdateError!void {1965 fn blockValue(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc, val: Value) anyerror!void {
1949 const ty = val.typeOf(wip_nav.pt.zcu);1966 const ty = val.typeOf(wip_nav.pt.zcu);
1950 const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa);1967 const dibw = &wip_nav.debug_info.buffered_writer;
1951 const bytes = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0;1968 const bytes = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0;
1952 try uleb128(diw, bytes);1969 try dibw.writeLeb128(bytes);
1953 if (bytes == 0) return;1970 if (bytes == 0) return;
1954 const old_len = wip_nav.debug_info.items.len;1971 var dial = wip_nav.debug_info.toArrayList();
1972 defer _ = wip_nav.debug_info.fromArrayList(wip_nav.dwarf.gpa, &dial);
1973 const old_len = dial.items.len;
1955 try codegen.generateSymbol(1974 try codegen.generateSymbol(
1956 wip_nav.dwarf.bin_file,1975 wip_nav.dwarf.bin_file,
1957 wip_nav.pt,1976 wip_nav.pt,
1958 src_loc,1977 src_loc,
1959 val,1978 val,
1960 &wip_nav.debug_info,1979 &dial,
1961 .{ .debug_output = .{ .dwarf = wip_nav } },1980 .{ .debug_output = .{ .dwarf = wip_nav } },
1962 );1981 );
1963 if (old_len + bytes != wip_nav.debug_info.items.len) {1982 if (old_len + bytes != wip_nav.debug_info.items.len) {
1964 std.debug.print("{} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });1983 std.debug.print("{f} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), bytes, wip_nav.debug_info.items.len - old_len });
1965 unreachable;1984 unreachable;
1966 }1985 }
1967 }1986 }
...@@ -1977,9 +1996,9 @@ pub const WipNav = struct {...@@ -1977,9 +1996,9 @@ pub const WipNav = struct {
1977 abbrev_code: AbbrevCodeForForm,1996 abbrev_code: AbbrevCodeForForm,
1978 ty: Type,1997 ty: Type,
1979 big_int: std.math.big.int.Const,1998 big_int: std.math.big.int.Const,
1980 ) UpdateError!void {1999 ) anyerror!void {
1981 const zcu = wip_nav.pt.zcu;2000 const zcu = wip_nav.pt.zcu;
1982 const diw = wip_nav.debug_info.writer(wip_nav.dwarf.gpa);2001 const dibw = &wip_nav.debug_info.buffered_writer;
1983 const signedness = switch (ty.toIntern()) {2002 const signedness = switch (ty.toIntern()) {
1984 .comptime_int_type, .comptime_float_type => .signed,2003 .comptime_int_type, .comptime_float_type => .signed,
1985 else => ty.intInfo(zcu).signedness,2004 else => ty.intInfo(zcu).signedness,
...@@ -1990,7 +2009,7 @@ pub const WipNav = struct {...@@ -1990,7 +2009,7 @@ pub const WipNav = struct {
1990 .signed => abbrev_code.sdata,2009 .signed => abbrev_code.sdata,
1991 .unsigned => abbrev_code.udata,2010 .unsigned => abbrev_code.udata,
1992 });2011 });
1993 try wip_nav.debug_info.ensureUnusedCapacity(wip_nav.dwarf.gpa, std.math.divCeil(usize, bits, 7) catch unreachable);2012 _ = try dibw.writableSlice(std.math.divCeil(usize, bits, 7) catch unreachable);
1994 var bit: usize = 0;2013 var bit: usize = 0;
1995 var carry: u1 = 1;2014 var carry: u1 = 1;
1996 while (bit < bits) {2015 while (bit < bits) {
...@@ -2007,16 +2026,17 @@ pub const WipNav = struct {...@@ -2007,16 +2026,17 @@ pub const WipNav = struct {
2007 break :twos_comp_part twos_comp_part;2026 break :twos_comp_part twos_comp_part;
2008 };2027 };
2009 bit += 7;2028 bit += 7;
2010 wip_nav.debug_info.appendAssumeCapacity(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part);2029 dibw.writeByte(@as(u8, if (bit < bits) 0x80 else 0x00) | twos_comp_part) catch unreachable;
2011 }2030 }
2012 } else {2031 } else {
2013 try wip_nav.abbrevCode(abbrev_code.block);2032 try wip_nav.abbrevCode(abbrev_code.block);
2014 const bytes = @max(ty.abiSize(zcu), std.math.divCeil(usize, bits, 8) catch unreachable);2033 const bytes = @max(ty.abiSize(zcu), std.math.divCeil(usize, bits, 8) catch unreachable);
2015 try uleb128(diw, bytes);2034 try dibw.writeLeb128(bytes);
2016 big_int.writeTwosComplement(2035 big_int.writeTwosComplement(
2017 try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)),2036 try dibw.writableSlice(@intCast(bytes)),
2018 wip_nav.dwarf.endian,2037 wip_nav.dwarf.endian,
2019 );2038 );
2039 dibw.advance(@intCast(bytes));
2020 }2040 }
2021 }2041 }
20222042
...@@ -2025,7 +2045,7 @@ pub const WipNav = struct {...@@ -2025,7 +2045,7 @@ pub const WipNav = struct {
2025 loaded_enum: InternPool.LoadedEnumType,2045 loaded_enum: InternPool.LoadedEnumType,
2026 abbrev_code: AbbrevCodeForForm,2046 abbrev_code: AbbrevCodeForForm,
2027 field_index: usize,2047 field_index: usize,
2028 ) UpdateError!void {2048 ) anyerror!void {
2029 const zcu = wip_nav.pt.zcu;2049 const zcu = wip_nav.pt.zcu;
2030 const ip = &zcu.intern_pool;2050 const ip = &zcu.intern_pool;
2031 var big_int_space: Value.BigIntSpace = undefined;2051 var big_int_space: Value.BigIntSpace = undefined;
...@@ -2045,11 +2065,11 @@ pub const WipNav = struct {...@@ -2045,11 +2065,11 @@ pub const WipNav = struct {
2045 nav: *const InternPool.Nav,2065 nav: *const InternPool.Nav,
2046 file: Zcu.File.Index,2066 file: Zcu.File.Index,
2047 decl: *const std.zig.Zir.Inst.Declaration.Unwrapped,2067 decl: *const std.zig.Zir.Inst.Declaration.Unwrapped,
2048 ) UpdateError!void {2068 ) anyerror!void {
2049 const zcu = wip_nav.pt.zcu;2069 const zcu = wip_nav.pt.zcu;
2050 const ip = &zcu.intern_pool;2070 const ip = &zcu.intern_pool;
2051 const dwarf = wip_nav.dwarf;2071 const dwarf = wip_nav.dwarf;
2052 const diw = wip_nav.debug_info.writer(dwarf.gpa);2072 const dibw = &wip_nav.debug_info.buffered_writer;
20532073
2054 const orig_entry = wip_nav.entry;2074 const orig_entry = wip_nav.entry;
2055 defer wip_nav.entry = orig_entry;2075 defer wip_nav.entry = orig_entry;
...@@ -2100,15 +2120,15 @@ pub const WipNav = struct {...@@ -2100,15 +2120,15 @@ pub const WipNav = struct {
2100 try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl);2120 try wip_nav.abbrevCode(if (is_generic_decl) abbrev_code.generic_decl else abbrev_code.decl);
2101 try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse2121 try wip_nav.refType((if (is_generic_decl) null else parent_type) orelse
2102 .fromInterned(zcu.fileRootType(file)));2122 .fromInterned(zcu.fileRootType(file)));
2103 assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));2123 assert(dibw.count == DebugInfo.declEntryLineOff(dwarf));
2104 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);2124 try dibw.writeInt(u32, decl.src_line + 1, dwarf.endian);
2105 try uleb128(diw, decl.src_column + 1);2125 try dibw.writeLeb128(decl.src_column + 1);
2106 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);2126 try dibw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
2107 try wip_nav.strp(nav.name.toSlice(ip));2127 try wip_nav.strp(nav.name.toSlice(ip));
21082128
2109 if (!is_generic_decl) return;2129 if (!is_generic_decl) return;
2110 const generic_decl_entry = wip_nav.entry;2130 const generic_decl_entry = wip_nav.entry;
2111 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.items);2131 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, generic_decl_entry, dwarf, wip_nav.debug_info.getWritten());
2112 wip_nav.debug_info.clearRetainingCapacity();2132 wip_nav.debug_info.clearRetainingCapacity();
2113 wip_nav.entry = orig_entry;2133 wip_nav.entry = orig_entry;
2114 try wip_nav.abbrevCode(abbrev_code.decl_instance);2134 try wip_nav.abbrevCode(abbrev_code.decl_instance);
...@@ -2123,7 +2143,7 @@ pub const WipNav = struct {...@@ -2123,7 +2143,7 @@ pub const WipNav = struct {
2123 const empty: PendingLazy = .{ .types = .empty, .values = .empty };2143 const empty: PendingLazy = .{ .types = .empty, .values = .empty };
2124 };2144 };
21252145
2126 fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) UpdateError!void {2146 fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) anyerror!void {
2127 while (true) if (wip_nav.pending_lazy.types.pop()) |pending_ty|2147 while (true) if (wip_nav.pending_lazy.types.pop()) |pending_ty|
2128 try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, pending_ty, &wip_nav.pending_lazy)2148 try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, pending_ty, &wip_nav.pending_lazy)
2129 else if (wip_nav.pending_lazy.values.pop()) |pending_val|2149 else if (wip_nav.pending_lazy.values.pop()) |pending_val|
...@@ -2346,7 +2366,7 @@ pub fn deinit(dwarf: *Dwarf) void {...@@ -2346,7 +2366,7 @@ pub fn deinit(dwarf: *Dwarf) void {
2346 dwarf.* = undefined;2366 dwarf.* = undefined;
2347}2367}
23482368
2349fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {2369fn getUnit(dwarf: *Dwarf, mod: *Module) anyerror!Unit.Index {
2350 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);2370 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);
2351 const unit: Unit.Index = @enumFromInt(mod_gop.index);2371 const unit: Unit.Index = @enumFromInt(mod_gop.index);
2352 if (!mod_gop.found_existing) {2372 if (!mod_gop.found_existing) {
...@@ -2412,18 +2432,69 @@ pub fn initWipNav(...@@ -2412,18 +2432,69 @@ pub fn initWipNav(
2412 nav_index: InternPool.Nav.Index,2432 nav_index: InternPool.Nav.Index,
2413 sym_index: u32,2433 sym_index: u32,
2414) error{ OutOfMemory, CodegenFail }!?WipNav {2434) error{ OutOfMemory, CodegenFail }!?WipNav {
2415 return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {2435 return dwarf.initWipNavInner(pt, nav_index, sym_index) catch |err| switch (@as(UpdateError, @errorCast(err))) {
2436 error.OutOfMemory => return error.OutOfMemory,
2437 else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf nav: {s}", .{@errorName(e)}),
2438 };
2439}
2440
2441pub fn finishWipNavFunc(
2442 dwarf: *Dwarf,
2443 pt: Zcu.PerThread,
2444 nav_index: InternPool.Nav.Index,
2445 code_size: u64,
2446 wip_nav: *WipNav,
2447) error{ OutOfMemory, CodegenFail }!void {
2448 return dwarf.finishWipNavFuncInner(pt, nav_index, code_size, wip_nav) catch |err| switch (@as(UpdateError, @errorCast(err))) {
2416 error.OutOfMemory => return error.OutOfMemory,2449 error.OutOfMemory => return error.OutOfMemory,
2417 else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),2450 else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf func nav: {s}", .{@errorName(e)}),
2418 };2451 };
2419}2452}
24202453
2454pub fn finishWipNav(
2455 dwarf: *Dwarf,
2456 pt: Zcu.PerThread,
2457 nav_index: InternPool.Nav.Index,
2458 wip_nav: *WipNav,
2459) error{ OutOfMemory, CodegenFail }!void {
2460 return dwarf.finishWipNavInner(pt, nav_index, wip_nav) catch |err| switch (@as(UpdateError, @errorCast(err))) {
2461 error.OutOfMemory => return error.OutOfMemory,
2462 else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
2463 };
2464}
2465
2466pub fn updateComptimeNav(
2467 dwarf: *Dwarf,
2468 pt: Zcu.PerThread,
2469 nav_index: InternPool.Nav.Index,
2470) error{ OutOfMemory, CodegenFail }!void {
2471 return dwarf.updateComptimeNavInner(pt, nav_index) catch |err| switch (@as(UpdateError, @errorCast(err))) {
2472 error.OutOfMemory => return error.OutOfMemory,
2473 else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}),
2474 };
2475}
2476
2477pub fn updateContainerType(
2478 dwarf: *Dwarf,
2479 pt: Zcu.PerThread,
2480 type_index: InternPool.Index,
2481) error{ OutOfMemory, CodegenFail }!void {
2482 return dwarf.updateContainerType(pt, type_index) catch |err| switch (@as(UpdateError, @errorCast(err))) {
2483 error.OutOfMemory => return error.OutOfMemory,
2484 else => |e| return pt.zcu.codegenFailType(type_index, "failed to update dwarf comptime nav: {s}", .{@errorName(e)}),
2485 };
2486}
2487
2488pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
2489 return @errorCast(dwarf.flushModuleInner(pt));
2490}
2491
2421fn initWipNavInner(2492fn initWipNavInner(
2422 dwarf: *Dwarf,2493 dwarf: *Dwarf,
2423 pt: Zcu.PerThread,2494 pt: Zcu.PerThread,
2424 nav_index: InternPool.Nav.Index,2495 nav_index: InternPool.Nav.Index,
2425 sym_index: u32,2496 sym_index: u32,
2426) !?WipNav {2497) anyerror!?WipNav {
2427 const zcu = pt.zcu;2498 const zcu = pt.zcu;
2428 const ip = &zcu.intern_pool;2499 const ip = &zcu.intern_pool;
24292500
...@@ -2431,7 +2502,7 @@ fn initWipNavInner(...@@ -2431,7 +2502,7 @@ fn initWipNavInner(
2431 const inst_info = nav.srcInst(ip).resolveFull(ip).?;2502 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
2432 const file = zcu.fileByIndex(inst_info.file);2503 const file = zcu.fileByIndex(inst_info.file);
2433 const decl = file.zir.?.getDeclaration(inst_info.inst);2504 const decl = file.zir.?.getDeclaration(inst_info.inst);
2434 log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{2505 log.debug("initWipNav({s}:{d}:{d} %{d} = {f})", .{
2435 file.sub_file_path,2506 file.sub_file_path,
2436 decl.src_line + 1,2507 decl.src_line + 1,
2437 decl.src_column + 1,2508 decl.src_column + 1,
...@@ -2472,17 +2543,17 @@ fn initWipNavInner(...@@ -2472,17 +2543,17 @@ fn initWipNavInner(
2472 .func_high_pc = undefined,2543 .func_high_pc = undefined,
2473 .blocks = undefined,2544 .blocks = undefined,
2474 .cfi = undefined,2545 .cfi = undefined,
2475 .debug_frame = .empty,2546 .debug_frame = undefined,
2476 .debug_info = .empty,2547 .debug_info = undefined,
2477 .debug_line = .empty,2548 .debug_line = undefined,
2478 .debug_loclists = .empty,2549 .debug_loclists = undefined,
2479 .pending_lazy = .empty,2550 .pending_lazy = .empty,
2480 };2551 };
2481 errdefer wip_nav.deinit();2552 errdefer wip_nav.deinit();
24822553
2483 switch (nav_key) {2554 switch (nav_key) {
2484 else => {2555 else => {
2485 const diw = wip_nav.debug_info.writer(dwarf.gpa);2556 const dibw = &wip_nav.debug_info.buffered_writer;
2486 try wip_nav.declCommon(.{2557 try wip_nav.declCommon(.{
2487 .decl = .decl_var,2558 .decl = .decl_var,
2488 .generic_decl = .generic_decl_var,2559 .generic_decl = .generic_decl_var,
...@@ -2497,9 +2568,9 @@ fn initWipNavInner(...@@ -2497,9 +2568,9 @@ fn initWipNavInner(
2497 .@"const" => {2568 .@"const" => {
2498 const const_ty_reloc_index = try wip_nav.refForward();2569 const const_ty_reloc_index = try wip_nav.refForward();
2499 try wip_nav.infoExprLoc(loc);2570 try wip_nav.infoExprLoc(loc);
2500 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse2571 try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2501 ty.abiAlignment(zcu).toByteUnits().?);2572 ty.abiAlignment(zcu).toByteUnits().?);
2502 try diw.writeByte(@intFromBool(decl.linkage != .normal));2573 try dibw.writeByte(@intFromBool(decl.linkage != .normal));
2503 wip_nav.finishForward(const_ty_reloc_index);2574 wip_nav.finishForward(const_ty_reloc_index);
2504 try wip_nav.abbrevCode(.is_const);2575 try wip_nav.abbrevCode(.is_const);
2505 try wip_nav.refType(ty);2576 try wip_nav.refType(ty);
...@@ -2507,9 +2578,9 @@ fn initWipNavInner(...@@ -2507,9 +2578,9 @@ fn initWipNavInner(
2507 .@"var" => {2578 .@"var" => {
2508 try wip_nav.refType(ty);2579 try wip_nav.refType(ty);
2509 try wip_nav.infoExprLoc(loc);2580 try wip_nav.infoExprLoc(loc);
2510 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse2581 try dibw.writeLeb128(dibw, nav.status.fully_resolved.alignment.toByteUnits() orelse
2511 ty.abiAlignment(zcu).toByteUnits().?);2582 ty.abiAlignment(zcu).toByteUnits().?);
2512 try diw.writeByte(@intFromBool(decl.linkage != .normal));2583 try dibw.writeByte(@intFromBool(decl.linkage != .normal));
2513 },2584 },
2514 }2585 }
2515 },2586 },
...@@ -2534,39 +2605,39 @@ fn initWipNavInner(...@@ -2534,39 +2605,39 @@ fn initWipNavInner(
2534 .none => {},2605 .none => {},
2535 .debug_frame, .eh_frame => |format| {2606 .debug_frame, .eh_frame => |format| {
2536 const entry = dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);2607 const entry = dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);
2537 const dfw = wip_nav.debug_frame.writer(dwarf.gpa);2608 const dfbw = &wip_nav.debug_frame.buffered_writer;
2538 switch (dwarf.format) {2609 switch (dwarf.format) {
2539 .@"32" => try dfw.writeInt(u32, undefined, dwarf.endian),2610 .@"32" => try dfbw.writeInt(u32, undefined, dwarf.endian),
2540 .@"64" => {2611 .@"64" => {
2541 try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian);2612 try dfbw.writeInt(u32, std.math.maxInt(u32), dwarf.endian);
2542 try dfw.writeInt(u64, undefined, dwarf.endian);2613 try dfbw.writeInt(u64, undefined, dwarf.endian);
2543 },2614 },
2544 }2615 }
2545 switch (format) {2616 switch (format) {
2546 .none => unreachable,2617 .none => unreachable,
2547 .debug_frame => {2618 .debug_frame => {
2548 try entry.cross_entry_relocs.append(dwarf.gpa, .{2619 try entry.cross_entry_relocs.append(dwarf.gpa, .{
2549 .source_off = @intCast(wip_nav.debug_frame.items.len),2620 .source_off = @intCast(dfbw.count),
2550 });2621 });
2551 try dfw.writeByteNTimes(0, dwarf.sectionOffsetBytes());2622 try dfbw.splatByteAll(0, dwarf.sectionOffsetBytes());
2552 try wip_nav.frameAddrSym(sym_index, 0);2623 try wip_nav.frameAddrSym(sym_index, 0);
2553 try dfw.writeByteNTimes(undefined, @intFromEnum(dwarf.address_size));2624 try dfbw.splatByteAll(undefined, @intFromEnum(dwarf.address_size));
2554 },2625 },
2555 .eh_frame => {2626 .eh_frame => {
2556 try dfw.writeInt(u32, undefined, dwarf.endian);2627 try dfbw.writeInt(u32, undefined, dwarf.endian);
2557 try wip_nav.frameExternalReloc(.{2628 try wip_nav.frameExternalReloc(.{
2558 .source_off = @intCast(wip_nav.debug_frame.items.len),2629 .source_off = @intCast(dfbw.count),
2559 .target_sym = sym_index,2630 .target_sym = sym_index,
2560 });2631 });
2561 try dfw.writeInt(u32, 0, dwarf.endian);2632 try dfbw.writeInt(u32, 0, dwarf.endian);
2562 try dfw.writeInt(u32, undefined, dwarf.endian);2633 try dfbw.writeInt(u32, undefined, dwarf.endian);
2563 try uleb128(dfw, 0);2634 try dfbw.writeUleb128(0);
2564 },2635 },
2565 }2636 }
2566 },2637 },
2567 }2638 }
25682639
2569 const diw = wip_nav.debug_info.writer(dwarf.gpa);2640 const dibw = &wip_nav.debug_info.buffered_writer;
2570 try wip_nav.declCommon(.{2641 try wip_nav.declCommon(.{
2571 .decl = .decl_func,2642 .decl = .decl_func,
2572 .generic_decl = .generic_decl_func,2643 .generic_decl = .generic_decl_func,
...@@ -2576,47 +2647,47 @@ fn initWipNavInner(...@@ -2576,47 +2647,47 @@ fn initWipNavInner(
2576 try wip_nav.refType(.fromInterned(func_type.return_type));2647 try wip_nav.refType(.fromInterned(func_type.return_type));
2577 try wip_nav.infoAddrSym(sym_index, 0);2648 try wip_nav.infoAddrSym(sym_index, 0);
2578 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);2649 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);
2579 try diw.writeInt(u32, 0, dwarf.endian);2650 try dibw.writeInt(u32, 0, dwarf.endian);
2580 const target = &mod.resolved_target.result;2651 const target = &mod.resolved_target.result;
2581 try uleb128(diw, switch (nav.status.fully_resolved.alignment) {2652 try dibw.writeLeb128(switch (nav.status.fully_resolved.alignment) {
2582 .none => target_info.defaultFunctionAlignment(target),2653 .none => target_info.defaultFunctionAlignment(target),
2583 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),2654 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
2584 }.toByteUnits().?);2655 }.toByteUnits().?);
2585 try diw.writeByte(@intFromBool(decl.linkage != .normal));2656 try dibw.writeByte(@intFromBool(decl.linkage != .normal));
2586 try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));2657 try dibw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
25872658
2588 const dlw = wip_nav.debug_line.writer(dwarf.gpa);2659 const dlbw = &wip_nav.debug_line.buffered_writer;
2589 try dlw.writeByte(DW.LNS.extended_op);2660 try dlbw.writeByte(DW.LNS.extended_op);
2590 if (dwarf.incremental()) {2661 if (dwarf.incremental()) {
2591 try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());2662 try dlbw.writeLeb128(1 + dwarf.sectionOffsetBytes());
2592 try dlw.writeByte(DW.LNE.ZIG_set_decl);2663 try dlbw.writeByte(DW.LNE.ZIG_set_decl);
2593 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{2664 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
2594 .source_off = @intCast(wip_nav.debug_line.items.len),2665 .source_off = @intCast(dlbw.count),
2595 .target_sec = .debug_info,2666 .target_sec = .debug_info,
2596 .target_unit = wip_nav.unit,2667 .target_unit = wip_nav.unit,
2597 .target_entry = wip_nav.entry.toOptional(),2668 .target_entry = wip_nav.entry.toOptional(),
2598 });2669 });
2599 try dlw.writeByteNTimes(0, dwarf.sectionOffsetBytes());2670 try dlbw.splatByteAll(0, dwarf.sectionOffsetBytes());
26002671
2601 try dlw.writeByte(DW.LNS.set_column);2672 try dlbw.writeByte(DW.LNS.set_column);
2602 try uleb128(dlw, func.lbrace_column + 1);2673 try dlbw.writeLeb128(func.lbrace_column + 1);
26032674
2604 try wip_nav.advancePCAndLine(func.lbrace_line, 0);2675 try wip_nav.advancePCAndLine(func.lbrace_line, 0);
2605 } else {2676 } else {
2606 try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));2677 try dlbw.writeLeb128(1 + @intFromEnum(dwarf.address_size));
2607 try dlw.writeByte(DW.LNE.set_address);2678 try dlbw.writeByte(DW.LNE.set_address);
2608 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{2679 try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
2609 .source_off = @intCast(wip_nav.debug_line.items.len),2680 .source_off = @intCast(dlbw.count),
2610 .target_sym = sym_index,2681 .target_sym = sym_index,
2611 });2682 });
2612 try dlw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));2683 try dlbw.splatByteAll(0, @intFromEnum(dwarf.address_size));
26132684
2614 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);2685 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);
2615 try dlw.writeByte(DW.LNS.set_file);2686 try dlbw.writeByte(DW.LNS.set_file);
2616 try uleb128(dlw, file_gop.index);2687 try dlbw.writeLeb128(file_gop.index);
26172688
2618 try dlw.writeByte(DW.LNS.set_column);2689 try dlbw.writeByte(DW.LNS.set_column);
2619 try uleb128(dlw, func.lbrace_column + 1);2690 try dlbw.writeLeb128(func.lbrace_column + 1);
26202691
2621 try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0);2692 try wip_nav.advancePCAndLine(@intCast(decl.src_line + func.lbrace_line), 0);
2622 }2693 }
...@@ -2625,18 +2696,18 @@ fn initWipNavInner(...@@ -2625,18 +2696,18 @@ fn initWipNavInner(
2625 return wip_nav;2696 return wip_nav;
2626}2697}
26272698
2628pub fn finishWipNavFunc(2699fn finishWipNavFuncInner(
2629 dwarf: *Dwarf,2700 dwarf: *Dwarf,
2630 pt: Zcu.PerThread,2701 pt: Zcu.PerThread,
2631 nav_index: InternPool.Nav.Index,2702 nav_index: InternPool.Nav.Index,
2632 code_size: u64,2703 code_size: u64,
2633 wip_nav: *WipNav,2704 wip_nav: *WipNav,
2634) UpdateError!void {2705) anyerror!void {
2635 const zcu = pt.zcu;2706 const zcu = pt.zcu;
2636 const ip = &zcu.intern_pool;2707 const ip = &zcu.intern_pool;
2637 const nav = ip.getNav(nav_index);2708 const nav = ip.getNav(nav_index);
2638 assert(wip_nav.func != .none);2709 assert(wip_nav.func != .none);
2639 log.debug("finishWipNavFunc({})", .{nav.fqn.fmt(ip)});2710 log.debug("finishWipNavFunc({f})", .{nav.fqn.fmt(ip)});
26402711
2641 {2712 {
2642 const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;2713 const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
...@@ -2654,12 +2725,9 @@ pub fn finishWipNavFunc(...@@ -2654,12 +2725,9 @@ pub fn finishWipNavFunc(
2654 switch (dwarf.debug_frame.header.format) {2725 switch (dwarf.debug_frame.header.format) {
2655 .none => {},2726 .none => {},
2656 .debug_frame, .eh_frame => |format| {2727 .debug_frame, .eh_frame => |format| {
2657 try wip_nav.debug_frame.appendNTimes(2728 const dfbw = &wip_nav.debug_frame.buffered_writer;
2658 dwarf.gpa,2729 try dfbw.splatByteAll(DW.CFA.nop, @intCast(dwarf.debug_frame.section.alignment.forward(dfbw.count) - dfbw.count));
2659 DW.CFA.nop,2730 const contents = wip_nav.debug_frame.getWritten();
2660 @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len),
2661 );
2662 const contents = wip_nav.debug_frame.items;
2663 try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len));2731 try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len));
2664 const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit);2732 const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit);
2665 const entry = unit.getEntry(wip_nav.entry);2733 const entry = unit.getEntry(wip_nav.entry);
...@@ -2686,14 +2754,15 @@ pub fn finishWipNavFunc(...@@ -2686,14 +2754,15 @@ pub fn finishWipNavFunc(
2686 },2754 },
2687 }2755 }
2688 {2756 {
2689 std.mem.writeInt(u32, wip_nav.debug_info.items[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian);2757 std.mem.writeInt(u32, wip_nav.debug_info.getWritten()[wip_nav.func_high_pc..][0..4], @intCast(code_size), dwarf.endian);
2690 if (wip_nav.any_children) {2758 if (wip_nav.any_children) {
2691 const diw = wip_nav.debug_info.writer(dwarf.gpa);2759 const dibw = &wip_nav.debug_info.buffered_writer;
2692 try uleb128(diw, @intFromEnum(AbbrevCode.null));2760 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2693 } else {2761 } else {
2694 const abbrev_code_buf = wip_nav.debug_info.items[0..AbbrevCode.decl_bytes];2762 const abbrev_code_buf = wip_nav.debug_info.getWritten()[0..AbbrevCode.decl_bytes];
2695 var abbrev_code_fbs = std.io.fixedBufferStream(abbrev_code_buf);2763 var abbrev_code_br: std.io.BufferedReader = undefined;
2696 const abbrev_code: AbbrevCode = @enumFromInt(std.leb.readUleb128(@typeInfo(AbbrevCode).@"enum".tag_type, abbrev_code_fbs.reader()) catch unreachable);2764 abbrev_code_br.initFixed(abbrev_code_buf);
2765 const abbrev_code: AbbrevCode = @enumFromInt(abbrev_code_br.takeLeb128(@typeInfo(AbbrevCode).@"enum".tag_type) catch unreachable);
2697 std.leb.writeUnsignedFixed(2766 std.leb.writeUnsignedFixed(
2698 AbbrevCode.decl_bytes,2767 AbbrevCode.decl_bytes,
2699 abbrev_code_buf,2768 abbrev_code_buf,
...@@ -2725,41 +2794,35 @@ pub fn finishWipNavFunc(...@@ -2725,41 +2794,35 @@ pub fn finishWipNavFunc(
2725 );2794 );
2726 }2795 }
27272796
2728 try dwarf.finishWipNav(pt, nav_index, wip_nav);2797 try dwarf.finishWipNavInner(pt, nav_index, wip_nav);
2729}2798}
27302799
2731pub fn finishWipNav(2800fn finishWipNavInner(
2732 dwarf: *Dwarf,2801 dwarf: *Dwarf,
2733 pt: Zcu.PerThread,2802 pt: Zcu.PerThread,
2734 nav_index: InternPool.Nav.Index,2803 nav_index: InternPool.Nav.Index,
2735 wip_nav: *WipNav,2804 wip_nav: *WipNav,
2736) UpdateError!void {2805) anyerror!void {
2737 const zcu = pt.zcu;2806 const zcu = pt.zcu;
2738 const ip = &zcu.intern_pool;2807 const ip = &zcu.intern_pool;
2739 const nav = ip.getNav(nav_index);2808 const nav = ip.getNav(nav_index);
2740 log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});2809 log.debug("finishWipNav({f})", .{nav.fqn.fmt(ip)});
27412810
2742 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);2811 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten());
2743 if (wip_nav.debug_line.items.len > 0) {2812 const debug_line = wip_nav.debug_line.getWritten();
2744 const dlw = wip_nav.debug_line.writer(dwarf.gpa);2813 if (debug_line.len > 0) {
2745 try dlw.writeByte(DW.LNS.extended_op);2814 const dlbw = &wip_nav.debug_line.buffered_writer;
2746 try uleb128(dlw, 1);2815 try dlbw.writeByte(DW.LNS.extended_op);
2747 try dlw.writeByte(DW.LNE.end_sequence);2816 try dlbw.writeUleb128(1);
2748 try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.items);2817 try dlbw.writeByte(DW.LNE.end_sequence);
2818 try dwarf.debug_line.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_line.getWritten());
2749 }2819 }
2750 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items);2820 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.getWritten());
27512821
2752 try wip_nav.updateLazy(zcu.navSrcLoc(nav_index));2822 try wip_nav.updateLazy(zcu.navSrcLoc(nav_index));
2753}2823}
27542824
2755pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {2825fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) anyerror!void {
2756 return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) {
2757 error.OutOfMemory => return error.OutOfMemory,
2758 else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}),
2759 };
2760}
2761
2762fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
2763 const zcu = pt.zcu;2826 const zcu = pt.zcu;
2764 const ip = &zcu.intern_pool;2827 const ip = &zcu.intern_pool;
2765 const nav_src_loc = zcu.navSrcLoc(nav_index);2828 const nav_src_loc = zcu.navSrcLoc(nav_index);
...@@ -2769,7 +2832,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2769,7 +2832,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2769 const inst_info = nav.srcInst(ip).resolveFull(ip).?;2832 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
2770 const file = zcu.fileByIndex(inst_info.file);2833 const file = zcu.fileByIndex(inst_info.file);
2771 const decl = file.zir.?.getDeclaration(inst_info.inst);2834 const decl = file.zir.?.getDeclaration(inst_info.inst);
2772 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{2835 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{
2773 file.sub_file_path,2836 file.sub_file_path,
2774 decl.src_line + 1,2837 decl.src_line + 1,
2775 decl.src_column + 1,2838 decl.src_column + 1,
...@@ -2797,12 +2860,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2797,12 +2860,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2797 .func_high_pc = undefined,2860 .func_high_pc = undefined,
2798 .blocks = undefined,2861 .blocks = undefined,
2799 .cfi = undefined,2862 .cfi = undefined,
2800 .debug_frame = .empty,2863 .debug_frame = undefined,
2801 .debug_info = .empty,2864 .debug_info = undefined,
2802 .debug_line = .empty,2865 .debug_line = undefined,
2803 .debug_loclists = .empty,2866 .debug_loclists = undefined,
2804 .pending_lazy = .empty,2867 .pending_lazy = .empty,
2805 };2868 };
2869 wip_nav.init();
2806 defer wip_nav.deinit();2870 defer wip_nav.deinit();
28072871
2808 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);2872 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
...@@ -2846,7 +2910,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2846,7 +2910,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2846 }2910 }
2847 wip_nav.entry = nav_gop.value_ptr.*;2911 wip_nav.entry = nav_gop.value_ptr.*;
28482912
2849 const diw = wip_nav.debug_info.writer(dwarf.gpa);2913 const dibw = &wip_nav.debug_info.buffered_writer;
28502914
2851 switch (loaded_struct.layout) {2915 switch (loaded_struct.layout) {
2852 .auto, .@"extern" => {2916 .auto, .@"extern" => {
...@@ -2859,9 +2923,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2859,9 +2923,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2859 .generic_decl = .generic_decl_const,2923 .generic_decl = .generic_decl_const,
2860 .decl_instance = .decl_instance_struct,2924 .decl_instance = .decl_instance_struct,
2861 }, &nav, inst_info.file, &decl);2925 }, &nav, inst_info.file, &decl);
2862 if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else {2926 if (loaded_struct.field_types.len == 0) try dibw.writeByte(@intFromBool(false)) else {
2863 try uleb128(diw, nav_val.toType().abiSize(zcu));2927 try dibw.writeLeb128(nav_val.toType().abiSize(zcu));
2864 try uleb128(diw, nav_val.toType().abiAlignment(zcu).toByteUnits().?);2928 try dibw.writeLeb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?);
2865 for (0..loaded_struct.field_types.len) |field_index| {2929 for (0..loaded_struct.field_types.len) |field_index| {
2866 const is_comptime = loaded_struct.fieldIsComptime(ip, field_index);2930 const is_comptime = loaded_struct.fieldIsComptime(ip, field_index);
2867 const field_init = loaded_struct.fieldInit(ip, field_index);2931 const field_init = loaded_struct.fieldInit(ip, field_index);
...@@ -2897,8 +2961,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2897,8 +2961,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2897 }2961 }
2898 try wip_nav.refType(field_type);2962 try wip_nav.refType(field_type);
2899 if (!is_comptime) {2963 if (!is_comptime) {
2900 try uleb128(diw, loaded_struct.offsets.get(ip)[field_index]);2964 try dibw.writeLeb128(loaded_struct.offsets.get(ip)[field_index]);
2901 try uleb128(diw, loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse2965 try dibw.writeLeb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse
2902 field_type.abiAlignment(zcu).toByteUnits().?);2966 field_type.abiAlignment(zcu).toByteUnits().?);
2903 }2967 }
2904 if (has_comptime_state)2968 if (has_comptime_state)
...@@ -2906,7 +2970,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2906,7 +2970,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2906 else if (has_runtime_bits)2970 else if (has_runtime_bits)
2907 try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init));2971 try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init));
2908 }2972 }
2909 try uleb128(diw, @intFromEnum(AbbrevCode.null));2973 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2910 }2974 }
2911 },2975 },
2912 .@"packed" => {2976 .@"packed" => {
...@@ -2922,10 +2986,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2922,10 +2986,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2922 try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip));2986 try wip_nav.strp(loaded_struct.fieldName(ip, field_index).unwrap().?.toSlice(ip));
2923 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);2987 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
2924 try wip_nav.refType(field_type);2988 try wip_nav.refType(field_type);
2925 try uleb128(diw, field_bit_offset);2989 try dibw.writeLeb128(field_bit_offset);
2926 field_bit_offset += @intCast(field_type.bitSize(zcu));2990 field_bit_offset += @intCast(field_type.bitSize(zcu));
2927 }2991 }
2928 try uleb128(diw, @intFromEnum(AbbrevCode.null));2992 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2929 },2993 },
2930 }2994 }
2931 break :tag .done;2995 break :tag .done;
...@@ -2948,7 +3012,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2948,7 +3012,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2948 type_gop.value_ptr.* = nav_gop.value_ptr.*;3012 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2949 }3013 }
2950 wip_nav.entry = nav_gop.value_ptr.*;3014 wip_nav.entry = nav_gop.value_ptr.*;
2951 const diw = wip_nav.debug_info.writer(dwarf.gpa);3015 const dibw = &wip_nav.debug_info.buffered_writer;
2952 try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{3016 try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{
2953 .decl = .decl_enum,3017 .decl = .decl_enum,
2954 .generic_decl = .generic_decl_const,3018 .generic_decl = .generic_decl_const,
...@@ -2967,7 +3031,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2967,7 +3031,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2967 }, field_index);3031 }, field_index);
2968 try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip));3032 try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip));
2969 }3033 }
2970 if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));3034 if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
2971 break :tag .done;3035 break :tag .done;
2972 },3036 },
2973 .union_type => tag: {3037 .union_type => tag: {
...@@ -2987,15 +3051,15 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2987,15 +3051,15 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2987 type_gop.value_ptr.* = nav_gop.value_ptr.*;3051 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2988 }3052 }
2989 wip_nav.entry = nav_gop.value_ptr.*;3053 wip_nav.entry = nav_gop.value_ptr.*;
2990 const diw = wip_nav.debug_info.writer(dwarf.gpa);3054 const dibw = &wip_nav.debug_info.buffered_writer;
2991 try wip_nav.declCommon(.{3055 try wip_nav.declCommon(.{
2992 .decl = .decl_union,3056 .decl = .decl_union,
2993 .generic_decl = .generic_decl_const,3057 .generic_decl = .generic_decl_const,
2994 .decl_instance = .decl_instance_union,3058 .decl_instance = .decl_instance_union,
2995 }, &nav, inst_info.file, &decl);3059 }, &nav, inst_info.file, &decl);
2996 const union_layout = Type.getUnionLayout(loaded_union, zcu);3060 const union_layout = Type.getUnionLayout(loaded_union, zcu);
2997 try uleb128(diw, union_layout.abi_size);3061 try dibw.writeLeb128(union_layout.abi_size);
2998 try uleb128(diw, union_layout.abi_align.toByteUnits().?);3062 try dibw.writeLeb128(union_layout.abi_align.toByteUnits().?);
2999 const loaded_tag = loaded_union.loadTagType(ip);3063 const loaded_tag = loaded_union.loadTagType(ip);
3000 if (loaded_union.hasTag(ip)) {3064 if (loaded_union.hasTag(ip)) {
3001 try wip_nav.abbrevCode(.tagged_union);3065 try wip_nav.abbrevCode(.tagged_union);
...@@ -3003,13 +3067,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3003,13 +3067,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3003 .debug_info,3067 .debug_info,
3004 wip_nav.unit,3068 wip_nav.unit,
3005 wip_nav.entry,3069 wip_nav.entry,
3006 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),3070 @intCast(dibw.count + dwarf.sectionOffsetBytes()),
3007 );3071 );
3008 {3072 {
3009 try wip_nav.abbrevCode(.generated_field);3073 try wip_nav.abbrevCode(.generated_field);
3010 try wip_nav.strp("tag");3074 try wip_nav.strp("tag");
3011 try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty));3075 try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty));
3012 try uleb128(diw, union_layout.tagOffset());3076 try dibw.writeLeb128(union_layout.tagOffset());
30133077
3014 for (0..loaded_union.field_types.len) |field_index| {3078 for (0..loaded_union.field_types.len) |field_index| {
3015 try wip_nav.enumConstValue(loaded_tag, .{3079 try wip_nav.enumConstValue(loaded_tag, .{
...@@ -3022,23 +3086,23 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3022,23 +3086,23 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3022 try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));3086 try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
3023 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);3087 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3024 try wip_nav.refType(field_type);3088 try wip_nav.refType(field_type);
3025 try uleb128(diw, union_layout.payloadOffset());3089 try dibw.writeLeb128(union_layout.payloadOffset());
3026 try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse3090 try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse
3027 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);3091 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
3028 }3092 }
3029 try uleb128(diw, @intFromEnum(AbbrevCode.null));3093 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3030 }3094 }
3031 }3095 }
3032 try uleb128(diw, @intFromEnum(AbbrevCode.null));3096 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3033 } else for (0..loaded_union.field_types.len) |field_index| {3097 } else for (0..loaded_union.field_types.len) |field_index| {
3034 try wip_nav.abbrevCode(.untagged_union_field);3098 try wip_nav.abbrevCode(.untagged_union_field);
3035 try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));3099 try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip));
3036 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);3100 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3037 try wip_nav.refType(field_type);3101 try wip_nav.refType(field_type);
3038 try uleb128(diw, loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse3102 try dibw.writeLeb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse
3039 field_type.abiAlignment(zcu).toByteUnits().?);3103 field_type.abiAlignment(zcu).toByteUnits().?);
3040 }3104 }
3041 try uleb128(diw, @intFromEnum(AbbrevCode.null));3105 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3042 break :tag .done;3106 break :tag .done;
3043 },3107 },
3044 .opaque_type => tag: {3108 .opaque_type => tag: {
...@@ -3058,13 +3122,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3058,13 +3122,13 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3058 type_gop.value_ptr.* = nav_gop.value_ptr.*;3122 type_gop.value_ptr.* = nav_gop.value_ptr.*;
3059 }3123 }
3060 wip_nav.entry = nav_gop.value_ptr.*;3124 wip_nav.entry = nav_gop.value_ptr.*;
3061 const diw = wip_nav.debug_info.writer(dwarf.gpa);3125 const dibw = &wip_nav.debug_info.buffered_writer;
3062 try wip_nav.declCommon(.{3126 try wip_nav.declCommon(.{
3063 .decl = .decl_namespace_struct,3127 .decl = .decl_namespace_struct,
3064 .generic_decl = .generic_decl_const,3128 .generic_decl = .generic_decl_const,
3065 .decl_instance = .decl_instance_namespace_struct,3129 .decl_instance = .decl_instance_namespace_struct,
3066 }, &nav, inst_info.file, &decl);3130 }, &nav, inst_info.file, &decl);
3067 try diw.writeByte(@intFromBool(true));3131 try dibw.writeByte(@intFromBool(true));
3068 break :tag .done;3132 break :tag .done;
3069 },3133 },
3070 .undef,3134 .undef,
...@@ -3102,7 +3166,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3102,7 +3166,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3102 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {3166 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {
3103 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;3167 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;
3104 } else true;3168 } else true;
3105 const diw = wip_nav.debug_info.writer(dwarf.gpa);3169 const dibw = &wip_nav.debug_info.buffered_writer;
3106 try wip_nav.declCommon(if (is_nullary) .{3170 try wip_nav.declCommon(if (is_nullary) .{
3107 .decl = .decl_nullary_func_generic,3171 .decl = .decl_nullary_func_generic,
3108 .generic_decl = .generic_decl_func,3172 .generic_decl = .generic_decl_func,
...@@ -3121,7 +3185,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3121,7 +3185,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3121 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));3185 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3122 }3186 }
3123 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);3187 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3124 try uleb128(diw, @intFromEnum(AbbrevCode.null));3188 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3125 }3189 }
3126 break :tag .done;3190 break :tag .done;
3127 },3191 },
...@@ -3146,7 +3210,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3146,7 +3210,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3146 try wip_nav.refType(nav_val.toType());3210 try wip_nav.refType(nav_val.toType());
3147 },3211 },
3148 .decl_var => {3212 .decl_var => {
3149 const diw = wip_nav.debug_info.writer(dwarf.gpa);3213 const dibw = &wip_nav.debug_info.buffered_writer;
3150 try wip_nav.declCommon(.{3214 try wip_nav.declCommon(.{
3151 .decl = .decl_var,3215 .decl = .decl_var,
3152 .generic_decl = .generic_decl_var,3216 .generic_decl = .generic_decl_var,
...@@ -3156,12 +3220,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3156,12 +3220,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3156 const nav_ty = nav_val.typeOf(zcu);3220 const nav_ty = nav_val.typeOf(zcu);
3157 try wip_nav.refType(nav_ty);3221 try wip_nav.refType(nav_ty);
3158 try wip_nav.blockValue(nav_src_loc, nav_val);3222 try wip_nav.blockValue(nav_src_loc, nav_val);
3159 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse3223 try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
3160 nav_ty.abiAlignment(zcu).toByteUnits().?);3224 nav_ty.abiAlignment(zcu).toByteUnits().?);
3161 try diw.writeByte(@intFromBool(decl.linkage != .normal));3225 try dibw.writeByte(@intFromBool(decl.linkage != .normal));
3162 },3226 },
3163 .decl_const => {3227 .decl_const => {
3164 const diw = wip_nav.debug_info.writer(dwarf.gpa);3228 const dibw = &wip_nav.debug_info.buffered_writer;
3165 const nav_ty = nav_val.typeOf(zcu);3229 const nav_ty = nav_val.typeOf(zcu);
3166 const has_runtime_bits = nav_ty.hasRuntimeBits(zcu);3230 const has_runtime_bits = nav_ty.hasRuntimeBits(zcu);
3167 const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null;3231 const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null;
...@@ -3184,9 +3248,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3184,9 +3248,9 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3184 }, &nav, inst_info.file, &decl);3248 }, &nav, inst_info.file, &decl);
3185 try wip_nav.strp(nav.fqn.toSlice(ip));3249 try wip_nav.strp(nav.fqn.toSlice(ip));
3186 const nav_ty_reloc_index = try wip_nav.refForward();3250 const nav_ty_reloc_index = try wip_nav.refForward();
3187 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse3251 try dibw.writeLeb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
3188 nav_ty.abiAlignment(zcu).toByteUnits().?);3252 nav_ty.abiAlignment(zcu).toByteUnits().?);
3189 try diw.writeByte(@intFromBool(decl.linkage != .normal));3253 try dibw.writeByte(@intFromBool(decl.linkage != .normal));
3190 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);3254 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);
3191 if (has_comptime_state) try wip_nav.refValue(nav_val);3255 if (has_comptime_state) try wip_nav.refValue(nav_val);
3192 wip_nav.finishForward(nav_ty_reloc_index);3256 wip_nav.finishForward(nav_ty_reloc_index);
...@@ -3202,7 +3266,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3202,7 +3266,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3202 try wip_nav.refNav(owner_nav);3266 try wip_nav.refNav(owner_nav);
3203 },3267 },
3204 }3268 }
3205 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);3269 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten());
3206 try wip_nav.updateLazy(nav_src_loc);3270 try wip_nav.updateLazy(nav_src_loc);
3207}3271}
32083272
...@@ -3212,14 +3276,14 @@ fn updateLazyType(...@@ -3212,14 +3276,14 @@ fn updateLazyType(
3212 src_loc: Zcu.LazySrcLoc,3276 src_loc: Zcu.LazySrcLoc,
3213 type_index: InternPool.Index,3277 type_index: InternPool.Index,
3214 pending_lazy: *WipNav.PendingLazy,3278 pending_lazy: *WipNav.PendingLazy,
3215) UpdateError!void {3279) anyerror!void {
3216 const zcu = pt.zcu;3280 const zcu = pt.zcu;
3217 const ip = &zcu.intern_pool;3281 const ip = &zcu.intern_pool;
3218 assert(ip.typeOf(type_index) == .type_type);3282 assert(ip.typeOf(type_index) == .type_type);
3219 const ty: Type = .fromInterned(type_index);3283 const ty: Type = .fromInterned(type_index);
3220 switch (type_index) {3284 switch (type_index) {
3221 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),3285 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),
3222 else => log.debug("updateLazyType({})", .{ty.fmt(pt)}),3286 else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}),
3223 }3287 }
32243288
3225 var wip_nav: WipNav = .{3289 var wip_nav: WipNav = .{
...@@ -3233,21 +3297,22 @@ fn updateLazyType(...@@ -3233,21 +3297,22 @@ fn updateLazyType(
3233 .func_high_pc = undefined,3297 .func_high_pc = undefined,
3234 .blocks = undefined,3298 .blocks = undefined,
3235 .cfi = undefined,3299 .cfi = undefined,
3236 .debug_frame = .empty,3300 .debug_frame = undefined,
3237 .debug_info = .empty,3301 .debug_info = undefined,
3238 .debug_line = .empty,3302 .debug_line = undefined,
3239 .debug_loclists = .empty,3303 .debug_loclists = undefined,
3240 .pending_lazy = pending_lazy.*,3304 .pending_lazy = pending_lazy.*,
3241 };3305 };
3306 wip_nav.init();
3242 defer {3307 defer {
3243 pending_lazy.* = wip_nav.pending_lazy;3308 pending_lazy.* = wip_nav.pending_lazy;
3244 wip_nav.pending_lazy = .empty;3309 wip_nav.pending_lazy = .empty;
3245 wip_nav.deinit();3310 wip_nav.deinit();
3246 }3311 }
3247 const diw = wip_nav.debug_info.writer(dwarf.gpa);3312 const dibw = &wip_nav.debug_info.buffered_writer;
3248 const name = switch (type_index) {3313 const name = switch (type_index) {
3249 .generic_poison_type => "",3314 .generic_poison_type => "",
3250 else => try std.fmt.allocPrint(dwarf.gpa, "{}", .{ty.fmt(pt)}),3315 else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}),
3251 };3316 };
3252 defer dwarf.gpa.free(name);3317 defer dwarf.gpa.free(name);
32533318
...@@ -3259,12 +3324,12 @@ fn updateLazyType(...@@ -3259,12 +3324,12 @@ fn updateLazyType(
3259 .int_type => |int_type| {3324 .int_type => |int_type| {
3260 try wip_nav.abbrevCode(.numeric_type);3325 try wip_nav.abbrevCode(.numeric_type);
3261 try wip_nav.strp(name);3326 try wip_nav.strp(name);
3262 try diw.writeByte(switch (int_type.signedness) {3327 try dibw.writeByte(switch (int_type.signedness) {
3263 inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),3328 inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),
3264 });3329 });
3265 try uleb128(diw, int_type.bits);3330 try dibw.writeLeb128(int_type.bits);
3266 try uleb128(diw, ty.abiSize(zcu));3331 try dibw.writeLeb128(ty.abiSize(zcu));
3267 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3332 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3268 },3333 },
3269 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {3334 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3270 .one, .many, .c => {3335 .one, .many, .c => {
...@@ -3272,14 +3337,14 @@ fn updateLazyType(...@@ -3272,14 +3337,14 @@ fn updateLazyType(
3272 try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type);3337 try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type);
3273 try wip_nav.strp(name);3338 try wip_nav.strp(name);
3274 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));3339 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));
3275 try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse3340 try dibw.writeLeb128(ptr_type.flags.alignment.toByteUnits() orelse
3276 ptr_child_type.abiAlignment(zcu).toByteUnits().?);3341 ptr_child_type.abiAlignment(zcu).toByteUnits().?);
3277 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));3342 try dibw.writeByte(@intFromEnum(ptr_type.flags.address_space));
3278 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(3343 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(
3279 .debug_info,3344 .debug_info,
3280 wip_nav.unit,3345 wip_nav.unit,
3281 wip_nav.entry,3346 wip_nav.entry,
3282 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),3347 @intCast(dibw.count + dwarf.sectionOffsetBytes()),
3283 ) else try wip_nav.refType(ptr_child_type);3348 ) else try wip_nav.refType(ptr_child_type);
3284 if (ptr_type.flags.is_const) {3349 if (ptr_type.flags.is_const) {
3285 try wip_nav.abbrevCode(.is_const);3350 try wip_nav.abbrevCode(.is_const);
...@@ -3287,7 +3352,7 @@ fn updateLazyType(...@@ -3287,7 +3352,7 @@ fn updateLazyType(
3287 .debug_info,3352 .debug_info,
3288 wip_nav.unit,3353 wip_nav.unit,
3289 wip_nav.entry,3354 wip_nav.entry,
3290 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),3355 @intCast(dibw.count + dwarf.sectionOffsetBytes()),
3291 ) else try wip_nav.refType(ptr_child_type);3356 ) else try wip_nav.refType(ptr_child_type);
3292 }3357 }
3293 if (ptr_type.flags.is_volatile) {3358 if (ptr_type.flags.is_volatile) {
...@@ -3298,19 +3363,19 @@ fn updateLazyType(...@@ -3298,19 +3363,19 @@ fn updateLazyType(
3298 .slice => {3363 .slice => {
3299 try wip_nav.abbrevCode(.generated_struct_type);3364 try wip_nav.abbrevCode(.generated_struct_type);
3300 try wip_nav.strp(name);3365 try wip_nav.strp(name);
3301 try uleb128(diw, ty.abiSize(zcu));3366 try dibw.writeLeb128(ty.abiSize(zcu));
3302 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3367 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3303 try wip_nav.abbrevCode(.generated_field);3368 try wip_nav.abbrevCode(.generated_field);
3304 try wip_nav.strp("ptr");3369 try wip_nav.strp("ptr");
3305 const ptr_field_type = ty.slicePtrFieldType(zcu);3370 const ptr_field_type = ty.slicePtrFieldType(zcu);
3306 try wip_nav.refType(ptr_field_type);3371 try wip_nav.refType(ptr_field_type);
3307 try uleb128(diw, 0);3372 try dibw.writeUleb128(0);
3308 try wip_nav.abbrevCode(.generated_field);3373 try wip_nav.abbrevCode(.generated_field);
3309 try wip_nav.strp("len");3374 try wip_nav.strp("len");
3310 const len_field_type: Type = .usize;3375 const len_field_type: Type = .usize;
3311 try wip_nav.refType(len_field_type);3376 try wip_nav.refType(len_field_type);
3312 try uleb128(diw, len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu)));3377 try dibw.writeLeb128(len_field_type.abiAlignment(zcu).forward(ptr_field_type.abiSize(zcu)));
3313 try uleb128(diw, @intFromEnum(AbbrevCode.null));3378 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3314 },3379 },
3315 },3380 },
3316 .array_type => |array_type| {3381 .array_type => |array_type| {
...@@ -3321,8 +3386,8 @@ fn updateLazyType(...@@ -3321,8 +3386,8 @@ fn updateLazyType(
3321 try wip_nav.refType(array_child_type);3386 try wip_nav.refType(array_child_type);
3322 try wip_nav.abbrevCode(.array_index);3387 try wip_nav.abbrevCode(.array_index);
3323 try wip_nav.refType(.usize);3388 try wip_nav.refType(.usize);
3324 try uleb128(diw, array_type.len);3389 try dibw.writeLeb128(array_type.len);
3325 try uleb128(diw, @intFromEnum(AbbrevCode.null));3390 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3326 },3391 },
3327 .vector_type => |vector_type| {3392 .vector_type => |vector_type| {
3328 try wip_nav.abbrevCode(.vector_type);3393 try wip_nav.abbrevCode(.vector_type);
...@@ -3330,22 +3395,22 @@ fn updateLazyType(...@@ -3330,22 +3395,22 @@ fn updateLazyType(
3330 try wip_nav.refType(.fromInterned(vector_type.child));3395 try wip_nav.refType(.fromInterned(vector_type.child));
3331 try wip_nav.abbrevCode(.array_index);3396 try wip_nav.abbrevCode(.array_index);
3332 try wip_nav.refType(.usize);3397 try wip_nav.refType(.usize);
3333 try uleb128(diw, vector_type.len);3398 try dibw.writeLeb128(vector_type.len);
3334 try uleb128(diw, @intFromEnum(AbbrevCode.null));3399 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3335 },3400 },
3336 .opt_type => |opt_child_type_index| {3401 .opt_type => |opt_child_type_index| {
3337 const opt_child_type: Type = .fromInterned(opt_child_type_index);3402 const opt_child_type: Type = .fromInterned(opt_child_type_index);
3338 const opt_repr = optRepr(opt_child_type, zcu);3403 const opt_repr = optRepr(opt_child_type, zcu);
3339 try wip_nav.abbrevCode(.generated_union_type);3404 try wip_nav.abbrevCode(.generated_union_type);
3340 try wip_nav.strp(name);3405 try wip_nav.strp(name);
3341 try uleb128(diw, ty.abiSize(zcu));3406 try dibw.writeLeb128(ty.abiSize(zcu));
3342 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3407 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3343 switch (opt_repr) {3408 switch (opt_repr) {
3344 .opv_null => {3409 .opv_null => {
3345 try wip_nav.abbrevCode(.generated_field);3410 try wip_nav.abbrevCode(.generated_field);
3346 try wip_nav.strp("null");3411 try wip_nav.strp("null");
3347 try wip_nav.refType(.null);3412 try wip_nav.refType(.null);
3348 try uleb128(diw, 0);3413 try dibw.writeUleb128(0);
3349 },3414 },
3350 .unpacked, .error_set, .pointer => {3415 .unpacked, .error_set, .pointer => {
3351 try wip_nav.abbrevCode(.tagged_union);3416 try wip_nav.abbrevCode(.tagged_union);
...@@ -3353,7 +3418,7 @@ fn updateLazyType(...@@ -3353,7 +3418,7 @@ fn updateLazyType(
3353 .debug_info,3418 .debug_info,
3354 wip_nav.unit,3419 wip_nav.unit,
3355 wip_nav.entry,3420 wip_nav.entry,
3356 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),3421 @intCast(dibw.count + dwarf.sectionOffsetBytes()),
3357 );3422 );
3358 {3423 {
3359 try wip_nav.abbrevCode(.generated_field);3424 try wip_nav.abbrevCode(.generated_field);
...@@ -3362,7 +3427,7 @@ fn updateLazyType(...@@ -3362,7 +3427,7 @@ fn updateLazyType(
3362 .opv_null => unreachable,3427 .opv_null => unreachable,
3363 .unpacked => {3428 .unpacked => {
3364 try wip_nav.refType(.bool);3429 try wip_nav.refType(.bool);
3365 try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu))3430 try dibw.writeLeb128(if (opt_child_type.hasRuntimeBits(zcu))
3366 opt_child_type.abiSize(zcu)3431 opt_child_type.abiSize(zcu)
3367 else3432 else
3368 0);3433 0);
...@@ -3372,37 +3437,37 @@ fn updateLazyType(...@@ -3372,37 +3437,37 @@ fn updateLazyType(
3372 .signedness = .unsigned,3437 .signedness = .unsigned,
3373 .bits = zcu.errorSetBits(),3438 .bits = zcu.errorSetBits(),
3374 } })));3439 } })));
3375 try uleb128(diw, 0);3440 try dibw.writeUleb128(0);
3376 },3441 },
3377 .pointer => {3442 .pointer => {
3378 try wip_nav.refType(.usize);3443 try wip_nav.refType(.usize);
3379 try uleb128(diw, 0);3444 try dibw.writeUleb128(0);
3380 },3445 },
3381 }3446 }
33823447
3383 try wip_nav.abbrevCode(.unsigned_tagged_union_field);3448 try wip_nav.abbrevCode(.unsigned_tagged_union_field);
3384 try uleb128(diw, 0);3449 try dibw.writeUleb128(0);
3385 {3450 {
3386 try wip_nav.abbrevCode(.generated_field);3451 try wip_nav.abbrevCode(.generated_field);
3387 try wip_nav.strp("null");3452 try wip_nav.strp("null");
3388 try wip_nav.refType(.null);3453 try wip_nav.refType(.null);
3389 try uleb128(diw, 0);3454 try dibw.writeUleb128(0);
3390 }3455 }
3391 try uleb128(diw, @intFromEnum(AbbrevCode.null));3456 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
33923457
3393 try wip_nav.abbrevCode(.tagged_union_default_field);3458 try wip_nav.abbrevCode(.tagged_union_default_field);
3394 {3459 {
3395 try wip_nav.abbrevCode(.generated_field);3460 try wip_nav.abbrevCode(.generated_field);
3396 try wip_nav.strp("?");3461 try wip_nav.strp("?");
3397 try wip_nav.refType(opt_child_type);3462 try wip_nav.refType(opt_child_type);
3398 try uleb128(diw, 0);3463 try dibw.writeUleb128(0);
3399 }3464 }
3400 try uleb128(diw, @intFromEnum(AbbrevCode.null));3465 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3401 }3466 }
3402 try uleb128(diw, @intFromEnum(AbbrevCode.null));3467 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3403 },3468 },
3404 }3469 }
3405 try uleb128(diw, @intFromEnum(AbbrevCode.null));3470 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3406 },3471 },
3407 .anyframe_type => unreachable,3472 .anyframe_type => unreachable,
3408 .error_union_type => |error_union_type| {3473 .error_union_type => |error_union_type| {
...@@ -3421,11 +3486,11 @@ fn updateLazyType(...@@ -3421,11 +3486,11 @@ fn updateLazyType(
3421 if (error_union_type.error_set_type != .generic_poison_type and3486 if (error_union_type.error_set_type != .generic_poison_type and
3422 error_union_type.payload_type != .generic_poison_type)3487 error_union_type.payload_type != .generic_poison_type)
3423 {3488 {
3424 try uleb128(diw, ty.abiSize(zcu));3489 try dibw.writeLeb128(ty.abiSize(zcu));
3425 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3490 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3426 } else {3491 } else {
3427 try uleb128(diw, 0);3492 try dibw.writeUleb128(0);
3428 try uleb128(diw, 1);3493 try dibw.writeUleb128(1);
3429 }3494 }
3430 {3495 {
3431 try wip_nav.abbrevCode(.tagged_union);3496 try wip_nav.abbrevCode(.tagged_union);
...@@ -3433,7 +3498,7 @@ fn updateLazyType(...@@ -3433,7 +3498,7 @@ fn updateLazyType(
3433 .debug_info,3498 .debug_info,
3434 wip_nav.unit,3499 wip_nav.unit,
3435 wip_nav.entry,3500 wip_nav.entry,
3436 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),3501 @intCast(dibw.count + dwarf.sectionOffsetBytes()),
3437 );3502 );
3438 {3503 {
3439 try wip_nav.abbrevCode(.generated_field);3504 try wip_nav.abbrevCode(.generated_field);
...@@ -3442,30 +3507,30 @@ fn updateLazyType(...@@ -3442,30 +3507,30 @@ fn updateLazyType(
3442 .signedness = .unsigned,3507 .signedness = .unsigned,
3443 .bits = zcu.errorSetBits(),3508 .bits = zcu.errorSetBits(),
3444 } })));3509 } })));
3445 try uleb128(diw, error_union_error_set_offset);3510 try dibw.writeLeb128(error_union_error_set_offset);
34463511
3447 try wip_nav.abbrevCode(.unsigned_tagged_union_field);3512 try wip_nav.abbrevCode(.unsigned_tagged_union_field);
3448 try uleb128(diw, 0);3513 try dibw.writeUleb128(0);
3449 {3514 {
3450 try wip_nav.abbrevCode(.generated_field);3515 try wip_nav.abbrevCode(.generated_field);
3451 try wip_nav.strp("value");3516 try wip_nav.strp("value");
3452 try wip_nav.refType(error_union_payload_type);3517 try wip_nav.refType(error_union_payload_type);
3453 try uleb128(diw, error_union_payload_offset);3518 try dibw.writeLeb128(error_union_payload_offset);
3454 }3519 }
3455 try uleb128(diw, @intFromEnum(AbbrevCode.null));3520 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
34563521
3457 try wip_nav.abbrevCode(.tagged_union_default_field);3522 try wip_nav.abbrevCode(.tagged_union_default_field);
3458 {3523 {
3459 try wip_nav.abbrevCode(.generated_field);3524 try wip_nav.abbrevCode(.generated_field);
3460 try wip_nav.strp("error");3525 try wip_nav.strp("error");
3461 try wip_nav.refType(error_union_error_set_type);3526 try wip_nav.refType(error_union_error_set_type);
3462 try uleb128(diw, error_union_error_set_offset);3527 try dibw.writeLeb128(error_union_error_set_offset);
3463 }3528 }
3464 try uleb128(diw, @intFromEnum(AbbrevCode.null));3529 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3465 }3530 }
3466 try uleb128(diw, @intFromEnum(AbbrevCode.null));3531 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3467 }3532 }
3468 try uleb128(diw, @intFromEnum(AbbrevCode.null));3533 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3469 },3534 },
3470 .simple_type => |simple_type| switch (simple_type) {3535 .simple_type => |simple_type| switch (simple_type) {
3471 .f16,3536 .f16,
...@@ -3489,7 +3554,7 @@ fn updateLazyType(...@@ -3489,7 +3554,7 @@ fn updateLazyType(
3489 => {3554 => {
3490 try wip_nav.abbrevCode(.numeric_type);3555 try wip_nav.abbrevCode(.numeric_type);
3491 try wip_nav.strp(name);3556 try wip_nav.strp(name);
3492 try diw.writeByte(if (type_index == .bool_type)3557 try dibw.writeByte(if (type_index == .bool_type)
3493 DW.ATE.boolean3558 DW.ATE.boolean
3494 else if (ty.isRuntimeFloat())3559 else if (ty.isRuntimeFloat())
3495 DW.ATE.float3560 DW.ATE.float
...@@ -3499,9 +3564,9 @@ fn updateLazyType(...@@ -3499,9 +3564,9 @@ fn updateLazyType(
3499 DW.ATE.unsigned3564 DW.ATE.unsigned
3500 else3565 else
3501 unreachable);3566 unreachable);
3502 try uleb128(diw, ty.bitSize(zcu));3567 try dibw.writeLeb128(ty.bitSize(zcu));
3503 try uleb128(diw, ty.abiSize(zcu));3568 try dibw.writeLeb128(ty.abiSize(zcu));
3504 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3569 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3505 },3570 },
3506 .anyopaque,3571 .anyopaque,
3507 .void,3572 .void,
...@@ -3527,12 +3592,12 @@ fn updateLazyType(...@@ -3527,12 +3592,12 @@ fn updateLazyType(
3527 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {3592 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
3528 try wip_nav.abbrevCode(.generated_empty_struct_type);3593 try wip_nav.abbrevCode(.generated_empty_struct_type);
3529 try wip_nav.strp(name);3594 try wip_nav.strp(name);
3530 try diw.writeByte(@intFromBool(false));3595 try dibw.writeByte(@intFromBool(false));
3531 } else {3596 } else {
3532 try wip_nav.abbrevCode(.generated_struct_type);3597 try wip_nav.abbrevCode(.generated_struct_type);
3533 try wip_nav.strp(name);3598 try wip_nav.strp(name);
3534 try uleb128(diw, ty.abiSize(zcu));3599 try dibw.writeLeb128(ty.abiSize(zcu));
3535 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3600 try dibw.writeLeb128(ty.abiAlignment(zcu).toByteUnits().?);
3536 var field_byte_offset: u64 = 0;3601 var field_byte_offset: u64 = 0;
3537 for (0..tuple_type.types.len) |field_index| {3602 for (0..tuple_type.types.len) |field_index| {
3538 const comptime_value = tuple_type.values.get(ip)[field_index];3603 const comptime_value = tuple_type.values.get(ip)[field_index];
...@@ -3561,8 +3626,8 @@ fn updateLazyType(...@@ -3561,8 +3626,8 @@ fn updateLazyType(
3561 if (comptime_value == .none) {3626 if (comptime_value == .none) {
3562 const field_align = field_type.abiAlignment(zcu);3627 const field_align = field_type.abiAlignment(zcu);
3563 field_byte_offset = field_align.forward(field_byte_offset);3628 field_byte_offset = field_align.forward(field_byte_offset);
3564 try uleb128(diw, field_byte_offset);3629 try dibw.writeLeb128(field_byte_offset);
3565 try uleb128(diw, field_type.abiAlignment(zcu).toByteUnits().?);3630 try dibw.writeLeb128(field_type.abiAlignment(zcu).toByteUnits().?);
3566 field_byte_offset += field_type.abiSize(zcu);3631 field_byte_offset += field_type.abiSize(zcu);
3567 }3632 }
3568 if (has_comptime_state)3633 if (has_comptime_state)
...@@ -3570,7 +3635,7 @@ fn updateLazyType(...@@ -3570,7 +3635,7 @@ fn updateLazyType(
3570 else if (has_runtime_bits)3635 else if (has_runtime_bits)
3571 try wip_nav.blockValue(src_loc, .fromInterned(comptime_value));3636 try wip_nav.blockValue(src_loc, .fromInterned(comptime_value));
3572 }3637 }
3573 try uleb128(diw, @intFromEnum(AbbrevCode.null));3638 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3574 },3639 },
3575 .enum_type => {3640 .enum_type => {
3576 const loaded_enum = ip.loadEnumType(type_index);3641 const loaded_enum = ip.loadEnumType(type_index);
...@@ -3585,7 +3650,7 @@ fn updateLazyType(...@@ -3585,7 +3650,7 @@ fn updateLazyType(
3585 }, field_index);3650 }, field_index);
3586 try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip));3651 try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip));
3587 }3652 }
3588 if (loaded_enum.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));3653 if (loaded_enum.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3589 },3654 },
3590 .func_type => |func_type| {3655 .func_type => |func_type| {
3591 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;3656 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
...@@ -3653,7 +3718,7 @@ fn updateLazyType(...@@ -3653,7 +3718,7 @@ fn updateLazyType(
3653 else => .nocall,3718 else => .nocall,
3654 };3719 };
3655 };3720 };
3656 try diw.writeByte(@intFromEnum(cc));3721 try dibw.writeByte(@intFromEnum(cc));
3657 try wip_nav.refType(.fromInterned(func_type.return_type));3722 try wip_nav.refType(.fromInterned(func_type.return_type));
3658 if (!is_nullary) {3723 if (!is_nullary) {
3659 for (0..func_type.param_types.len) |param_index| {3724 for (0..func_type.param_types.len) |param_index| {
...@@ -3661,7 +3726,7 @@ fn updateLazyType(...@@ -3661,7 +3726,7 @@ fn updateLazyType(
3661 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));3726 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3662 }3727 }
3663 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);3728 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3664 try uleb128(diw, @intFromEnum(AbbrevCode.null));3729 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3665 }3730 }
3666 },3731 },
3667 .error_set_type => |error_set_type| {3732 .error_set_type => |error_set_type| {
...@@ -3674,10 +3739,10 @@ fn updateLazyType(...@@ -3674,10 +3739,10 @@ fn updateLazyType(
3674 for (0..error_set_type.names.len) |field_index| {3739 for (0..error_set_type.names.len) |field_index| {
3675 const field_name = error_set_type.names.get(ip)[field_index];3740 const field_name = error_set_type.names.get(ip)[field_index];
3676 try wip_nav.abbrevCode(.unsigned_enum_field);3741 try wip_nav.abbrevCode(.unsigned_enum_field);
3677 try uleb128(diw, ip.getErrorValueIfExists(field_name).?);3742 try dibw.writeLeb128(ip.getErrorValueIfExists(field_name).?);
3678 try wip_nav.strp(field_name.toSlice(ip));3743 try wip_nav.strp(field_name.toSlice(ip));
3679 }3744 }
3680 if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));3745 if (error_set_type.names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3681 },3746 },
3682 .inferred_error_set_type => |func| {3747 .inferred_error_set_type => |func| {
3683 try wip_nav.abbrevCode(.inferred_error_set_type);3748 try wip_nav.abbrevCode(.inferred_error_set_type);
...@@ -3709,7 +3774,7 @@ fn updateLazyType(...@@ -3709,7 +3774,7 @@ fn updateLazyType(
3709 .memoized_call,3774 .memoized_call,
3710 => unreachable,3775 => unreachable,
3711 }3776 }
3712 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);3777 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten());
3713}3778}
37143779
3715fn updateLazyValue(3780fn updateLazyValue(
...@@ -3718,11 +3783,11 @@ fn updateLazyValue(...@@ -3718,11 +3783,11 @@ fn updateLazyValue(
3718 src_loc: Zcu.LazySrcLoc,3783 src_loc: Zcu.LazySrcLoc,
3719 value_index: InternPool.Index,3784 value_index: InternPool.Index,
3720 pending_lazy: *WipNav.PendingLazy,3785 pending_lazy: *WipNav.PendingLazy,
3721) UpdateError!void {3786) anyerror!void {
3722 const zcu = pt.zcu;3787 const zcu = pt.zcu;
3723 const ip = &zcu.intern_pool;3788 const ip = &zcu.intern_pool;
3724 assert(ip.typeOf(value_index) != .type_type);3789 assert(ip.typeOf(value_index) != .type_type);
3725 log.debug("updateLazyValue(@as({}, {}))", .{3790 log.debug("updateLazyValue(@as({f}, {f}))", .{
3726 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),3791 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),
3727 Value.fromInterned(value_index).fmtValue(pt),3792 Value.fromInterned(value_index).fmtValue(pt),
3728 });3793 });
...@@ -3737,18 +3802,19 @@ fn updateLazyValue(...@@ -3737,18 +3802,19 @@ fn updateLazyValue(
3737 .func_high_pc = undefined,3802 .func_high_pc = undefined,
3738 .blocks = undefined,3803 .blocks = undefined,
3739 .cfi = undefined,3804 .cfi = undefined,
3740 .debug_frame = .empty,3805 .debug_frame = undefined,
3741 .debug_info = .empty,3806 .debug_info = undefined,
3742 .debug_line = .empty,3807 .debug_line = undefined,
3743 .debug_loclists = .empty,3808 .debug_loclists = undefined,
3744 .pending_lazy = pending_lazy.*,3809 .pending_lazy = pending_lazy.*,
3745 };3810 };
3811 wip_nav.init();
3746 defer {3812 defer {
3747 pending_lazy.* = wip_nav.pending_lazy;3813 pending_lazy.* = wip_nav.pending_lazy;
3748 wip_nav.pending_lazy = .empty;3814 wip_nav.pending_lazy = .empty;
3749 wip_nav.deinit();3815 wip_nav.deinit();
3750 }3816 }
3751 const diw = wip_nav.debug_info.writer(dwarf.gpa);3817 const dibw = &wip_nav.debug_info.buffered_writer;
3752 var big_int_space: Value.BigIntSpace = undefined;3818 var big_int_space: Value.BigIntSpace = undefined;
3753 switch (ip.indexToKey(value_index)) {3819 switch (ip.indexToKey(value_index)) {
3754 .int_type,3820 .int_type,
...@@ -3786,7 +3852,7 @@ fn updateLazyValue(...@@ -3786,7 +3852,7 @@ fn updateLazyValue(
3786 .err => |err| {3852 .err => |err| {
3787 try wip_nav.abbrevCode(.udata_comptime_value);3853 try wip_nav.abbrevCode(.udata_comptime_value);
3788 try wip_nav.refType(.fromInterned(err.ty));3854 try wip_nav.refType(.fromInterned(err.ty));
3789 try uleb128(diw, try pt.getErrorValue(err.name));3855 try dibw.writeLeb128(try pt.getErrorValue(err.name));
3790 },3856 },
3791 .error_union => |error_union| {3857 .error_union => |error_union| {
3792 try wip_nav.abbrevCode(.aggregate_comptime_value);3858 try wip_nav.abbrevCode(.aggregate_comptime_value);
...@@ -3798,8 +3864,8 @@ fn updateLazyValue(...@@ -3798,8 +3864,8 @@ fn updateLazyValue(
3798 {3864 {
3799 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);3865 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
3800 try wip_nav.strp("is_error");3866 try wip_nav.strp("is_error");
3801 try uleb128(diw, err_abi_size);3867 try dibw.writeLeb128(err_abi_size);
3802 dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value);3868 try dwarf.writeIntTo(dibw, err_abi_size, err_value);
3803 }3869 }
3804 payload_field: switch (error_union.val) {3870 payload_field: switch (error_union.val) {
3805 .err_name => {},3871 .err_name => {},
...@@ -3823,8 +3889,8 @@ fn updateLazyValue(...@@ -3823,8 +3889,8 @@ fn updateLazyValue(
3823 {3889 {
3824 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);3890 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
3825 try wip_nav.strp("error");3891 try wip_nav.strp("error");
3826 try uleb128(diw, err_abi_size);3892 try dibw.writeLeb128(err_abi_size);
3827 dwarf.writeInt(try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, err_abi_size), err_value);3893 try dwarf.writeIntTo(dibw, err_abi_size, err_value);
3828 }3894 }
3829 switch (error_union.val) {3895 switch (error_union.val) {
3830 .err_name => {},3896 .err_name => {},
...@@ -3834,7 +3900,7 @@ fn updateLazyValue(...@@ -3834,7 +3900,7 @@ fn updateLazyValue(
3834 },3900 },
3835 }3901 }
3836 try wip_nav.refType(.fromInterned(error_union.ty));3902 try wip_nav.refType(.fromInterned(error_union.ty));
3837 try uleb128(diw, @intFromEnum(AbbrevCode.null));3903 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3838 },3904 },
3839 .enum_literal => |enum_literal| {3905 .enum_literal => |enum_literal| {
3840 try wip_nav.abbrevCode(.string_comptime_value);3906 try wip_nav.abbrevCode(.string_comptime_value);
...@@ -3855,24 +3921,24 @@ fn updateLazyValue(...@@ -3855,24 +3921,24 @@ fn updateLazyValue(
3855 switch (float.storage) {3921 switch (float.storage) {
3856 .f16 => |f16_val| {3922 .f16 => |f16_val| {
3857 try wip_nav.abbrevCode(.data2_comptime_value);3923 try wip_nav.abbrevCode(.data2_comptime_value);
3858 try diw.writeInt(u16, @bitCast(f16_val), dwarf.endian);3924 try dibw.writeInt(u16, @bitCast(f16_val), dwarf.endian);
3859 },3925 },
3860 .f32 => |f32_val| {3926 .f32 => |f32_val| {
3861 try wip_nav.abbrevCode(.data4_comptime_value);3927 try wip_nav.abbrevCode(.data4_comptime_value);
3862 try diw.writeInt(u32, @bitCast(f32_val), dwarf.endian);3928 try dibw.writeInt(u32, @bitCast(f32_val), dwarf.endian);
3863 },3929 },
3864 .f64 => |f64_val| {3930 .f64 => |f64_val| {
3865 try wip_nav.abbrevCode(.data8_comptime_value);3931 try wip_nav.abbrevCode(.data8_comptime_value);
3866 try diw.writeInt(u64, @bitCast(f64_val), dwarf.endian);3932 try dibw.writeInt(u64, @bitCast(f64_val), dwarf.endian);
3867 },3933 },
3868 .f80 => |f80_val| {3934 .f80 => |f80_val| {
3869 try wip_nav.abbrevCode(.block_comptime_value);3935 try wip_nav.abbrevCode(.block_comptime_value);
3870 try uleb128(diw, @divExact(80, 8));3936 try dibw.writeUleb128(@divExact(80, 8));
3871 try diw.writeInt(u80, @bitCast(f80_val), dwarf.endian);3937 try dibw.writeInt(u80, @bitCast(f80_val), dwarf.endian);
3872 },3938 },
3873 .f128 => |f128_val| {3939 .f128 => |f128_val| {
3874 try wip_nav.abbrevCode(.data16_comptime_value);3940 try wip_nav.abbrevCode(.data16_comptime_value);
3875 try diw.writeInt(u128, @bitCast(f128_val), dwarf.endian);3941 try dibw.writeInt(u128, @bitCast(f128_val), dwarf.endian);
3876 },3942 },
3877 }3943 }
3878 try wip_nav.refType(.fromInterned(float.ty));3944 try wip_nav.refType(.fromInterned(float.ty));
...@@ -3889,14 +3955,14 @@ fn updateLazyValue(...@@ -3889,14 +3955,14 @@ fn updateLazyValue(
3889 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));3955 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
3890 if (try uav_ty.onePossibleValue(pt)) |_| {3956 if (try uav_ty.onePossibleValue(pt)) |_| {
3891 try wip_nav.abbrevCode(.udata_comptime_value);3957 try wip_nav.abbrevCode(.udata_comptime_value);
3892 try uleb128(diw, ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse3958 try dibw.writeLeb128(ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse
3893 uav_ty.abiAlignment(zcu).toByteUnits().?);3959 uav_ty.abiAlignment(zcu).toByteUnits().?);
3894 break :location;3960 break :location;
3895 } else break try wip_nav.getValueEntry(.fromInterned(uav.val));3961 } else break try wip_nav.getValueEntry(.fromInterned(uav.val));
3896 },3962 },
3897 .int => {3963 .int => {
3898 try wip_nav.abbrevCode(.udata_comptime_value);3964 try wip_nav.abbrevCode(.udata_comptime_value);
3899 try uleb128(diw, byte_offset);3965 try dibw.writeLeb128(byte_offset);
3900 break :location;3966 break :location;
3901 },3967 },
3902 .eu_payload => |eu_ptr| {3968 .eu_payload => |eu_ptr| {
...@@ -3935,7 +4001,7 @@ fn updateLazyValue(...@@ -3935,7 +4001,7 @@ fn updateLazyValue(
3935 try wip_nav.strp("len");4001 try wip_nav.strp("len");
3936 try wip_nav.blockValue(src_loc, .fromInterned(slice.len));4002 try wip_nav.blockValue(src_loc, .fromInterned(slice.len));
3937 }4003 }
3938 try uleb128(diw, @intFromEnum(AbbrevCode.null));4004 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3939 },4005 },
3940 .opt => |opt| {4006 .opt => |opt| {
3941 const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);4007 const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);
...@@ -3945,7 +4011,7 @@ fn updateLazyValue(...@@ -3945,7 +4011,7 @@ fn updateLazyValue(
3945 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);4011 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
3946 try wip_nav.strp("has_value");4012 try wip_nav.strp("has_value");
3947 switch (optRepr(opt_child_type, zcu)) {4013 switch (optRepr(opt_child_type, zcu)) {
3948 .opv_null => try uleb128(diw, 0),4014 .opv_null => try dibw.writeUleb128(0),
3949 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),4015 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
3950 .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),4016 .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
3951 .pointer => if (opt_child_type.comptimeOnly(zcu)) {4017 .pointer => if (opt_child_type.comptimeOnly(zcu)) {
...@@ -3955,8 +4021,8 @@ fn updateLazyValue(...@@ -3955,8 +4021,8 @@ fn updateLazyValue(
3955 .none => 0,4021 .none => 0,
3956 else => opt_child_type.ptrAlignment(zcu).toByteUnits().?,4022 else => opt_child_type.ptrAlignment(zcu).toByteUnits().?,
3957 });4023 });
3958 try uleb128(diw, bytes.len);4024 try dibw.writeLeb128(bytes.len);
3959 try diw.writeAll(bytes);4025 try dibw.writeAll(bytes);
3960 } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)),4026 } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
3961 }4027 }
3962 }4028 }
...@@ -3975,7 +4041,7 @@ fn updateLazyValue(...@@ -3975,7 +4041,7 @@ fn updateLazyValue(
3975 else4041 else
3976 try wip_nav.blockValue(src_loc, .fromInterned(opt.val));4042 try wip_nav.blockValue(src_loc, .fromInterned(opt.val));
3977 }4043 }
3978 try uleb128(diw, @intFromEnum(AbbrevCode.null));4044 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
3979 },4045 },
3980 .aggregate => |aggregate| {4046 .aggregate => |aggregate| {
3981 try wip_nav.abbrevCode(.aggregate_comptime_value);4047 try wip_nav.abbrevCode(.aggregate_comptime_value);
...@@ -4060,7 +4126,7 @@ fn updateLazyValue(...@@ -4060,7 +4126,7 @@ fn updateLazyValue(
4060 },4126 },
4061 else => unreachable,4127 else => unreachable,
4062 }4128 }
4063 try uleb128(diw, @intFromEnum(AbbrevCode.null));4129 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
4064 },4130 },
4065 .un => |un| {4131 .un => |un| {
4066 try wip_nav.abbrevCode(.aggregate_comptime_value);4132 try wip_nav.abbrevCode(.aggregate_comptime_value);
...@@ -4085,11 +4151,11 @@ fn updateLazyValue(...@@ -4085,11 +4151,11 @@ fn updateLazyValue(
4085 else4151 else
4086 try wip_nav.blockValue(src_loc, .fromInterned(un.val));4152 try wip_nav.blockValue(src_loc, .fromInterned(un.val));
4087 }4153 }
4088 try uleb128(diw, @intFromEnum(AbbrevCode.null));4154 try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
4089 },4155 },
4090 .memoized_call => unreachable, // not a value4156 .memoized_call => unreachable, // not a value
4091 }4157 }
4092 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);4158 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.getWritten());
4093}4159}
40944160
4095fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {4161fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {
...@@ -4109,12 +4175,12 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {...@@ -4109,12 +4175,12 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {
4109 };4175 };
4110}4176}
41114177
4112pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void {4178fn updateContainerTypeInner(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) anyerror!void {
4113 const zcu = pt.zcu;4179 const zcu = pt.zcu;
4114 const ip = &zcu.intern_pool;4180 const ip = &zcu.intern_pool;
4115 const ty: Type = .fromInterned(type_index);4181 const ty: Type = .fromInterned(type_index);
4116 const ty_src_loc = ty.srcLoc(zcu);4182 const ty_src_loc = ty.srcLoc(zcu);
4117 log.debug("updateContainerType({})", .{ty.fmt(pt)});4183 log.debug("updateContainerType({f})", .{ty.fmt(pt)});
41184184
4119 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;4185 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;
4120 const file = zcu.fileByIndex(inst_info.file);4186 const file = zcu.fileByIndex(inst_info.file);
...@@ -4432,29 +4498,31 @@ pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void {...@@ -4432,29 +4498,31 @@ pub fn freeNav(dwarf: *Dwarf, nav_index: InternPool.Nav.Index) void {
4432 _ = nav_index;4498 _ = nav_index;
4433}4499}
44344500
4435fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(AbbrevCode).@"enum".tag_type {4501fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) anyerror!@typeInfo(AbbrevCode).@"enum".tag_type {
4436 assert(abbrev_code != .null);4502 assert(abbrev_code != .null);
4437 const entry: Entry.Index = @enumFromInt(@intFromEnum(abbrev_code));4503 const entry: Entry.Index = @enumFromInt(@intFromEnum(abbrev_code));
4438 if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @intFromEnum(abbrev_code);4504 if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @intFromEnum(abbrev_code);
4439 var debug_abbrev: std.ArrayList(u8) = .init(dwarf.gpa);4505 var daaw: std.io.AllocatingWriter = undefined;
4440 defer debug_abbrev.deinit();4506 daaw.init(dwarf.gpa);
4441 const daw = debug_abbrev.writer();4507 defer daaw.deinit();
4508 const dabw = &daaw.buffered_writer;
4442 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);4509 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
4443 try uleb128(daw, @intFromEnum(abbrev_code));4510 try dabw.writeLeb128(@intFromEnum(abbrev_code));
4444 try uleb128(daw, @intFromEnum(abbrev.tag));4511 try dabw.writeLeb128(@intFromEnum(abbrev.tag));
4445 try daw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);4512 try dabw.writeByte(if (abbrev.children) DW.CHILDREN.yes else DW.CHILDREN.no);
4446 for (abbrev.attrs) |*attr| inline for (attr) |info| try uleb128(daw, @intFromEnum(info));4513 for (abbrev.attrs) |*attr| inline for (attr) |info| try dabw.writeLeb128(@intFromEnum(info));
4447 for (0..2) |_| try uleb128(daw, 0);4514 for (0..2) |_| try dabw.writeUleb128(0);
4448 try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, debug_abbrev.items);4515 try dwarf.debug_abbrev.section.replaceEntry(DebugAbbrev.unit, entry, dwarf, daaw.getWritten());
4449 return @intFromEnum(abbrev_code);4516 return @intFromEnum(abbrev_code);
4450}4517}
44514518
4452pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {4519pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4520 const gpa = dwarf.gpa;
4453 const zcu = pt.zcu;4521 const zcu = pt.zcu;
4454 const ip = &zcu.intern_pool;4522 const ip = &zcu.intern_pool;
44554523
4456 {4524 {
4457 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type);4525 const type_gop = try dwarf.types.getOrPut(gpa, .anyerror_type);
4458 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main);4526 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main);
4459 var wip_nav: WipNav = .{4527 var wip_nav: WipNav = .{
4460 .dwarf = dwarf,4528 .dwarf = dwarf,
...@@ -4467,14 +4535,15 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4467,14 +4535,15 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4467 .func_high_pc = undefined,4535 .func_high_pc = undefined,
4468 .blocks = undefined,4536 .blocks = undefined,
4469 .cfi = undefined,4537 .cfi = undefined,
4470 .debug_frame = .empty,4538 .debug_frame = undefined,
4471 .debug_info = .empty,4539 .debug_info = undefined,
4472 .debug_line = .empty,4540 .debug_line = undefined,
4473 .debug_loclists = .empty,4541 .debug_loclists = undefined,
4474 .pending_lazy = .empty,4542 .pending_lazy = .empty,
4475 };4543 };
4544 wip_nav.init();
4476 defer wip_nav.deinit();4545 defer wip_nav.deinit();
4477 const diw = wip_nav.debug_info.writer(dwarf.gpa);4546 const dibw = &wip_nav.debug_info.buffered_writer;
4478 const global_error_set_names = ip.global_error_set.getNamesFromMainThread();4547 const global_error_set_names = ip.global_error_set.getNamesFromMainThread();
4479 try wip_nav.abbrevCode(if (global_error_set_names.len == 0) .generated_empty_enum_type else .generated_enum_type);4548 try wip_nav.abbrevCode(if (global_error_set_names.len == 0) .generated_empty_enum_type else .generated_enum_type);
4480 try wip_nav.strp("anyerror");4549 try wip_nav.strp("anyerror");
...@@ -4484,50 +4553,52 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4484,50 +4553,52 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4484 } })));4553 } })));
4485 for (global_error_set_names, 1..) |name, value| {4554 for (global_error_set_names, 1..) |name, value| {
4486 try wip_nav.abbrevCode(.unsigned_enum_field);4555 try wip_nav.abbrevCode(.unsigned_enum_field);
4487 try uleb128(diw, value);4556 try dibw.writeLeb128(value);
4488 try wip_nav.strp(name.toSlice(ip));4557 try wip_nav.strp(name.toSlice(ip));
4489 }4558 }
4490 if (global_error_set_names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));4559 if (global_error_set_names.len > 0) try dibw.writeLeb128(@intFromEnum(AbbrevCode.null));
4491 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);4560 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, dibw.getWritten());
4492 try wip_nav.updateLazy(.unneeded);4561 try wip_nav.updateLazy(.unneeded);
4493 }4562 }
44944563
4495 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {4564 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {
4496 const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa);4565 const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, gpa);
4497 defer dwarf.gpa.free(root_dir_path);4566 defer gpa.free(root_dir_path);
4498 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);4567 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);
4499 }4568 }
45004569
4501 var header: std.ArrayList(u8) = .init(dwarf.gpa);4570 var header: std.ArrayListUnmanaged(u8) = .empty;
4502 defer header.deinit();4571 defer header.deinit(gpa);
4572 var header_bw: std.io.BufferedWriter = undefined;
4503 if (dwarf.debug_aranges.section.dirty) {4573 if (dwarf.debug_aranges.section.dirty) {
4504 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {4574 for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
4505 const unit: Unit.Index = @enumFromInt(unit_index);4575 const unit: Unit.Index = @enumFromInt(unit_index);
4506 unit_ptr.clear();4576 unit_ptr.clear();
4507 try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1);4577 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 1);
4508 header.clearRetainingCapacity();4578 try header.resize(gpa, unit_ptr.header_len);
4509 try header.ensureTotalCapacity(unit_ptr.header_len);4579 header_bw.initFixed(header.items);
4510 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|4580 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
4511 dwarf.debug_aranges.section.getUnit(next_unit).off4581 dwarf.debug_aranges.section.getUnit(next_unit).off
4512 else4582 else
4513 dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes();4583 dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes();
4514 switch (dwarf.format) {4584 switch (dwarf.format) {
4515 .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),4585 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
4516 .@"64" => {4586 .@"64" => {
4517 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);4587 header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
4518 std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);4588 header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
4519 },4589 },
4520 }4590 }
4521 std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 2, dwarf.endian);4591 header_bw.writeInt(u16, 2, dwarf.endian) catch unreachable;
4522 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4592 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4523 .source_off = @intCast(header.items.len),4593 .source_off = @intCast(header_bw.end),
4524 .target_sec = .debug_info,4594 .target_sec = .debug_info,
4525 .target_unit = unit,4595 .target_unit = unit,
4526 });4596 });
4527 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4597 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4528 header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 });4598 header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable;
4529 header.appendNTimesAssumeCapacity(0, unit_ptr.header_len - header.items.len);4599 header_bw.splatByteAll(0, unit_ptr.header_len - header_bw.end) catch unreachable;
4530 try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header.items);4600 assert(header_bw.end == header_bw.buffer.len);
4601 try unit_ptr.replaceHeader(&dwarf.debug_aranges.section, dwarf, header_bw.buffer);
4531 try unit_ptr.writeTrailer(&dwarf.debug_aranges.section, dwarf);4602 try unit_ptr.writeTrailer(&dwarf.debug_aranges.section, dwarf);
4532 }4603 }
4533 dwarf.debug_aranges.section.dirty = false;4604 dwarf.debug_aranges.section.dirty = false;
...@@ -4542,31 +4613,33 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4542,31 +4613,33 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4542 dev.check(.x86_64_backend);4613 dev.check(.x86_64_backend);
4543 const Register = @import("../arch/x86_64/bits.zig").Register;4614 const Register = @import("../arch/x86_64/bits.zig").Register;
4544 for (dwarf.debug_frame.section.units.items) |*unit| {4615 for (dwarf.debug_frame.section.units.items) |*unit| {
4545 header.clearRetainingCapacity();4616 try header.resize(gpa, unit.header_len);
4546 try header.ensureTotalCapacity(unit.header_len);4617 header_bw.initFixed(header.items);
4547 const unit_len = unit.header_len - dwarf.unitLengthBytes();4618 const unit_len = unit.header_len - dwarf.unitLengthBytes();
4548 switch (dwarf.format) {4619 switch (dwarf.format) {
4549 .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),4620 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
4550 .@"64" => {4621 .@"64" => {
4551 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);4622 header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
4552 std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);4623 header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
4553 },4624 },
4554 }4625 }
4555 header.appendNTimesAssumeCapacity(0, 4);4626 header_bw.splatByteAll(0, 4) catch unreachable;
4556 header.appendAssumeCapacity(1);4627 header_bw.writeByte(1) catch unreachable;
4557 header.appendSliceAssumeCapacity("zR\x00");4628 header_bw.writeAll("zR\x00") catch unreachable;
4558 uleb128(header.fixedWriter(), dwarf.debug_frame.header.code_alignment_factor) catch unreachable;4629 header_bw.writeLeb128(dwarf.debug_frame.header.code_alignment_factor) catch unreachable;
4559 sleb128(header.fixedWriter(), dwarf.debug_frame.header.data_alignment_factor) catch unreachable;4630 header_bw.writeLeb128(dwarf.debug_frame.header.data_alignment_factor) catch unreachable;
4560 uleb128(header.fixedWriter(), dwarf.debug_frame.header.return_address_register) catch unreachable;4631 header_bw.writeLeb128(dwarf.debug_frame.header.return_address_register) catch unreachable;
4561 uleb128(header.fixedWriter(), 1) catch unreachable;4632 header_bw.writeUleb128(1) catch unreachable;
4562 header.appendAssumeCapacity(DW.EH.PE.pcrel | DW.EH.PE.sdata4);4633 header_bw.writeByte(DW.EH.PE.pcrel | DW.EH.PE.sdata4) catch unreachable;
4563 header.appendAssumeCapacity(DW.CFA.def_cfa_sf);4634 header_bw.writeByte(DW.CFA.def_cfa_sf) catch unreachable;
4564 uleb128(header.fixedWriter(), Register.rsp.dwarfNum()) catch unreachable;4635 header_bw.writeUleb128(1) catch unreachable;
4565 sleb128(header.fixedWriter(), -1) catch unreachable;4636 header_bw.writeLeb128(Register.rsp.dwarfNum()) catch unreachable;
4566 header.appendAssumeCapacity(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum());4637 header_bw.writeSleb128(-1) catch unreachable;
4567 uleb128(header.fixedWriter(), 1) catch unreachable;4638 header_bw.writeByte(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()) catch unreachable;
4568 header.appendNTimesAssumeCapacity(DW.CFA.nop, unit.header_len - header.items.len);4639 header_bw.writeUleb128(1) catch unreachable;
4569 try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header.items);4640 header_bw.splatByteAll(DW.CFA.nop, unit.header_len - header_bw.end) catch unreachable;
4641 assert(header_bw.end == header_bw.buffer.len);
4642 try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header_bw.buffer);
4570 try unit.writeTrailer(&dwarf.debug_frame.section, dwarf);4643 try unit.writeTrailer(&dwarf.debug_frame.section, dwarf);
4571 }4644 }
4572 },4645 },
...@@ -4579,83 +4652,84 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4579,83 +4652,84 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4579 for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {4652 for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {
4580 const unit: Unit.Index = @enumFromInt(unit_index);4653 const unit: Unit.Index = @enumFromInt(unit_index);
4581 unit_ptr.clear();4654 unit_ptr.clear();
4582 try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1);4655 try unit_ptr.cross_unit_relocs.ensureTotalCapacity(gpa, 1);
4583 try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7);4656 try unit_ptr.cross_section_relocs.ensureTotalCapacity(gpa, 7);
4584 header.clearRetainingCapacity();4657 try header.resize(gpa, unit_ptr.header_len);
4585 try header.ensureTotalCapacity(unit_ptr.header_len);4658 header_bw.initFixed(header.items);
4586 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|4659 const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
4587 dwarf.debug_info.section.getUnit(next_unit).off4660 dwarf.debug_info.section.getUnit(next_unit).off
4588 else4661 else
4589 dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes();4662 dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes();
4590 switch (dwarf.format) {4663 switch (dwarf.format) {
4591 .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),4664 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
4592 .@"64" => {4665 .@"64" => {
4593 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);4666 header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
4594 std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);4667 header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
4595 },4668 },
4596 }4669 }
4597 std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian);4670 header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable;
4598 header.appendSliceAssumeCapacity(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) });4671 header_bw.writeAll(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }) catch unreachable;
4599 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4672 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4600 .source_off = @intCast(header.items.len),4673 .source_off = @intCast(header_bw.end),
4601 .target_sec = .debug_abbrev,4674 .target_sec = .debug_abbrev,
4602 .target_unit = DebugAbbrev.unit,4675 .target_unit = DebugAbbrev.unit,
4603 });4676 });
4604 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4677 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4605 const compile_unit_off: u32 = @intCast(header.items.len);4678 const compile_unit_off: u32 = @intCast(header_bw.end);
4606 uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.compile_unit)) catch unreachable;4679 header_bw.writeLeb128(try dwarf.refAbbrevCode(.compile_unit)) catch unreachable;
4607 header.appendAssumeCapacity(DW.LANG.Zig);4680 header_bw.writeByte(DW.LANG.Zig) catch unreachable;
4608 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4681 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4609 .source_off = @intCast(header.items.len),4682 .source_off = @intCast(header_bw.end),
4610 .target_sec = .debug_line_str,4683 .target_sec = .debug_line_str,
4611 .target_unit = StringSection.unit,4684 .target_unit = StringSection.unit,
4612 .target_entry = (try dwarf.debug_line_str.addString(dwarf, "zig " ++ @import("build_options").version)).toOptional(),4685 .target_entry = (try dwarf.debug_line_str.addString(dwarf, "zig " ++ @import("build_options").version)).toOptional(),
4613 });4686 });
4614 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4687 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4615 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4688 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4616 .source_off = @intCast(header.items.len),4689 .source_off = @intCast(header_bw.end),
4617 .target_sec = .debug_line_str,4690 .target_sec = .debug_line_str,
4618 .target_unit = StringSection.unit,4691 .target_unit = StringSection.unit,
4619 .target_entry = mod_info.root_dir_path.toOptional(),4692 .target_entry = mod_info.root_dir_path.toOptional(),
4620 });4693 });
4621 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4694 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4622 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4695 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4623 .source_off = @intCast(header.items.len),4696 .source_off = @intCast(header_bw.end),
4624 .target_sec = .debug_line_str,4697 .target_sec = .debug_line_str,
4625 .target_unit = StringSection.unit,4698 .target_unit = StringSection.unit,
4626 .target_entry = (try dwarf.debug_line_str.addString(dwarf, mod.root_src_path)).toOptional(),4699 .target_entry = (try dwarf.debug_line_str.addString(dwarf, mod.root_src_path)).toOptional(),
4627 });4700 });
4628 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4701 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4629 unit_ptr.cross_unit_relocs.appendAssumeCapacity(.{4702 unit_ptr.cross_unit_relocs.appendAssumeCapacity(.{
4630 .source_off = @intCast(header.items.len),4703 .source_off = @intCast(header_bw.end),
4631 .target_unit = .main,4704 .target_unit = .main,
4632 .target_off = compile_unit_off,4705 .target_off = compile_unit_off,
4633 });4706 });
4634 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4707 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4635 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4708 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4636 .source_off = @intCast(header.items.len),4709 .source_off = @intCast(header_bw.end),
4637 .target_sec = .debug_line,4710 .target_sec = .debug_line,
4638 .target_unit = unit,4711 .target_unit = unit,
4639 });4712 });
4640 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4713 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4641 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4714 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4642 .source_off = @intCast(header.items.len),4715 .source_off = @intCast(header_bw.end),
4643 .target_sec = .debug_rnglists,4716 .target_sec = .debug_rnglists,
4644 .target_unit = unit,4717 .target_unit = unit,
4645 .target_off = DebugRngLists.baseOffset(dwarf),4718 .target_off = DebugRngLists.baseOffset(dwarf),
4646 });4719 });
4647 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4720 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4648 uleb128(header.fixedWriter(), 0) catch unreachable;4721 header_bw.writeUleb128(0) catch unreachable;
4649 uleb128(header.fixedWriter(), try dwarf.refAbbrevCode(.module)) catch unreachable;4722 header_bw.writeLeb128(try dwarf.refAbbrevCode(.module)) catch unreachable;
4650 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{4723 unit_ptr.cross_section_relocs.appendAssumeCapacity(.{
4651 .source_off = @intCast(header.items.len),4724 .source_off = @intCast(header_bw.end),
4652 .target_sec = .debug_str,4725 .target_sec = .debug_str,
4653 .target_unit = StringSection.unit,4726 .target_unit = StringSection.unit,
4654 .target_entry = (try dwarf.debug_str.addString(dwarf, mod.fully_qualified_name)).toOptional(),4727 .target_entry = (try dwarf.debug_str.addString(dwarf, mod.fully_qualified_name)).toOptional(),
4655 });4728 });
4656 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4729 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4657 uleb128(header.fixedWriter(), 0) catch unreachable;4730 header_bw.writeUleb128(0) catch unreachable;
4658 try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header.items);4731 assert(header_bw.end == header_bw.buffer.len);
4732 try unit_ptr.replaceHeader(&dwarf.debug_info.section, dwarf, header_bw.buffer);
4659 try unit_ptr.writeTrailer(&dwarf.debug_info.section, dwarf);4733 try unit_ptr.writeTrailer(&dwarf.debug_info.section, dwarf);
4660 }4734 }
4661 dwarf.debug_info.section.dirty = false;4735 dwarf.debug_info.section.dirty = false;
...@@ -4679,33 +4753,37 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4679,33 +4753,37 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4679 );4753 );
4680 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {4754 for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
4681 unit.clear();4755 unit.clear();
4682 try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, mod_info.dirs.count() + 2 * (mod_info.files.count()));4756 try unit.cross_section_relocs.ensureTotalCapacity(gpa, mod_info.dirs.count() + 2 * (mod_info.files.count()));
4683 header.clearRetainingCapacity();4757 try header.resize(gpa, unit.header_len);
4684 try header.ensureTotalCapacity(unit.header_len);4758 header_bw.initFixed(header.items);
4685 const unit_len = (if (unit.next.unwrap()) |next_unit|4759 const unit_len = (if (unit.next.unwrap()) |next_unit|
4686 dwarf.debug_line.section.getUnit(next_unit).off4760 dwarf.debug_line.section.getUnit(next_unit).off
4687 else4761 else
4688 dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes();4762 dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes();
4689 switch (dwarf.format) {4763 switch (dwarf.format) {
4690 .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),4764 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
4691 .@"64" => {4765 .@"64" => {
4692 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);4766 header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
4693 std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);4767 header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
4694 },4768 },
4695 }4769 }
4696 std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian);4770 header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable;
4697 header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 });4771 header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable;
4698 dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len);4772 dwarf.writeIntTo(
4773 &header_bw,
4774 dwarf.sectionOffsetBytes(),
4775 unit.header_len - header_bw.end,
4776 ) catch unreachable;
4699 const StandardOpcode = DeclValEnum(DW.LNS);4777 const StandardOpcode = DeclValEnum(DW.LNS);
4700 header.appendSliceAssumeCapacity(&[_]u8{4778 header_bw.writeAll(&.{
4701 dwarf.debug_line.header.minimum_instruction_length,4779 dwarf.debug_line.header.minimum_instruction_length,
4702 dwarf.debug_line.header.maximum_operations_per_instruction,4780 dwarf.debug_line.header.maximum_operations_per_instruction,
4703 @intFromBool(dwarf.debug_line.header.default_is_stmt),4781 @intFromBool(dwarf.debug_line.header.default_is_stmt),
4704 @bitCast(dwarf.debug_line.header.line_base),4782 @bitCast(dwarf.debug_line.header.line_base),
4705 dwarf.debug_line.header.line_range,4783 dwarf.debug_line.header.line_range,
4706 dwarf.debug_line.header.opcode_base,4784 dwarf.debug_line.header.opcode_base,
4707 });4785 }) catch unreachable;
4708 header.appendSliceAssumeCapacity(std.enums.EnumArray(StandardOpcode, u8).init(.{4786 header_bw.writeAll(std.enums.EnumArray(StandardOpcode, u8).init(.{
4709 .extended_op = undefined,4787 .extended_op = undefined,
4710 .copy = 0,4788 .copy = 0,
4711 .advance_pc = 1,4789 .advance_pc = 1,
...@@ -4719,44 +4797,45 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4719,44 +4797,45 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4719 .set_prologue_end = 0,4797 .set_prologue_end = 0,
4720 .set_epilogue_begin = 0,4798 .set_epilogue_begin = 0,
4721 .set_isa = 1,4799 .set_isa = 1,
4722 }).values[1..dwarf.debug_line.header.opcode_base]);4800 }).values[1..dwarf.debug_line.header.opcode_base]) catch unreachable;
4723 header.appendAssumeCapacity(1);4801 header_bw.writeByte(1) catch unreachable;
4724 uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable;4802 header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable;
4725 uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable;4803 header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable;
4726 uleb128(header.fixedWriter(), mod_info.dirs.count()) catch unreachable;4804 header_bw.writeLeb128(mod_info.dirs.count()) catch unreachable;
4727 for (mod_info.dirs.keys()) |dir_unit| {4805 for (mod_info.dirs.keys()) |dir_unit| {
4728 unit.cross_section_relocs.appendAssumeCapacity(.{4806 unit.cross_section_relocs.appendAssumeCapacity(.{
4729 .source_off = @intCast(header.items.len),4807 .source_off = @intCast(header_bw.end),
4730 .target_sec = .debug_line_str,4808 .target_sec = .debug_line_str,
4731 .target_unit = StringSection.unit,4809 .target_unit = StringSection.unit,
4732 .target_entry = dwarf.getModInfo(dir_unit).root_dir_path.toOptional(),4810 .target_entry = dwarf.getModInfo(dir_unit).root_dir_path.toOptional(),
4733 });4811 });
4734 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4812 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4735 }4813 }
4736 const dir_index_info = DebugLine.dirIndexInfo(@intCast(mod_info.dirs.count()));4814 const dir_index_info = DebugLine.dirIndexInfo(@intCast(mod_info.dirs.count()));
4737 header.appendAssumeCapacity(3);4815 header_bw.writeByte(3) catch unreachable;
4738 uleb128(header.fixedWriter(), DW.LNCT.path) catch unreachable;4816 header_bw.writeLeb128(@as(u14, DW.LNCT.path)) catch unreachable;
4739 uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable;4817 header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable;
4740 uleb128(header.fixedWriter(), DW.LNCT.directory_index) catch unreachable;4818 header_bw.writeLeb128(@as(u14, DW.LNCT.directory_index)) catch unreachable;
4741 uleb128(header.fixedWriter(), @intFromEnum(dir_index_info.form)) catch unreachable;4819 header_bw.writeLeb128(@intFromEnum(dir_index_info.form)) catch unreachable;
4742 uleb128(header.fixedWriter(), DW.LNCT.LLVM_source) catch unreachable;4820 header_bw.writeLeb128(@as(u14, DW.LNCT.LLVM_source)) catch unreachable;
4743 uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable;4821 header_bw.writeLeb128(@as(u13, DW.FORM.line_strp)) catch unreachable;
4744 uleb128(header.fixedWriter(), mod_info.files.count()) catch unreachable;4822 header_bw.writeLeb128(mod_info.files.count()) catch unreachable;
4745 for (mod_info.files.keys()) |file_index| {4823 for (mod_info.files.keys()) |file_index| {
4746 const file = zcu.fileByIndex(file_index);4824 const file = zcu.fileByIndex(file_index);
4747 unit.cross_section_relocs.appendAssumeCapacity(.{4825 unit.cross_section_relocs.appendAssumeCapacity(.{
4748 .source_off = @intCast(header.items.len),4826 .source_off = @intCast(header_bw.end),
4749 .target_sec = .debug_line_str,4827 .target_sec = .debug_line_str,
4750 .target_unit = StringSection.unit,4828 .target_unit = StringSection.unit,
4751 .target_entry = (try dwarf.debug_line_str.addString(dwarf, file.sub_file_path)).toOptional(),4829 .target_entry = (try dwarf.debug_line_str.addString(dwarf, file.sub_file_path)).toOptional(),
4752 });4830 });
4753 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4831 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());
4754 dwarf.writeInt(4832 dwarf.writeIntTo(
4755 header.addManyAsSliceAssumeCapacity(dir_index_info.bytes),4833 &header_bw,
4834 dir_index_info.bytes,
4756 mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod.?).?) orelse 0,4835 mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod.?).?) orelse 0,
4757 );4836 );
4758 unit.cross_section_relocs.appendAssumeCapacity(.{4837 unit.cross_section_relocs.appendAssumeCapacity(.{
4759 .source_off = @intCast(header.items.len),4838 .source_off = @intCast(header_bw.end),
4760 .target_sec = .debug_line_str,4839 .target_sec = .debug_line_str,
4761 .target_unit = StringSection.unit,4840 .target_unit = StringSection.unit,
4762 .target_entry = (try dwarf.debug_line_str.addString(4841 .target_entry = (try dwarf.debug_line_str.addString(
...@@ -4764,9 +4843,10 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4764,9 +4843,10 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4764 if (file.is_builtin) file.source.? else "",4843 if (file.is_builtin) file.source.? else "",
4765 )).toOptional(),4844 )).toOptional(),
4766 });4845 });
4767 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4846 header_bw.splatByteAll(0, dwarf.sectionOffsetBytes()) catch unreachable;
4768 }4847 }
4769 try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header.items);4848 assert(header_bw.end == header_bw.buffer.len);
4849 try unit.replaceHeader(&dwarf.debug_line.section, dwarf, header_bw.buffer);
4770 try unit.writeTrailer(&dwarf.debug_line.section, dwarf);4850 try unit.writeTrailer(&dwarf.debug_line.section, dwarf);
4771 }4851 }
4772 dwarf.debug_line.section.dirty = false;4852 dwarf.debug_line.section.dirty = false;
...@@ -4782,24 +4862,25 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4782,24 +4862,25 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4782 }4862 }
4783 if (dwarf.debug_rnglists.section.dirty) {4863 if (dwarf.debug_rnglists.section.dirty) {
4784 for (dwarf.debug_rnglists.section.units.items) |*unit| {4864 for (dwarf.debug_rnglists.section.units.items) |*unit| {
4785 header.clearRetainingCapacity();4865 try header.resize(gpa, unit.header_len);
4786 try header.ensureTotalCapacity(unit.header_len);4866 header_bw.initFixed(header.items);
4787 const unit_len = (if (unit.next.unwrap()) |next_unit|4867 const unit_len = (if (unit.next.unwrap()) |next_unit|
4788 dwarf.debug_rnglists.section.getUnit(next_unit).off4868 dwarf.debug_rnglists.section.getUnit(next_unit).off
4789 else4869 else
4790 dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes();4870 dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes();
4791 switch (dwarf.format) {4871 switch (dwarf.format) {
4792 .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian),4872 .@"32" => header_bw.writeInt(u32, @intCast(unit_len), dwarf.endian) catch unreachable,
4793 .@"64" => {4873 .@"64" => {
4794 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian);4874 header_bw.writeInt(u32, std.math.maxInt(u32), dwarf.endian) catch unreachable;
4795 std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian);4875 header_bw.writeInt(u64, unit_len, dwarf.endian) catch unreachable;
4796 },4876 },
4797 }4877 }
4798 std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian);4878 header_bw.writeInt(u16, 5, dwarf.endian) catch unreachable;
4799 header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 });4879 header_bw.writeAll(&.{ @intFromEnum(dwarf.address_size), 0 }) catch unreachable;
4800 std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), 1, dwarf.endian);4880 header_bw.writeInt(u32, 1, dwarf.endian) catch unreachable;
4801 dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), dwarf.sectionOffsetBytes() * 1);4881 dwarf.writeIntTo(&header_bw, dwarf.sectionOffsetBytes(), dwarf.sectionOffsetBytes() * 1) catch unreachable;
4802 try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header.items);4882 assert(header_bw.end == header_bw.buffer.len);
4883 try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header_bw.buffer);
4803 try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf);4884 try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf);
4804 }4885 }
4805 dwarf.debug_rnglists.section.dirty = false;4886 dwarf.debug_rnglists.section.dirty = false;
...@@ -4815,6 +4896,9 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4815,6 +4896,9 @@ pub fn flush(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4815 assert(!dwarf.debug_str.section.dirty);4896 assert(!dwarf.debug_str.section.dirty);
4816}4897}
48174898
4899const sleb128 = {};
4900const uleb128 = {};
4901
4818pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {4902pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {
4819 for ([_]*Section{4903 for ([_]*Section{
4820 &dwarf.debug_abbrev.section,4904 &dwarf.debug_abbrev.section,
...@@ -5979,7 +6063,7 @@ fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index {...@@ -5979,7 +6063,7 @@ fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index {
5979 return entry;6063 return entry;
5980}6064}
59816065
5982fn freeCommonEntry(dwarf: *Dwarf, unit: Unit.Index, entry: Entry.Index) UpdateError!void {6066fn freeCommonEntry(dwarf: *Dwarf, unit: Unit.Index, entry: Entry.Index) anyerror!void {
5983 try dwarf.debug_aranges.section.freeEntry(unit, entry, dwarf);6067 try dwarf.debug_aranges.section.freeEntry(unit, entry, dwarf);
5984 try dwarf.debug_frame.section.freeEntry(unit, entry, dwarf);6068 try dwarf.debug_frame.section.freeEntry(unit, entry, dwarf);
5985 try dwarf.debug_info.section.freeEntry(unit, entry, dwarf);6069 try dwarf.debug_info.section.freeEntry(unit, entry, dwarf);
...@@ -5998,6 +6082,11 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {...@@ -5998,6 +6082,11 @@ fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {
5998 }6082 }
5999}6083}
60006084
6085fn writeIntTo(dwarf: *Dwarf, bw: *std.io.BufferedWriter, len: usize, int: u64) anyerror!void {
6086 dwarf.writeInt((try bw.writableSlice(len))[0..len], int);
6087 bw.advance(len);
6088}
6089
6001fn resolveReloc(dwarf: *Dwarf, source: u64, target: u64, size: u32) RelocError!void {6090fn resolveReloc(dwarf: *Dwarf, source: u64, target: u64, size: u32) RelocError!void {
6002 var buf: [8]u8 = undefined;6091 var buf: [8]u8 = undefined;
6003 dwarf.writeInt(buf[0..size], target);6092 dwarf.writeInt(buf[0..size], target);
...@@ -6019,21 +6108,34 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 {...@@ -6019,21 +6108,34 @@ fn sectionOffsetBytes(dwarf: *Dwarf) u32 {
6019}6108}
60206109
6021fn uleb128Bytes(value: anytype) u32 {6110fn uleb128Bytes(value: anytype) u32 {
6022 var buffer: [std.atomic.cache_line]u8 = undefined;6111 return leb128Bytes(switch (@typeInfo(@TypeOf(value))) {
6023 var bw: std.io.BufferedWriter = .{6112 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
6024 .unbuffered_writer = .null,6113 .int => |value_info| switch (value_info.signedness) {
6025 .buffer = .initBuffer(&buffer),6114 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),
6026 };6115 .unsigned => value,
6027 return try std.leb.writeUleb128Count(&bw, value);6116 },
6117 else => comptime unreachable,
6118 });
6028}6119}
6029
6030fn sleb128Bytes(value: anytype) u32 {6120fn sleb128Bytes(value: anytype) u32 {
6031 var buffer: [std.atomic.cache_line]u8 = undefined;6121 return leb128Bytes(switch (@typeInfo(@TypeOf(value))) {
6032 var bw: std.io.BufferedWriter = .{6122 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
6033 .unbuffered_writer = .null,6123 .int => |value_info| switch (value_info.signedness) {
6034 .buffer = .initBuffer(&buffer),6124 .signed => value,
6035 };6125 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),
6036 return try std.leb.writeIleb128Count(&bw, value);6126 },
6127 else => comptime unreachable,
6128 });
6129}
6130fn leb128Bytes(value: anytype) u32 {
6131 const value_info = @typeInfo(@TypeOf(value)).int;
6132 var buffer: [
6133 std.math.divCeil(u16, @intFromBool(value_info.signedness == .signed) + value_info.bits, 7) catch unreachable
6134 ]u8 = undefined;
6135 var bw: std.io.BufferedWriter = undefined;
6136 bw.initFixed(&buffer);
6137 bw.writeLeb128(value) catch unreachable;
6138 return @intCast(bw.end);
6037}6139}
60386140
6039/// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional6141/// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional
...@@ -6055,7 +6157,5 @@ const codegen = @import("../codegen.zig");...@@ -6055,7 +6157,5 @@ const codegen = @import("../codegen.zig");
6055const dev = @import("../dev.zig");6157const dev = @import("../dev.zig");
6056const link = @import("../link.zig");6158const link = @import("../link.zig");
6057const log = std.log.scoped(.dwarf);6159const log = std.log.scoped(.dwarf);
6058const sleb128 = std.leb.writeIleb128;
6059const std = @import("std");6160const std = @import("std");
6060const target_info = @import("../target.zig");6161const target_info = @import("../target.zig");
6061const uleb128 = std.leb.writeUleb128;
src/link/Elf.zig+132-143
...@@ -702,7 +702,7 @@ pub fn allocateChunk(self: *Elf, args: struct {...@@ -702,7 +702,7 @@ pub fn allocateChunk(self: *Elf, args: struct {
702 shdr.sh_addr + res.value,702 shdr.sh_addr + res.value,
703 shdr.sh_offset + res.value,703 shdr.sh_offset + res.value,
704 });704 });
705 log.debug(" placement {}, {s}", .{705 log.debug(" placement {f}, {s}", .{
706 res.placement,706 res.placement,
707 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",707 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",
708 });708 });
...@@ -869,7 +869,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -869,7 +869,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
869 // Dump the state for easy debugging.869 // Dump the state for easy debugging.
870 // State can be dumped via `--debug-log link_state`.870 // State can be dumped via `--debug-log link_state`.
871 if (build_options.enable_logging) {871 if (build_options.enable_logging) {
872 state_log.debug("{}", .{self.dumpState()});872 state_log.debug("{f}", .{self.dumpState()});
873 }873 }
874874
875 // Beyond this point, everything has been allocated a virtual address and we can resolve875 // Beyond this point, everything has been allocated a virtual address and we can resolve
...@@ -1849,7 +1849,7 @@ pub fn updateMergeSectionSizes(self: *Elf) !void {...@@ -1849,7 +1849,7 @@ pub fn updateMergeSectionSizes(self: *Elf) !void {
18491849
1850pub fn writeMergeSections(self: *Elf) !void {1850pub fn writeMergeSections(self: *Elf) !void {
1851 const gpa = self.base.comp.gpa;1851 const gpa = self.base.comp.gpa;
1852 var buffer = std.ArrayList(u8).init(gpa);1852 var buffer: std.ArrayList(u8) = .init(gpa);
1853 defer buffer.deinit();1853 defer buffer.deinit();
18541854
1855 for (self.merge_sections.items) |*msec| {1855 for (self.merge_sections.items) |*msec| {
...@@ -2996,7 +2996,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -2996,7 +2996,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
2996 }2996 }
2997}2997}
29982998
2999fn writeAtoms(self: *Elf) !void {2999fn writeAtoms(self: *Elf) anyerror!void {
3000 const gpa = self.base.comp.gpa;3000 const gpa = self.base.comp.gpa;
30013001
3002 var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)) = .init(gpa);3002 var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)) = .init(gpa);
...@@ -3005,7 +3005,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -3005,7 +3005,7 @@ fn writeAtoms(self: *Elf) !void {
3005 undefs.deinit();3005 undefs.deinit();
3006 }3006 }
30073007
3008 var buffer = std.ArrayList(u8).init(gpa);3008 var buffer: std.ArrayList(u8) = .init(gpa);
3009 defer buffer.deinit();3009 defer buffer.deinit();
30103010
3011 const slice = self.sections.slice();3011 const slice = self.sections.slice();
...@@ -3028,14 +3028,14 @@ fn writeAtoms(self: *Elf) !void {...@@ -3028,14 +3028,14 @@ fn writeAtoms(self: *Elf) !void {
30283028
3029 if (self.requiresThunks()) {3029 if (self.requiresThunks()) {
3030 for (self.thunks.items) |th| {3030 for (self.thunks.items) |th| {
3031 const thunk_size = th.size(self);3031 try buffer.resize(th.size(self));
3032 try buffer.ensureUnusedCapacity(thunk_size);3032 var bw: std.io.BufferedWriter = undefined;
3033 bw.initFixed(buffer.items);
3033 const shdr = slice.items(.shdr)[th.output_section_index];3034 const shdr = slice.items(.shdr)[th.output_section_index];
3034 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;3035 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
3035 try th.write(self, buffer.writer());3036 try th.write(self, &bw);
3036 assert(buffer.items.len == thunk_size);3037 assert(bw.end == bw.buffer.len);
3037 try self.pwriteAll(buffer.items, offset);3038 try self.pwriteAll(bw.buffer, offset);
3038 buffer.clearRetainingCapacity();
3039 }3039 }
3040 }3040 }
3041}3041}
...@@ -3130,32 +3130,36 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -3130,32 +3130,36 @@ pub fn updateSymtabSize(self: *Elf) !void {
3130 strtab.sh_size = strsize + 1;3130 strtab.sh_size = strsize + 1;
3131}3131}
31323132
3133fn writeSyntheticSections(self: *Elf) !void {3133fn writeSyntheticSections(self: *Elf) anyerror!void {
3134 const gpa = self.base.comp.gpa;3134 const gpa = self.base.comp.gpa;
3135 const slice = self.sections.slice();3135 const slice = self.sections.slice();
31363136
3137 var buffer: std.ArrayListUnmanaged(u8) = .empty;
3138 defer buffer.deinit(gpa);
3139 var bw: std.io.BufferedWriter = undefined;
3140
3137 if (self.section_indexes.interp) |shndx| {3141 if (self.section_indexes.interp) |shndx| {
3138 var buffer: [256]u8 = undefined;
3139 const interp = self.getTarget().dynamic_linker.get().?;
3140 @memcpy(buffer[0..interp.len], interp);
3141 buffer[interp.len] = 0;
3142 const contents = buffer[0 .. interp.len + 1];
3143 const shdr = slice.items(.shdr)[shndx];3142 const shdr = slice.items(.shdr)[shndx];
3144 assert(shdr.sh_size == contents.len);3143 const interp = self.getTarget().dynamic_linker.get().?;
3145 try self.pwriteAll(contents, shdr.sh_offset);3144 assert(shdr.sh_size == interp.len + 1);
3145 try buffer.resize(gpa, shdr.sh_size);
3146 @memcpy(buffer.items[0..interp.len], interp);
3147 buffer.items[interp.len] = 0;
3148 try self.pwriteAll(buffer.items, shdr.sh_offset);
3146 }3149 }
31473150
3148 if (self.section_indexes.hash) |shndx| {3151 if (self.section_indexes.hash) |shndx| {
3149 const shdr = slice.items(.shdr)[shndx];3152 const shdr = slice.items(.shdr)[shndx];
3150 try self.pwriteAll(self.hash.buffer.items, shdr.sh_offset);3153 try self.pwriteAll(@ptrCast(self.hash.buffer), shdr.sh_offset);
3151 }3154 }
31523155
3153 if (self.section_indexes.gnu_hash) |shndx| {3156 if (self.section_indexes.gnu_hash) |shndx| {
3154 const shdr = slice.items(.shdr)[shndx];3157 const shdr = slice.items(.shdr)[shndx];
3155 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());3158 try buffer.resize(gpa, self.gnu_hash.size());
3156 defer buffer.deinit();3159 bw.initFixed(buffer.items);
3157 try self.gnu_hash.write(self, buffer.writer());3160 try self.gnu_hash.write(self, &bw);
3158 try self.pwriteAll(buffer.items, shdr.sh_offset);3161 assert(bw.end == bw.buffer.len);
3162 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3159 }3163 }
31603164
3161 if (self.section_indexes.versym) |shndx| {3165 if (self.section_indexes.versym) |shndx| {
...@@ -3165,26 +3169,29 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3165,26 +3169,29 @@ fn writeSyntheticSections(self: *Elf) !void {
31653169
3166 if (self.section_indexes.verneed) |shndx| {3170 if (self.section_indexes.verneed) |shndx| {
3167 const shdr = slice.items(.shdr)[shndx];3171 const shdr = slice.items(.shdr)[shndx];
3168 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size());3172 try buffer.resize(gpa, self.verneed.size());
3169 defer buffer.deinit();3173 bw.initFixed(buffer.items);
3170 try self.verneed.write(buffer.writer());3174 try self.verneed.write(&bw);
3171 try self.pwriteAll(buffer.items, shdr.sh_offset);3175 assert(bw.end == bw.buffer.len);
3176 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3172 }3177 }
31733178
3174 if (self.section_indexes.dynamic) |shndx| {3179 if (self.section_indexes.dynamic) |shndx| {
3175 const shdr = slice.items(.shdr)[shndx];3180 const shdr = slice.items(.shdr)[shndx];
3176 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self));3181 try buffer.resize(gpa, self.dynamic.size(self));
3177 defer buffer.deinit();3182 bw.initFixed(buffer.items);
3178 try self.dynamic.write(self, buffer.writer());3183 try self.dynamic.write(self, &bw);
3179 try self.pwriteAll(buffer.items, shdr.sh_offset);3184 assert(bw.end == bw.buffer.len);
3185 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3180 }3186 }
31813187
3182 if (self.section_indexes.dynsymtab) |shndx| {3188 if (self.section_indexes.dynsymtab) |shndx| {
3183 const shdr = slice.items(.shdr)[shndx];3189 const shdr = slice.items(.shdr)[shndx];
3184 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size());3190 try buffer.resize(gpa, self.dynsym.size());
3185 defer buffer.deinit();3191 bw.initFixed(buffer.items);
3186 try self.dynsym.write(self, buffer.writer());3192 try self.dynsym.write(self, &bw);
3187 try self.pwriteAll(buffer.items, shdr.sh_offset);3193 assert(bw.end == bw.buffer.len);
3194 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3188 }3195 }
31893196
3190 if (self.section_indexes.dynstrtab) |shndx| {3197 if (self.section_indexes.dynstrtab) |shndx| {
...@@ -3200,28 +3207,30 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3200,28 +3207,30 @@ fn writeSyntheticSections(self: *Elf) !void {
3200 };3207 };
3201 const shdr = slice.items(.shdr)[shndx];3208 const shdr = slice.items(.shdr)[shndx];
3202 const sh_size = try self.cast(usize, shdr.sh_size);3209 const sh_size = try self.cast(usize, shdr.sh_size);
3203 var buffer = try std.ArrayList(u8).initCapacity(gpa, @intCast(sh_size - existing_size));3210 try buffer.resize(gpa, @intCast(sh_size - existing_size));
3204 defer buffer.deinit();3211 bw.initFixed(buffer.items);
3205 try eh_frame.writeEhFrame(self, buffer.writer());3212 try eh_frame.writeEhFrame(self, &bw);
3206 assert(buffer.items.len == sh_size - existing_size);3213 assert(bw.end == bw.buffer.len);
3207 try self.pwriteAll(buffer.items, shdr.sh_offset + existing_size);3214 try self.pwriteAll(bw.buffer, shdr.sh_offset + existing_size);
3208 }3215 }
32093216
3210 if (self.section_indexes.eh_frame_hdr) |shndx| {3217 if (self.section_indexes.eh_frame_hdr) |shndx| {
3211 const shdr = slice.items(.shdr)[shndx];3218 const shdr = slice.items(.shdr)[shndx];
3212 const sh_size = try self.cast(usize, shdr.sh_size);3219 const sh_size = try self.cast(usize, shdr.sh_size);
3213 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);3220 try buffer.resize(gpa, sh_size);
3214 defer buffer.deinit();3221 bw.initFixed(buffer.items);
3215 try eh_frame.writeEhFrameHdr(self, buffer.writer());3222 try eh_frame.writeEhFrameHdr(self, &bw);
3216 try self.pwriteAll(buffer.items, shdr.sh_offset);3223 assert(bw.end == bw.buffer.len);
3224 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3217 }3225 }
32183226
3219 if (self.section_indexes.got) |index| {3227 if (self.section_indexes.got) |index| {
3220 const shdr = slice.items(.shdr)[index];3228 const shdr = slice.items(.shdr)[index];
3221 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));3229 try buffer.resize(gpa, self.got.size(self));
3222 defer buffer.deinit();3230 bw.initFixed(buffer.items);
3223 try self.got.write(self, buffer.writer());3231 try self.got.write(self, &bw);
3224 try self.pwriteAll(buffer.items, shdr.sh_offset);3232 assert(bw.end == bw.buffer.len);
3233 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3225 }3234 }
32263235
3227 if (self.section_indexes.rela_dyn) |shndx| {3236 if (self.section_indexes.rela_dyn) |shndx| {
...@@ -3234,26 +3243,29 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3234,26 +3243,29 @@ fn writeSyntheticSections(self: *Elf) !void {
32343243
3235 if (self.section_indexes.plt) |shndx| {3244 if (self.section_indexes.plt) |shndx| {
3236 const shdr = slice.items(.shdr)[shndx];3245 const shdr = slice.items(.shdr)[shndx];
3237 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));3246 try buffer.resize(gpa, self.plt.size(self));
3238 defer buffer.deinit();3247 bw.initFixed(buffer.items);
3239 try self.plt.write(self, buffer.writer());3248 try self.plt.write(self, &bw);
3240 try self.pwriteAll(buffer.items, shdr.sh_offset);3249 assert(bw.end == bw.buffer.len);
3250 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3241 }3251 }
32423252
3243 if (self.section_indexes.got_plt) |shndx| {3253 if (self.section_indexes.got_plt) |shndx| {
3244 const shdr = slice.items(.shdr)[shndx];3254 const shdr = slice.items(.shdr)[shndx];
3245 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self));3255 try buffer.resize(gpa, self.got_plt.size(self));
3246 defer buffer.deinit();3256 bw.initFixed(buffer.items);
3247 try self.got_plt.write(self, buffer.writer());3257 try self.got_plt.write(self, &bw);
3248 try self.pwriteAll(buffer.items, shdr.sh_offset);3258 assert(bw.end == bw.buffer.len);
3259 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3249 }3260 }
32503261
3251 if (self.section_indexes.plt_got) |shndx| {3262 if (self.section_indexes.plt_got) |shndx| {
3252 const shdr = slice.items(.shdr)[shndx];3263 const shdr = slice.items(.shdr)[shndx];
3253 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));3264 try buffer.resize(gpa, self.plt_got.size(self));
3254 defer buffer.deinit();3265 bw.initFixed(buffer.items);
3255 try self.plt_got.write(self, buffer.writer());3266 try self.plt_got.write(self, &bw);
3256 try self.pwriteAll(buffer.items, shdr.sh_offset);3267 assert(bw.end == bw.buffer.len);
3268 try self.pwriteAll(bw.buffer, shdr.sh_offset);
3257 }3269 }
32583270
3259 if (self.section_indexes.rela_plt) |shndx| {3271 if (self.section_indexes.rela_plt) |shndx| {
...@@ -3544,7 +3556,7 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {...@@ -3544,7 +3556,7 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {
3544}3556}
35453557
3546pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {3558pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {
3547 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{3559 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
3548 relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch),3560 relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch),
3549 opts.offset,3561 opts.offset,
3550 opts.sym,3562 opts.sym,
...@@ -3754,9 +3766,8 @@ fn shString(...@@ -3754,9 +3766,8 @@ fn shString(
37543766
3755pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {3767pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
3756 const gpa = self.base.comp.gpa;3768 const gpa = self.base.comp.gpa;
3757 const off = @as(u32, @intCast(self.shstrtab.items.len));3769 const off: u32 = @intCast(self.shstrtab.items.len);
3758 try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1);3770 try self.shstrtab.print(gpa, "{s}\x00", .{name});
3759 self.shstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable;
3760 return off;3771 return off;
3761}3772}
37623773
...@@ -3769,7 +3780,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {...@@ -3769,7 +3780,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
3769 const gpa = self.base.comp.gpa;3780 const gpa = self.base.comp.gpa;
3770 const off = @as(u32, @intCast(self.dynstrtab.items.len));3781 const off = @as(u32, @intCast(self.dynstrtab.items.len));
3771 try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1);3782 try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1);
3772 self.dynstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable;3783 self.dynstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable;
3773 return off;3784 return off;
3774}3785}
37753786
...@@ -3791,7 +3802,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {...@@ -3791,7 +3802,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
3791 for (refs.items[0..nrefs]) |ref| {3802 for (refs.items[0..nrefs]) |ref| {
3792 const atom_ptr = self.atom(ref).?;3803 const atom_ptr = self.atom(ref).?;
3793 const file_ptr = atom_ptr.file(self).?;3804 const file_ptr = atom_ptr.file(self).?;
3794 err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });3805 err.addNote("referenced by {f}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
3795 }3806 }
37963807
3797 if (refs.items.len > max_notes) {3808 if (refs.items.len > max_notes) {
...@@ -3813,12 +3824,12 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor...@@ -3813,12 +3824,12 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor
38133824
3814 var err = try diags.addErrorWithNotes(nnotes + 1);3825 var err = try diags.addErrorWithNotes(nnotes + 1);
3815 try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)});3826 try err.addMsg("duplicate symbol definition: {s}", .{sym.name(self)});
3816 err.addNote("defined by {}", .{sym.file(self).?.fmtPath()});3827 err.addNote("defined by {f}", .{sym.file(self).?.fmtPath()});
38173828
3818 var inote: usize = 0;3829 var inote: usize = 0;
3819 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {3830 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
3820 const file_ptr = self.file(notes.items[inote]).?;3831 const file_ptr = self.file(notes.items[inote]).?;
3821 err.addNote("defined by {}", .{file_ptr.fmtPath()});3832 err.addNote("defined by {f}", .{file_ptr.fmtPath()});
3822 }3833 }
38233834
3824 if (notes.items.len > max_notes) {3835 if (notes.items.len > max_notes) {
...@@ -3847,7 +3858,7 @@ pub fn addFileError(...@@ -3847,7 +3858,7 @@ pub fn addFileError(
3847 const diags = &self.base.comp.link_diags;3858 const diags = &self.base.comp.link_diags;
3848 var err = try diags.addErrorWithNotes(1);3859 var err = try diags.addErrorWithNotes(1);
3849 try err.addMsg(format, args);3860 try err.addMsg(format, args);
3850 err.addNote("while parsing {}", .{self.file(file_index).?.fmtPath()});3861 err.addNote("while parsing {f}", .{self.file(file_index).?.fmtPath()});
3851}3862}
38523863
3853pub fn failFile(3864pub fn failFile(
...@@ -3872,16 +3883,10 @@ fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) {...@@ -3872,16 +3883,10 @@ fn fmtShdr(self: *Elf, shdr: elf.Elf64_Shdr) std.fmt.Formatter(formatShdr) {
3872 } };3883 } };
3873}3884}
38743885
3875fn formatShdr(3886fn formatShdr(ctx: FormatShdrCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
3876 ctx: FormatShdrCtx,
3877 comptime unused_fmt_string: []const u8,
3878 options: std.fmt.FormatOptions,
3879 writer: anytype,
3880) !void {
3881 _ = options;
3882 _ = unused_fmt_string;3887 _ = unused_fmt_string;
3883 const shdr = ctx.shdr;3888 const shdr = ctx.shdr;
3884 try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({})", .{3889 try bw.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({f})", .{
3885 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,3890 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,
3886 shdr.sh_addr, shdr.sh_addralign,3891 shdr.sh_addr, shdr.sh_addralign,
3887 shdr.sh_size, shdr.sh_entsize,3892 shdr.sh_size, shdr.sh_entsize,
...@@ -3893,55 +3898,49 @@ pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) {...@@ -3893,55 +3898,49 @@ pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) {
3893 return .{ .data = sh_flags };3898 return .{ .data = sh_flags };
3894}3899}
38953900
3896fn formatShdrFlags(3901fn formatShdrFlags(sh_flags: u64, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) !void {
3897 sh_flags: u64,
3898 comptime unused_fmt_string: []const u8,
3899 options: std.fmt.FormatOptions,
3900 writer: anytype,
3901) !void {
3902 _ = unused_fmt_string;3902 _ = unused_fmt_string;
3903 _ = options;
3904 if (elf.SHF_WRITE & sh_flags != 0) {3903 if (elf.SHF_WRITE & sh_flags != 0) {
3905 try writer.writeAll("W");3904 try bw.writeByte('W');
3906 }3905 }
3907 if (elf.SHF_ALLOC & sh_flags != 0) {3906 if (elf.SHF_ALLOC & sh_flags != 0) {
3908 try writer.writeAll("A");3907 try bw.writeByte('A');
3909 }3908 }
3910 if (elf.SHF_EXECINSTR & sh_flags != 0) {3909 if (elf.SHF_EXECINSTR & sh_flags != 0) {
3911 try writer.writeAll("X");3910 try bw.writeByte('X');
3912 }3911 }
3913 if (elf.SHF_MERGE & sh_flags != 0) {3912 if (elf.SHF_MERGE & sh_flags != 0) {
3914 try writer.writeAll("M");3913 try bw.writeByte('M');
3915 }3914 }
3916 if (elf.SHF_STRINGS & sh_flags != 0) {3915 if (elf.SHF_STRINGS & sh_flags != 0) {
3917 try writer.writeAll("S");3916 try bw.writeByte('S');
3918 }3917 }
3919 if (elf.SHF_INFO_LINK & sh_flags != 0) {3918 if (elf.SHF_INFO_LINK & sh_flags != 0) {
3920 try writer.writeAll("I");3919 try bw.writeByte('I');
3921 }3920 }
3922 if (elf.SHF_LINK_ORDER & sh_flags != 0) {3921 if (elf.SHF_LINK_ORDER & sh_flags != 0) {
3923 try writer.writeAll("L");3922 try bw.writeByte('L');
3924 }3923 }
3925 if (elf.SHF_EXCLUDE & sh_flags != 0) {3924 if (elf.SHF_EXCLUDE & sh_flags != 0) {
3926 try writer.writeAll("E");3925 try bw.writeByte('E');
3927 }3926 }
3928 if (elf.SHF_COMPRESSED & sh_flags != 0) {3927 if (elf.SHF_COMPRESSED & sh_flags != 0) {
3929 try writer.writeAll("C");3928 try bw.writeByte('C');
3930 }3929 }
3931 if (elf.SHF_GROUP & sh_flags != 0) {3930 if (elf.SHF_GROUP & sh_flags != 0) {
3932 try writer.writeAll("G");3931 try bw.writeByte('G');
3933 }3932 }
3934 if (elf.SHF_OS_NONCONFORMING & sh_flags != 0) {3933 if (elf.SHF_OS_NONCONFORMING & sh_flags != 0) {
3935 try writer.writeAll("O");3934 try bw.writeByte('O');
3936 }3935 }
3937 if (elf.SHF_TLS & sh_flags != 0) {3936 if (elf.SHF_TLS & sh_flags != 0) {
3938 try writer.writeAll("T");3937 try bw.writeByte('T');
3939 }3938 }
3940 if (elf.SHF_X86_64_LARGE & sh_flags != 0) {3939 if (elf.SHF_X86_64_LARGE & sh_flags != 0) {
3941 try writer.writeAll("l");3940 try bw.writeByte('l');
3942 }3941 }
3943 if (elf.SHF_MIPS_ADDR & sh_flags != 0 or elf.SHF_ARM_PURECODE & sh_flags != 0) {3942 if (elf.SHF_MIPS_ADDR & sh_flags != 0 or elf.SHF_ARM_PURECODE & sh_flags != 0) {
3944 try writer.writeAll("p");3943 try bw.writeByte('p');
3945 }3944 }
3946}3945}
39473946
...@@ -3959,11 +3958,9 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) {...@@ -3959,11 +3958,9 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Formatter(formatPhdr) {
39593958
3960fn formatPhdr(3959fn formatPhdr(
3961 ctx: FormatPhdrCtx,3960 ctx: FormatPhdrCtx,
3961 bw: *std.io.BufferedWriter,
3962 comptime unused_fmt_string: []const u8,3962 comptime unused_fmt_string: []const u8,
3963 options: std.fmt.FormatOptions,
3964 writer: anytype,
3965) !void {3963) !void {
3966 _ = options;
3967 _ = unused_fmt_string;3964 _ = unused_fmt_string;
3968 const phdr = ctx.phdr;3965 const phdr = ctx.phdr;
3969 const write = phdr.p_flags & elf.PF_W != 0;3966 const write = phdr.p_flags & elf.PF_W != 0;
...@@ -3985,7 +3982,7 @@ fn formatPhdr(...@@ -3985,7 +3982,7 @@ fn formatPhdr(
3985 elf.PT_NOTE => "NOTE",3982 elf.PT_NOTE => "NOTE",
3986 else => "UNKNOWN",3983 else => "UNKNOWN",
3987 };3984 };
3988 try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{3985 try bw.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{
3989 p_type, flags, phdr.p_offset, phdr.p_vaddr,3986 p_type, flags, phdr.p_offset, phdr.p_vaddr,
3990 phdr.p_align, phdr.p_filesz, phdr.p_memsz,3987 phdr.p_align, phdr.p_filesz, phdr.p_memsz,
3991 });3988 });
...@@ -3997,30 +3994,28 @@ pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {...@@ -3997,30 +3994,28 @@ pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {
39973994
3998fn fmtDumpState(3995fn fmtDumpState(
3999 self: *Elf,3996 self: *Elf,
3997 bw: *std.io.BufferedWriter,
4000 comptime unused_fmt_string: []const u8,3998 comptime unused_fmt_string: []const u8,
4001 options: std.fmt.FormatOptions,
4002 writer: anytype,
4003) !void {3999) !void {
4004 _ = unused_fmt_string;4000 _ = unused_fmt_string;
4005 _ = options;
40064001
4007 const shared_objects = self.shared_objects.values();4002 const shared_objects = self.shared_objects.values();
40084003
4009 if (self.zigObjectPtr()) |zig_object| {4004 if (self.zigObjectPtr()) |zig_object| {
4010 try writer.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.basename });4005 try bw.print("zig_object({d}) : {s}\n", .{ zig_object.index, zig_object.basename });
4011 try writer.print("{}{}", .{4006 try bw.print("{f}{f}", .{
4012 zig_object.fmtAtoms(self),4007 zig_object.fmtAtoms(self),
4013 zig_object.fmtSymtab(self),4008 zig_object.fmtSymtab(self),
4014 });4009 });
4015 try writer.writeByte('\n');4010 try bw.writeByte('\n');
4016 }4011 }
40174012
4018 for (self.objects.items) |index| {4013 for (self.objects.items) |index| {
4019 const object = self.file(index).?.object;4014 const object = self.file(index).?.object;
4020 try writer.print("object({d}) : {}", .{ index, object.fmtPath() });4015 try bw.print("object({d}) : {f}", .{ index, object.fmtPath() });
4021 if (!object.alive) try writer.writeAll(" : [*]");4016 if (!object.alive) try bw.writeAll(" : [*]");
4022 try writer.writeByte('\n');4017 try bw.writeByte('\n');
4023 try writer.print("{}{}{}{}{}\n", .{4018 try bw.print("{f}{f}{f}{f}{f}\n", .{
4024 object.fmtAtoms(self),4019 object.fmtAtoms(self),
4025 object.fmtCies(self),4020 object.fmtCies(self),
4026 object.fmtFdes(self),4021 object.fmtFdes(self),
...@@ -4031,59 +4026,59 @@ fn fmtDumpState(...@@ -4031,59 +4026,59 @@ fn fmtDumpState(
40314026
4032 for (shared_objects) |index| {4027 for (shared_objects) |index| {
4033 const shared_object = self.file(index).?.shared_object;4028 const shared_object = self.file(index).?.shared_object;
4034 try writer.print("shared_object({d}) : {} : needed({})", .{4029 try bw.print("shared_object({d}) : {f} : needed({})", .{
4035 index, shared_object.path, shared_object.needed,4030 index, shared_object.path, shared_object.needed,
4036 });4031 });
4037 if (!shared_object.alive) try writer.writeAll(" : [*]");4032 if (!shared_object.alive) try bw.writeAll(" : [*]");
4038 try writer.writeByte('\n');4033 try bw.writeByte('\n');
4039 try writer.print("{}\n", .{shared_object.fmtSymtab(self)});4034 try bw.print("{f}\n", .{shared_object.fmtSymtab(self)});
4040 }4035 }
40414036
4042 if (self.linker_defined_index) |index| {4037 if (self.linker_defined_index) |index| {
4043 const linker_defined = self.file(index).?.linker_defined;4038 const linker_defined = self.file(index).?.linker_defined;
4044 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});4039 try bw.print("linker_defined({d}) : (linker defined)\n", .{index});
4045 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});4040 try bw.print("{f}\n", .{linker_defined.fmtSymtab(self)});
4046 }4041 }
40474042
4048 const slice = self.sections.slice();4043 const slice = self.sections.slice();
4049 {4044 {
4050 try writer.writeAll("atom lists\n");4045 try bw.writeAll("atom lists\n");
4051 for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {4046 for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {
4052 try writer.print("shdr({d}) : {s} : {}\n", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });4047 try bw.print("shdr({d}) : {s} : {f}\n", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });
4053 }4048 }
4054 }4049 }
40554050
4056 if (self.requiresThunks()) {4051 if (self.requiresThunks()) {
4057 try writer.writeAll("thunks\n");4052 try bw.writeAll("thunks\n");
4058 for (self.thunks.items, 0..) |th, index| {4053 for (self.thunks.items, 0..) |th, index| {
4059 try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });4054 try bw.print("thunk({d}) : {f}\n", .{ index, th.fmt(self) });
4060 }4055 }
4061 }4056 }
40624057
4063 try writer.print("{}\n", .{self.got.fmt(self)});4058 try bw.print("{f}\n", .{self.got.fmt(self)});
4064 try writer.print("{}\n", .{self.plt.fmt(self)});4059 try bw.print("{f}\n", .{self.plt.fmt(self)});
40654060
4066 try writer.writeAll("Output groups\n");4061 try bw.writeAll("Output groups\n");
4067 for (self.group_sections.items) |cg| {4062 for (self.group_sections.items) |cg| {
4068 try writer.print(" shdr({d}) : GROUP({})\n", .{ cg.shndx, cg.cg_ref });4063 try bw.print(" shdr({d}) : GROUP({f})\n", .{ cg.shndx, cg.cg_ref });
4069 }4064 }
40704065
4071 try writer.writeAll("\nOutput merge sections\n");4066 try bw.writeAll("\nOutput merge sections\n");
4072 for (self.merge_sections.items) |msec| {4067 for (self.merge_sections.items) |msec| {
4073 try writer.print(" shdr({d}) : {}\n", .{ msec.output_section_index, msec.fmt(self) });4068 try bw.print(" shdr({d}) : {f}\n", .{ msec.output_section_index, msec.fmt(self) });
4074 }4069 }
40754070
4076 try writer.writeAll("\nOutput shdrs\n");4071 try bw.writeAll("\nOutput shdrs\n");
4077 for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {4072 for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {
4078 try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{4073 try bw.print(" shdr({d}) : phdr({?d}) : {f}\n", .{
4079 shndx,4074 shndx,
4080 phndx,4075 phndx,
4081 self.fmtShdr(shdr),4076 self.fmtShdr(shdr),
4082 });4077 });
4083 }4078 }
4084 try writer.writeAll("\nOutput phdrs\n");4079 try bw.writeAll("\nOutput phdrs\n");
4085 for (self.phdrs.items, 0..) |phdr, phndx| {4080 for (self.phdrs.items, 0..) |phdr, phndx| {
4086 try writer.print(" phdr({d}) : {}\n", .{ phndx, self.fmtPhdr(phdr) });4081 try bw.print(" phdr({d}) : {f}\n", .{ phndx, self.fmtPhdr(phdr) });
4087 }4082 }
4088}4083}
40894084
...@@ -4221,15 +4216,9 @@ pub const Ref = struct {...@@ -4221,15 +4216,9 @@ pub const Ref = struct {
4221 return ref.index == other.index and ref.file == other.file;4216 return ref.index == other.index and ref.file == other.file;
4222 }4217 }
42234218
4224 pub fn format(4219 pub fn format(ref: Ref, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
4225 ref: Ref,
4226 comptime unused_fmt_string: []const u8,
4227 options: std.fmt.FormatOptions,
4228 writer: anytype,
4229 ) !void {
4230 _ = unused_fmt_string;4220 _ = unused_fmt_string;
4231 _ = options;4221 try bw.print("ref({},{})", .{ ref.index, ref.file });
4232 try writer.print("ref({},{})", .{ ref.index, ref.file });
4233 }4222 }
4234};4223};
42354224
...@@ -4424,7 +4413,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -4424,7 +4413,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
4424 for (atom_list.atoms.keys()[start..i]) |ref| {4413 for (atom_list.atoms.keys()[start..i]) |ref| {
4425 const atom_ptr = elf_file.atom(ref).?;4414 const atom_ptr = elf_file.atom(ref).?;
4426 const file_ptr = atom_ptr.file(elf_file).?;4415 const file_ptr = atom_ptr.file(elf_file).?;
4427 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });4416 log.debug("atom({f}) {s}", .{ ref, atom_ptr.name(elf_file) });
4428 for (atom_ptr.relocs(elf_file)) |rel| {4417 for (atom_ptr.relocs(elf_file)) |rel| {
4429 const is_reachable = switch (cpu_arch) {4418 const is_reachable = switch (cpu_arch) {
4430 .aarch64 => r: {4419 .aarch64 => r: {
...@@ -4453,7 +4442,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -4453,7 +4442,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
44534442
4454 thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));4443 thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
44554444
4456 log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) });4445 log.debug("thunk({d}) : {f}", .{ thunk_index, thunk_ptr.fmt(elf_file) });
4457 }4446 }
4458}4447}
44594448
src/link/Elf/Archive.zig+20-55
...@@ -44,7 +44,7 @@ pub fn parse(...@@ -44,7 +44,7 @@ pub fn parse(
44 pos += @sizeOf(elf.ar_hdr);44 pos += @sizeOf(elf.ar_hdr);
4545
46 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {46 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {
47 return diags.failParse(path, "invalid archive header delimiter: {s}", .{47 return diags.failParse(path, "invalid archive header delimiter: {f}", .{
48 std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),48 std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
49 });49 });
50 }50 }
...@@ -83,8 +83,8 @@ pub fn parse(...@@ -83,8 +83,8 @@ pub fn parse(
83 .alive = false,83 .alive = false,
84 };84 };
8585
86 log.debug("extracting object '{}' from archive '{}'", .{86 log.debug("extracting object '{f}' from archive '{f}'", .{
87 @as(Path, object.path), @as(Path, path),87 object.path, path,
88 });88 });
8989
90 try objects.append(gpa, object);90 try objects.append(gpa, object);
...@@ -110,33 +110,16 @@ pub fn setArHdr(opts: struct {...@@ -110,33 +110,16 @@ pub fn setArHdr(opts: struct {
110 },110 },
111 size: usize,111 size: usize,
112}) elf.ar_hdr {112}) elf.ar_hdr {
113 var hdr: elf.ar_hdr = .{113 var hdr: elf.ar_hdr = undefined;
114 .ar_name = undefined,114 @memset(mem.asBytes(&hdr), ' ');
115 .ar_date = undefined,
116 .ar_uid = undefined,
117 .ar_gid = undefined,
118 .ar_mode = undefined,
119 .ar_size = undefined,
120 .ar_fmag = undefined,
121 };
122 @memset(mem.asBytes(&hdr), 0x20);
123 @memcpy(&hdr.ar_fmag, elf.ARFMAG);115 @memcpy(&hdr.ar_fmag, elf.ARFMAG);
124116 switch (opts.name) {
125 {117 .symtab => _ = std.fmt.bufPrint(&hdr.ar_name, "{s}", .{elf.SYM64NAME}) catch unreachable,
126 var stream = std.io.fixedBufferStream(&hdr.ar_name);118 .strtab => _ = std.fmt.bufPrint(&hdr.ar_name, "//", .{}) catch unreachable,
127 const writer = stream.writer();119 .name => |x| _ = std.fmt.bufPrint(&hdr.ar_name, "{s}/", .{x}) catch unreachable,
128 switch (opts.name) {120 .name_off => |x| _ = std.fmt.bufPrint(&hdr.ar_name, "/{d}", .{x}) catch unreachable,
129 .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable,
130 .strtab => writer.print("//", .{}) catch unreachable,
131 .name => |x| writer.print("{s}/", .{x}) catch unreachable,
132 .name_off => |x| writer.print("/{d}", .{x}) catch unreachable,
133 }
134 }121 }
135 {122 _ = std.fmt.bufPrint(&hdr.ar_size, "{d}", .{opts.size}) catch unreachable;
136 var stream = std.io.fixedBufferStream(&hdr.ar_size);
137 stream.writer().print("{d}", .{opts.size}) catch unreachable;
138 }
139
140 return hdr;123 return hdr;
141}124}
142125
...@@ -201,16 +184,10 @@ pub const ArSymtab = struct {...@@ -201,16 +184,10 @@ pub const ArSymtab = struct {
201 }184 }
202 }185 }
203186
204 pub fn format(187 pub fn format(ar: ArSymtab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
205 ar: ArSymtab,
206 comptime unused_fmt_string: []const u8,
207 options: std.fmt.FormatOptions,
208 writer: anytype,
209 ) !void {
210 _ = ar;188 _ = ar;
189 _ = bw;
211 _ = unused_fmt_string;190 _ = unused_fmt_string;
212 _ = options;
213 _ = writer;
214 @compileError("do not format ar symtab directly; use fmt instead");191 @compileError("do not format ar symtab directly; use fmt instead");
215 }192 }
216193
...@@ -226,20 +203,14 @@ pub const ArSymtab = struct {...@@ -226,20 +203,14 @@ pub const ArSymtab = struct {
226 } };203 } };
227 }204 }
228205
229 fn format2(206 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
230 ctx: FormatContext,
231 comptime unused_fmt_string: []const u8,
232 options: std.fmt.FormatOptions,
233 writer: anytype,
234 ) !void {
235 _ = unused_fmt_string;207 _ = unused_fmt_string;
236 _ = options;
237 const ar = ctx.ar;208 const ar = ctx.ar;
238 const elf_file = ctx.elf_file;209 const elf_file = ctx.elf_file;
239 for (ar.symtab.items, 0..) |entry, i| {210 for (ar.symtab.items, 0..) |entry, i| {
240 const name = ar.strtab.getAssumeExists(entry.off);211 const name = ar.strtab.getAssumeExists(entry.off);
241 const file = elf_file.file(entry.file_index).?;212 const file = elf_file.file(entry.file_index).?;
242 try writer.print(" {d}: {s} in file({d})({})\n", .{ i, name, entry.file_index, file.fmtPath() });213 try bw.print(" {d}: {s} in file({d})({f})\n", .{ i, name, entry.file_index, file.fmtPath() });
243 }214 }
244 }215 }
245216
...@@ -264,9 +235,9 @@ pub const ArStrtab = struct {...@@ -264,9 +235,9 @@ pub const ArStrtab = struct {
264 ar.buffer.deinit(allocator);235 ar.buffer.deinit(allocator);
265 }236 }
266237
267 pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 {238 pub fn insert(ar: *ArStrtab, gpa: Allocator, name: []const u8) error{OutOfMemory}!u32 {
268 const off = @as(u32, @intCast(ar.buffer.items.len));239 const off: u32 = @intCast(ar.buffer.items.len);
269 try ar.buffer.writer(allocator).print("{s}/{c}", .{ name, strtab_delimiter });240 try ar.buffer.print(gpa, "{s}/{c}", .{ name, strtab_delimiter });
270 return off;241 return off;
271 }242 }
272243
...@@ -280,15 +251,9 @@ pub const ArStrtab = struct {...@@ -280,15 +251,9 @@ pub const ArStrtab = struct {
280 try writer.writeAll(ar.buffer.items);251 try writer.writeAll(ar.buffer.items);
281 }252 }
282253
283 pub fn format(254 pub fn format(ar: ArStrtab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
284 ar: ArStrtab,
285 comptime unused_fmt_string: []const u8,
286 options: std.fmt.FormatOptions,
287 writer: anytype,
288 ) !void {
289 _ = unused_fmt_string;255 _ = unused_fmt_string;
290 _ = options;256 try bw.print("{f}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
291 try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
292 }257 }
293};258};
294259
src/link/Elf/Atom.zig+181-219
...@@ -142,7 +142,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {...@@ -142,7 +142,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
142}142}
143143
144pub fn free(self: *Atom, elf_file: *Elf) void {144pub fn free(self: *Atom, elf_file: *Elf) void {
145 log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) });145 log.debug("freeAtom atom({f}) ({s})", .{ self.ref(), self.name(elf_file) });
146146
147 const comp = elf_file.base.comp;147 const comp = elf_file.base.comp;
148 const gpa = comp.gpa;148 const gpa = comp.gpa;
...@@ -243,7 +243,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El...@@ -243,7 +243,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
243 },243 },
244 }244 }
245245
246 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{246 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
247 relocation.fmtRelocType(rel.r_type(), cpu_arch),247 relocation.fmtRelocType(rel.r_type(), cpu_arch),
248 r_offset,248 r_offset,
249 r_sym,249 r_sym,
...@@ -316,7 +316,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype...@@ -316,7 +316,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
316 };316 };
317 // Violation of One Definition Rule for COMDATs.317 // Violation of One Definition Rule for COMDATs.
318 // TODO convert into an error318 // TODO convert into an error
319 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{319 log.debug("{f}: {s}: {s} refers to a discarded COMDAT section", .{
320 file_ptr.fmtPath(),320 file_ptr.fmtPath(),
321 self.name(elf_file),321 self.name(elf_file),
322 sym_name,322 sym_name,
...@@ -519,11 +519,11 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 {...@@ -519,11 +519,11 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 {
519fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void {519fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void {
520 const diags = &elf_file.base.comp.link_diags;520 const diags = &elf_file.base.comp.link_diags;
521 var err = try diags.addErrorWithNotes(1);521 var err = try diags.addErrorWithNotes(1);
522 try err.addMsg("fatal linker error: unhandled relocation type {} at offset 0x{x}", .{522 try err.addMsg("fatal linker error: unhandled relocation type {f} at offset 0x{x}", .{
523 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),523 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
524 rel.r_offset,524 rel.r_offset,
525 });525 });
526 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });526 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
527 return error.RelocFailure;527 return error.RelocFailure;
528}528}
529529
...@@ -539,7 +539,7 @@ fn reportTextRelocError(...@@ -539,7 +539,7 @@ fn reportTextRelocError(
539 rel.r_offset,539 rel.r_offset,
540 symbol.name(elf_file),540 symbol.name(elf_file),
541 });541 });
542 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });542 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
543 return error.RelocFailure;543 return error.RelocFailure;
544}544}
545545
...@@ -555,7 +555,7 @@ fn reportPicError(...@@ -555,7 +555,7 @@ fn reportPicError(
555 rel.r_offset,555 rel.r_offset,
556 symbol.name(elf_file),556 symbol.name(elf_file),
557 });557 });
558 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });558 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
559 err.addNote("recompile with -fPIC", .{});559 err.addNote("recompile with -fPIC", .{});
560 return error.RelocFailure;560 return error.RelocFailure;
561}561}
...@@ -572,7 +572,7 @@ fn reportNoPicError(...@@ -572,7 +572,7 @@ fn reportNoPicError(
572 rel.r_offset,572 rel.r_offset,
573 symbol.name(elf_file),573 symbol.name(elf_file),
574 });574 });
575 err.addNote("in {}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });575 err.addNote("in {f}:{s}", .{ self.file(elf_file).?.fmtPath(), self.name(elf_file) });
576 err.addNote("recompile with -fno-PIC", .{});576 err.addNote("recompile with -fno-PIC", .{});
577 return error.RelocFailure;577 return error.RelocFailure;
578}578}
...@@ -621,7 +621,9 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -621,7 +621,9 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
621621
622 const cpu_arch = elf_file.getTarget().cpu.arch;622 const cpu_arch = elf_file.getTarget().cpu.arch;
623 const file_ptr = self.file(elf_file).?;623 const file_ptr = self.file(elf_file).?;
624 var stream = std.io.fixedBufferStream(code);624
625 var bw: std.io.BufferedWriter = undefined;
626 bw.initFixed(code);
625627
626 const rels = self.relocs(elf_file);628 const rels = self.relocs(elf_file);
627 var it = RelocsIterator{ .relocs = rels };629 var it = RelocsIterator{ .relocs = rels };
...@@ -652,7 +654,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -652,7 +654,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
652 // Address of the dynamic thread pointer.654 // Address of the dynamic thread pointer.
653 const DTP = elf_file.dtpAddress();655 const DTP = elf_file.dtpAddress();
654656
655 relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ({s})", .{657 relocs_log.debug(" {f}: {x}: [{x} => {x}] GOT({x}) ({s})", .{
656 relocation.fmtRelocType(rel.r_type(), cpu_arch),658 relocation.fmtRelocType(rel.r_type(), cpu_arch),
657 r_offset,659 r_offset,
658 P,660 P,
...@@ -661,32 +663,32 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -661,32 +663,32 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
661 target.name(elf_file),663 target.name(elf_file),
662 });664 });
663665
664 try stream.seekTo(r_offset);
665
666 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };666 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };
667667
668 bw.end = r_offset;
669 bw.count = 0;
668 switch (cpu_arch) {670 switch (cpu_arch) {
669 .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {671 .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, &bw) catch |err| switch (err) {
670 error.RelocFailure,672 error.RelocFailure,
671 error.RelaxFailure,673 error.RelaxFailure,
672 error.InvalidInstruction,674 error.InvalidInstruction,
673 error.CannotEncode,675 error.CannotEncode,
674 => has_reloc_errors = true,676 => has_reloc_errors = true,
675 else => |e| return e,677 else => |e| return @errorCast(e),
676 },678 },
677 .aarch64 => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {679 .aarch64 => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, &bw) catch |err| switch (err) {
678 error.RelocFailure,680 error.RelocFailure,
679 error.RelaxFailure,681 error.RelaxFailure,
680 error.UnexpectedRemainder,682 error.UnexpectedRemainder,
681 error.DivisionByZero,683 error.DivisionByZero,
682 => has_reloc_errors = true,684 => has_reloc_errors = true,
683 else => |e| return e,685 else => |e| return @errorCast(e),
684 },686 },
685 .riscv64 => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {687 .riscv64 => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, &bw) catch |err| switch (err) {
686 error.RelocFailure,688 error.RelocFailure,
687 error.RelaxFailure,689 error.RelaxFailure,
688 => has_reloc_errors = true,690 => has_reloc_errors = true,
689 else => |e| return e,691 else => |e| return @errorCast(e),
690 },692 },
691 else => return error.UnsupportedCpuArch,693 else => return error.UnsupportedCpuArch,
692 }694 }
...@@ -804,7 +806,9 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -804,7 +806,9 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
804806
805 const cpu_arch = elf_file.getTarget().cpu.arch;807 const cpu_arch = elf_file.getTarget().cpu.arch;
806 const file_ptr = self.file(elf_file).?;808 const file_ptr = self.file(elf_file).?;
807 var stream = std.io.fixedBufferStream(code);809
810 var bw: std.io.BufferedWriter = undefined;
811 bw.initFixed(code);
808812
809 const rels = self.relocs(elf_file);813 const rels = self.relocs(elf_file);
810 var has_reloc_errors = false;814 var has_reloc_errors = false;
...@@ -823,7 +827,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -823,7 +827,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
823 };827 };
824 // Violation of One Definition Rule for COMDATs.828 // Violation of One Definition Rule for COMDATs.
825 // TODO convert into an error829 // TODO convert into an error
826 log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{830 log.debug("{f}: {s}: {s} refers to a discarded COMDAT section", .{
827 file_ptr.fmtPath(),831 file_ptr.fmtPath(),
828 self.name(elf_file),832 self.name(elf_file),
829 sym_name,833 sym_name,
...@@ -855,7 +859,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -855,7 +859,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
855859
856 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };860 const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };
857861
858 relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{862 relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{
859 relocation.fmtRelocType(rel.r_type(), cpu_arch),863 relocation.fmtRelocType(rel.r_type(), cpu_arch),
860 rel.r_offset,864 rel.r_offset,
861 P,865 P,
...@@ -863,18 +867,18 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -863,18 +867,18 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
863 target.name(elf_file),867 target.name(elf_file),
864 });868 });
865869
866 try stream.seekTo(r_offset);870 bw.end = r_offset;
867871 bw.count = 0;
868 switch (cpu_arch) {872 switch (cpu_arch) {
869 .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {873 .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &bw) catch |err| switch (err) {
870 error.RelocFailure => has_reloc_errors = true,874 error.RelocFailure => has_reloc_errors = true,
871 else => |e| return e,875 else => |e| return e,
872 },876 },
873 .aarch64 => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {877 .aarch64 => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &bw) catch |err| switch (err) {
874 error.RelocFailure => has_reloc_errors = true,878 error.RelocFailure => has_reloc_errors = true,
875 else => |e| return e,879 else => |e| return e,
876 },880 },
877 .riscv64 => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {881 .riscv64 => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &bw) catch |err| switch (err) {
878 error.RelocFailure => has_reloc_errors = true,882 error.RelocFailure => has_reloc_errors = true,
879 else => |e| return e,883 else => |e| return e,
880 },884 },
...@@ -904,16 +908,10 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {...@@ -904,16 +908,10 @@ pub fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
904 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);908 atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
905}909}
906910
907pub fn format(911pub fn format(atom: Atom, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
908 atom: Atom,
909 comptime unused_fmt_string: []const u8,
910 options: std.fmt.FormatOptions,
911 writer: anytype,
912) !void {
913 _ = atom;912 _ = atom;
913 _ = bw;
914 _ = unused_fmt_string;914 _ = unused_fmt_string;
915 _ = options;
916 _ = writer;
917 @compileError("do not format Atom directly");915 @compileError("do not format Atom directly");
918}916}
919917
...@@ -929,17 +927,11 @@ const FormatContext = struct {...@@ -929,17 +927,11 @@ const FormatContext = struct {
929 elf_file: *Elf,927 elf_file: *Elf,
930};928};
931929
932fn format2(930fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
933 ctx: FormatContext,
934 comptime unused_fmt_string: []const u8,
935 options: std.fmt.FormatOptions,
936 writer: anytype,
937) !void {
938 _ = options;
939 _ = unused_fmt_string;931 _ = unused_fmt_string;
940 const atom = ctx.atom;932 const atom = ctx.atom;
941 const elf_file = ctx.elf_file;933 const elf_file = ctx.elf_file;
942 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({}) : next({})", .{934 try bw.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{
943 atom.atom_index, atom.name(elf_file), atom.address(elf_file),935 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
944 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,936 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,
945 atom.prev_atom_ref, atom.next_atom_ref,937 atom.prev_atom_ref, atom.next_atom_ref,
...@@ -947,20 +939,20 @@ fn format2(...@@ -947,20 +939,20 @@ fn format2(
947 if (atom.file(elf_file)) |atom_file| switch (atom_file) {939 if (atom.file(elf_file)) |atom_file| switch (atom_file) {
948 .object => |object| {940 .object => |object| {
949 if (atom.fdes(object).len > 0) {941 if (atom.fdes(object).len > 0) {
950 try writer.writeAll(" : fdes{ ");942 try bw.writeAll(" : fdes{ ");
951 const extras = atom.extra(elf_file);943 const extras = atom.extra(elf_file);
952 for (atom.fdes(object), extras.fde_start..) |fde, i| {944 for (atom.fdes(object), extras.fde_start..) |fde, i| {
953 try writer.print("{d}", .{i});945 try bw.print("{d}", .{i});
954 if (!fde.alive) try writer.writeAll("([*])");946 if (!fde.alive) try bw.writeAll("([*])");
955 if (i - extras.fde_start < extras.fde_count - 1) try writer.writeAll(", ");947 if (i - extras.fde_start < extras.fde_count - 1) try bw.writeAll(", ");
956 }948 }
957 try writer.writeAll(" }");949 try bw.writeAll(" }");
958 }950 }
959 },951 },
960 else => {},952 else => {},
961 };953 };
962 if (!atom.alive) {954 if (!atom.alive) {
963 try writer.writeAll(" : [*]");955 try bw.writeAll(" : [*]");
964 }956 }
965}957}
966958
...@@ -1087,16 +1079,12 @@ const x86_64 = struct {...@@ -1087,16 +1079,12 @@ const x86_64 = struct {
1087 target: *const Symbol,1079 target: *const Symbol,
1088 args: ResolveArgs,1080 args: ResolveArgs,
1089 it: *RelocsIterator,1081 it: *RelocsIterator,
1090 code: []u8,1082 bw: *std.io.BufferedWriter,
1091 stream: anytype,1083 ) anyerror!void {
1092 ) (error{ InvalidInstruction, CannotEncode } || RelocError)!void {
1093 dev.check(.x86_64_backend);1084 dev.check(.x86_64_backend);
1094 const t = &elf_file.base.comp.root_mod.resolved_target.result;1085 const t = &elf_file.base.comp.root_mod.resolved_target.result;
1095 const diags = &elf_file.base.comp.link_diags;1086 const diags = &elf_file.base.comp.link_diags;
1096 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());1087 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1097 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1098
1099 const cwriter = stream.writer();
11001088
1101 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1089 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
11021090
...@@ -1109,58 +1097,54 @@ const x86_64 = struct {...@@ -1109,58 +1097,54 @@ const x86_64 = struct {
1109 rel,1097 rel,
1110 dynAbsRelocAction(target, elf_file),1098 dynAbsRelocAction(target, elf_file),
1111 elf_file,1099 elf_file,
1112 cwriter,1100 bw,
1113 );1101 );
1114 },1102 },
11151103
1116 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),1104 .PLT32 => try bw.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1117 .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),1105 .PC32 => try bw.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
11181106
1119 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),1107 .GOTPCREL => try bw.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
1120 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),1108 .GOTPC32 => try bw.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
1121 .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little),1109 .GOTPC64 => try bw.writeInt(i64, GOT + A - P, .little),
11221110
1123 .GOTPCRELX => {1111 .GOTPCRELX => if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1124 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1112 x86_64.relaxGotpcrelx(bw.buffer[bw.end - 2 ..], t) catch break :blk;
1125 x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk;1113 try bw.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
1126 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1114 } else {
1127 return;1115 try bw.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1128 }
1129 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1130 },1116 },
11311117
1132 .REX_GOTPCRELX => {1118 .REX_GOTPCRELX => if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1133 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1119 x86_64.relaxRexGotpcrelx(bw.buffer[bw.end - 3 ..], t) catch break :blk;
1134 x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk;1120 try bw.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
1135 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1121 } else {
1136 return;1122 try bw.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1137 }
1138 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1139 },1123 },
11401124
1141 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),1125 .@"32" => try bw.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
1142 .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),1126 .@"32S" => try bw.writeInt(i32, @as(i32, @truncate(S + A)), .little),
11431127
1144 .TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),1128 .TPOFF32 => try bw.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),
1145 .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little),1129 .TPOFF64 => try bw.writeInt(i64, S + A - TP, .little),
11461130
1147 .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little),1131 .DTPOFF32 => try bw.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little),
1148 .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),1132 .DTPOFF64 => try bw.writeInt(i64, S + A - DTP, .little),
11491133
1150 .TLSGD => {1134 .TLSGD => {
1151 if (target.flags.has_tlsgd) {1135 if (target.flags.has_tlsgd) {
1152 const S_ = target.tlsGdAddress(elf_file);1136 const S_ = target.tlsGdAddress(elf_file);
1153 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1137 try bw.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
1154 } else if (target.flags.has_gottp) {1138 } else if (target.flags.has_gottp) {
1155 const S_ = target.gotTpAddress(elf_file);1139 const S_ = target.gotTpAddress(elf_file);
1156 try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream);1140 try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, bw);
1157 } else {1141 } else {
1158 try x86_64.relaxTlsGdToLe(1142 try x86_64.relaxTlsGdToLe(
1159 atom,1143 atom,
1160 &.{ rel, it.next().? },1144 &.{ rel, it.next().? },
1161 @as(i32, @intCast(S - TP)),1145 @as(i32, @intCast(S - TP)),
1162 elf_file,1146 elf_file,
1163 stream,1147 bw,
1164 );1148 );
1165 }1149 }
1166 },1150 },
...@@ -1169,14 +1153,14 @@ const x86_64 = struct {...@@ -1169,14 +1153,14 @@ const x86_64 = struct {
1169 if (elf_file.got.tlsld_index) |entry_index| {1153 if (elf_file.got.tlsld_index) |entry_index| {
1170 const tlsld_entry = elf_file.got.entries.items[entry_index];1154 const tlsld_entry = elf_file.got.entries.items[entry_index];
1171 const S_ = tlsld_entry.address(elf_file);1155 const S_ = tlsld_entry.address(elf_file);
1172 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1156 try bw.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
1173 } else {1157 } else {
1174 try x86_64.relaxTlsLdToLe(1158 try x86_64.relaxTlsLdToLe(
1175 atom,1159 atom,
1176 &.{ rel, it.next().? },1160 &.{ rel, it.next().? },
1177 @as(i32, @intCast(TP - elf_file.tlsAddress())),1161 @as(i32, @intCast(TP - elf_file.tlsAddress())),
1178 elf_file,1162 elf_file,
1179 stream,1163 bw,
1180 );1164 );
1181 }1165 }
1182 },1166 },
...@@ -1184,38 +1168,38 @@ const x86_64 = struct {...@@ -1184,38 +1168,38 @@ const x86_64 = struct {
1184 .GOTPC32_TLSDESC => {1168 .GOTPC32_TLSDESC => {
1185 if (target.flags.has_tlsdesc) {1169 if (target.flags.has_tlsdesc) {
1186 const S_ = target.tlsDescAddress(elf_file);1170 const S_ = target.tlsDescAddress(elf_file);
1187 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1171 try bw.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
1188 } else {1172 } else {
1189 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {1173 x86_64.relaxGotPcTlsDesc(bw.buffer[bw.end - 3 ..], t) catch {
1190 var err = try diags.addErrorWithNotes(1);1174 var err = try diags.addErrorWithNotes(1);
1191 try err.addMsg("could not relax {s}", .{@tagName(r_type)});1175 try err.addMsg("could not relax {s}", .{@tagName(r_type)});
1192 err.addNote("in {}:{s} at offset 0x{x}", .{1176 err.addNote("in {f}:{s} at offset 0x{x}", .{
1193 atom.file(elf_file).?.fmtPath(),1177 atom.file(elf_file).?.fmtPath(),
1194 atom.name(elf_file),1178 atom.name(elf_file),
1195 rel.r_offset,1179 rel.r_offset,
1196 });1180 });
1197 return error.RelaxFailure;1181 return error.RelaxFailure;
1198 };1182 };
1199 try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little);1183 try bw.writeInt(i32, @as(i32, @intCast(S - TP)), .little);
1200 }1184 }
1201 },1185 },
12021186
1203 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {1187 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1204 // call -> nop1188 // call -> nop
1205 try cwriter.writeAll(&.{ 0x66, 0x90 });1189 try bw.writeAll(&.{ 0x66, 0x90 });
1206 },1190 },
12071191
1208 .GOTTPOFF => {1192 .GOTTPOFF => {
1209 if (target.flags.has_gottp) {1193 if (target.flags.has_gottp) {
1210 const S_ = target.gotTpAddress(elf_file);1194 const S_ = target.gotTpAddress(elf_file);
1211 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1195 try bw.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
1212 } else {1196 } else {
1213 x86_64.relaxGotTpOff(code[r_offset - 3 ..], t);1197 x86_64.relaxGotTpOff(bw.buffer[bw.end - 3 ..], t);
1214 try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little);1198 try bw.writeInt(i32, @as(i32, @intCast(S - TP)), .little);
1215 }1199 }
1216 },1200 },
12171201
1218 .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + A)), .little),1202 .GOT32 => try bw.writeInt(i32, @as(i32, @intCast(G + A)), .little),
12191203
1220 else => try atom.reportUnhandledRelocError(rel, elf_file),1204 else => try atom.reportUnhandledRelocError(rel, elf_file),
1221 }1205 }
...@@ -1227,45 +1211,40 @@ const x86_64 = struct {...@@ -1227,45 +1211,40 @@ const x86_64 = struct {
1227 rel: elf.Elf64_Rela,1211 rel: elf.Elf64_Rela,
1228 target: *const Symbol,1212 target: *const Symbol,
1229 args: ResolveArgs,1213 args: ResolveArgs,
1230 it: *RelocsIterator,1214 bw: *std.io.BufferedWriter,
1231 code: []u8,1215 ) anyerror!void {
1232 stream: anytype,
1233 ) !void {
1234 dev.check(.x86_64_backend);1216 dev.check(.x86_64_backend);
1235 _ = code;
1236 _ = it;
1237 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1238 const cwriter = stream.writer();
12391217
1218 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1240 _, const A, const S, const GOT, _, _, const DTP = args;1219 _, const A, const S, const GOT, _, _, const DTP = args;
12411220
1242 switch (r_type) {1221 switch (r_type) {
1243 .NONE => unreachable,1222 .NONE => unreachable,
1244 .@"8" => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),1223 .@"8" => try bw.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),
1245 .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),1224 .@"16" => try bw.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),
1246 .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),1225 .@"32" => try bw.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),
1247 .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1226 .@"32S" => try bw.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1248 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1227 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1249 try cwriter.writeInt(u64, value, .little)1228 try bw.writeInt(u64, value, .little)
1250 else1229 else
1251 try cwriter.writeInt(i64, S + A, .little),1230 try bw.writeInt(i64, S + A, .little),
1252 .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1231 .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1253 try cwriter.writeInt(u64, value, .little)1232 try bw.writeInt(u64, value, .little)
1254 else1233 else
1255 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),1234 try bw.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),
1256 .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1235 .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1257 try cwriter.writeInt(u64, value, .little)1236 try bw.writeInt(u64, value, .little)
1258 else1237 else
1259 try cwriter.writeInt(i64, S + A - DTP, .little),1238 try bw.writeInt(i64, S + A - DTP, .little),
1260 .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little),1239 .GOTOFF64 => try bw.writeInt(i64, S + A - GOT, .little),
1261 .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),1240 .GOTPC64 => try bw.writeInt(i64, GOT + A, .little),
1262 .SIZE32 => {1241 .SIZE32 => {
1263 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1242 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1264 try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little);1243 try bw.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little);
1265 },1244 },
1266 .SIZE64 => {1245 .SIZE64 => {
1267 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1246 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1268 try cwriter.writeInt(i64, @intCast(size + A), .little);1247 try bw.writeInt(i64, @intCast(size + A), .little);
1269 },1248 },
1270 else => try atom.reportUnhandledRelocError(rel, elf_file),1249 else => try atom.reportUnhandledRelocError(rel, elf_file),
1271 }1250 }
...@@ -1285,7 +1264,7 @@ const x86_64 = struct {...@@ -1285,7 +1264,7 @@ const x86_64 = struct {
1285 }, t),1264 }, t),
1286 else => return error.RelaxFailure,1265 else => return error.RelaxFailure,
1287 };1266 };
1288 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1267 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1289 const nop: Instruction = try .new(.none, .nop, &.{}, t);1268 const nop: Instruction = try .new(.none, .nop, &.{}, t);
1290 try encode(&.{ nop, inst }, code);1269 try encode(&.{ nop, inst }, code);
1291 }1270 }
...@@ -1296,7 +1275,7 @@ const x86_64 = struct {...@@ -1296,7 +1275,7 @@ const x86_64 = struct {
1296 switch (old_inst.encoding.mnemonic) {1275 switch (old_inst.encoding.mnemonic) {
1297 .mov => {1276 .mov => {
1298 const inst: Instruction = try .new(old_inst.prefix, .lea, &old_inst.ops, t);1277 const inst: Instruction = try .new(old_inst.prefix, .lea, &old_inst.ops, t);
1299 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1278 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1300 try encode(&.{inst}, code);1279 try encode(&.{inst}, code);
1301 },1280 },
1302 else => return error.RelaxFailure,1281 else => return error.RelaxFailure,
...@@ -1308,12 +1287,11 @@ const x86_64 = struct {...@@ -1308,12 +1287,11 @@ const x86_64 = struct {
1308 rels: []const elf.Elf64_Rela,1287 rels: []const elf.Elf64_Rela,
1309 value: i32,1288 value: i32,
1310 elf_file: *Elf,1289 elf_file: *Elf,
1311 stream: anytype,1290 bw: *std.io.BufferedWriter,
1312 ) !void {1291 ) !void {
1313 dev.check(.x86_64_backend);1292 dev.check(.x86_64_backend);
1314 assert(rels.len == 2);1293 assert(rels.len == 2);
1315 const diags = &elf_file.base.comp.link_diags;1294 const diags = &elf_file.base.comp.link_diags;
1316 const writer = stream.writer();
1317 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1295 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1318 switch (rel) {1296 switch (rel) {
1319 .PC32,1297 .PC32,
...@@ -1324,17 +1302,17 @@ const x86_64 = struct {...@@ -1324,17 +1302,17 @@ const x86_64 = struct {
1324 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax1302 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax
1325 };1303 };
1326 std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little);1304 std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little);
1327 try stream.seekBy(-4);1305 bw.end -= 4;
1328 try writer.writeAll(&insts);1306 try bw.writeAll(&insts);
1329 },1307 },
13301308
1331 else => {1309 else => {
1332 var err = try diags.addErrorWithNotes(1);1310 var err = try diags.addErrorWithNotes(1);
1333 try err.addMsg("TODO: rewrite {} when followed by {}", .{1311 try err.addMsg("TODO: rewrite {f} when followed by {f}", .{
1334 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1312 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1335 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1313 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1336 });1314 });
1337 err.addNote("in {}:{s} at offset 0x{x}", .{1315 err.addNote("in {f}:{s} at offset 0x{x}", .{
1338 self.file(elf_file).?.fmtPath(),1316 self.file(elf_file).?.fmtPath(),
1339 self.name(elf_file),1317 self.name(elf_file),
1340 rels[0].r_offset,1318 rels[0].r_offset,
...@@ -1349,12 +1327,11 @@ const x86_64 = struct {...@@ -1349,12 +1327,11 @@ const x86_64 = struct {
1349 rels: []const elf.Elf64_Rela,1327 rels: []const elf.Elf64_Rela,
1350 value: i32,1328 value: i32,
1351 elf_file: *Elf,1329 elf_file: *Elf,
1352 stream: anytype,1330 bw: *std.io.BufferedWriter,
1353 ) !void {1331 ) !void {
1354 dev.check(.x86_64_backend);1332 dev.check(.x86_64_backend);
1355 assert(rels.len == 2);1333 assert(rels.len == 2);
1356 const diags = &elf_file.base.comp.link_diags;1334 const diags = &elf_file.base.comp.link_diags;
1357 const writer = stream.writer();
1358 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1335 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1359 switch (rel) {1336 switch (rel) {
1360 .PC32,1337 .PC32,
...@@ -1366,8 +1343,8 @@ const x86_64 = struct {...@@ -1366,8 +1343,8 @@ const x86_64 = struct {
1366 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax1343 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax
1367 };1344 };
1368 std.mem.writeInt(i32, insts[8..][0..4], value, .little);1345 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1369 try stream.seekBy(-3);1346 bw.end -= 3;
1370 try writer.writeAll(&insts);1347 try bw.writeAll(&insts);
1371 },1348 },
13721349
1373 .GOTPCREL,1350 .GOTPCREL,
...@@ -1380,17 +1357,17 @@ const x86_64 = struct {...@@ -1380,17 +1357,17 @@ const x86_64 = struct {
1380 0x90, // nop1357 0x90, // nop
1381 };1358 };
1382 std.mem.writeInt(i32, insts[8..][0..4], value, .little);1359 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1383 try stream.seekBy(-3);1360 bw.end -= 3;
1384 try writer.writeAll(&insts);1361 try bw.writeAll(&insts);
1385 },1362 },
13861363
1387 else => {1364 else => {
1388 var err = try diags.addErrorWithNotes(1);1365 var err = try diags.addErrorWithNotes(1);
1389 try err.addMsg("TODO: rewrite {} when followed by {}", .{1366 try err.addMsg("TODO: rewrite {f} when followed by {f}", .{
1390 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1367 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1391 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1368 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1392 });1369 });
1393 err.addNote("in {}:{s} at offset 0x{x}", .{1370 err.addNote("in {f}:{s} at offset 0x{x}", .{
1394 self.file(elf_file).?.fmtPath(),1371 self.file(elf_file).?.fmtPath(),
1395 self.name(elf_file),1372 self.name(elf_file),
1396 rels[0].r_offset,1373 rels[0].r_offset,
...@@ -1410,7 +1387,12 @@ const x86_64 = struct {...@@ -1410,7 +1387,12 @@ const x86_64 = struct {
1410 // TODO: hack to force imm32s in the assembler1387 // TODO: hack to force imm32s in the assembler
1411 .{ .imm = .s(-129) },1388 .{ .imm = .s(-129) },
1412 }, t) catch return false;1389 }, t) catch return false;
1413 inst.encode(std.io.null_writer, .{}) catch return false;1390 var buf: [std.atomic.cache_line]u8 = undefined;
1391 var bw: std.io.BufferedWriter = .{
1392 .unbuffered_writer = .null,
1393 .buffer = &buf,
1394 };
1395 inst.encode(&bw, .{}) catch return false;
1414 return true;1396 return true;
1415 },1397 },
1416 else => return false,1398 else => return false,
...@@ -1427,7 +1409,7 @@ const x86_64 = struct {...@@ -1427,7 +1409,7 @@ const x86_64 = struct {
1427 // TODO: hack to force imm32s in the assembler1409 // TODO: hack to force imm32s in the assembler
1428 .{ .imm = .s(-129) },1410 .{ .imm = .s(-129) },
1429 }, t) catch unreachable;1411 }, t) catch unreachable;
1430 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1412 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1431 encode(&.{inst}, code) catch unreachable;1413 encode(&.{inst}, code) catch unreachable;
1432 },1414 },
1433 else => unreachable,1415 else => unreachable,
...@@ -1444,7 +1426,7 @@ const x86_64 = struct {...@@ -1444,7 +1426,7 @@ const x86_64 = struct {
1444 // TODO: hack to force imm32s in the assembler1426 // TODO: hack to force imm32s in the assembler
1445 .{ .imm = .s(-129) },1427 .{ .imm = .s(-129) },
1446 }, target);1428 }, target);
1447 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });1429 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
1448 try encode(&.{inst}, code);1430 try encode(&.{inst}, code);
1449 },1431 },
1450 else => return error.RelaxFailure,1432 else => return error.RelaxFailure,
...@@ -1456,12 +1438,11 @@ const x86_64 = struct {...@@ -1456,12 +1438,11 @@ const x86_64 = struct {
1456 rels: []const elf.Elf64_Rela,1438 rels: []const elf.Elf64_Rela,
1457 value: i32,1439 value: i32,
1458 elf_file: *Elf,1440 elf_file: *Elf,
1459 stream: anytype,1441 bw: *std.io.BufferedWriter,
1460 ) !void {1442 ) !void {
1461 dev.check(.x86_64_backend);1443 dev.check(.x86_64_backend);
1462 assert(rels.len == 2);1444 assert(rels.len == 2);
1463 const diags = &elf_file.base.comp.link_diags;1445 const diags = &elf_file.base.comp.link_diags;
1464 const writer = stream.writer();
1465 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1446 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1466 switch (rel) {1447 switch (rel) {
1467 .PC32,1448 .PC32,
...@@ -1474,9 +1455,9 @@ const x86_64 = struct {...@@ -1474,9 +1455,9 @@ const x86_64 = struct {
1474 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax1455 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax
1475 };1456 };
1476 std.mem.writeInt(i32, insts[12..][0..4], value, .little);1457 std.mem.writeInt(i32, insts[12..][0..4], value, .little);
1477 try stream.seekBy(-4);1458 bw.end -= 4;
1478 try writer.writeAll(&insts);1459 try bw.writeAll(&insts);
1479 relocs_log.debug(" relaxing {} and {}", .{1460 relocs_log.debug(" relaxing {f} and {f}", .{
1480 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1461 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1481 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1462 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1482 });1463 });
...@@ -1484,11 +1465,11 @@ const x86_64 = struct {...@@ -1484,11 +1465,11 @@ const x86_64 = struct {
14841465
1485 else => {1466 else => {
1486 var err = try diags.addErrorWithNotes(1);1467 var err = try diags.addErrorWithNotes(1);
1487 try err.addMsg("fatal linker error: rewrite {} when followed by {}", .{1468 try err.addMsg("fatal linker error: rewrite {f} when followed by {f}", .{
1488 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1469 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1489 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1470 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1490 });1471 });
1491 err.addNote("in {}:{s} at offset 0x{x}", .{1472 err.addNote("in {f}:{s} at offset 0x{x}", .{
1492 self.file(elf_file).?.fmtPath(),1473 self.file(elf_file).?.fmtPath(),
1493 self.name(elf_file),1474 self.name(elf_file),
1494 rels[0].r_offset,1475 rels[0].r_offset,
...@@ -1505,11 +1486,9 @@ const x86_64 = struct {...@@ -1505,11 +1486,9 @@ const x86_64 = struct {
1505 }1486 }
15061487
1507 fn encode(insts: []const Instruction, code: []u8) !void {1488 fn encode(insts: []const Instruction, code: []u8) !void {
1508 var stream = std.io.fixedBufferStream(code);1489 var bw: std.io.BufferedWriter = undefined;
1509 const writer = stream.writer();1490 bw.initFixed(code);
1510 for (insts) |inst| {1491 for (insts) |inst| try inst.encode(&bw, .{});
1511 try inst.encode(writer, .{});
1512 }
1513 }1492 }
15141493
1515 const bits = @import("../../arch/x86_64/bits.zig");1494 const bits = @import("../../arch/x86_64/bits.zig");
...@@ -1613,16 +1592,14 @@ const aarch64 = struct {...@@ -1613,16 +1592,14 @@ const aarch64 = struct {
1613 target: *const Symbol,1592 target: *const Symbol,
1614 args: ResolveArgs,1593 args: ResolveArgs,
1615 it: *RelocsIterator,1594 it: *RelocsIterator,
1616 code_buffer: []u8,1595 bw: *std.io.BufferedWriter,
1617 stream: anytype,1596 ) anyerror!void {
1618 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
1619 _ = it;1597 _ = it;
16201598
1621 const diags = &elf_file.base.comp.link_diags;1599 const diags = &elf_file.base.comp.link_diags;
1622 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1600 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1623 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1601 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1624 const cwriter = stream.writer();1602 const code = (try bw.writableSlice(4))[0..4];
1625 const code = code_buffer[r_offset..][0..4];
1626 const file_ptr = atom.file(elf_file).?;1603 const file_ptr = atom.file(elf_file).?;
16271604
1628 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1605 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
...@@ -1636,7 +1613,7 @@ const aarch64 = struct {...@@ -1636,7 +1613,7 @@ const aarch64 = struct {
1636 rel,1613 rel,
1637 dynAbsRelocAction(target, elf_file),1614 dynAbsRelocAction(target, elf_file),
1638 elf_file,1615 elf_file,
1639 cwriter,1616 bw,
1640 );1617 );
1641 },1618 },
16421619
...@@ -1649,17 +1626,17 @@ const aarch64 = struct {...@@ -1649,17 +1626,17 @@ const aarch64 = struct {
1649 const S_ = th.targetAddress(target_index, elf_file);1626 const S_ = th.targetAddress(target_index, elf_file);
1650 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;1627 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
1651 };1628 };
1652 aarch64_util.writeBranchImm(disp, code);1629 aarch64_util.writeBranchImm(disp, (try bw.writableSlice(4))[0..4]);
1653 },1630 },
16541631
1655 .PREL32 => {1632 .PREL32 => {
1656 const value = math.cast(i32, S + A - P) orelse return error.Overflow;1633 const value = math.cast(i32, S + A - P) orelse return error.Overflow;
1657 mem.writeInt(u32, code, @bitCast(value), .little);1634 try bw.writeInt(u32, @bitCast(value), .little);
1658 },1635 },
16591636
1660 .PREL64 => {1637 .PREL64 => {
1661 const value = S + A - P;1638 const value = S + A - P;
1662 mem.writeInt(u64, code_buffer[r_offset..][0..8], @bitCast(value), .little);1639 try bw.writeInt(u64, @bitCast(value), .little);
1663 },1640 },
16641641
1665 .ADR_PREL_PG_HI21 => {1642 .ADR_PREL_PG_HI21 => {
...@@ -1675,7 +1652,7 @@ const aarch64 = struct {...@@ -1675,7 +1652,7 @@ const aarch64 = struct {
1675 // TODO: relax1652 // TODO: relax
1676 var err = try diags.addErrorWithNotes(1);1653 var err = try diags.addErrorWithNotes(1);
1677 try err.addMsg("TODO: relax ADR_GOT_PAGE", .{});1654 try err.addMsg("TODO: relax ADR_GOT_PAGE", .{});
1678 err.addNote("in {}:{s} at offset 0x{x}", .{1655 err.addNote("in {f}:{s} at offset 0x{x}", .{
1679 atom.file(elf_file).?.fmtPath(),1656 atom.file(elf_file).?.fmtPath(),
1680 atom.name(elf_file),1657 atom.name(elf_file),
1681 r_offset,1658 r_offset,
...@@ -1818,25 +1795,18 @@ const aarch64 = struct {...@@ -1818,25 +1795,18 @@ const aarch64 = struct {
1818 rel: elf.Elf64_Rela,1795 rel: elf.Elf64_Rela,
1819 target: *const Symbol,1796 target: *const Symbol,
1820 args: ResolveArgs,1797 args: ResolveArgs,
1821 it: *RelocsIterator,1798 bw: *std.io.BufferedWriter,
1822 code: []u8,
1823 stream: anytype,
1824 ) !void {1799 ) !void {
1825 _ = it;
1826 _ = code;
1827
1828 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1800 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1829 const cwriter = stream.writer();
1830
1831 _, const A, const S, _, _, _, _ = args;1801 _, const A, const S, _, _, _, _ = args;
18321802
1833 switch (r_type) {1803 switch (r_type) {
1834 .NONE => unreachable,1804 .NONE => unreachable,
1835 .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1805 .ABS32 => try bw.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1836 .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1806 .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1837 try cwriter.writeInt(u64, value, .little)1807 try bw.writeInt(u64, value, .little)
1838 else1808 else
1839 try cwriter.writeInt(i64, S + A, .little),1809 try bw.writeInt(i64, S + A, .little),
1840 else => try atom.reportUnhandledRelocError(rel, elf_file),1810 else => try atom.reportUnhandledRelocError(rel, elf_file),
1841 }1811 }
1842 }1812 }
...@@ -1898,13 +1868,10 @@ const riscv = struct {...@@ -1898,13 +1868,10 @@ const riscv = struct {
1898 target: *const Symbol,1868 target: *const Symbol,
1899 args: ResolveArgs,1869 args: ResolveArgs,
1900 it: *RelocsIterator,1870 it: *RelocsIterator,
1901 code: []u8,1871 bw: *std.io.BufferedWriter,
1902 stream: anytype,
1903 ) !void {1872 ) !void {
1904 const diags = &elf_file.base.comp.link_diags;1873 const diags = &elf_file.base.comp.link_diags;
1905 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());1874 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
1906 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1907 const cwriter = stream.writer();
19081875
1909 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1876 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
1910 _ = TP;1877 _ = TP;
...@@ -1913,7 +1880,7 @@ const riscv = struct {...@@ -1913,7 +1880,7 @@ const riscv = struct {
1913 switch (r_type) {1880 switch (r_type) {
1914 .NONE => unreachable,1881 .NONE => unreachable,
19151882
1916 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),1883 .@"32" => try bw.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
19171884
1918 .@"64" => {1885 .@"64" => {
1919 try atom.resolveDynAbsReloc(1886 try atom.resolveDynAbsReloc(
...@@ -1921,34 +1888,35 @@ const riscv = struct {...@@ -1921,34 +1888,35 @@ const riscv = struct {
1921 rel,1888 rel,
1922 dynAbsRelocAction(target, elf_file),1889 dynAbsRelocAction(target, elf_file),
1923 elf_file,1890 elf_file,
1924 cwriter,1891 bw,
1925 );1892 );
1926 },1893 },
19271894
1928 .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A),1895 .ADD32 => try riscv_util.writeAddend(i32, .add, S + A, bw),
1929 .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A),1896 .SUB32 => try riscv_util.writeAddend(i32, .sub, S + A, bw),
19301897
1931 .HI20 => {1898 .HI20 => {
1932 const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);1899 const value: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
1933 riscv_util.writeInstU(code[r_offset..][0..4], value);1900 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], value);
1934 },1901 },
19351902
1936 .GOT_HI20 => {1903 .GOT_HI20 => {
1937 assert(target.flags.has_got);1904 assert(target.flags.has_got);
1938 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);1905 const disp: u32 = @bitCast(math.cast(i32, G + GOT + A - P) orelse return error.Overflow);
1939 riscv_util.writeInstU(code[r_offset..][0..4], disp);1906 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], disp);
1940 },1907 },
19411908
1942 .CALL_PLT => {1909 .CALL_PLT => {
1943 // TODO: relax1910 // TODO: relax
1944 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);1911 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);
1945 riscv_util.writeInstU(code[r_offset..][0..4], disp); // auipc1912 const code = (try bw.writableSlice(8))[0..8];
1946 riscv_util.writeInstI(code[r_offset + 4 ..][0..4], disp); // jalr1913 riscv_util.writeInstU(code[0..4], disp); // auipc
1914 riscv_util.writeInstI(code[4..8], disp); // jalr
1947 },1915 },
19481916
1949 .PCREL_HI20 => {1917 .PCREL_HI20 => {
1950 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);1918 const disp: u32 = @bitCast(math.cast(i32, S + A - P) orelse return error.Overflow);
1951 riscv_util.writeInstU(code[r_offset..][0..4], disp);1919 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], disp);
1952 },1920 },
19531921
1954 .PCREL_LO12_I,1922 .PCREL_LO12_I,
...@@ -1965,7 +1933,7 @@ const riscv = struct {...@@ -1965,7 +1933,7 @@ const riscv = struct {
1965 // TODO: implement searching forward1933 // TODO: implement searching forward
1966 var err = try diags.addErrorWithNotes(1);1934 var err = try diags.addErrorWithNotes(1);
1967 try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{});1935 try err.addMsg("TODO: find HI20 paired reloc scanning forward", .{});
1968 err.addNote("in {}:{s} at offset 0x{x}", .{1936 err.addNote("in {f}:{s} at offset 0x{x}", .{
1969 atom.file(elf_file).?.fmtPath(),1937 atom.file(elf_file).?.fmtPath(),
1970 atom.name(elf_file),1938 atom.name(elf_file),
1971 rel.r_offset,1939 rel.r_offset,
...@@ -1986,8 +1954,8 @@ const riscv = struct {...@@ -1986,8 +1954,8 @@ const riscv = struct {
1986 };1954 };
1987 relocs_log.debug(" [{x} => {x}]", .{ P_, disp + P_ });1955 relocs_log.debug(" [{x} => {x}]", .{ P_, disp + P_ });
1988 switch (r_type) {1956 switch (r_type) {
1989 .PCREL_LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], @bitCast(disp)),1957 .PCREL_LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], @bitCast(disp)),
1990 .PCREL_LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], @bitCast(disp)),1958 .PCREL_LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], @bitCast(disp)),
1991 else => unreachable,1959 else => unreachable,
1992 }1960 }
1993 },1961 },
...@@ -1997,8 +1965,8 @@ const riscv = struct {...@@ -1997,8 +1965,8 @@ const riscv = struct {
1997 => {1965 => {
1998 const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);1966 const disp: u32 = @bitCast(math.cast(i32, S + A) orelse return error.Overflow);
1999 switch (r_type) {1967 switch (r_type) {
2000 .LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], disp),1968 .LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], disp),
2001 .LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], disp),1969 .LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], disp),
2002 else => unreachable,1970 else => unreachable,
2003 }1971 }
2004 },1972 },
...@@ -2006,7 +1974,7 @@ const riscv = struct {...@@ -2006,7 +1974,7 @@ const riscv = struct {
2006 .TPREL_HI20 => {1974 .TPREL_HI20 => {
2007 const target_addr: u32 = @intCast(target.address(.{}, elf_file));1975 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
2008 const val: i32 = @intCast(S + A - target_addr);1976 const val: i32 = @intCast(S + A - target_addr);
2009 riscv_util.writeInstU(code[r_offset..][0..4], @bitCast(val));1977 riscv_util.writeInstU((try bw.writableSlice(4))[0..4], @bitCast(val));
2010 },1978 },
20111979
2012 .TPREL_LO12_I,1980 .TPREL_LO12_I,
...@@ -2015,8 +1983,8 @@ const riscv = struct {...@@ -2015,8 +1983,8 @@ const riscv = struct {
2015 const target_addr: u32 = @intCast(target.address(.{}, elf_file));1983 const target_addr: u32 = @intCast(target.address(.{}, elf_file));
2016 const val: i32 = @intCast(S + A - target_addr);1984 const val: i32 = @intCast(S + A - target_addr);
2017 switch (r_type) {1985 switch (r_type) {
2018 .TPREL_LO12_I => riscv_util.writeInstI(code[r_offset..][0..4], @bitCast(val)),1986 .TPREL_LO12_I => riscv_util.writeInstI((try bw.writableSlice(4))[0..4], @bitCast(val)),
2019 .TPREL_LO12_S => riscv_util.writeInstS(code[r_offset..][0..4], @bitCast(val)),1987 .TPREL_LO12_S => riscv_util.writeInstS((try bw.writableSlice(4))[0..4], @bitCast(val)),
2020 else => unreachable,1988 else => unreachable,
2021 }1989 }
2022 },1990 },
...@@ -2035,15 +2003,9 @@ const riscv = struct {...@@ -2035,15 +2003,9 @@ const riscv = struct {
2035 rel: elf.Elf64_Rela,2003 rel: elf.Elf64_Rela,
2036 target: *const Symbol,2004 target: *const Symbol,
2037 args: ResolveArgs,2005 args: ResolveArgs,
2038 it: *RelocsIterator,2006 bw: *std.io.BufferedWriter,
2039 code: []u8,2007 ) anyerror!void {
2040 stream: anytype,
2041 ) !void {
2042 _ = it;
2043
2044 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());2008 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
2045 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
2046 const cwriter = stream.writer();
20472009
2048 _, const A, const S, const GOT, _, _, const DTP = args;2010 _, const A, const S, const GOT, _, _, const DTP = args;
2049 _ = GOT;2011 _ = GOT;
...@@ -2052,30 +2014,30 @@ const riscv = struct {...@@ -2052,30 +2014,30 @@ const riscv = struct {
2052 switch (r_type) {2014 switch (r_type) {
2053 .NONE => unreachable,2015 .NONE => unreachable,
20542016
2055 .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),2017 .@"32" => try bw.writeInt(i32, @as(i32, @intCast(S + A)), .little),
2056 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|2018 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
2057 try cwriter.writeInt(u64, value, .little)2019 try bw.writeInt(u64, value, .little)
2058 else2020 else
2059 try cwriter.writeInt(i64, S + A, .little),2021 try bw.writeInt(i64, S + A, .little),
20602022
2061 .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A),2023 .ADD8 => try riscv_util.writeAddend(i8, .add, S + A, bw),
2062 .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A),2024 .SUB8 => try riscv_util.writeAddend(i8, .sub, S + A, bw),
2063 .ADD16 => riscv_util.writeAddend(i16, .add, code[r_offset..][0..2], S + A),2025 .ADD16 => try riscv_util.writeAddend(i16, .add, S + A, bw),
2064 .SUB16 => riscv_util.writeAddend(i16, .sub, code[r_offset..][0..2], S + A),2026 .SUB16 => try riscv_util.writeAddend(i16, .sub, S + A, bw),
2065 .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A),2027 .ADD32 => try riscv_util.writeAddend(i32, .add, S + A, bw),
2066 .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A),2028 .SUB32 => try riscv_util.writeAddend(i32, .sub, S + A, bw),
2067 .ADD64 => riscv_util.writeAddend(i64, .add, code[r_offset..][0..8], S + A),2029 .ADD64 => try riscv_util.writeAddend(i64, .add, S + A, bw),
2068 .SUB64 => riscv_util.writeAddend(i64, .sub, code[r_offset..][0..8], S + A),2030 .SUB64 => try riscv_util.writeAddend(i64, .sub, S + A, bw),
20692031
2070 .SET8 => mem.writeInt(i8, code[r_offset..][0..1], @as(i8, @truncate(S + A)), .little),2032 .SET8 => try bw.writeInt(i8, @truncate(S + A), .little),
2071 .SET16 => mem.writeInt(i16, code[r_offset..][0..2], @as(i16, @truncate(S + A)), .little),2033 .SET16 => try bw.writeInt(i16, @truncate(S + A), .little),
2072 .SET32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little),2034 .SET32 => try bw.writeInt(i32, @truncate(S + A), .little),
20732035
2074 .SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A),2036 .SET6 => try riscv_util.writeSetSub6(.set, S + A, bw),
2075 .SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A),2037 .SUB6 => try riscv_util.writeSetSub6(.sub, S + A, bw),
20762038
2077 .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A),2039 .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, S + A, bw),
2078 .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A),2040 .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, S - A, bw),
20792041
2080 else => try atom.reportUnhandledRelocError(rel, elf_file),2042 else => try atom.reportUnhandledRelocError(rel, elf_file),
2081 }2043 }
src/link/Elf/AtomList.zig+10-22
...@@ -108,7 +108,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi...@@ -108,7 +108,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi
108 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;108 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;
109 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;109 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
110110
111 log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off });111 log.debug(" atom({f}) at 0x{x}", .{ ref, list.offset(elf_file) + off });
112112
113 const object = atom_ptr.file(elf_file).?.object;113 const object = atom_ptr.file(elf_file).?.object;
114 const code = try object.codeDecompressAlloc(elf_file, ref.index);114 const code = try object.codeDecompressAlloc(elf_file, ref.index);
...@@ -144,7 +144,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -144,7 +144,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
144 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;144 const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow;
145 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;145 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
146146
147 log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off });147 log.debug(" atom({f}) at 0x{x}", .{ ref, list.offset(elf_file) + off });
148148
149 const object = atom_ptr.file(elf_file).?.object;149 const object = atom_ptr.file(elf_file).?.object;
150 const code = try object.codeDecompressAlloc(elf_file, ref.index);150 const code = try object.codeDecompressAlloc(elf_file, ref.index);
...@@ -167,16 +167,10 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {...@@ -167,16 +167,10 @@ pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {
167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;167 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;
168}168}
169169
170pub fn format(170pub fn format(list: AtomList, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
171 list: AtomList,
172 comptime unused_fmt_string: []const u8,
173 options: std.fmt.FormatOptions,
174 writer: anytype,
175) !void {
176 _ = list;171 _ = list;
172 _ = bw;
177 _ = unused_fmt_string;173 _ = unused_fmt_string;
178 _ = options;
179 _ = writer;
180 @compileError("do not format AtomList directly");174 @compileError("do not format AtomList directly");
181}175}
182176
...@@ -186,25 +180,19 @@ pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) {...@@ -186,25 +180,19 @@ pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) {
186 return .{ .data = .{ list, elf_file } };180 return .{ .data = .{ list, elf_file } };
187}181}
188182
189fn format2(183fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
190 ctx: FormatCtx,
191 comptime unused_fmt_string: []const u8,
192 options: std.fmt.FormatOptions,
193 writer: anytype,
194) !void {
195 _ = unused_fmt_string;184 _ = unused_fmt_string;
196 _ = options;
197 const list, const elf_file = ctx;185 const list, const elf_file = ctx;
198 try writer.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{186 try bw.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{
199 list.address(elf_file), list.output_section_index,187 list.address(elf_file), list.output_section_index,
200 list.alignment.toByteUnits() orelse 0, list.size,188 list.alignment.toByteUnits() orelse 0, list.size,
201 });189 });
202 try writer.writeAll(" : atoms{ ");190 try bw.writeAll(" : atoms{ ");
203 for (list.atoms.keys(), 0..) |ref, i| {191 for (list.atoms.keys(), 0..) |ref, i| {
204 try writer.print("{}", .{ref});192 try bw.print("{f}", .{ref});
205 if (i < list.atoms.keys().len - 1) try writer.writeAll(", ");193 if (i < list.atoms.keys().len - 1) try bw.writeAll(", ");
206 }194 }
207 try writer.writeAll(" }");195 try bw.writeAll(" }");
208}196}
209197
210const assert = std.debug.assert;198const assert = std.debug.assert;
src/link/Elf/LinkerDefined.zig+4-10
...@@ -449,23 +449,17 @@ const FormatContext = struct {...@@ -449,23 +449,17 @@ const FormatContext = struct {
449 elf_file: *Elf,449 elf_file: *Elf,
450};450};
451451
452fn formatSymtab(452fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
453 ctx: FormatContext,
454 comptime unused_fmt_string: []const u8,
455 options: std.fmt.FormatOptions,
456 writer: anytype,
457) !void {
458 _ = unused_fmt_string;453 _ = unused_fmt_string;
459 _ = options;
460 const self = ctx.self;454 const self = ctx.self;
461 const elf_file = ctx.elf_file;455 const elf_file = ctx.elf_file;
462 try writer.writeAll(" globals\n");456 try bw.writeAll(" globals\n");
463 for (self.symbols.items, 0..) |sym, i| {457 for (self.symbols.items, 0..) |sym, i| {
464 const ref = self.resolveSymbol(@intCast(i), elf_file);458 const ref = self.resolveSymbol(@intCast(i), elf_file);
465 if (elf_file.symbol(ref)) |ref_sym| {459 if (elf_file.symbol(ref)) |ref_sym| {
466 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});460 try bw.print(" {f}\n", .{ref_sym.fmt(elf_file)});
467 } else {461 } else {
468 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});462 try bw.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
469 }463 }
470 }464 }
471}465}
src/link/Elf/Merge.zig+10-34
...@@ -157,16 +157,10 @@ pub const Section = struct {...@@ -157,16 +157,10 @@ pub const Section = struct {
157 }157 }
158 };158 };
159159
160 pub fn format(160 pub fn format(msec: Section, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
161 msec: Section,
162 comptime unused_fmt_string: []const u8,
163 options: std.fmt.FormatOptions,
164 writer: anytype,
165 ) !void {
166 _ = msec;161 _ = msec;
162 _ = bw;
167 _ = unused_fmt_string;163 _ = unused_fmt_string;
168 _ = options;
169 _ = writer;
170 @compileError("do not format directly");164 @compileError("do not format directly");
171 }165 }
172166
...@@ -182,17 +176,11 @@ pub const Section = struct {...@@ -182,17 +176,11 @@ pub const Section = struct {
182 elf_file: *Elf,176 elf_file: *Elf,
183 };177 };
184178
185 pub fn format2(179 pub fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
186 ctx: FormatContext,
187 comptime unused_fmt_string: []const u8,
188 options: std.fmt.FormatOptions,
189 writer: anytype,
190 ) !void {
191 _ = options;
192 _ = unused_fmt_string;180 _ = unused_fmt_string;
193 const msec = ctx.msec;181 const msec = ctx.msec;
194 const elf_file = ctx.elf_file;182 const elf_file = ctx.elf_file;
195 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{183 try bw.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{
196 msec.name(elf_file),184 msec.name(elf_file),
197 msec.address(elf_file),185 msec.address(elf_file),
198 msec.size,186 msec.size,
...@@ -202,7 +190,7 @@ pub const Section = struct {...@@ -202,7 +190,7 @@ pub const Section = struct {
202 msec.flags,190 msec.flags,
203 });191 });
204 for (msec.subsections.items) |msub| {192 for (msec.subsections.items) |msub| {
205 try writer.print(" {}\n", .{msub.fmt(elf_file)});193 try bw.print(" {f}\n", .{msub.fmt(elf_file)});
206 }194 }
207 }195 }
208196
...@@ -231,16 +219,10 @@ pub const Subsection = struct {...@@ -231,16 +219,10 @@ pub const Subsection = struct {
231 return msec.bytes.items[msub.string_index..][0..msub.size];219 return msec.bytes.items[msub.string_index..][0..msub.size];
232 }220 }
233221
234 pub fn format(222 pub fn format(msub: Subsection, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
235 msub: Subsection,
236 comptime unused_fmt_string: []const u8,
237 options: std.fmt.FormatOptions,
238 writer: anytype,
239 ) !void {
240 _ = msub;223 _ = msub;
224 _ = bw;
241 _ = unused_fmt_string;225 _ = unused_fmt_string;
242 _ = options;
243 _ = writer;
244 @compileError("do not format directly");226 @compileError("do not format directly");
245 }227 }
246228
...@@ -256,22 +238,16 @@ pub const Subsection = struct {...@@ -256,22 +238,16 @@ pub const Subsection = struct {
256 elf_file: *Elf,238 elf_file: *Elf,
257 };239 };
258240
259 pub fn format2(241 pub fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
260 ctx: FormatContext,
261 comptime unused_fmt_string: []const u8,
262 options: std.fmt.FormatOptions,
263 writer: anytype,
264 ) !void {
265 _ = options;
266 _ = unused_fmt_string;242 _ = unused_fmt_string;
267 const msub = ctx.msub;243 const msub = ctx.msub;
268 const elf_file = ctx.elf_file;244 const elf_file = ctx.elf_file;
269 try writer.print("@{x} : align({x}) : size({x})", .{245 try bw.print("@{x} : align({x}) : size({x})", .{
270 msub.address(elf_file),246 msub.address(elf_file),
271 msub.alignment,247 msub.alignment,
272 msub.size,248 msub.size,
273 });249 });
274 if (!msub.alive) try writer.writeAll(" : [*]");250 if (!msub.alive) try bw.writeAll(" : [*]");
275 }251 }
276252
277 pub const Index = u32;253 pub const Index = u32;
src/link/Elf/Object.zig+47-90
...@@ -281,7 +281,7 @@ fn initAtoms(...@@ -281,7 +281,7 @@ fn initAtoms(
281 elf.SHT_GROUP => {281 elf.SHT_GROUP => {
282 if (shdr.sh_info >= self.symtab.items.len) {282 if (shdr.sh_info >= self.symtab.items.len) {
283 // TODO convert into an error283 // TODO convert into an error
284 log.debug("{}: invalid symbol index in sh_info", .{self.fmtPath()});284 log.debug("{f}: invalid symbol index in sh_info", .{self.fmtPath()});
285 continue;285 continue;
286 }286 }
287 const group_info_sym = self.symtab.items[shdr.sh_info];287 const group_info_sym = self.symtab.items[shdr.sh_info];
...@@ -448,7 +448,8 @@ fn parseEhFrame(...@@ -448,7 +448,8 @@ fn parseEhFrame(
448 const fdes_start = self.fdes.items.len;448 const fdes_start = self.fdes.items.len;
449 const cies_start = self.cies.items.len;449 const cies_start = self.cies.items.len;
450450
451 var it = eh_frame.Iterator{ .data = raw };451 var it: eh_frame.Iterator = undefined;
452 it.br.initFixed(raw);
452 while (try it.next()) |rec| {453 while (try it.next()) |rec| {
453 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);454 const rel_range = filterRelocs(self.relocs.items[rel_start..][0..relocs.len], rec.offset, rec.size + 4);
454 switch (rec.tag) {455 switch (rec.tag) {
...@@ -488,7 +489,7 @@ fn parseEhFrame(...@@ -488,7 +489,7 @@ fn parseEhFrame(
488 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));489 if (cie.offset == cie_ptr) break @as(u32, @intCast(cie_index));
489 } else {490 } else {
490 // TODO convert into an error491 // TODO convert into an error
491 log.debug("{s}: no matching CIE found for FDE at offset {x}", .{492 log.debug("{f}: no matching CIE found for FDE at offset {x}", .{
492 self.fmtPath(),493 self.fmtPath(),
493 fde.offset,494 fde.offset,
494 });495 });
...@@ -582,7 +583,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {...@@ -582,7 +583,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
582 if (sym.flags.import) {583 if (sym.flags.import) {
583 if (sym.type(elf_file) != elf.STT_FUNC)584 if (sym.type(elf_file) != elf.STT_FUNC)
584 // TODO convert into an error585 // TODO convert into an error
585 log.debug("{s}: {s}: CIE referencing external data reference", .{586 log.debug("{fs}: {s}: CIE referencing external data reference", .{
586 self.fmtPath(), sym.name(elf_file),587 self.fmtPath(), sym.name(elf_file),
587 });588 });
588 sym.flags.needs_plt = true;589 sym.flags.needs_plt = true;
...@@ -796,7 +797,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -796,7 +797,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
796 if (!isNull(data[end .. end + sh_entsize])) {797 if (!isNull(data[end .. end + sh_entsize])) {
797 var err = try diags.addErrorWithNotes(1);798 var err = try diags.addErrorWithNotes(1);
798 try err.addMsg("string not null terminated", .{});799 try err.addMsg("string not null terminated", .{});
799 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });800 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
800 return error.LinkFailure;801 return error.LinkFailure;
801 }802 }
802 end += sh_entsize;803 end += sh_entsize;
...@@ -811,7 +812,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {...@@ -811,7 +812,7 @@ pub fn initInputMergeSections(self: *Object, elf_file: *Elf) !void {
811 if (shdr.sh_size % sh_entsize != 0) {812 if (shdr.sh_size % sh_entsize != 0) {
812 var err = try diags.addErrorWithNotes(1);813 var err = try diags.addErrorWithNotes(1);
813 try err.addMsg("size not a multiple of sh_entsize", .{});814 try err.addMsg("size not a multiple of sh_entsize", .{});
814 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });815 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
815 return error.LinkFailure;816 return error.LinkFailure;
816 }817 }
817818
...@@ -889,7 +890,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -889,7 +890,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
889 var err = try diags.addErrorWithNotes(2);890 var err = try diags.addErrorWithNotes(2);
890 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});891 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
891 err.addNote("for symbol {s}", .{sym.name(elf_file)});892 err.addNote("for symbol {s}", .{sym.name(elf_file)});
892 err.addNote("in {}", .{self.fmtPath()});893 err.addNote("in {f}", .{self.fmtPath()});
893 return error.LinkFailure;894 return error.LinkFailure;
894 };895 };
895896
...@@ -914,7 +915,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{...@@ -914,7 +915,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) error{
914 const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {915 const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {
915 var err = try diags.addErrorWithNotes(1);916 var err = try diags.addErrorWithNotes(1);
916 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});917 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
917 err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });918 err.addNote("in {f}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
918 return error.LinkFailure;919 return error.LinkFailure;
919 };920 };
920921
...@@ -952,7 +953,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -952,7 +953,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
952 const is_tls = sym.type(elf_file) == elf.STT_TLS;953 const is_tls = sym.type(elf_file) == elf.STT_TLS;
953 const name = if (is_tls) ".tls_common" else ".common";954 const name = if (is_tls) ".tls_common" else ".common";
954 const name_offset = @as(u32, @intCast(self.strtab.items.len));955 const name_offset = @as(u32, @intCast(self.strtab.items.len));
955 try self.strtab.writer(gpa).print("{s}\x00", .{name});956 try self.strtab.print(gpa, "{s}\x00", .{name});
956957
957 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;958 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
958 if (is_tls) sh_flags |= elf.SHF_TLS;959 if (is_tls) sh_flags |= elf.SHF_TLS;
...@@ -1191,28 +1192,26 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index...@@ -1191,28 +1192,26 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index
1191 const atom_ptr = self.atom(atom_index).?;1192 const atom_ptr = self.atom(atom_index).?;
1192 const shdr = atom_ptr.inputShdr(elf_file);1193 const shdr = atom_ptr.inputShdr(elf_file);
1193 const handle = elf_file.fileHandle(self.file_handle);1194 const handle = elf_file.fileHandle(self.file_handle);
1194 const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index);1195 var br: std.io.BufferedReader = undefined;
1195 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(data);1196 br.initFixed(try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index));
1197 defer if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) gpa.free(br.storageBuffer());
11961198
1197 if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {1199 if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
1198 const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;1200 const chdr = (try br.takeStruct(elf.Elf64_Chdr)).*;
1199 switch (chdr.ch_type) {1201 switch (chdr.ch_type) {
1200 .ZLIB => {1202 .ZLIB => {
1201 var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]);1203 var bw: std.io.BufferedWriter = undefined;
1202 var zlib_stream = std.compress.zlib.decompressor(stream.reader());1204 bw.initFixed(try gpa.alloc(u8, std.math.cast(usize, chdr.ch_size) orelse return error.Overflow));
1203 const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow;1205 errdefer gpa.free(bw.buffer);
1204 const decomp = try gpa.alloc(u8, size);1206 try std.compress.zlib.decompress(&br, &bw);
1205 const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput;1207 if (bw.end != bw.buffer.len) return error.InputOutput;
1206 if (nread != decomp.len) {1208 return bw.buffer;
1207 return error.InputOutput;
1208 }
1209 return decomp;
1210 },1209 },
1211 else => @panic("TODO unhandled compression scheme"),1210 else => @panic("TODO unhandled compression scheme"),
1212 }1211 }
1213 }1212 }
12141213
1215 return data;1214 return br.storageBuffer();
1216}1215}
12171216
1218fn locals(self: *Object) []Symbol {1217fn locals(self: *Object) []Symbol {
...@@ -1432,16 +1431,10 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {...@@ -1432,16 +1431,10 @@ pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {
1432 return &self.groups.items[index];1431 return &self.groups.items[index];
1433}1432}
14341433
1435pub fn format(1434pub fn format(self: *Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1436 self: *Object,
1437 comptime unused_fmt_string: []const u8,
1438 options: std.fmt.FormatOptions,
1439 writer: anytype,
1440) !void {
1441 _ = self;1435 _ = self;
1436 _ = bw;
1442 _ = unused_fmt_string;1437 _ = unused_fmt_string;
1443 _ = options;
1444 _ = writer;
1445 @compileError("do not format objects directly");1438 @compileError("do not format objects directly");
1446}1439}
14471440
...@@ -1457,28 +1450,22 @@ const FormatContext = struct {...@@ -1457,28 +1450,22 @@ const FormatContext = struct {
1457 elf_file: *Elf,1450 elf_file: *Elf,
1458};1451};
14591452
1460fn formatSymtab(1453fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1461 ctx: FormatContext,
1462 comptime unused_fmt_string: []const u8,
1463 options: std.fmt.FormatOptions,
1464 writer: anytype,
1465) !void {
1466 _ = unused_fmt_string;1454 _ = unused_fmt_string;
1467 _ = options;
1468 const object = ctx.object;1455 const object = ctx.object;
1469 const elf_file = ctx.elf_file;1456 const elf_file = ctx.elf_file;
1470 try writer.writeAll(" locals\n");1457 try bw.writeAll(" locals\n");
1471 for (object.locals()) |sym| {1458 for (object.locals()) |sym| {
1472 try writer.print(" {}\n", .{sym.fmt(elf_file)});1459 try bw.print(" {f}\n", .{sym.fmt(elf_file)});
1473 }1460 }
1474 try writer.writeAll(" globals\n");1461 try bw.writeAll(" globals\n");
1475 for (object.globals(), 0..) |sym, i| {1462 for (object.globals(), 0..) |sym, i| {
1476 const first_global = object.first_global.?;1463 const first_global = object.first_global.?;
1477 const ref = object.resolveSymbol(@intCast(i + first_global), elf_file);1464 const ref = object.resolveSymbol(@intCast(i + first_global), elf_file);
1478 if (elf_file.symbol(ref)) |ref_sym| {1465 if (elf_file.symbol(ref)) |ref_sym| {
1479 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});1466 try bw.print(" {f}\n", .{ref_sym.fmt(elf_file)});
1480 } else {1467 } else {
1481 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});1468 try bw.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
1482 }1469 }
1483 }1470 }
1484}1471}
...@@ -1490,19 +1477,13 @@ pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {...@@ -1490,19 +1477,13 @@ pub fn fmtAtoms(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatAtoms) {
1490 } };1477 } };
1491}1478}
14921479
1493fn formatAtoms(1480fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1494 ctx: FormatContext,
1495 comptime unused_fmt_string: []const u8,
1496 options: std.fmt.FormatOptions,
1497 writer: anytype,
1498) !void {
1499 _ = unused_fmt_string;1481 _ = unused_fmt_string;
1500 _ = options;
1501 const object = ctx.object;1482 const object = ctx.object;
1502 try writer.writeAll(" atoms\n");1483 try bw.writeAll(" atoms\n");
1503 for (object.atoms_indexes.items) |atom_index| {1484 for (object.atoms_indexes.items) |atom_index| {
1504 const atom_ptr = object.atom(atom_index) orelse continue;1485 const atom_ptr = object.atom(atom_index) orelse continue;
1505 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});1486 try bw.print(" {f}\n", .{atom_ptr.fmt(ctx.elf_file)});
1506 }1487 }
1507}1488}
15081489
...@@ -1513,18 +1494,12 @@ pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {...@@ -1513,18 +1494,12 @@ pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
1513 } };1494 } };
1514}1495}
15151496
1516fn formatCies(1497fn formatCies(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1517 ctx: FormatContext,
1518 comptime unused_fmt_string: []const u8,
1519 options: std.fmt.FormatOptions,
1520 writer: anytype,
1521) !void {
1522 _ = unused_fmt_string;1498 _ = unused_fmt_string;
1523 _ = options;
1524 const object = ctx.object;1499 const object = ctx.object;
1525 try writer.writeAll(" cies\n");1500 try bw.writeAll(" cies\n");
1526 for (object.cies.items, 0..) |cie, i| {1501 for (object.cies.items, 0..) |cie, i| {
1527 try writer.print(" cie({d}) : {}\n", .{ i, cie.fmt(ctx.elf_file) });1502 try bw.print(" cie({d}) : {f}\n", .{ i, cie.fmt(ctx.elf_file) });
1528 }1503 }
1529}1504}
15301505
...@@ -1535,18 +1510,12 @@ pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) {...@@ -1535,18 +1510,12 @@ pub fn fmtFdes(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatFdes) {
1535 } };1510 } };
1536}1511}
15371512
1538fn formatFdes(1513fn formatFdes(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1539 ctx: FormatContext,
1540 comptime unused_fmt_string: []const u8,
1541 options: std.fmt.FormatOptions,
1542 writer: anytype,
1543) !void {
1544 _ = unused_fmt_string;1514 _ = unused_fmt_string;
1545 _ = options;
1546 const object = ctx.object;1515 const object = ctx.object;
1547 try writer.writeAll(" fdes\n");1516 try bw.writeAll(" fdes\n");
1548 for (object.fdes.items, 0..) |fde, i| {1517 for (object.fdes.items, 0..) |fde, i| {
1549 try writer.print(" fde({d}) : {}\n", .{ i, fde.fmt(ctx.elf_file) });1518 try bw.print(" fde({d}) : {f}\n", .{ i, fde.fmt(ctx.elf_file) });
1550 }1519 }
1551}1520}
15521521
...@@ -1557,26 +1526,20 @@ pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups)...@@ -1557,26 +1526,20 @@ pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups)
1557 } };1526 } };
1558}1527}
15591528
1560fn formatGroups(1529fn formatGroups(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1561 ctx: FormatContext,
1562 comptime unused_fmt_string: []const u8,
1563 options: std.fmt.FormatOptions,
1564 writer: anytype,
1565) !void {
1566 _ = unused_fmt_string;1530 _ = unused_fmt_string;
1567 _ = options;
1568 const object = ctx.object;1531 const object = ctx.object;
1569 const elf_file = ctx.elf_file;1532 const elf_file = ctx.elf_file;
1570 try writer.writeAll(" groups\n");1533 try bw.writeAll(" groups\n");
1571 for (object.groups.items, 0..) |g, g_index| {1534 for (object.groups.items, 0..) |g, g_index| {
1572 try writer.print(" {s}({d})", .{ if (g.is_comdat) "COMDAT" else "GROUP", g_index });1535 try bw.print(" {s}({d})", .{ if (g.is_comdat) "COMDAT" else "GROUP", g_index });
1573 if (!g.alive) try writer.writeAll(" : [*]");1536 if (!g.alive) try bw.writeAll(" : [*]");
1574 try writer.writeByte('\n');1537 try bw.writeByte('\n');
1575 const g_members = g.members(elf_file);1538 const g_members = g.members(elf_file);
1576 for (g_members) |shndx| {1539 for (g_members) |shndx| {
1577 const atom_index = object.atoms_indexes.items[shndx];1540 const atom_index = object.atoms_indexes.items[shndx];
1578 const atom_ptr = object.atom(atom_index) orelse continue;1541 const atom_ptr = object.atom(atom_index) orelse continue;
1579 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });1542 try bw.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
1580 }1543 }
1581 }1544 }
1582}1545}
...@@ -1585,18 +1548,12 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {...@@ -1585,18 +1548,12 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
1585 return .{ .data = self };1548 return .{ .data = self };
1586}1549}
15871550
1588fn formatPath(1551fn formatPath(object: Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1589 object: Object,
1590 comptime unused_fmt_string: []const u8,
1591 options: std.fmt.FormatOptions,
1592 writer: anytype,
1593) !void {
1594 _ = unused_fmt_string;1552 _ = unused_fmt_string;
1595 _ = options;
1596 if (object.archive) |ar| {1553 if (object.archive) |ar| {
1597 try writer.print("{}({})", .{ ar.path, object.path });1554 try bw.print("{f}({f})", .{ ar.path, object.path });
1598 } else {1555 } else {
1599 try writer.print("{}", .{object.path});1556 try bw.print("{f}", .{object.path});
1600 }1557 }
1601}1558}
16021559
src/link/Elf/SharedObject.zig+6-18
...@@ -509,16 +509,10 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void...@@ -509,16 +509,10 @@ pub fn setSymbolExtra(self: *SharedObject, index: u32, extra: Symbol.Extra) void
509 }509 }
510}510}
511511
512pub fn format(512pub fn format(self: SharedObject, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
513 self: SharedObject,
514 comptime unused_fmt_string: []const u8,
515 options: std.fmt.FormatOptions,
516 writer: anytype,
517) !void {
518 _ = self;513 _ = self;
514 _ = bw;
519 _ = unused_fmt_string;515 _ = unused_fmt_string;
520 _ = options;
521 _ = writer;
522 @compileError("unreachable");516 @compileError("unreachable");
523}517}
524518
...@@ -534,23 +528,17 @@ const FormatContext = struct {...@@ -534,23 +528,17 @@ const FormatContext = struct {
534 elf_file: *Elf,528 elf_file: *Elf,
535};529};
536530
537fn formatSymtab(531fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
538 ctx: FormatContext,
539 comptime unused_fmt_string: []const u8,
540 options: std.fmt.FormatOptions,
541 writer: anytype,
542) !void {
543 _ = unused_fmt_string;532 _ = unused_fmt_string;
544 _ = options;
545 const shared = ctx.shared;533 const shared = ctx.shared;
546 const elf_file = ctx.elf_file;534 const elf_file = ctx.elf_file;
547 try writer.writeAll(" globals\n");535 try bw.writeAll(" globals\n");
548 for (shared.symbols.items, 0..) |sym, i| {536 for (shared.symbols.items, 0..) |sym, i| {
549 const ref = shared.resolveSymbol(@intCast(i), elf_file);537 const ref = shared.resolveSymbol(@intCast(i), elf_file);
550 if (elf_file.symbol(ref)) |ref_sym| {538 if (elf_file.symbol(ref)) |ref_sym| {
551 try writer.print(" {}\n", .{ref_sym.fmt(elf_file)});539 try bw.print(" {f}\n", .{ref_sym.fmt(elf_file)});
552 } else {540 } else {
553 try writer.print(" {s} : unclaimed\n", .{sym.name(elf_file)});541 try bw.print(" {s} : unclaimed\n", .{sym.name(elf_file)});
554 }542 }
555 }543 }
556}544}
src/link/Elf/Symbol.zig+15-33
...@@ -316,16 +316,10 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -316,16 +316,10 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
316 out.st_size = esym.st_size;316 out.st_size = esym.st_size;
317}317}
318318
319pub fn format(319pub fn format(symbol: Symbol, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
320 symbol: Symbol,
321 comptime unused_fmt_string: []const u8,
322 options: std.fmt.FormatOptions,
323 writer: anytype,
324) !void {
325 _ = symbol;320 _ = symbol;
321 _ = bw;
326 _ = unused_fmt_string;322 _ = unused_fmt_string;
327 _ = options;
328 _ = writer;
329 @compileError("do not format Symbol directly");323 @compileError("do not format Symbol directly");
330}324}
331325
...@@ -341,24 +335,18 @@ pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) {...@@ -341,24 +335,18 @@ pub fn fmtName(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(formatName) {
341 } };335 } };
342}336}
343337
344fn formatName(338fn formatName(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
345 ctx: FormatContext,
346 comptime unused_fmt_string: []const u8,
347 options: std.fmt.FormatOptions,
348 writer: anytype,
349) !void {
350 _ = options;
351 _ = unused_fmt_string;339 _ = unused_fmt_string;
352 const elf_file = ctx.elf_file;340 const elf_file = ctx.elf_file;
353 const symbol = ctx.symbol;341 const symbol = ctx.symbol;
354 try writer.writeAll(symbol.name(elf_file));342 try bw.writeAll(symbol.name(elf_file));
355 switch (symbol.version_index.VERSION) {343 switch (symbol.version_index.VERSION) {
356 @intFromEnum(elf.VER_NDX.LOCAL), @intFromEnum(elf.VER_NDX.GLOBAL) => {},344 @intFromEnum(elf.VER_NDX.LOCAL), @intFromEnum(elf.VER_NDX.GLOBAL) => {},
357 else => {345 else => {
358 const file_ptr = symbol.file(elf_file).?;346 const file_ptr = symbol.file(elf_file).?;
359 assert(file_ptr == .shared_object);347 assert(file_ptr == .shared_object);
360 const shared_object = file_ptr.shared_object;348 const shared_object = file_ptr.shared_object;
361 try writer.print("@{s}", .{shared_object.versionString(symbol.version_index)});349 try bw.print("@{s}", .{shared_object.versionString(symbol.version_index)});
362 },350 },
363 }351 }
364}352}
...@@ -370,17 +358,11 @@ pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) {...@@ -370,17 +358,11 @@ pub fn fmt(symbol: Symbol, elf_file: *Elf) std.fmt.Formatter(format2) {
370 } };358 } };
371}359}
372360
373fn format2(361fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
374 ctx: FormatContext,
375 comptime unused_fmt_string: []const u8,
376 options: std.fmt.FormatOptions,
377 writer: anytype,
378) !void {
379 _ = options;
380 _ = unused_fmt_string;362 _ = unused_fmt_string;
381 const symbol = ctx.symbol;363 const symbol = ctx.symbol;
382 const elf_file = ctx.elf_file;364 const elf_file = ctx.elf_file;
383 try writer.print("%{d} : {s} : @{x}", .{365 try bw.print("%{d} : {f} : @{x}", .{
384 symbol.esym_index,366 symbol.esym_index,
385 symbol.fmtName(elf_file),367 symbol.fmtName(elf_file),
386 symbol.address(.{ .plt = false, .trampoline = false }, elf_file),368 symbol.address(.{ .plt = false, .trampoline = false }, elf_file),
...@@ -388,25 +370,25 @@ fn format2(...@@ -388,25 +370,25 @@ fn format2(
388 if (symbol.file(elf_file)) |file_ptr| {370 if (symbol.file(elf_file)) |file_ptr| {
389 if (symbol.isAbs(elf_file)) {371 if (symbol.isAbs(elf_file)) {
390 if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) {372 if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) {
391 try writer.writeAll(" : undef");373 try bw.writeAll(" : undef");
392 } else {374 } else {
393 try writer.writeAll(" : absolute");375 try bw.writeAll(" : absolute");
394 }376 }
395 } else if (symbol.outputShndx(elf_file)) |shndx| {377 } else if (symbol.outputShndx(elf_file)) |shndx| {
396 try writer.print(" : shdr({d})", .{shndx});378 try bw.print(" : shdr({d})", .{shndx});
397 }379 }
398 if (symbol.atom(elf_file)) |atom_ptr| {380 if (symbol.atom(elf_file)) |atom_ptr| {
399 try writer.print(" : atom({d})", .{atom_ptr.atom_index});381 try bw.print(" : atom({d})", .{atom_ptr.atom_index});
400 }382 }
401 var buf: [2]u8 = .{'_'} ** 2;383 var buf: [2]u8 = .{'_'} ** 2;
402 if (symbol.flags.@"export") buf[0] = 'E';384 if (symbol.flags.@"export") buf[0] = 'E';
403 if (symbol.flags.import) buf[1] = 'I';385 if (symbol.flags.import) buf[1] = 'I';
404 try writer.print(" : {s}", .{&buf});386 try bw.print(" : {s}", .{&buf});
405 if (symbol.flags.weak) try writer.writeAll(" : weak");387 if (symbol.flags.weak) try bw.writeAll(" : weak");
406 switch (file_ptr) {388 switch (file_ptr) {
407 inline else => |x| try writer.print(" : {s}({d})", .{ @tagName(file_ptr), x.index }),389 inline else => |x| try bw.print(" : {s}({d})", .{ @tagName(file_ptr), x.index }),
408 }390 }
409 } else try writer.writeAll(" : unresolved");391 } else try bw.writeAll(" : unresolved");
410}392}
411393
412pub const Flags = packed struct {394pub const Flags = packed struct {
src/link/Elf/Thunk.zig+5-17
...@@ -65,16 +65,10 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {...@@ -65,16 +65,10 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {
65 };65 };
66}66}
6767
68pub fn format(68pub fn format(thunk: Thunk, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
69 thunk: Thunk,
70 comptime unused_fmt_string: []const u8,
71 options: std.fmt.FormatOptions,
72 writer: anytype,
73) !void {
74 _ = thunk;69 _ = thunk;
70 _ = bw;
75 _ = unused_fmt_string;71 _ = unused_fmt_string;
76 _ = options;
77 _ = writer;
78 @compileError("do not format Thunk directly");72 @compileError("do not format Thunk directly");
79}73}
8074
...@@ -90,20 +84,14 @@ const FormatContext = struct {...@@ -90,20 +84,14 @@ const FormatContext = struct {
90 elf_file: *Elf,84 elf_file: *Elf,
91};85};
9286
93fn format2(87fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
94 ctx: FormatContext,
95 comptime unused_fmt_string: []const u8,
96 options: std.fmt.FormatOptions,
97 writer: anytype,
98) !void {
99 _ = options;
100 _ = unused_fmt_string;88 _ = unused_fmt_string;
101 const thunk = ctx.thunk;89 const thunk = ctx.thunk;
102 const elf_file = ctx.elf_file;90 const elf_file = ctx.elf_file;
103 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });91 try bw.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
104 for (thunk.symbols.keys()) |ref| {92 for (thunk.symbols.keys()) |ref| {
105 const sym = elf_file.symbol(ref).?;93 const sym = elf_file.symbol(ref).?;
106 try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });94 try bw.print(" {f} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });
107 }95 }
108}96}
10997
src/link/Elf/ZigObject.zig+20-41
...@@ -35,9 +35,6 @@ lazy_syms: LazySymbolTable = .{},...@@ -35,9 +35,6 @@ lazy_syms: LazySymbolTable = .{},
35/// Table of tracked `Nav`s.35/// Table of tracked `Nav`s.
36navs: NavTable = .{},36navs: NavTable = .{},
3737
38/// TLS variables indexed by Atom.Index.
39tls_variables: TlsTable = .{},
40
41/// Table of tracked `Uav`s.38/// Table of tracked `Uav`s.
42uavs: UavTable = .{},39uavs: UavTable = .{},
4340
...@@ -257,7 +254,6 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {...@@ -257,7 +254,6 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
257 meta.exports.deinit(allocator);254 meta.exports.deinit(allocator);
258 }255 }
259 self.uavs.deinit(allocator);256 self.uavs.deinit(allocator);
260 self.tls_variables.deinit(allocator);
261257
262 if (self.dwarf) |*dwarf| {258 if (self.dwarf) |*dwarf| {
263 dwarf.deinit();259 dwarf.deinit();
...@@ -925,7 +921,7 @@ pub fn getNavVAddr(...@@ -925,7 +921,7 @@ pub fn getNavVAddr(
925 const zcu = pt.zcu;921 const zcu = pt.zcu;
926 const ip = &zcu.intern_pool;922 const ip = &zcu.intern_pool;
927 const nav = ip.getNav(nav_index);923 const nav = ip.getNav(nav_index);
928 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });924 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
929 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(925 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
930 elf_file,926 elf_file,
931 nav.name.toSlice(ip),927 nav.name.toSlice(ip),
...@@ -1268,7 +1264,7 @@ fn updateNavCode(...@@ -1268,7 +1264,7 @@ fn updateNavCode(
1268 const ip = &zcu.intern_pool;1264 const ip = &zcu.intern_pool;
1269 const nav = ip.getNav(nav_index);1265 const nav = ip.getNav(nav_index);
12701266
1271 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });1267 log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
12721268
1273 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1269 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1274 const required_alignment = switch (pt.navAlignment(nav_index)) {1270 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -1302,7 +1298,7 @@ fn updateNavCode(...@@ -1302,7 +1298,7 @@ fn updateNavCode(
1302 self.allocateAtom(atom_ptr, true, elf_file) catch |err|1298 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1303 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});1299 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
13041300
1305 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });1301 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
1306 if (old_vaddr != atom_ptr.value) {1302 if (old_vaddr != atom_ptr.value) {
1307 sym.value = 0;1303 sym.value = 0;
1308 esym.st_value = 0;1304 esym.st_value = 0;
...@@ -1347,7 +1343,7 @@ fn updateNavCode(...@@ -1347,7 +1343,7 @@ fn updateNavCode(
1347 const file_offset = atom_ptr.offset(elf_file);1343 const file_offset = atom_ptr.offset(elf_file);
1348 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|1344 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|
1349 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});1345 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});
1350 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });1346 log.debug("writing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
1351 }1347 }
1352}1348}
13531349
...@@ -1365,7 +1361,7 @@ fn updateTlv(...@@ -1365,7 +1361,7 @@ fn updateTlv(
1365 const gpa = zcu.gpa;1361 const gpa = zcu.gpa;
1366 const nav = ip.getNav(nav_index);1362 const nav = ip.getNav(nav_index);
13671363
1368 log.debug("updateTlv {}({d})", .{ nav.fqn.fmt(ip), nav_index });1364 log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
13691365
1370 const required_alignment = pt.navAlignment(nav_index);1366 const required_alignment = pt.navAlignment(nav_index);
13711367
...@@ -1386,9 +1382,6 @@ fn updateTlv(...@@ -1386,9 +1382,6 @@ fn updateTlv(
1386 atom_ptr.alignment = required_alignment;1382 atom_ptr.alignment = required_alignment;
1387 atom_ptr.size = code.len;1383 atom_ptr.size = code.len;
13881384
1389 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
1390 assert(!gop.found_existing); // TODO incremental updates
1391
1392 self.allocateAtom(atom_ptr, true, elf_file) catch |err|1385 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1393 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});1386 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
1394 sym.value = 0;1387 sym.value = 0;
...@@ -1424,7 +1417,7 @@ pub fn updateFunc(...@@ -1424,7 +1417,7 @@ pub fn updateFunc(
1424 const gpa = elf_file.base.comp.gpa;1417 const gpa = elf_file.base.comp.gpa;
1425 const func = zcu.funcInfo(func_index);1418 const func = zcu.funcInfo(func_index);
14261419
1427 log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });1420 log.debug("updateFunc {f}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });
14281421
1429 const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav);1422 const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav);
1430 self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self);1423 self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self);
...@@ -1447,7 +1440,7 @@ pub fn updateFunc(...@@ -1447,7 +1440,7 @@ pub fn updateFunc(
1447 const code = code_buffer.items;1440 const code = code_buffer.items;
14481441
1449 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);1442 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);
1450 log.debug("setting shdr({x},{s}) for {}", .{1443 log.debug("setting shdr({x},{s}) for {f}", .{
1451 shndx,1444 shndx,
1452 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),1445 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
1453 ip.getNav(func.owner_nav).fqn.fmt(ip),1446 ip.getNav(func.owner_nav).fqn.fmt(ip),
...@@ -1529,7 +1522,7 @@ pub fn updateNav(...@@ -1529,7 +1522,7 @@ pub fn updateNav(
1529 const ip = &zcu.intern_pool;1522 const ip = &zcu.intern_pool;
1530 const nav = ip.getNav(nav_index);1523 const nav = ip.getNav(nav_index);
15311524
1532 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });1525 log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
15331526
1534 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {1527 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
1535 .func => .none,1528 .func => .none,
...@@ -1546,7 +1539,6 @@ pub fn updateNav(...@@ -1546,7 +1539,6 @@ pub fn updateNav(
1546 defer debug_wip_nav.deinit();1539 defer debug_wip_nav.deinit();
1547 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {1540 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
1548 error.OutOfMemory => return error.OutOfMemory,1541 error.OutOfMemory => return error.OutOfMemory,
1549 error.Overflow => return error.Overflow,
1550 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),1542 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
1551 };1543 };
1552 }1544 }
...@@ -1576,7 +1568,7 @@ pub fn updateNav(...@@ -1576,7 +1568,7 @@ pub fn updateNav(
1576 const code = code_buffer.items;1568 const code = code_buffer.items;
15771569
1578 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);1570 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);
1579 log.debug("setting shdr({x},{s}) for {}", .{1571 log.debug("setting shdr({x},{s}) for {f}", .{
1580 shndx,1572 shndx,
1581 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),1573 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
1582 nav.fqn.fmt(ip),1574 nav.fqn.fmt(ip),
...@@ -1588,7 +1580,6 @@ pub fn updateNav(...@@ -1588,7 +1580,6 @@ pub fn updateNav(
15881580
1589 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {1581 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
1590 error.OutOfMemory => return error.OutOfMemory,1582 error.OutOfMemory => return error.OutOfMemory,
1591 error.Overflow => return error.Overflow,
1592 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),1583 else => |e| return elf_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
1593 };1584 };
1594 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);1585 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
...@@ -1622,7 +1613,7 @@ fn updateLazySymbol(...@@ -1622,7 +1613,7 @@ fn updateLazySymbol(
1622 defer code_buffer.deinit(gpa);1613 defer code_buffer.deinit(gpa);
16231614
1624 const name_str_index = blk: {1615 const name_str_index = blk: {
1625 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1616 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1626 @tagName(sym.kind),1617 @tagName(sym.kind),
1627 Type.fromInterned(sym.ty).fmt(pt),1618 Type.fromInterned(sym.ty).fmt(pt),
1628 });1619 });
...@@ -2207,25 +2198,19 @@ const FormatContext = struct {...@@ -2207,25 +2198,19 @@ const FormatContext = struct {
2207 elf_file: *Elf,2198 elf_file: *Elf,
2208};2199};
22092200
2210fn formatSymtab(2201fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2211 ctx: FormatContext,
2212 comptime unused_fmt_string: []const u8,
2213 options: std.fmt.FormatOptions,
2214 writer: anytype,
2215) !void {
2216 _ = unused_fmt_string;2202 _ = unused_fmt_string;
2217 _ = options;
2218 const self = ctx.self;2203 const self = ctx.self;
2219 const elf_file = ctx.elf_file;2204 const elf_file = ctx.elf_file;
2220 try writer.writeAll(" locals\n");2205 try bw.writeAll(" locals\n");
2221 for (self.local_symbols.items) |index| {2206 for (self.local_symbols.items) |index| {
2222 const local = self.symbols.items[index];2207 const local = self.symbols.items[index];
2223 try writer.print(" {}\n", .{local.fmt(elf_file)});2208 try bw.print(" {f}\n", .{local.fmt(elf_file)});
2224 }2209 }
2225 try writer.writeAll(" globals\n");2210 try bw.writeAll(" globals\n");
2226 for (ctx.self.global_symbols.items) |index| {2211 for (ctx.self.global_symbols.items) |index| {
2227 const global = self.symbols.items[index];2212 const global = self.symbols.items[index];
2228 try writer.print(" {}\n", .{global.fmt(elf_file)});2213 try bw.print(" {f}\n", .{global.fmt(elf_file)});
2229 }2214 }
2230}2215}
22312216
...@@ -2236,18 +2221,12 @@ pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms)...@@ -2236,18 +2221,12 @@ pub fn fmtAtoms(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatAtoms)
2236 } };2221 } };
2237}2222}
22382223
2239fn formatAtoms(2224fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2240 ctx: FormatContext,
2241 comptime unused_fmt_string: []const u8,
2242 options: std.fmt.FormatOptions,
2243 writer: anytype,
2244) !void {
2245 _ = unused_fmt_string;2225 _ = unused_fmt_string;
2246 _ = options;2226 try bw.writeAll(" atoms\n");
2247 try writer.writeAll(" atoms\n");
2248 for (ctx.self.atoms_indexes.items) |atom_index| {2227 for (ctx.self.atoms_indexes.items) |atom_index| {
2249 const atom_ptr = ctx.self.atom(atom_index) orelse continue;2228 const atom_ptr = ctx.self.atom(atom_index) orelse continue;
2250 try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});2229 try bw.print(" {f}\n", .{atom_ptr.fmt(ctx.elf_file)});
2251 }2230 }
2252}2231}
22532232
...@@ -2285,7 +2264,7 @@ fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMet...@@ -2285,7 +2264,7 @@ fn checkNavAllocated(pt: Zcu.PerThread, index: InternPool.Nav.Index, meta: AvMet
2285 const zcu = pt.zcu;2264 const zcu = pt.zcu;
2286 const ip = &zcu.intern_pool;2265 const ip = &zcu.intern_pool;
2287 const nav = ip.getNav(index);2266 const nav = ip.getNav(index);
2288 log.err("NAV {}({d}) assigned symbol {d} but not allocated!", .{2267 log.err("NAV {f}({d}) assigned symbol {d} but not allocated!", .{
2289 nav.fqn.fmt(ip),2268 nav.fqn.fmt(ip),
2290 index,2269 index,
2291 meta.symbol_index,2270 meta.symbol_index,
...@@ -2298,7 +2277,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat...@@ -2298,7 +2277,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat
2298 const zcu = pt.zcu;2277 const zcu = pt.zcu;
2299 const uav = Value.fromInterned(index);2278 const uav = Value.fromInterned(index);
2300 const ty = uav.typeOf(zcu);2279 const ty = uav.typeOf(zcu);
2301 log.err("UAV {}({d}) assigned symbol {d} but not allocated!", .{2280 log.err("UAV {f}({d}) assigned symbol {d} but not allocated!", .{
2302 ty.fmt(pt),2281 ty.fmt(pt),
2303 index,2282 index,
2304 meta.symbol_index,2283 meta.symbol_index,
src/link/Elf/eh_frame.zig+37-50
...@@ -49,14 +49,12 @@ pub const Fde = struct {...@@ -49,14 +49,12 @@ pub const Fde = struct {
4949
50 pub fn format(50 pub fn format(
51 fde: Fde,51 fde: Fde,
52 bw: *std.io.BufferedWriter,
52 comptime unused_fmt_string: []const u8,53 comptime unused_fmt_string: []const u8,
53 options: std.fmt.FormatOptions,
54 writer: *std.io.BufferedWriter,
55 ) !void {54 ) !void {
56 _ = fde;55 _ = fde;
57 _ = unused_fmt_string;56 _ = unused_fmt_string;
58 _ = options;57 _ = bw;
59 _ = writer;
60 @compileError("do not format FDEs directly");58 @compileError("do not format FDEs directly");
61 }59 }
6260
...@@ -74,24 +72,22 @@ pub const Fde = struct {...@@ -74,24 +72,22 @@ pub const Fde = struct {
7472
75 fn format2(73 fn format2(
76 ctx: FdeFormatContext,74 ctx: FdeFormatContext,
75 bw: *std.io.BufferedWriter,
77 comptime unused_fmt_string: []const u8,76 comptime unused_fmt_string: []const u8,
78 options: std.fmt.FormatOptions,
79 writer: *std.io.BufferedWriter,
80 ) !void {77 ) !void {
81 _ = unused_fmt_string;78 _ = unused_fmt_string;
82 _ = options;
83 const fde = ctx.fde;79 const fde = ctx.fde;
84 const elf_file = ctx.elf_file;80 const elf_file = ctx.elf_file;
85 const base_addr = fde.address(elf_file);81 const base_addr = fde.address(elf_file);
86 const object = elf_file.file(fde.file_index).?.object;82 const object = elf_file.file(fde.file_index).?.object;
87 const atom_name = fde.atom(object).name(elf_file);83 const atom_name = fde.atom(object).name(elf_file);
88 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{84 try bw.print("@{x} : size({x}) : cie({d}) : {s}", .{
89 base_addr + fde.out_offset,85 base_addr + fde.out_offset,
90 fde.calcSize(),86 fde.calcSize(),
91 fde.cie_index,87 fde.cie_index,
92 atom_name,88 atom_name,
93 });89 });
94 if (!fde.alive) try writer.writeAll(" : [*]");90 if (!fde.alive) try bw.writeAll(" : [*]");
95 }91 }
96};92};
9793
...@@ -152,14 +148,12 @@ pub const Cie = struct {...@@ -152,14 +148,12 @@ pub const Cie = struct {
152148
153 pub fn format(149 pub fn format(
154 cie: Cie,150 cie: Cie,
151 bw: *std.io.BufferedWriter,
155 comptime unused_fmt_string: []const u8,152 comptime unused_fmt_string: []const u8,
156 options: std.fmt.FormatOptions,
157 writer: *std.io.BufferedWriter,
158 ) !void {153 ) !void {
159 _ = cie;154 _ = cie;
160 _ = unused_fmt_string;155 _ = unused_fmt_string;
161 _ = options;156 _ = bw;
162 _ = writer;
163 @compileError("do not format CIEs directly");157 @compileError("do not format CIEs directly");
164 }158 }
165159
...@@ -177,26 +171,23 @@ pub const Cie = struct {...@@ -177,26 +171,23 @@ pub const Cie = struct {
177171
178 fn format2(172 fn format2(
179 ctx: CieFormatContext,173 ctx: CieFormatContext,
174 bw: *std.io.BufferedWriter,
180 comptime unused_fmt_string: []const u8,175 comptime unused_fmt_string: []const u8,
181 options: std.fmt.FormatOptions,
182 writer: *std.io.BufferedWriter,
183 ) !void {176 ) !void {
184 _ = unused_fmt_string;177 _ = unused_fmt_string;
185 _ = options;
186 const cie = ctx.cie;178 const cie = ctx.cie;
187 const elf_file = ctx.elf_file;179 const elf_file = ctx.elf_file;
188 const base_addr = cie.address(elf_file);180 const base_addr = cie.address(elf_file);
189 try writer.print("@{x} : size({x})", .{181 try bw.print("@{x} : size({x})", .{
190 base_addr + cie.out_offset,182 base_addr + cie.out_offset,
191 cie.calcSize(),183 cie.calcSize(),
192 });184 });
193 if (!cie.alive) try writer.writeAll(" : [*]");185 if (!cie.alive) try bw.writeAll(" : [*]");
194 }186 }
195};187};
196188
197pub const Iterator = struct {189pub const Iterator = struct {
198 data: []const u8,190 br: std.io.BufferedReader,
199 pos: usize = 0,
200191
201 pub const Record = struct {192 pub const Record = struct {
202 tag: enum { fde, cie },193 tag: enum { fde, cie },
...@@ -205,22 +196,18 @@ pub const Iterator = struct {...@@ -205,22 +196,18 @@ pub const Iterator = struct {
205 };196 };
206197
207 pub fn next(it: *Iterator) !?Record {198 pub fn next(it: *Iterator) !?Record {
208 if (it.pos >= it.data.len) return null;199 if (it.br.seek >= it.br.storageBuffer().len) return null;
209200
210 var stream = std.io.fixedBufferStream(it.data[it.pos..]);201 const size = try it.br.takeInt(u32, .little);
211 const reader = stream.reader();202 if (size == 0xFFFFFFFF) @panic("DWARF CFI is 32bit on macOS");
212203
213 const size = try reader.readInt(u32, .little);204 const id = try it.br.takeInt(u32, .little);
214 if (size == 0) return null;205 const record: Record = .{
215 if (size == 0xFFFFFFFF) @panic("TODO");
216
217 const id = try reader.readInt(u32, .little);
218 const record = Record{
219 .tag = if (id == 0) .cie else .fde,206 .tag = if (id == 0) .cie else .fde,
220 .offset = it.pos,207 .offset = it.br.seek,
221 .size = size,208 .size = size,
222 };209 };
223 it.pos += size + 4;210 try it.br.discard(size);
224211
225 return record;212 return record;
226 }213 }
...@@ -316,7 +303,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -316,7 +303,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
316 const S = math.cast(i64, sym.address(.{}, elf_file)) orelse return error.Overflow;303 const S = math.cast(i64, sym.address(.{}, elf_file)) orelse return error.Overflow;
317 const A = rel.r_addend;304 const A = rel.r_addend;
318305
319 relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{306 relocs_log.debug(" {f}: {x}: [{x} => {x}] ({s})", .{
320 relocation.fmtRelocType(rel.r_type(), cpu_arch),307 relocation.fmtRelocType(rel.r_type(), cpu_arch),
321 offset,308 offset,
322 P,309 P,
...@@ -332,7 +319,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -332,7 +319,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
332 }319 }
333}320}
334321
335pub fn writeEhFrame(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {322pub fn writeEhFrame(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {
336 relocs_log.debug("{x}: .eh_frame", .{323 relocs_log.debug("{x}: .eh_frame", .{
337 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,324 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,
338 });325 });
...@@ -356,7 +343,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {...@@ -356,7 +343,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {
356 };343 };
357 }344 }
358345
359 try writer.writeAll(contents);346 try bw.writeAll(contents);
360 }347 }
361 }348 }
362349
...@@ -384,22 +371,22 @@ pub fn writeEhFrame(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {...@@ -384,22 +371,22 @@ pub fn writeEhFrame(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {
384 };371 };
385 }372 }
386373
387 try writer.writeAll(contents);374 try bw.writeAll(contents);
388 }375 }
389 }376 }
390377
391 try writer.writeInt(u32, 0, .little);378 try bw.writeInt(u32, 0, .little);
392379
393 if (has_reloc_errors) return error.RelocFailure;380 if (has_reloc_errors) return error.RelocFailure;
394}381}
395382
396pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {383pub fn writeEhFrameRelocatable(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {
397 for (elf_file.objects.items) |index| {384 for (elf_file.objects.items) |index| {
398 const object = elf_file.file(index).?.object;385 const object = elf_file.file(index).?.object;
399386
400 for (object.cies.items) |cie| {387 for (object.cies.items) |cie| {
401 if (!cie.alive) continue;388 if (!cie.alive) continue;
402 try writer.writeAll(cie.data(elf_file));389 try bw.writeAll(cie.data(elf_file));
403 }390 }
404 }391 }
405392
...@@ -418,7 +405,7 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: *std.io.BufferedWriter) !...@@ -418,7 +405,7 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: *std.io.BufferedWriter) !
418 .little,405 .little,
419 );406 );
420407
421 try writer.writeAll(contents);408 try bw.writeAll(contents);
422 }409 }
423 }410 }
424}411}
...@@ -438,7 +425,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R...@@ -438,7 +425,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R
438 },425 },
439 }426 }
440427
441 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{428 relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
442 relocation.fmtRelocType(r_type, cpu_arch),429 relocation.fmtRelocType(r_type, cpu_arch),
443 r_offset,430 r_offset,
444 r_sym,431 r_sym,
...@@ -495,14 +482,14 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, relocs: *std.ArrayList(elf.Elf64_Rela)...@@ -495,14 +482,14 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, relocs: *std.ArrayList(elf.Elf64_Rela)
495 }482 }
496}483}
497484
498pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {485pub fn writeEhFrameHdr(elf_file: *Elf, bw: *std.io.BufferedWriter) !void {
499 const comp = elf_file.base.comp;486 const comp = elf_file.base.comp;
500 const gpa = comp.gpa;487 const gpa = comp.gpa;
501488
502 try writer.writeByte(1); // version489 try bw.writeByte(1); // version
503 try writer.writeByte(DW_EH_PE.pcrel | DW_EH_PE.sdata4);490 try bw.writeByte(DW_EH_PE.pcrel | DW_EH_PE.sdata4);
504 try writer.writeByte(DW_EH_PE.udata4);491 try bw.writeByte(DW_EH_PE.udata4);
505 try writer.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4);492 try bw.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4);
506493
507 const shdrs = elf_file.sections.items(.shdr);494 const shdrs = elf_file.sections.items(.shdr);
508 const eh_frame_shdr = shdrs[elf_file.section_indexes.eh_frame.?];495 const eh_frame_shdr = shdrs[elf_file.section_indexes.eh_frame.?];
...@@ -513,7 +500,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {...@@ -513,7 +500,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {
513 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);500 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
514 break :existing_size sym.atom(elf_file).?.size;501 break :existing_size sym.atom(elf_file).?.size;
515 };502 };
516 try writer.writeInt(503 try bw.writeInt(
517 u32,504 u32,
518 @as(u32, @bitCast(@as(505 @as(u32, @bitCast(@as(
519 i32,506 i32,
...@@ -521,7 +508,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {...@@ -521,7 +508,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {
521 ))),508 ))),
522 .little,509 .little,
523 );510 );
524 try writer.writeInt(u32, num_fdes, .little);511 try bw.writeInt(u32, num_fdes, .little);
525512
526 const Entry = struct {513 const Entry = struct {
527 init_addr: u32,514 init_addr: u32,
...@@ -561,7 +548,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {...@@ -561,7 +548,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: *std.io.BufferedWriter) !void {
561 }548 }
562549
563 std.mem.sort(Entry, entries.items, {}, Entry.lessThan);550 std.mem.sort(Entry, entries.items, {}, Entry.lessThan);
564 try writer.writeAll(std.mem.sliceAsBytes(entries.items));551 try bw.writeAll(std.mem.sliceAsBytes(entries.items));
565}552}
566553
567const eh_frame_hdr_header_size: usize = 12;554const eh_frame_hdr_header_size: usize = 12;
...@@ -607,11 +594,11 @@ const riscv = struct {...@@ -607,11 +594,11 @@ const riscv = struct {
607fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {594fn reportInvalidReloc(rec: anytype, elf_file: *Elf, rel: elf.Elf64_Rela) !void {
608 const diags = &elf_file.base.comp.link_diags;595 const diags = &elf_file.base.comp.link_diags;
609 var err = try diags.addErrorWithNotes(1);596 var err = try diags.addErrorWithNotes(1);
610 try err.addMsg("invalid relocation type {} at offset 0x{x}", .{597 try err.addMsg("invalid relocation type {f} at offset 0x{x}", .{
611 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),598 relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch),
612 rel.r_offset,599 rel.r_offset,
613 });600 });
614 err.addNote("in {}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});601 err.addNote("in {f}:.eh_frame", .{elf_file.file(rec.file_index).?.fmtPath()});
615 return error.RelocFailure;602 return error.RelocFailure;
616}603}
617604
src/link/Elf/file.zig+5-11
...@@ -14,19 +14,13 @@ pub const File = union(enum) {...@@ -14,19 +14,13 @@ pub const File = union(enum) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(17 fn formatPath(file: File, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
18 file: File,
19 comptime unused_fmt_string: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = unused_fmt_string;18 _ = unused_fmt_string;
24 _ = options;
25 switch (file) {19 switch (file) {
26 .zig_object => |zo| try writer.writeAll(zo.basename),20 .zig_object => |zo| try bw.writeAll(zo.basename),
27 .linker_defined => try writer.writeAll("(linker defined)"),21 .linker_defined => try bw.writeAll("(linker defined)"),
28 .object => |x| try writer.print("{}", .{x.fmtPath()}),22 .object => |x| try bw.print("{f}", .{x.fmtPath()}),
29 .shared_object => |x| try writer.print("{}", .{@as(Path, x.path)}),23 .shared_object => |x| try bw.print("{f}", .{x.path}),
30 }24 }
31 }25 }
3226
src/link/Elf/gc.zig+5-11
...@@ -111,7 +111,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {...@@ -111,7 +111,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
111 const target_sym = elf_file.symbol(ref) orelse continue;111 const target_sym = elf_file.symbol(ref) orelse continue;
112 const target_atom = target_sym.atom(elf_file) orelse continue;112 const target_atom = target_sym.atom(elf_file) orelse continue;
113 target_atom.alive = true;113 target_atom.alive = true;
114 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });114 gc_track_live_log.debug("{f}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
115 if (markAtom(target_atom)) markLive(target_atom, elf_file);115 if (markAtom(target_atom)) markLive(target_atom, elf_file);
116 }116 }
117 }117 }
...@@ -128,7 +128,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {...@@ -128,7 +128,7 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
128 }128 }
129 const target_atom = target_sym.atom(elf_file) orelse continue;129 const target_atom = target_sym.atom(elf_file) orelse continue;
130 target_atom.alive = true;130 target_atom.alive = true;
131 gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });131 gc_track_live_log.debug("{f}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
132 if (markAtom(target_atom)) markLive(target_atom, elf_file);132 if (markAtom(target_atom)) markLive(target_atom, elf_file);
133 }133 }
134}134}
...@@ -170,7 +170,7 @@ pub fn dumpPrunedAtoms(elf_file: *Elf) !void {...@@ -170,7 +170,7 @@ pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
170 for (file.atoms()) |atom_index| {170 for (file.atoms()) |atom_index| {
171 const atom = file.atom(atom_index) orelse continue;171 const atom = file.atom(atom_index) orelse continue;
172 if (!atom.alive)172 if (!atom.alive)
173 try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{173 try stderr.print("link: removing unused section '{s}' in file '{f}'\n", .{
174 atom.name(elf_file),174 atom.name(elf_file),
175 atom.file(elf_file).?.fmtPath(),175 atom.file(elf_file).?.fmtPath(),
176 });176 });
...@@ -185,15 +185,9 @@ const Level = struct {...@@ -185,15 +185,9 @@ const Level = struct {
185 self.value += 1;185 self.value += 1;
186 }186 }
187187
188 pub fn format(188 pub fn format(self: *const @This(), bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
189 self: *const @This(),
190 comptime unused_fmt_string: []const u8,
191 options: std.fmt.FormatOptions,
192 writer: anytype,
193 ) !void {
194 _ = unused_fmt_string;189 _ = unused_fmt_string;
195 _ = options;190 try bw.splatByteAll(' ', self.value);
196 try writer.writeByteNTimes(' ', self.value);
197 }191 }
198};192};
199193
src/link/Elf/relocatable.zig+21-23
...@@ -31,7 +31,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -31,7 +31,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
31 try elf_file.allocateNonAllocSections();31 try elf_file.allocateNonAllocSections();
3232
33 if (build_options.enable_logging) {33 if (build_options.enable_logging) {
34 state_log.debug("{}", .{elf_file.dumpState()});34 state_log.debug("{f}", .{elf_file.dumpState()});
35 }35 }
3636
37 try elf_file.writeMergeSections();37 try elf_file.writeMergeSections();
...@@ -96,36 +96,35 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -96,36 +96,35 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
96 };96 };
9797
98 if (build_options.enable_logging) {98 if (build_options.enable_logging) {
99 state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(elf_file)});99 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)});
100 state_log.debug("ar_strtab\n{}\n", .{ar_strtab});100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
101 }101 }
102102
103 var buffer = std.ArrayList(u8).init(gpa);103 var bw: std.io.BufferedWriter = undefined;
104 defer buffer.deinit();104 bw.initFixed(try gpa.alloc(u8, total_size));
105 try buffer.ensureTotalCapacityPrecise(total_size);105 defer gpa.free(bw.buffer);
106106
107 // Write magic107 // Write magic
108 try buffer.writer().writeAll(elf.ARMAG);108 try bw.writeAll(elf.ARMAG);
109109
110 // Write symtab110 // Write symtab
111 try ar_symtab.write(.p64, elf_file, buffer.writer());111 try ar_symtab.write(.p64, elf_file, &bw);
112112
113 // Write strtab113 // Write strtab
114 if (ar_strtab.size() > 0) {114 if (ar_strtab.size() > 0) {
115 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);115 if (!mem.isAligned(bw.count, 2)) try bw.writeByte(0);
116 try ar_strtab.write(buffer.writer());116 try ar_strtab.write(&bw);
117 }117 }
118118
119 // Write object files119 // Write object files
120 for (files.items) |index| {120 for (files.items) |index| {
121 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);121 if (!mem.isAligned(bw.count, 2)) try bw.writeByte(0);
122 try elf_file.file(index).?.writeAr(elf_file, buffer.writer());122 try elf_file.file(index).?.writeAr(elf_file, &bw);
123 }123 }
124124
125 assert(buffer.items.len == total_size);125 assert(bw.end == bw.buffer.len);
126
127 try elf_file.base.file.?.setEndPos(total_size);126 try elf_file.base.file.?.setEndPos(total_size);
128 try elf_file.base.file.?.pwriteAll(buffer.items, 0);127 try elf_file.base.file.?.pwriteAll(bw.buffer, 0);
129128
130 if (diags.hasErrors()) return error.LinkFailure;129 if (diags.hasErrors()) return error.LinkFailure;
131}130}
...@@ -170,7 +169,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {...@@ -170,7 +169,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
170 try elf_file.allocateNonAllocSections();169 try elf_file.allocateNonAllocSections();
171170
172 if (build_options.enable_logging) {171 if (build_options.enable_logging) {
173 state_log.debug("{}", .{elf_file.dumpState()});172 state_log.debug("{f}", .{elf_file.dumpState()});
174 }173 }
175174
176 try writeAtoms(elf_file);175 try writeAtoms(elf_file);
...@@ -407,17 +406,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -407,17 +406,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
407 };406 };
408 const shdr = slice.items(.shdr)[shndx];407 const shdr = slice.items(.shdr)[shndx];
409 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;408 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
410 var buffer: std.io.AllocatingWriter = undefined;409 var bw: std.io.BufferedWriter = undefined;
411 const bw = buffer.init(gpa);410 bw.initFixed(try gpa.alloc(u8, sh_size - existing_size));
412 defer buffer.deinit();411 defer gpa.free(bw.buffer);
413 try buffer.ensureTotalCapacity(gpa, sh_size - existing_size);412 try eh_frame.writeEhFrameRelocatable(elf_file, &bw);
414 try eh_frame.writeEhFrameRelocatable(elf_file, bw);
415 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{413 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{
416 shdr.sh_offset + existing_size,414 shdr.sh_offset + existing_size,
417 shdr.sh_offset + sh_size,415 shdr.sh_offset + sh_size,
418 });416 });
419 assert(buffer.getWritten().len == sh_size - existing_size);417 assert(bw.end == bw.buffer.len);
420 try elf_file.base.file.?.pwriteAll(buffer.getWritten(), shdr.sh_offset + existing_size);418 try elf_file.base.file.?.pwriteAll(bw.buffer, shdr.sh_offset + existing_size);
421 }419 }
422 if (elf_file.section_indexes.eh_frame_rela) |shndx| {420 if (elf_file.section_indexes.eh_frame_rela) |shndx| {
423 const shdr = slice.items(.shdr)[shndx];421 const shdr = slice.items(.shdr)[shndx];
src/link/Elf/relocation.zig+4-10
...@@ -148,19 +148,13 @@ pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatte...@@ -148,19 +148,13 @@ pub fn fmtRelocType(r_type: u32, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatte
148 } };148 } };
149}149}
150150
151fn formatRelocType(151fn formatRelocType(ctx: FormatRelocTypeCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
152 ctx: FormatRelocTypeCtx,
153 comptime unused_fmt_string: []const u8,
154 options: std.fmt.FormatOptions,
155 writer: anytype,
156) !void {
157 _ = unused_fmt_string;152 _ = unused_fmt_string;
158 _ = options;
159 const r_type = ctx.r_type;153 const r_type = ctx.r_type;
160 switch (ctx.cpu_arch) {154 switch (ctx.cpu_arch) {
161 .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),155 .x86_64 => try bw.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}),
162 .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}),156 .aarch64 => try bw.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}),
163 .riscv64 => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}),157 .riscv64 => try bw.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}),
164 else => unreachable,158 else => unreachable,
165 }159 }
166}160}
src/link/Elf/synthetic_sections.zig+111-131
...@@ -94,115 +94,115 @@ pub const DynamicSection = struct {...@@ -94,115 +94,115 @@ pub const DynamicSection = struct {
94 return nentries * @sizeOf(elf.Elf64_Dyn);94 return nentries * @sizeOf(elf.Elf64_Dyn);
95 }95 }
9696
97 pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void {97 pub fn write(dt: DynamicSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
98 const shdrs = elf_file.sections.items(.shdr);98 const shdrs = elf_file.sections.items(.shdr);
9999
100 // NEEDED100 // NEEDED
101 for (dt.needed.items) |off| {101 for (dt.needed.items) |off| {
102 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });102 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });
103 }103 }
104104
105 if (dt.soname) |off| {105 if (dt.soname) |off| {
106 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off });106 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off });
107 }107 }
108108
109 // RUNPATH109 // RUNPATH
110 // TODO add option in Options to revert to old RPATH tag110 // TODO add option in Options to revert to old RPATH tag
111 if (dt.rpath > 0) {111 if (dt.rpath > 0) {
112 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath });112 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath });
113 }113 }
114114
115 // INIT115 // INIT
116 if (elf_file.sectionByName(".init")) |shndx| {116 if (elf_file.sectionByName(".init")) |shndx| {
117 const addr = shdrs[shndx].sh_addr;117 const addr = shdrs[shndx].sh_addr;
118 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });118 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });
119 }119 }
120120
121 // FINI121 // FINI
122 if (elf_file.sectionByName(".fini")) |shndx| {122 if (elf_file.sectionByName(".fini")) |shndx| {
123 const addr = shdrs[shndx].sh_addr;123 const addr = shdrs[shndx].sh_addr;
124 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });124 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });
125 }125 }
126126
127 // INIT_ARRAY127 // INIT_ARRAY
128 if (elf_file.sectionByName(".init_array")) |shndx| {128 if (elf_file.sectionByName(".init_array")) |shndx| {
129 const shdr = shdrs[shndx];129 const shdr = shdrs[shndx];
130 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });130 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });
131 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });131 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });
132 }132 }
133133
134 // FINI_ARRAY134 // FINI_ARRAY
135 if (elf_file.sectionByName(".fini_array")) |shndx| {135 if (elf_file.sectionByName(".fini_array")) |shndx| {
136 const shdr = shdrs[shndx];136 const shdr = shdrs[shndx];
137 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });137 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });
138 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });138 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });
139 }139 }
140140
141 // RELA141 // RELA
142 if (elf_file.section_indexes.rela_dyn) |shndx| {142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143 const shdr = shdrs[shndx];143 const shdr = shdrs[shndx];
144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });144 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });145 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
146 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });146 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });
147 }147 }
148148
149 // JMPREL149 // JMPREL
150 if (elf_file.section_indexes.rela_plt) |shndx| {150 if (elf_file.section_indexes.rela_plt) |shndx| {
151 const shdr = shdrs[shndx];151 const shdr = shdrs[shndx];
152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });152 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });153 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
154 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });154 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });
155 }155 }
156156
157 // PLTGOT157 // PLTGOT
158 if (elf_file.section_indexes.got_plt) |shndx| {158 if (elf_file.section_indexes.got_plt) |shndx| {
159 const addr = shdrs[shndx].sh_addr;159 const addr = shdrs[shndx].sh_addr;
160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });160 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
161 }161 }
162162
163 {163 {
164 assert(elf_file.section_indexes.hash != null);164 assert(elf_file.section_indexes.hash != null);
165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;
166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });166 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
167 }167 }
168168
169 if (elf_file.section_indexes.gnu_hash) |shndx| {169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170 const addr = shdrs[shndx].sh_addr;170 const addr = shdrs[shndx].sh_addr;
171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });171 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
172 }172 }
173173
174 // TEXTREL174 // TEXTREL
175 if (elf_file.has_text_reloc) {175 if (elf_file.has_text_reloc) {
176 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 });176 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 });
177 }177 }
178178
179 // SYMTAB + SYMENT179 // SYMTAB + SYMENT
180 {180 {
181 assert(elf_file.section_indexes.dynsymtab != null);181 assert(elf_file.section_indexes.dynsymtab != null);
182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];
183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });183 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });184 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
185 }185 }
186186
187 // STRTAB + STRSZ187 // STRTAB + STRSZ
188 {188 {
189 assert(elf_file.section_indexes.dynstrtab != null);189 assert(elf_file.section_indexes.dynstrtab != null);
190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];
191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });191 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });192 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
193 }193 }
194194
195 // VERSYM195 // VERSYM
196 if (elf_file.section_indexes.versym) |shndx| {196 if (elf_file.section_indexes.versym) |shndx| {
197 const addr = shdrs[shndx].sh_addr;197 const addr = shdrs[shndx].sh_addr;
198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });198 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
199 }199 }
200200
201 // VERNEED + VERNEEDNUM201 // VERNEED + VERNEEDNUM
202 if (elf_file.section_indexes.verneed) |shndx| {202 if (elf_file.section_indexes.verneed) |shndx| {
203 const addr = shdrs[shndx].sh_addr;203 const addr = shdrs[shndx].sh_addr;
204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });204 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
205 try writer.writeStruct(elf.Elf64_Dyn{205 try bw.writeStruct(elf.Elf64_Dyn{
206 .d_tag = elf.DT_VERNEEDNUM,206 .d_tag = elf.DT_VERNEEDNUM,
207 .d_val = elf_file.verneed.verneed.items.len,207 .d_val = elf_file.verneed.verneed.items.len,
208 });208 });
...@@ -210,18 +210,18 @@ pub const DynamicSection = struct {...@@ -210,18 +210,18 @@ pub const DynamicSection = struct {
210210
211 // FLAGS211 // FLAGS
212 if (dt.getFlags(elf_file)) |flags| {212 if (dt.getFlags(elf_file)) |flags| {
213 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags });213 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags });
214 }214 }
215 // FLAGS_1215 // FLAGS_1
216 if (dt.getFlags1(elf_file)) |flags_1| {216 if (dt.getFlags1(elf_file)) |flags_1| {
217 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 });217 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 });
218 }218 }
219219
220 // DEBUG220 // DEBUG
221 if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });221 if (!elf_file.isEffectivelyDynLib()) try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });
222222
223 // NULL223 // NULL
224 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });224 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });
225 }225 }
226};226};
227227
...@@ -360,7 +360,7 @@ pub const GotSection = struct {...@@ -360,7 +360,7 @@ pub const GotSection = struct {
360 return s;360 return s;
361 }361 }
362362
363 pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {363 pub fn write(got: GotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
364 const comp = elf_file.base.comp;364 const comp = elf_file.base.comp;
365 const is_dyn_lib = elf_file.isEffectivelyDynLib();365 const is_dyn_lib = elf_file.isEffectivelyDynLib();
366 const apply_relocs = true; // TODO add user option for this366 const apply_relocs = true; // TODO add user option for this
...@@ -381,47 +381,47 @@ pub const GotSection = struct {...@@ -381,47 +381,47 @@ pub const GotSection = struct {
381 }381 }
382 break :blk value;382 break :blk value;
383 };383 };
384 try writeInt(value, elf_file, writer);384 try writeInt(value, elf_file, bw);
385 },385 },
386 .tlsld => {386 .tlsld => {
387 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, writer);387 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, bw);
388 try writeInt(0, elf_file, writer);388 try writeInt(0, elf_file, bw);
389 },389 },
390 .tlsgd => {390 .tlsgd => {
391 if (symbol.?.flags.import) {391 if (symbol.?.flags.import) {
392 try writeInt(0, elf_file, writer);392 try writeInt(0, elf_file, bw);
393 try writeInt(0, elf_file, writer);393 try writeInt(0, elf_file, bw);
394 } else {394 } else {
395 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, writer);395 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, bw);
396 const offset = symbol.?.address(.{}, elf_file) - elf_file.dtpAddress();396 const offset = symbol.?.address(.{}, elf_file) - elf_file.dtpAddress();
397 try writeInt(offset, elf_file, writer);397 try writeInt(offset, elf_file, bw);
398 }398 }
399 },399 },
400 .gottp => {400 .gottp => {
401 if (symbol.?.flags.import) {401 if (symbol.?.flags.import) {
402 try writeInt(0, elf_file, writer);402 try writeInt(0, elf_file, bw);
403 } else if (is_dyn_lib) {403 } else if (is_dyn_lib) {
404 const offset = if (apply_relocs)404 const offset = if (apply_relocs)
405 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()405 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()
406 else406 else
407 0;407 0;
408 try writeInt(offset, elf_file, writer);408 try writeInt(offset, elf_file, bw);
409 } else {409 } else {
410 const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress();410 const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress();
411 try writeInt(offset, elf_file, writer);411 try writeInt(offset, elf_file, bw);
412 }412 }
413 },413 },
414 .tlsdesc => {414 .tlsdesc => {
415 if (symbol.?.flags.import) {415 if (symbol.?.flags.import) {
416 try writeInt(0, elf_file, writer);416 try writeInt(0, elf_file, bw);
417 try writeInt(0, elf_file, writer);417 try writeInt(0, elf_file, bw);
418 } else {418 } else {
419 try writeInt(0, elf_file, writer);419 try writeInt(0, elf_file, bw);
420 const offset = if (apply_relocs)420 const offset = if (apply_relocs)
421 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()421 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()
422 else422 else
423 0;423 0;
424 try writeInt(offset, elf_file, writer);424 try writeInt(offset, elf_file, bw);
425 }425 }
426 },426 },
427 }427 }
...@@ -615,20 +615,14 @@ pub const GotSection = struct {...@@ -615,20 +615,14 @@ pub const GotSection = struct {
615 return .{ .data = .{ .got = got, .elf_file = elf_file } };615 return .{ .data = .{ .got = got, .elf_file = elf_file } };
616 }616 }
617617
618 pub fn format2(618 pub fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
619 ctx: FormatCtx,
620 comptime unused_fmt_string: []const u8,
621 options: std.fmt.FormatOptions,
622 writer: anytype,
623 ) !void {
624 _ = options;
625 _ = unused_fmt_string;619 _ = unused_fmt_string;
626 const got = ctx.got;620 const got = ctx.got;
627 const elf_file = ctx.elf_file;621 const elf_file = ctx.elf_file;
628 try writer.writeAll("GOT\n");622 try bw.writeAll("GOT\n");
629 for (got.entries.items) |entry| {623 for (got.entries.items) |entry| {
630 const symbol = elf_file.symbol(entry.ref).?;624 const symbol = elf_file.symbol(entry.ref).?;
631 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{625 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
632 entry.cell_index,626 entry.cell_index,
633 entry.address(elf_file),627 entry.address(elf_file),
634 entry.ref,628 entry.ref,
...@@ -678,11 +672,11 @@ pub const PltSection = struct {...@@ -678,11 +672,11 @@ pub const PltSection = struct {
678 };672 };
679 }673 }
680674
681 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {675 pub fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
682 const cpu_arch = elf_file.getTarget().cpu.arch;676 const cpu_arch = elf_file.getTarget().cpu.arch;
683 switch (cpu_arch) {677 switch (cpu_arch) {
684 .x86_64 => try x86_64.write(plt, elf_file, writer),678 .x86_64 => try x86_64.write(plt, elf_file, bw),
685 .aarch64 => try aarch64.write(plt, elf_file, writer),679 .aarch64 => try aarch64.write(plt, elf_file, bw),
686 else => return error.UnsupportedCpuArch,680 else => return error.UnsupportedCpuArch,
687 }681 }
688 }682 }
...@@ -703,7 +697,7 @@ pub const PltSection = struct {...@@ -703,7 +697,7 @@ pub const PltSection = struct {
703 const r_sym: u64 = extra.dynamic;697 const r_sym: u64 = extra.dynamic;
704 const r_type = relocation.encode(.jump_slot, cpu_arch);698 const r_type = relocation.encode(.jump_slot, cpu_arch);
705699
706 relocs_log.debug(" {s}: [{x} => {d}({s})] + 0", .{700 relocs_log.debug(" {f}: [{x} => {d}({s})] + 0", .{
707 relocation.fmtRelocType(r_type, cpu_arch),701 relocation.fmtRelocType(r_type, cpu_arch),
708 r_offset,702 r_offset,
709 r_sym,703 r_sym,
...@@ -758,20 +752,14 @@ pub const PltSection = struct {...@@ -758,20 +752,14 @@ pub const PltSection = struct {
758 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };752 return .{ .data = .{ .plt = plt, .elf_file = elf_file } };
759 }753 }
760754
761 pub fn format2(755 pub fn format2(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
762 ctx: FormatCtx,
763 comptime unused_fmt_string: []const u8,
764 options: std.fmt.FormatOptions,
765 writer: anytype,
766 ) !void {
767 _ = options;
768 _ = unused_fmt_string;756 _ = unused_fmt_string;
769 const plt = ctx.plt;757 const plt = ctx.plt;
770 const elf_file = ctx.elf_file;758 const elf_file = ctx.elf_file;
771 try writer.writeAll("PLT\n");759 try bw.writeAll("PLT\n");
772 for (plt.symbols.items, 0..) |ref, i| {760 for (plt.symbols.items, 0..) |ref, i| {
773 const symbol = elf_file.symbol(ref).?;761 const symbol = elf_file.symbol(ref).?;
774 try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{762 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
775 i,763 i,
776 symbol.pltAddress(elf_file),764 symbol.pltAddress(elf_file),
777 ref,765 ref,
...@@ -782,7 +770,7 @@ pub const PltSection = struct {...@@ -782,7 +770,7 @@ pub const PltSection = struct {
782 }770 }
783771
784 const x86_64 = struct {772 const x86_64 = struct {
785 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {773 fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
786 const shdrs = elf_file.sections.items(.shdr);774 const shdrs = elf_file.sections.items(.shdr);
787 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;775 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
788 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;776 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
...@@ -796,8 +784,8 @@ pub const PltSection = struct {...@@ -796,8 +784,8 @@ pub const PltSection = struct {
796 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);784 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);
797 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;785 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
798 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);786 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
799 try writer.writeAll(&preamble);787 try bw.writeAll(&preamble);
800 try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len);788 try bw.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len);
801789
802 for (plt.symbols.items, 0..) |ref, i| {790 for (plt.symbols.items, 0..) |ref, i| {
803 const sym = elf_file.symbol(ref).?;791 const sym = elf_file.symbol(ref).?;
...@@ -811,13 +799,13 @@ pub const PltSection = struct {...@@ -811,13 +799,13 @@ pub const PltSection = struct {
811 };799 };
812 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);800 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);
813 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);801 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);
814 try writer.writeAll(&entry);802 try bw.writeAll(&entry);
815 }803 }
816 }804 }
817 };805 };
818806
819 const aarch64 = struct {807 const aarch64 = struct {
820 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {808 fn write(plt: PltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
821 {809 {
822 const shdrs = elf_file.sections.items(.shdr);810 const shdrs = elf_file.sections.items(.shdr);
823 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);811 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
...@@ -845,7 +833,7 @@ pub const PltSection = struct {...@@ -845,7 +833,7 @@ pub const PltSection = struct {
845 };833 };
846 comptime assert(preamble.len == 8);834 comptime assert(preamble.len == 8);
847 for (preamble) |inst| {835 for (preamble) |inst| {
848 try writer.writeInt(u32, inst.toU32(), .little);836 try bw.writeInt(u32, inst.toU32(), .little);
849 }837 }
850 }838 }
851839
...@@ -864,7 +852,7 @@ pub const PltSection = struct {...@@ -864,7 +852,7 @@ pub const PltSection = struct {
864 };852 };
865 comptime assert(insts.len == 4);853 comptime assert(insts.len == 4);
866 for (insts) |inst| {854 for (insts) |inst| {
867 try writer.writeInt(u32, inst.toU32(), .little);855 try bw.writeInt(u32, inst.toU32(), .little);
868 }856 }
869 }857 }
870 }858 }
...@@ -883,22 +871,22 @@ pub const GotPltSection = struct {...@@ -883,22 +871,22 @@ pub const GotPltSection = struct {
883 return preamble_size + elf_file.plt.symbols.items.len * 8;871 return preamble_size + elf_file.plt.symbols.items.len * 8;
884 }872 }
885873
886 pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: anytype) !void {874 pub fn write(got_plt: GotPltSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
887 _ = got_plt;875 _ = got_plt;
888 {876 {
889 // [0]: _DYNAMIC877 // [0]: _DYNAMIC
890 const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;878 const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;
891 try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);879 try bw.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);
892 }880 }
893 // [1]: 0x0881 // [1]: 0x0
894 // [2]: 0x0882 // [2]: 0x0
895 try writer.writeInt(u64, 0x0, .little);883 try bw.writeInt(u64, 0x0, .little);
896 try writer.writeInt(u64, 0x0, .little);884 try bw.writeInt(u64, 0x0, .little);
897 if (elf_file.section_indexes.plt) |shndx| {885 if (elf_file.section_indexes.plt) |shndx| {
898 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;886 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
899 for (0..elf_file.plt.symbols.items.len) |_| {887 for (0..elf_file.plt.symbols.items.len) |_| {
900 // [N]: .plt888 // [N]: .plt
901 try writer.writeInt(u64, plt_addr, .little);889 try bw.writeInt(u64, plt_addr, .little);
902 }890 }
903 }891 }
904 }892 }
...@@ -934,11 +922,11 @@ pub const PltGotSection = struct {...@@ -934,11 +922,11 @@ pub const PltGotSection = struct {
934 };922 };
935 }923 }
936924
937 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {925 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
938 const cpu_arch = elf_file.getTarget().cpu.arch;926 const cpu_arch = elf_file.getTarget().cpu.arch;
939 switch (cpu_arch) {927 switch (cpu_arch) {
940 .x86_64 => try x86_64.write(plt_got, elf_file, writer),928 .x86_64 => try x86_64.write(plt_got, elf_file, bw),
941 .aarch64 => try aarch64.write(plt_got, elf_file, writer),929 .aarch64 => try aarch64.write(plt_got, elf_file, bw),
942 else => return error.UnsupportedCpuArch,930 else => return error.UnsupportedCpuArch,
943 }931 }
944 }932 }
...@@ -970,7 +958,7 @@ pub const PltGotSection = struct {...@@ -970,7 +958,7 @@ pub const PltGotSection = struct {
970 }958 }
971959
972 const x86_64 = struct {960 const x86_64 = struct {
973 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {961 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
974 for (plt_got.symbols.items) |ref| {962 for (plt_got.symbols.items) |ref| {
975 const sym = elf_file.symbol(ref).?;963 const sym = elf_file.symbol(ref).?;
976 const target_addr = sym.gotAddress(elf_file);964 const target_addr = sym.gotAddress(elf_file);
...@@ -982,13 +970,13 @@ pub const PltGotSection = struct {...@@ -982,13 +970,13 @@ pub const PltGotSection = struct {
982 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,970 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
983 };971 };
984 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);972 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
985 try writer.writeAll(&entry);973 try bw.writeAll(&entry);
986 }974 }
987 }975 }
988 };976 };
989977
990 const aarch64 = struct {978 const aarch64 = struct {
991 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {979 fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
992 for (plt_got.symbols.items) |ref| {980 for (plt_got.symbols.items) |ref| {
993 const sym = elf_file.symbol(ref).?;981 const sym = elf_file.symbol(ref).?;
994 const target_addr = sym.gotAddress(elf_file);982 const target_addr = sym.gotAddress(elf_file);
...@@ -1003,7 +991,7 @@ pub const PltGotSection = struct {...@@ -1003,7 +991,7 @@ pub const PltGotSection = struct {
1003 };991 };
1004 comptime assert(insts.len == 4);992 comptime assert(insts.len == 4);
1005 for (insts) |inst| {993 for (insts) |inst| {
1006 try writer.writeInt(u32, inst.toU32(), .little);994 try bw.writeInt(u32, inst.toU32(), .little);
1007 }995 }
1008 }996 }
1009 }997 }
...@@ -1167,23 +1155,23 @@ pub const DynsymSection = struct {...@@ -1167,23 +1155,23 @@ pub const DynsymSection = struct {
1167 return @as(u32, @intCast(dynsym.entries.items.len + 1));1155 return @as(u32, @intCast(dynsym.entries.items.len + 1));
1168 }1156 }
11691157
1170 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void {1158 pub fn write(dynsym: DynsymSection, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
1171 try writer.writeStruct(Elf.null_sym);1159 try bw.writeStruct(Elf.null_sym);
1172 for (dynsym.entries.items) |entry| {1160 for (dynsym.entries.items) |entry| {
1173 const sym = elf_file.symbol(entry.ref).?;1161 const sym = elf_file.symbol(entry.ref).?;
1174 var out_sym: elf.Elf64_Sym = Elf.null_sym;1162 var out_sym: elf.Elf64_Sym = Elf.null_sym;
1175 sym.setOutputSym(elf_file, &out_sym);1163 sym.setOutputSym(elf_file, &out_sym);
1176 out_sym.st_name = entry.off;1164 out_sym.st_name = entry.off;
1177 try writer.writeStruct(out_sym);1165 try bw.writeStruct(out_sym);
1178 }1166 }
1179 }1167 }
1180};1168};
11811169
1182pub const HashSection = struct {1170pub const HashSection = struct {
1183 buffer: std.ArrayListUnmanaged(u8) = .empty,1171 buffer: []u32 = &.{},
11841172
1185 pub fn deinit(hs: *HashSection, allocator: Allocator) void {1173 pub fn deinit(hs: *HashSection, gpa: Allocator) void {
1186 hs.buffer.deinit(allocator);1174 gpa.free(hs.buffer);
1187 }1175 }
11881176
1189 pub fn generate(hs: *HashSection, elf_file: *Elf) !void {1177 pub fn generate(hs: *HashSection, elf_file: *Elf) !void {
...@@ -1193,30 +1181,25 @@ pub const HashSection = struct {...@@ -1193,30 +1181,25 @@ pub const HashSection = struct {
1193 const gpa = comp.gpa;1181 const gpa = comp.gpa;
1194 const nsyms = elf_file.dynsym.count();1182 const nsyms = elf_file.dynsym.count();
11951183
1196 var buckets = try gpa.alloc(u32, nsyms);1184 assert(hs.buffer.len == 0);
1197 defer gpa.free(buckets);1185 hs.buffer = try gpa.alloc(u32, 2 * (1 + nsyms));
1198 @memset(buckets, 0);
11991186
1200 var chains = try gpa.alloc(u32, nsyms);1187 @memset(hs.buffer[0..2], std.mem.nativeToLittle(u32, @intCast(nsyms)));
1201 defer gpa.free(chains);1188 const buckets = hs.buffer[2..][0..nsyms];
1189 @memset(buckets, 0);
1190 const chains = hs.buffer[2 + nsyms ..][0..nsyms];
1202 @memset(chains, 0);1191 @memset(chains, 0);
12031192
1204 for (elf_file.dynsym.entries.items, 1..) |entry, i| {1193 for (elf_file.dynsym.entries.items, 1..) |entry, i| {
1205 const name = elf_file.getDynString(entry.off);1194 const name = elf_file.getDynString(entry.off);
1206 const hash = hasher(name) % buckets.len;1195 const hash = hasher(name) % nsyms;
1207 chains[@as(u32, @intCast(i))] = buckets[hash];1196 chains[i] = buckets[hash];
1208 buckets[hash] = @as(u32, @intCast(i));1197 buckets[hash] = std.mem.nativeToLittle(u32, @intCast(i));
1209 }1198 }
1210
1211 try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4);
1212 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1213 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1214 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(buckets)) catch unreachable;
1215 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(chains)) catch unreachable;
1216 }1199 }
12171200
1218 pub inline fn size(hs: HashSection) usize {1201 pub inline fn size(hs: HashSection) usize {
1219 return hs.buffer.items.len;1202 return @sizeOf(u32) * hs.buffer.len;
1220 }1203 }
12211204
1222 pub fn hasher(name: [:0]const u8) u32 {1205 pub fn hasher(name: [:0]const u8) u32 {
...@@ -1266,17 +1249,14 @@ pub const GnuHashSection = struct {...@@ -1266,17 +1249,14 @@ pub const GnuHashSection = struct {
1266 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;1249 return header_size + hash.num_bloom * 8 + hash.num_buckets * 4 + hash.num_exports * 4;
1267 }1250 }
12681251
1269 pub fn write(hash: GnuHashSection, elf_file: *Elf, writer: anytype) !void {1252 pub fn write(hash: GnuHashSection, elf_file: *Elf, br: *std.io.BufferedWriter) !void {
1270 const exports = getExports(elf_file);1253 const exports = getExports(elf_file);
1271 const export_off = elf_file.dynsym.count() - hash.num_exports;1254 const export_off = elf_file.dynsym.count() - hash.num_exports;
12721255
1273 var counting = std.io.countingWriter(writer);1256 try br.writeInt(u32, hash.num_buckets, .little);
1274 const cwriter = counting.writer();1257 try br.writeInt(u32, export_off, .little);
12751258 try br.writeInt(u32, hash.num_bloom, .little);
1276 try cwriter.writeInt(u32, hash.num_buckets, .little);1259 try br.writeInt(u32, bloom_shift, .little);
1277 try cwriter.writeInt(u32, export_off, .little);
1278 try cwriter.writeInt(u32, hash.num_bloom, .little);
1279 try cwriter.writeInt(u32, bloom_shift, .little);
12801260
1281 const comp = elf_file.base.comp;1261 const comp = elf_file.base.comp;
1282 const gpa = comp.gpa;1262 const gpa = comp.gpa;
...@@ -1300,7 +1280,7 @@ pub const GnuHashSection = struct {...@@ -1300,7 +1280,7 @@ pub const GnuHashSection = struct {
1300 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));1280 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
1301 }1281 }
13021282
1303 try cwriter.writeAll(mem.sliceAsBytes(bloom));1283 try br.writeAll(mem.sliceAsBytes(bloom));
13041284
1305 // Fill in the hash bucket indices1285 // Fill in the hash bucket indices
1306 const buckets = try gpa.alloc(u32, hash.num_buckets);1286 const buckets = try gpa.alloc(u32, hash.num_buckets);
...@@ -1313,7 +1293,7 @@ pub const GnuHashSection = struct {...@@ -1313,7 +1293,7 @@ pub const GnuHashSection = struct {
1313 }1293 }
1314 }1294 }
13151295
1316 try cwriter.writeAll(mem.sliceAsBytes(buckets));1296 try br.writeAll(mem.sliceAsBytes(buckets));
13171297
1318 // Finally, write the hash table1298 // Finally, write the hash table
1319 const table = try gpa.alloc(u32, hash.num_exports);1299 const table = try gpa.alloc(u32, hash.num_exports);
...@@ -1329,9 +1309,9 @@ pub const GnuHashSection = struct {...@@ -1329,9 +1309,9 @@ pub const GnuHashSection = struct {
1329 }1309 }
1330 }1310 }
13311311
1332 try cwriter.writeAll(mem.sliceAsBytes(table));1312 try br.writeAll(mem.sliceAsBytes(table));
13331313
1334 assert(counting.bytes_written == hash.size());1314 assert(br.count == hash.size());
1335 }1315 }
13361316
1337 pub fn hasher(name: [:0]const u8) u32 {1317 pub fn hasher(name: [:0]const u8) u32 {
...@@ -1478,9 +1458,9 @@ pub const VerneedSection = struct {...@@ -1478,9 +1458,9 @@ pub const VerneedSection = struct {
1478 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);1458 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);
1479 }1459 }
14801460
1481 pub fn write(vern: VerneedSection, writer: anytype) !void {1461 pub fn write(vern: VerneedSection, bw: *std.io.BufferedWriter) anyerror!void {
1482 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));1462 try bw.writeAll(mem.sliceAsBytes(vern.verneed.items));
1483 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));1463 try bw.writeAll(mem.sliceAsBytes(vern.vernaux.items));
1484 }1464 }
1485};1465};
14861466
...@@ -1506,11 +1486,11 @@ pub const GroupSection = struct {...@@ -1506,11 +1486,11 @@ pub const GroupSection = struct {
1506 return (members.len + 1) * @sizeOf(u32);1486 return (members.len + 1) * @sizeOf(u32);
1507 }1487 }
15081488
1509 pub fn write(cgs: GroupSection, elf_file: *Elf, writer: anytype) !void {1489 pub fn write(cgs: GroupSection, elf_file: *Elf, bw: *std.io.BufferedWriter) !void {
1510 const cg = cgs.group(elf_file);1490 const cg = cgs.group(elf_file);
1511 const object = cg.file(elf_file).object;1491 const object = cg.file(elf_file).object;
1512 const members = cg.members(elf_file);1492 const members = cg.members(elf_file);
1513 try writer.writeInt(u32, if (cg.is_comdat) elf.GRP_COMDAT else 0, .little);1493 try bw.writeInt(u32, if (cg.is_comdat) elf.GRP_COMDAT else 0, .little);
1514 for (members) |shndx| {1494 for (members) |shndx| {
1515 const shdr = object.shdrs.items[shndx];1495 const shdr = object.shdrs.items[shndx];
1516 switch (shdr.sh_type) {1496 switch (shdr.sh_type) {
...@@ -1522,26 +1502,26 @@ pub const GroupSection = struct {...@@ -1522,26 +1502,26 @@ pub const GroupSection = struct {
1522 atom.output_section_index == rela_shdr.sh_info)1502 atom.output_section_index == rela_shdr.sh_info)
1523 break rela_shndx;1503 break rela_shndx;
1524 } else unreachable;1504 } else unreachable;
1525 try writer.writeInt(u32, @intCast(rela_shndx), .little);1505 try bw.writeInt(u32, @intCast(rela_shndx), .little);
1526 },1506 },
1527 else => {1507 else => {
1528 const atom_index = object.atoms_indexes.items[shndx];1508 const atom_index = object.atoms_indexes.items[shndx];
1529 const atom = object.atom(atom_index).?;1509 const atom = object.atom(atom_index).?;
1530 try writer.writeInt(u32, atom.output_section_index, .little);1510 try bw.writeInt(u32, atom.output_section_index, .little);
1531 },1511 },
1532 }1512 }
1533 }1513 }
1534 }1514 }
1535};1515};
15361516
1537fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {1517fn writeInt(value: anytype, elf_file: *Elf, bw: *std.io.BufferedWriter) anyerror!void {
1538 const entry_size = elf_file.archPtrWidthBytes();1518 const entry_size = elf_file.archPtrWidthBytes();
1539 const target = elf_file.getTarget();1519 const target = elf_file.getTarget();
1540 const endian = target.cpu.arch.endian();1520 const endian = target.cpu.arch.endian();
1541 switch (entry_size) {1521 switch (entry_size) {
1542 2 => try writer.writeInt(u16, @intCast(value), endian),1522 2 => try bw.writeInt(u16, @intCast(value), endian),
1543 4 => try writer.writeInt(u32, @intCast(value), endian),1523 4 => try bw.writeInt(u32, @intCast(value), endian),
1544 8 => try writer.writeInt(u64, @intCast(value), endian),1524 8 => try bw.writeInt(u64, @intCast(value), endian),
1545 else => unreachable,1525 else => unreachable,
1546 }1526 }
1547}1527}
src/link/LdScript.zig+1-1
...@@ -41,7 +41,7 @@ pub fn parse(...@@ -41,7 +41,7 @@ pub fn parse(
41 try line_col.append(gpa, .{ .line = line, .column = column });41 try line_col.append(gpa, .{ .line = line, .column = column });
42 switch (tok.id) {42 switch (tok.id) {
43 .invalid => {43 .invalid => {
44 return diags.failParse(path, "invalid token in LD script: '{s}' ({d}:{d})", .{44 return diags.failParse(path, "invalid token in LD script: '{f}' ({d}:{d})", .{
45 std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column,45 std.fmt.fmtSliceEscapeLower(tok.get(data)), line, column,
46 });46 });
47 },47 },
src/link/MachO.zig+148-178
...@@ -41,9 +41,9 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE },...@@ -41,9 +41,9 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE },
41uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },41uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 },
42codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE },42codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE },
4343
44pagezero_seg_index: ?u8 = null,44pagezero_seg_index: ?u4 = null,
45text_seg_index: ?u8 = null,45text_seg_index: ?u4 = null,
46linkedit_seg_index: ?u8 = null,46linkedit_seg_index: ?u4 = null,
47text_sect_index: ?u8 = null,47text_sect_index: ?u8 = null,
48data_sect_index: ?u8 = null,48data_sect_index: ?u8 = null,
49got_sect_index: ?u8 = null,49got_sect_index: ?u8 = null,
...@@ -76,10 +76,10 @@ unwind_info: UnwindInfo = .{},...@@ -76,10 +76,10 @@ unwind_info: UnwindInfo = .{},
76data_in_code: DataInCode = .{},76data_in_code: DataInCode = .{},
7777
78/// Tracked loadable segments during incremental linking.78/// Tracked loadable segments during incremental linking.
79zig_text_seg_index: ?u8 = null,79zig_text_seg_index: ?u4 = null,
80zig_const_seg_index: ?u8 = null,80zig_const_seg_index: ?u4 = null,
81zig_data_seg_index: ?u8 = null,81zig_data_seg_index: ?u4 = null,
82zig_bss_seg_index: ?u8 = null,82zig_bss_seg_index: ?u4 = null,
8383
84/// Tracked section headers with incremental updates to Zig object.84/// Tracked section headers with incremental updates to Zig object.
85zig_text_sect_index: ?u8 = null,85zig_text_sect_index: ?u8 = null,
...@@ -543,7 +543,7 @@ pub fn flush(...@@ -543,7 +543,7 @@ pub fn flush(
543 self.allocateSyntheticSymbols();543 self.allocateSyntheticSymbols();
544544
545 if (build_options.enable_logging) {545 if (build_options.enable_logging) {
546 state_log.debug("{}", .{self.dumpState()});546 state_log.debug("{f}", .{self.dumpState()});
547 }547 }
548548
549 // Beyond this point, everything has been allocated a virtual address and we can resolve549 // Beyond this point, everything has been allocated a virtual address and we can resolve
...@@ -591,6 +591,7 @@ pub fn flush(...@@ -591,6 +591,7 @@ pub fn flush(
591 error.NoSpaceLeft => unreachable,591 error.NoSpaceLeft => unreachable,
592 error.OutOfMemory => return error.OutOfMemory,592 error.OutOfMemory => return error.OutOfMemory,
593 error.LinkFailure => return error.LinkFailure,593 error.LinkFailure => return error.LinkFailure,
594 else => unreachable,
594 };595 };
595 try self.writeHeader(ncmds, sizeofcmds);596 try self.writeHeader(ncmds, sizeofcmds);
596 self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()) catch |err| switch (err) {597 self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()) catch |err| switch (err) {
...@@ -677,12 +678,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {...@@ -677,12 +678,12 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
677678
678 try argv.append("-platform_version");679 try argv.append("-platform_version");
679 try argv.append(@tagName(self.platform.os_tag));680 try argv.append(@tagName(self.platform.os_tag));
680 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));681 try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version}));
681682
682 if (self.sdk_version) |ver| {683 if (self.sdk_version) |ver| {
683 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));684 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
684 } else {685 } else {
685 try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version}));686 try argv.append(try std.fmt.allocPrint(arena, "{f}", .{self.platform.version}));
686 }687 }
687688
688 if (comp.sysroot) |syslibroot| {689 if (comp.sysroot) |syslibroot| {
...@@ -863,7 +864,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void {...@@ -863,7 +864,7 @@ pub fn classifyInputFile(self: *MachO, input: link.Input) !void {
863864
864 const path, const file = input.pathAndFile().?;865 const path, const file = input.pathAndFile().?;
865 // TODO don't classify now, it's too late. The input file has already been classified866 // TODO don't classify now, it's too late. The input file has already been classified
866 log.debug("classifying input file {}", .{path});867 log.debug("classifying input file {f}", .{path});
867868
868 const fh = try self.addFileHandle(file);869 const fh = try self.addFileHandle(file);
869 var buffer: [Archive.SARMAG]u8 = undefined;870 var buffer: [Archive.SARMAG]u8 = undefined;
...@@ -1074,7 +1075,7 @@ fn accessLibPath(...@@ -1074,7 +1075,7 @@ fn accessLibPath(
10741075
1075 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {1076 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1076 test_path.clearRetainingCapacity();1077 test_path.clearRetainingCapacity();
1077 try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext });1078 try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext });
1078 try checked_paths.append(try arena.dupe(u8, test_path.items));1079 try checked_paths.append(try arena.dupe(u8, test_path.items));
1079 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {1080 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1080 error.FileNotFound => continue,1081 error.FileNotFound => continue,
...@@ -1097,7 +1098,7 @@ fn accessFrameworkPath(...@@ -1097,7 +1098,7 @@ fn accessFrameworkPath(
10971098
1098 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {1099 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1099 test_path.clearRetainingCapacity();1100 test_path.clearRetainingCapacity();
1100 try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{1101 try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
1101 search_dir,1102 search_dir,
1102 name,1103 name,
1103 name,1104 name,
...@@ -1178,9 +1179,9 @@ fn parseDependentDylibs(self: *MachO) !void {...@@ -1178,9 +1179,9 @@ fn parseDependentDylibs(self: *MachO) !void {
1178 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {1179 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
1179 test_path.clearRetainingCapacity();1180 test_path.clearRetainingCapacity();
1180 if (self.base.comp.sysroot) |root| {1181 if (self.base.comp.sysroot) |root| {
1181 try test_path.writer().print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext });1182 try test_path.print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext });
1182 } else {1183 } else {
1183 try test_path.writer().print("{s}{s}", .{ path, ext });1184 try test_path.print("{s}{s}", .{ path, ext });
1184 }1185 }
1185 try checked_paths.append(try arena.dupe(u8, test_path.items));1186 try checked_paths.append(try arena.dupe(u8, test_path.items));
1186 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {1187 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
...@@ -1591,7 +1592,7 @@ fn reportUndefs(self: *MachO) !void {...@@ -1591,7 +1592,7 @@ fn reportUndefs(self: *MachO) !void {
1591 const ref = refs.items[inote];1592 const ref = refs.items[inote];
1592 const file = self.getFile(ref.file).?;1593 const file = self.getFile(ref.file).?;
1593 const atom = ref.getAtom(self).?;1594 const atom = ref.getAtom(self).?;
1594 err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) });1595 err.addNote("referenced by {f}:{s}", .{ file.fmtPath(), atom.getName(self) });
1595 }1596 }
15961597
1597 if (refs.items.len > max_notes) {1598 if (refs.items.len > max_notes) {
...@@ -2131,7 +2132,7 @@ fn initSegments(self: *MachO) !void {...@@ -2131,7 +2132,7 @@ fn initSegments(self: *MachO) !void {
21312132
2132 mem.sort(Entry, entries.items, self, Entry.lessThan);2133 mem.sort(Entry, entries.items, self, Entry.lessThan);
21332134
2134 const backlinks = try gpa.alloc(u8, entries.items.len);2135 const backlinks = try gpa.alloc(u4, entries.items.len);
2135 defer gpa.free(backlinks);2136 defer gpa.free(backlinks);
2136 for (entries.items, 0..) |entry, i| {2137 for (entries.items, 0..) |entry, i| {
2137 backlinks[entry.index] = @intCast(i);2138 backlinks[entry.index] = @intCast(i);
...@@ -2145,7 +2146,7 @@ fn initSegments(self: *MachO) !void {...@@ -2145,7 +2146,7 @@ fn initSegments(self: *MachO) !void {
2145 self.segments.appendAssumeCapacity(segments[sorted.index]);2146 self.segments.appendAssumeCapacity(segments[sorted.index]);
2146 }2147 }
21472148
2148 for (&[_]*?u8{2149 for (&[_]*?u4{
2149 &self.pagezero_seg_index,2150 &self.pagezero_seg_index,
2150 &self.text_seg_index,2151 &self.text_seg_index,
2151 &self.linkedit_seg_index,2152 &self.linkedit_seg_index,
...@@ -2163,7 +2164,7 @@ fn initSegments(self: *MachO) !void {...@@ -2163,7 +2164,7 @@ fn initSegments(self: *MachO) !void {
2163 for (slice.items(.header), slice.items(.segment_id)) |header, *seg_id| {2164 for (slice.items(.header), slice.items(.segment_id)) |header, *seg_id| {
2164 const segname = header.segName();2165 const segname = header.segName();
2165 const segment_id = self.getSegmentByName(segname) orelse blk: {2166 const segment_id = self.getSegmentByName(segname) orelse blk: {
2166 const segment_id = @as(u8, @intCast(self.segments.items.len));2167 const segment_id: u4 = @intCast(self.segments.items.len);
2167 const protection = getSegmentProt(segname);2168 const protection = getSegmentProt(segname);
2168 try self.segments.append(gpa, .{2169 try self.segments.append(gpa, .{
2169 .cmdsize = @sizeOf(macho.segment_command_64),2170 .cmdsize = @sizeOf(macho.segment_command_64),
...@@ -2526,10 +2527,9 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void {...@@ -2526,10 +2527,9 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void {
25262527
2527 const doWork = struct {2528 const doWork = struct {
2528 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {2529 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {
2529 const off = try macho_file.cast(usize, th.value);2530 var bw: std.io.BufferedWriter = undefined;
2530 const size = th.size();2531 bw.initFixed(buffer[try macho_file.cast(usize, th.value)..][0..th.size()]);
2531 var stream = std.io.fixedBufferStream(buffer[off..][0..size]);2532 try th.write(macho_file, &bw);
2532 try th.write(macho_file, stream.writer());
2533 }2533 }
2534 }.doWork;2534 }.doWork;
2535 const out = self.sections.items(.out)[thunk.out_n_sect].items;2535 const out = self.sections.items(.out)[thunk.out_n_sect].items;
...@@ -2556,15 +2556,16 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void {...@@ -2556,15 +2556,16 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void {
25562556
2557 const doWork = struct {2557 const doWork = struct {
2558 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {2558 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {
2559 var stream = std.io.fixedBufferStream(buffer);2559 var bw: std.io.BufferedWriter = undefined;
2560 bw.initFixed(buffer);
2560 switch (tag) {2561 switch (tag) {
2561 .eh_frame => eh_frame.write(macho_file, buffer),2562 .eh_frame => eh_frame.write(macho_file, buffer),
2562 .unwind_info => try macho_file.unwind_info.write(macho_file, buffer),2563 .unwind_info => try macho_file.unwind_info.write(macho_file, &bw),
2563 .got => try macho_file.got.write(macho_file, stream.writer()),2564 .got => try macho_file.got.write(macho_file, &bw),
2564 .stubs => try macho_file.stubs.write(macho_file, stream.writer()),2565 .stubs => try macho_file.stubs.write(macho_file, &bw),
2565 .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()),2566 .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, &bw),
2566 .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()),2567 .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, &bw),
2567 .objc_stubs => try macho_file.objc_stubs.write(macho_file, stream.writer()),2568 .objc_stubs => try macho_file.objc_stubs.write(macho_file, &bw),
2568 }2569 }
2569 }2570 }
2570 }.doWork;2571 }.doWork;
...@@ -2605,8 +2606,9 @@ fn updateLazyBindSizeWorker(self: *MachO) void {...@@ -2605,8 +2606,9 @@ fn updateLazyBindSizeWorker(self: *MachO) void {
2605 try macho_file.lazy_bind_section.updateSize(macho_file);2606 try macho_file.lazy_bind_section.updateSize(macho_file);
2606 const sect_id = macho_file.stubs_helper_sect_index.?;2607 const sect_id = macho_file.stubs_helper_sect_index.?;
2607 const out = &macho_file.sections.items(.out)[sect_id];2608 const out = &macho_file.sections.items(.out)[sect_id];
2608 var stream = std.io.fixedBufferStream(out.items);2609 var bw: std.io.BufferedWriter = undefined;
2609 try macho_file.stubs_helper.write(macho_file, stream.writer());2610 bw.initFixed(out.items);
2611 try macho_file.stubs_helper.write(macho_file, &bw);
2610 }2612 }
2611 }.doWork;2613 }.doWork;
2612 doWork(self) catch |err|2614 doWork(self) catch |err|
...@@ -2665,23 +2667,21 @@ fn writeDyldInfo(self: *MachO) !void {...@@ -2665,23 +2667,21 @@ fn writeDyldInfo(self: *MachO) !void {
2665 needed_size += cmd.lazy_bind_size;2667 needed_size += cmd.lazy_bind_size;
2666 needed_size += cmd.export_size;2668 needed_size += cmd.export_size;
26672669
2668 const buffer = try gpa.alloc(u8, needed_size);2670 var bw: std.io.BufferedWriter = undefined;
2669 defer gpa.free(buffer);2671 bw.initFixed(try gpa.alloc(u8, needed_size));
2670 @memset(buffer, 0);2672 defer gpa.free(bw.buffer);
2673 @memset(bw.buffer, 0);
26712674
2672 var stream = std.io.fixedBufferStream(buffer);2675 try self.rebase_section.write(&bw);
2673 const writer = stream.writer();2676 bw.end = cmd.bind_off - base_off;
26742677 try self.bind_section.write(&bw);
2675 try self.rebase_section.write(writer);2678 bw.end = cmd.weak_bind_off - base_off;
2676 try stream.seekTo(cmd.bind_off - base_off);2679 try self.weak_bind_section.write(&bw);
2677 try self.bind_section.write(writer);2680 bw.end = cmd.lazy_bind_off - base_off;
2678 try stream.seekTo(cmd.weak_bind_off - base_off);2681 try self.lazy_bind_section.write(&bw);
2679 try self.weak_bind_section.write(writer);2682 bw.end = cmd.export_off - base_off;
2680 try stream.seekTo(cmd.lazy_bind_off - base_off);2683 try self.export_trie.write(&bw);
2681 try self.lazy_bind_section.write(writer);2684 try self.pwriteAll(bw.buffer, cmd.rebase_off);
2682 try stream.seekTo(cmd.export_off - base_off);
2683 try self.export_trie.write(writer);
2684 try self.pwriteAll(buffer, cmd.rebase_off);
2685}2685}
26862686
2687pub fn writeDataInCode(self: *MachO) !void {2687pub fn writeDataInCode(self: *MachO) !void {
...@@ -2689,22 +2689,30 @@ pub fn writeDataInCode(self: *MachO) !void {...@@ -2689,22 +2689,30 @@ pub fn writeDataInCode(self: *MachO) !void {
2689 defer tracy.end();2689 defer tracy.end();
2690 const gpa = self.base.comp.gpa;2690 const gpa = self.base.comp.gpa;
2691 const cmd = self.data_in_code_cmd;2691 const cmd = self.data_in_code_cmd;
2692 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.data_in_code.size());2692
2693 defer buffer.deinit();2693 var bw: std.io.BufferedWriter = undefined;
2694 try self.data_in_code.write(self, buffer.writer());2694 bw.initFixed(try gpa.alloc(u8, self.data_in_code.size()));
2695 try self.pwriteAll(buffer.items, cmd.dataoff);2695 defer gpa.free(bw.buffer);
2696
2697 try self.data_in_code.write(self, &bw);
2698 assert(bw.end == bw.buffer.len);
2699 try self.pwriteAll(bw.buffer, cmd.dataoff);
2696}2700}
26972701
2698fn writeIndsymtab(self: *MachO) !void {2702fn writeIndsymtab(self: *MachO) !void {
2699 const tracy = trace(@src());2703 const tracy = trace(@src());
2700 defer tracy.end();2704 defer tracy.end();
2705
2701 const gpa = self.base.comp.gpa;2706 const gpa = self.base.comp.gpa;
2702 const cmd = self.dysymtab_cmd;2707 const cmd = self.dysymtab_cmd;
2703 const needed_size = cmd.nindirectsyms * @sizeOf(u32);2708
2704 var buffer = try std.ArrayList(u8).initCapacity(gpa, needed_size);2709 var bw: std.io.BufferedWriter = undefined;
2705 defer buffer.deinit();2710 bw.initFixed(try gpa.alloc(u8, @sizeOf(u32) * cmd.nindirectsyms));
2706 try self.indsymtab.write(self, buffer.writer());2711 defer gpa.free(bw.buffer);
2707 try self.pwriteAll(buffer.items, cmd.indirectsymoff);2712
2713 try self.indsymtab.write(self, &bw);
2714 assert(bw.end == bw.buffer.len);
2715 try self.pwriteAll(bw.buffer, cmd.indirectsymoff);
2708}2716}
27092717
2710pub fn writeSymtabToFile(self: *MachO) !void {2718pub fn writeSymtabToFile(self: *MachO) !void {
...@@ -2814,15 +2822,13 @@ fn calcSymtabSize(self: *MachO) !void {...@@ -2814,15 +2822,13 @@ fn calcSymtabSize(self: *MachO) !void {
2814 }2822 }
2815}2823}
28162824
2817fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {2825fn writeLoadCommands(self: *MachO) anyerror!struct { usize, usize, u64 } {
2818 const comp = self.base.comp;2826 const comp = self.base.comp;
2819 const gpa = comp.gpa;2827 const gpa = comp.gpa;
2820 const needed_size = try load_commands.calcLoadCommandsSize(self, false);
2821 const buffer = try gpa.alloc(u8, needed_size);
2822 defer gpa.free(buffer);
28232828
2824 var stream = std.io.fixedBufferStream(buffer);2829 var bw: std.io.BufferedWriter = undefined;
2825 const writer = stream.writer();2830 bw.initFixed(try gpa.alloc(u8, try load_commands.calcLoadCommandsSize(self, false)));
2831 defer gpa.free(bw.buffer);
28262832
2827 var ncmds: usize = 0;2833 var ncmds: usize = 0;
28282834
...@@ -2831,26 +2837,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {...@@ -2831,26 +2837,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
2831 const slice = self.sections.slice();2837 const slice = self.sections.slice();
2832 var sect_id: usize = 0;2838 var sect_id: usize = 0;
2833 for (self.segments.items) |seg| {2839 for (self.segments.items) |seg| {
2834 try writer.writeStruct(seg);2840 try bw.writeStruct(seg);
2835 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {2841 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
2836 try writer.writeStruct(header);2842 try bw.writeStruct(header);
2837 }2843 }
2838 sect_id += seg.nsects;2844 sect_id += seg.nsects;
2839 }2845 }
2840 ncmds += self.segments.items.len;2846 ncmds += self.segments.items.len;
2841 }2847 }
28422848
2843 try writer.writeStruct(self.dyld_info_cmd);2849 try bw.writeStruct(self.dyld_info_cmd);
2844 ncmds += 1;2850 ncmds += 1;
2845 try writer.writeStruct(self.function_starts_cmd);2851 try bw.writeStruct(self.function_starts_cmd);
2846 ncmds += 1;2852 ncmds += 1;
2847 try writer.writeStruct(self.data_in_code_cmd);2853 try bw.writeStruct(self.data_in_code_cmd);
2848 ncmds += 1;2854 ncmds += 1;
2849 try writer.writeStruct(self.symtab_cmd);2855 try bw.writeStruct(self.symtab_cmd);
2850 ncmds += 1;2856 ncmds += 1;
2851 try writer.writeStruct(self.dysymtab_cmd);2857 try bw.writeStruct(self.dysymtab_cmd);
2852 ncmds += 1;2858 ncmds += 1;
2853 try load_commands.writeDylinkerLC(writer);2859 try load_commands.writeDylinkerLC(&bw);
2854 ncmds += 1;2860 ncmds += 1;
28552861
2856 if (self.getInternalObject()) |obj| {2862 if (self.getInternalObject()) |obj| {
...@@ -2861,7 +2867,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {...@@ -2861,7 +2867,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
2861 02867 0
2862 else2868 else
2863 @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr));2869 @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr));
2864 try writer.writeStruct(macho.entry_point_command{2870 try bw.writeStruct(macho.entry_point_command{
2865 .entryoff = entryoff,2871 .entryoff = entryoff,
2866 .stacksize = self.base.stack_size,2872 .stacksize = self.base.stack_size,
2867 });2873 });
...@@ -2870,35 +2876,35 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {...@@ -2870,35 +2876,35 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
2870 }2876 }
28712877
2872 if (self.base.isDynLib()) {2878 if (self.base.isDynLib()) {
2873 try load_commands.writeDylibIdLC(self, writer);2879 try load_commands.writeDylibIdLC(self, &bw);
2874 ncmds += 1;2880 ncmds += 1;
2875 }2881 }
28762882
2877 for (self.rpath_list) |rpath| {2883 for (self.rpath_list) |rpath| {
2878 try load_commands.writeRpathLC(rpath, writer);2884 try load_commands.writeRpathLC(&bw, rpath);
2879 ncmds += 1;2885 ncmds += 1;
2880 }2886 }
2881 if (comp.config.any_sanitize_thread) {2887 if (comp.config.any_sanitize_thread) {
2882 const path = try comp.tsan_lib.?.full_object_path.toString(gpa);2888 const path = try comp.tsan_lib.?.full_object_path.toString(gpa);
2883 defer gpa.free(path);2889 defer gpa.free(path);
2884 const rpath = std.fs.path.dirname(path) orelse ".";2890 const rpath = std.fs.path.dirname(path) orelse ".";
2885 try load_commands.writeRpathLC(rpath, writer);2891 try load_commands.writeRpathLC(&bw, rpath);
2886 ncmds += 1;2892 ncmds += 1;
2887 }2893 }
28882894
2889 try writer.writeStruct(macho.source_version_command{ .version = 0 });2895 try bw.writeStruct(macho.source_version_command{ .version = 0 });
2890 ncmds += 1;2896 ncmds += 1;
28912897
2892 if (self.platform.isBuildVersionCompatible()) {2898 if (self.platform.isBuildVersionCompatible()) {
2893 try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, writer);2899 try load_commands.writeBuildVersionLC(&bw, self.platform, self.sdk_version);
2894 ncmds += 1;2900 ncmds += 1;
2895 } else {2901 } else {
2896 try load_commands.writeVersionMinLC(self.platform, self.sdk_version, writer);2902 try load_commands.writeVersionMinLC(&bw, self.platform, self.sdk_version);
2897 ncmds += 1;2903 ncmds += 1;
2898 }2904 }
28992905
2900 const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + stream.pos;2906 const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + bw.count;
2901 try writer.writeStruct(self.uuid_cmd);2907 try bw.writeStruct(self.uuid_cmd);
2902 ncmds += 1;2908 ncmds += 1;
29032909
2904 for (self.dylibs.items) |index| {2910 for (self.dylibs.items) |index| {
...@@ -2916,20 +2922,19 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {...@@ -2916,20 +2922,19 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
2916 .timestamp = dylib_id.timestamp,2922 .timestamp = dylib_id.timestamp,
2917 .current_version = dylib_id.current_version,2923 .current_version = dylib_id.current_version,
2918 .compatibility_version = dylib_id.compatibility_version,2924 .compatibility_version = dylib_id.compatibility_version,
2919 }, writer);2925 }, &bw);
2920 ncmds += 1;2926 ncmds += 1;
2921 }2927 }
29222928
2923 if (self.requiresCodeSig()) {2929 if (self.requiresCodeSig()) {
2924 try writer.writeStruct(self.codesig_cmd);2930 try bw.writeStruct(self.codesig_cmd);
2925 ncmds += 1;2931 ncmds += 1;
2926 }2932 }
29272933
2928 assert(stream.pos == needed_size);2934 assert(bw.end == bw.buffer.len);
2935 try self.pwriteAll(bw.buffer, @sizeOf(macho.mach_header_64));
29292936
2930 try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64));2937 return .{ ncmds, bw.end, uuid_cmd_offset };
2931
2932 return .{ ncmds, buffer.len, uuid_cmd_offset };
2933}2938}
29342939
2935fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {2940fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {
...@@ -3012,27 +3017,28 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void {...@@ -3012,27 +3017,28 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void {
3012}3017}
30133018
3014pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void {3019pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void {
3020 const gpa = self.base.comp.gpa;
3015 const seg = self.getTextSegment();3021 const seg = self.getTextSegment();
3016 const offset = self.codesig_cmd.dataoff;3022 const offset = self.codesig_cmd.dataoff;
30173023
3018 var buffer = std.ArrayList(u8).init(self.base.comp.gpa);3024 var bw: std.io.BufferedWriter = undefined;
3019 defer buffer.deinit();3025 bw.initFixed(try gpa.alloc(u8, code_sig.size()));
3020 try buffer.ensureTotalCapacityPrecise(code_sig.size());3026 defer gpa.free(bw.buffer);
3021 try code_sig.writeAdhocSignature(self, .{3027 try code_sig.writeAdhocSignature(self, .{
3022 .file = self.base.file.?,3028 .file = self.base.file.?,
3023 .exec_seg_base = seg.fileoff,3029 .exec_seg_base = seg.fileoff,
3024 .exec_seg_limit = seg.filesize,3030 .exec_seg_limit = seg.filesize,
3025 .file_size = offset,3031 .file_size = offset,
3026 .dylib = self.base.isDynLib(),3032 .dylib = self.base.isDynLib(),
3027 }, buffer.writer());3033 }, &bw);
3028 assert(buffer.items.len == code_sig.size());
30293034
3030 log.debug("writing code signature from 0x{x} to 0x{x}", .{3035 log.debug("writing code signature from 0x{x} to 0x{x}", .{
3031 offset,3036 offset,
3032 offset + buffer.items.len,3037 offset + bw.end,
3033 });3038 });
30343039
3035 try self.pwriteAll(buffer.items, offset);3040 assert(bw.end == bw.buffer.len);
3041 try self.pwriteAll(bw.buffer, offset);
3036}3042}
30373043
3038pub fn updateFunc(3044pub fn updateFunc(
...@@ -3341,7 +3347,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {...@@ -3341,7 +3347,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3341 }3347 }
33423348
3343 const appendSect = struct {3349 const appendSect = struct {
3344 fn appendSect(macho_file: *MachO, sect_id: u8, seg_id: u8) void {3350 fn appendSect(macho_file: *MachO, sect_id: u8, seg_id: u4) void {
3345 const sect = &macho_file.sections.items(.header)[sect_id];3351 const sect = &macho_file.sections.items(.header)[sect_id];
3346 const seg = macho_file.segments.items[seg_id];3352 const seg = macho_file.segments.items[seg_id];
3347 sect.addr = seg.vmaddr;3353 sect.addr = seg.vmaddr;
...@@ -3600,7 +3606,7 @@ inline fn requiresThunks(self: MachO) bool {...@@ -3600,7 +3606,7 @@ inline fn requiresThunks(self: MachO) bool {
3600}3606}
36013607
3602pub fn isZigSegment(self: MachO, seg_id: u8) bool {3608pub fn isZigSegment(self: MachO, seg_id: u8) bool {
3603 inline for (&[_]?u8{3609 inline for (&[_]?u4{
3604 self.zig_text_seg_index,3610 self.zig_text_seg_index,
3605 self.zig_const_seg_index,3611 self.zig_const_seg_index,
3606 self.zig_data_seg_index,3612 self.zig_data_seg_index,
...@@ -3648,9 +3654,9 @@ pub fn addSegment(self: *MachO, name: []const u8, opts: struct {...@@ -3648,9 +3654,9 @@ pub fn addSegment(self: *MachO, name: []const u8, opts: struct {
3648 fileoff: u64 = 0,3654 fileoff: u64 = 0,
3649 filesize: u64 = 0,3655 filesize: u64 = 0,
3650 prot: macho.vm_prot_t = macho.PROT.NONE,3656 prot: macho.vm_prot_t = macho.PROT.NONE,
3651}) error{OutOfMemory}!u8 {3657}) error{OutOfMemory}!u4 {
3652 const gpa = self.base.comp.gpa;3658 const gpa = self.base.comp.gpa;
3653 const index = @as(u8, @intCast(self.segments.items.len));3659 const index: u4 = @intCast(self.segments.items.len);
3654 try self.segments.append(gpa, .{3660 try self.segments.append(gpa, .{
3655 .segname = makeStaticString(name),3661 .segname = makeStaticString(name),
3656 .vmaddr = opts.vmaddr,3662 .vmaddr = opts.vmaddr,
...@@ -3700,9 +3706,9 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -3700,9 +3706,9 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
3700 return buf;3706 return buf;
3701}3707}
37023708
3703pub fn getSegmentByName(self: MachO, segname: []const u8) ?u8 {3709pub fn getSegmentByName(self: MachO, segname: []const u8) ?u4 {
3704 for (self.segments.items, 0..) |seg, i| {3710 for (self.segments.items, 0..) |seg, i| {
3705 if (mem.eql(u8, segname, seg.segName())) return @as(u8, @intCast(i));3711 if (mem.eql(u8, segname, seg.segName())) return @intCast(i);
3706 } else return null;3712 } else return null;
3707}3713}
37083714
...@@ -3791,7 +3797,7 @@ pub fn reportParseError2(...@@ -3791,7 +3797,7 @@ pub fn reportParseError2(
3791 const diags = &self.base.comp.link_diags;3797 const diags = &self.base.comp.link_diags;
3792 var err = try diags.addErrorWithNotes(1);3798 var err = try diags.addErrorWithNotes(1);
3793 try err.addMsg(format, args);3799 try err.addMsg(format, args);
3794 err.addNote("while parsing {}", .{self.getFile(file_index).?.fmtPath()});3800 err.addNote("while parsing {f}", .{self.getFile(file_index).?.fmtPath()});
3795}3801}
37963802
3797fn reportMissingDependencyError(3803fn reportMissingDependencyError(
...@@ -3806,7 +3812,7 @@ fn reportMissingDependencyError(...@@ -3806,7 +3812,7 @@ fn reportMissingDependencyError(
3806 var err = try diags.addErrorWithNotes(2 + checked_paths.len);3812 var err = try diags.addErrorWithNotes(2 + checked_paths.len);
3807 try err.addMsg(format, args);3813 try err.addMsg(format, args);
3808 err.addNote("while resolving {s}", .{path});3814 err.addNote("while resolving {s}", .{path});
3809 err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});3815 err.addNote("a dependency of {f}", .{self.getFile(parent).?.fmtPath()});
3810 for (checked_paths) |p| {3816 for (checked_paths) |p| {
3811 err.addNote("tried {s}", .{p});3817 err.addNote("tried {s}", .{p});
3812 }3818 }
...@@ -3823,7 +3829,7 @@ fn reportDependencyError(...@@ -3823,7 +3829,7 @@ fn reportDependencyError(
3823 var err = try diags.addErrorWithNotes(2);3829 var err = try diags.addErrorWithNotes(2);
3824 try err.addMsg(format, args);3830 try err.addMsg(format, args);
3825 err.addNote("while parsing {s}", .{path});3831 err.addNote("while parsing {s}", .{path});
3826 err.addNote("a dependency of {}", .{self.getFile(parent).?.fmtPath()});3832 err.addNote("a dependency of {f}", .{self.getFile(parent).?.fmtPath()});
3827}3833}
38283834
3829fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {3835fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
...@@ -3853,12 +3859,12 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {...@@ -3853,12 +3859,12 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
38533859
3854 var err = try diags.addErrorWithNotes(nnotes + 1);3860 var err = try diags.addErrorWithNotes(nnotes + 1);
3855 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});3861 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});
3856 err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});3862 err.addNote("defined by {f}", .{sym.getFile(self).?.fmtPath()});
38573863
3858 var inote: usize = 0;3864 var inote: usize = 0;
3859 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {3865 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
3860 const file = self.getFile(notes.items[inote]).?;3866 const file = self.getFile(notes.items[inote]).?;
3861 err.addNote("defined by {}", .{file.fmtPath()});3867 err.addNote("defined by {f}", .{file.fmtPath()});
3862 }3868 }
38633869
3864 if (notes.items.len > max_notes) {3870 if (notes.items.len > max_notes) {
...@@ -3904,31 +3910,25 @@ pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {...@@ -3904,31 +3910,25 @@ pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) {
3904 return .{ .data = self };3910 return .{ .data = self };
3905}3911}
39063912
3907fn fmtDumpState(3913fn fmtDumpState(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
3908 self: *MachO,
3909 comptime unused_fmt_string: []const u8,
3910 options: std.fmt.FormatOptions,
3911 writer: anytype,
3912) !void {
3913 _ = options;
3914 _ = unused_fmt_string;3914 _ = unused_fmt_string;
3915 if (self.getZigObject()) |zo| {3915 if (self.getZigObject()) |zo| {
3916 try writer.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });3916 try bw.print("zig_object({d}) : {s}\n", .{ zo.index, zo.basename });
3917 try writer.print("{}{}\n", .{3917 try bw.print("{f}{f}\n", .{
3918 zo.fmtAtoms(self),3918 zo.fmtAtoms(self),
3919 zo.fmtSymtab(self),3919 zo.fmtSymtab(self),
3920 });3920 });
3921 }3921 }
3922 for (self.objects.items) |index| {3922 for (self.objects.items) |index| {
3923 const object = self.getFile(index).?.object;3923 const object = self.getFile(index).?.object;
3924 try writer.print("object({d}) : {} : has_debug({})", .{3924 try bw.print("object({d}) : {f} : has_debug({})", .{
3925 index,3925 index,
3926 object.fmtPath(),3926 object.fmtPath(),
3927 object.hasDebugInfo(),3927 object.hasDebugInfo(),
3928 });3928 });
3929 if (!object.alive) try writer.writeAll(" : ([*])");3929 if (!object.alive) try bw.writeAll(" : ([*])");
3930 try writer.writeByte('\n');3930 try bw.writeByte('\n');
3931 try writer.print("{}{}{}{}{}\n", .{3931 try bw.print("{f}{f}{f}{f}{f}\n", .{
3932 object.fmtAtoms(self),3932 object.fmtAtoms(self),
3933 object.fmtCies(self),3933 object.fmtCies(self),
3934 object.fmtFdes(self),3934 object.fmtFdes(self),
...@@ -3938,48 +3938,42 @@ fn fmtDumpState(...@@ -3938,48 +3938,42 @@ fn fmtDumpState(
3938 }3938 }
3939 for (self.dylibs.items) |index| {3939 for (self.dylibs.items) |index| {
3940 const dylib = self.getFile(index).?.dylib;3940 const dylib = self.getFile(index).?.dylib;
3941 try writer.print("dylib({d}) : {} : needed({}) : weak({})", .{3941 try bw.print("dylib({d}) : {f} : needed({}) : weak({})", .{
3942 index,3942 index,
3943 @as(Path, dylib.path),3943 @as(Path, dylib.path),
3944 dylib.needed,3944 dylib.needed,
3945 dylib.weak,3945 dylib.weak,
3946 });3946 });
3947 if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])");3947 if (!dylib.isAlive(self)) try bw.writeAll(" : ([*])");
3948 try writer.writeByte('\n');3948 try bw.writeByte('\n');
3949 try writer.print("{}\n", .{dylib.fmtSymtab(self)});3949 try bw.print("{f}\n", .{dylib.fmtSymtab(self)});
3950 }3950 }
3951 if (self.getInternalObject()) |internal| {3951 if (self.getInternalObject()) |internal| {
3952 try writer.print("internal({d}) : internal\n", .{internal.index});3952 try bw.print("internal({d}) : internal\n", .{internal.index});
3953 try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) });3953 try bw.print("{f}{f}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) });
3954 }3954 }
3955 try writer.writeAll("thunks\n");3955 try bw.writeAll("thunks\n");
3956 for (self.thunks.items, 0..) |thunk, index| {3956 for (self.thunks.items, 0..) |thunk, index| {
3957 try writer.print("thunk({d}) : {}\n", .{ index, thunk.fmt(self) });3957 try bw.print("thunk({d}) : {f}\n", .{ index, thunk.fmt(self) });
3958 }3958 }
3959 try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)});3959 try bw.print("stubs\n{f}\n", .{self.stubs.fmt(self)});
3960 try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)});3960 try bw.print("objc_stubs\n{f}\n", .{self.objc_stubs.fmt(self)});
3961 try writer.print("got\n{}\n", .{self.got.fmt(self)});3961 try bw.print("got\n{f}\n", .{self.got.fmt(self)});
3962 try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)});3962 try bw.print("tlv_ptr\n{f}\n", .{self.tlv_ptr.fmt(self)});
3963 try writer.writeByte('\n');3963 try bw.writeByte('\n');
3964 try writer.print("sections\n{}\n", .{self.fmtSections()});3964 try bw.print("sections\n{f}\n", .{self.fmtSections()});
3965 try writer.print("segments\n{}\n", .{self.fmtSegments()});3965 try bw.print("segments\n{f}\n", .{self.fmtSegments()});
3966}3966}
39673967
3968fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {3968fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) {
3969 return .{ .data = self };3969 return .{ .data = self };
3970}3970}
39713971
3972fn formatSections(3972fn formatSections(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
3973 self: *MachO,
3974 comptime unused_fmt_string: []const u8,
3975 options: std.fmt.FormatOptions,
3976 writer: anytype,
3977) !void {
3978 _ = options;
3979 _ = unused_fmt_string;3973 _ = unused_fmt_string;
3980 const slice = self.sections.slice();3974 const slice = self.sections.slice();
3981 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {3975 for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| {
3982 try writer.print(3976 try bw.print(
3983 "sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x}) : relocs({x};{d})\n",3977 "sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x}) : relocs({x};{d})\n",
3984 .{3978 .{
3985 i, seg_id, header.segName(), header.sectName(), header.addr, header.offset,3979 i, seg_id, header.segName(), header.sectName(), header.addr, header.offset,
...@@ -3993,16 +3987,10 @@ fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {...@@ -3993,16 +3987,10 @@ fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) {
3993 return .{ .data = self };3987 return .{ .data = self };
3994}3988}
39953989
3996fn formatSegments(3990fn formatSegments(self: *MachO, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
3997 self: *MachO,
3998 comptime unused_fmt_string: []const u8,
3999 options: std.fmt.FormatOptions,
4000 writer: anytype,
4001) !void {
4002 _ = options;
4003 _ = unused_fmt_string;3991 _ = unused_fmt_string;
4004 for (self.segments.items, 0..) |seg, i| {3992 for (self.segments.items, 0..) |seg, i| {
4005 try writer.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{3993 try bw.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{
4006 i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize,3994 i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize,
4007 seg.fileoff, seg.fileoff + seg.filesize,3995 seg.fileoff, seg.fileoff + seg.filesize,
4008 });3996 });
...@@ -4013,13 +4001,7 @@ pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {...@@ -4013,13 +4001,7 @@ pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) {
4013 return .{ .data = tt };4001 return .{ .data = tt };
4014}4002}
40154003
4016fn formatSectType(4004fn formatSectType(tt: u8, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
4017 tt: u8,
4018 comptime unused_fmt_string: []const u8,
4019 options: std.fmt.FormatOptions,
4020 writer: anytype,
4021) !void {
4022 _ = options;
4023 _ = unused_fmt_string;4005 _ = unused_fmt_string;
4024 const name = switch (tt) {4006 const name = switch (tt) {
4025 macho.S_REGULAR => "REGULAR",4007 macho.S_REGULAR => "REGULAR",
...@@ -4044,9 +4026,9 @@ fn formatSectType(...@@ -4044,9 +4026,9 @@ fn formatSectType(
4044 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS",4026 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS",
4045 macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS",4027 macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS",
4046 macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS",4028 macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS",
4047 else => |x| return writer.print("UNKNOWN({x})", .{x}),4029 else => |x| return bw.print("UNKNOWN({x})", .{x}),
4048 };4030 };
4049 try writer.print("{s}", .{name});4031 try bw.print("{s}", .{name});
4050}4032}
40514033
4052const is_hot_update_compatible = switch (builtin.target.os.tag) {4034const is_hot_update_compatible = switch (builtin.target.os.tag) {
...@@ -4058,7 +4040,7 @@ const default_entry_symbol_name = "_main";...@@ -4058,7 +4040,7 @@ const default_entry_symbol_name = "_main";
40584040
4059const Section = struct {4041const Section = struct {
4060 header: macho.section_64,4042 header: macho.section_64,
4061 segment_id: u8,4043 segment_id: u4,
4062 atoms: std.ArrayListUnmanaged(Ref) = .empty,4044 atoms: std.ArrayListUnmanaged(Ref) = .empty,
4063 free_list: std.ArrayListUnmanaged(Atom.Index) = .empty,4045 free_list: std.ArrayListUnmanaged(Atom.Index) = .empty,
4064 last_atom_index: Atom.Index = 0,4046 last_atom_index: Atom.Index = 0,
...@@ -4288,17 +4270,11 @@ pub const Platform = struct {...@@ -4288,17 +4270,11 @@ pub const Platform = struct {
4288 cpu_arch: std.Target.Cpu.Arch,4270 cpu_arch: std.Target.Cpu.Arch,
4289 };4271 };
42904272
4291 pub fn formatTarget(4273 pub fn formatTarget(ctx: FmtCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
4292 ctx: FmtCtx,
4293 comptime unused_fmt_string: []const u8,
4294 options: std.fmt.FormatOptions,
4295 writer: anytype,
4296 ) !void {
4297 _ = unused_fmt_string;4274 _ = unused_fmt_string;
4298 _ = options;4275 try bw.print("{s}-{s}", .{ @tagName(ctx.cpu_arch), @tagName(ctx.platform.os_tag) });
4299 try writer.print("{s}-{s}", .{ @tagName(ctx.cpu_arch), @tagName(ctx.platform.os_tag) });
4300 if (ctx.platform.abi != .none) {4276 if (ctx.platform.abi != .none) {
4301 try writer.print("-{s}", .{@tagName(ctx.platform.abi)});4277 try bw.print("-{s}", .{@tagName(ctx.platform.abi)});
4302 }4278 }
4303 }4279 }
43044280
...@@ -4390,7 +4366,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi...@@ -4390,7 +4366,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi
4390// The file/property is also available with vendored libc.4366// The file/property is also available with vendored libc.
4391fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 {4367fn readSdkVersionFromSettings(arena: Allocator, dir: []const u8) ![]const u8 {
4392 const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" });4368 const sdk_path = try fs.path.join(arena, &.{ dir, "SDKSettings.json" });
4393 const contents = try fs.cwd().readFileAlloc(arena, sdk_path, std.math.maxInt(u16));4369 const contents = try fs.cwd().readFileAlloc(sdk_path, arena, .limited(std.math.maxInt(u16)));
4394 const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{});4370 const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{});
4395 if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string;4371 if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string;
4396 return error.SdkVersionFailure;4372 return error.SdkVersionFailure;
...@@ -4406,7 +4382,7 @@ fn parseSdkVersion(raw: []const u8) ?std.SemanticVersion {...@@ -4406,7 +4382,7 @@ fn parseSdkVersion(raw: []const u8) ?std.SemanticVersion {
4406 };4382 };
44074383
4408 const parseNext = struct {4384 const parseNext = struct {
4409 fn parseNext(it: anytype) ?u16 {4385 fn parseNext(it: *std.mem.SplitIterator(u8, .any)) ?u16 {
4410 const nn = it.next() orelse return null;4386 const nn = it.next() orelse return null;
4411 return std.fmt.parseInt(u16, nn, 10) catch null;4387 return std.fmt.parseInt(u16, nn, 10) catch null;
4412 }4388 }
...@@ -4507,15 +4483,9 @@ pub const Ref = struct {...@@ -4507,15 +4483,9 @@ pub const Ref = struct {
4507 };4483 };
4508 }4484 }
45094485
4510 pub fn format(4486 pub fn format(ref: Ref, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
4511 ref: Ref,
4512 comptime unused_fmt_string: []const u8,
4513 options: std.fmt.FormatOptions,
4514 writer: anytype,
4515 ) !void {
4516 _ = unused_fmt_string;4487 _ = unused_fmt_string;
4517 _ = options;4488 try bw.print("%{d} in file({d})", .{ ref.index, ref.file });
4518 try writer.print("%{d} in file({d})", .{ ref.index, ref.file });
4519 }4489 }
4520};4490};
45214491
...@@ -5315,7 +5285,7 @@ fn createThunks(macho_file: *MachO, sect_id: u8) !void {...@@ -5315,7 +5285,7 @@ fn createThunks(macho_file: *MachO, sect_id: u8) !void {
5315 try scanThunkRelocs(thunk_index, gpa, atoms[start..i], macho_file);5285 try scanThunkRelocs(thunk_index, gpa, atoms[start..i], macho_file);
5316 thunk.value = advanceSection(header, thunk.size(), .@"4");5286 thunk.value = advanceSection(header, thunk.size(), .@"4");
53175287
5318 log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(macho_file) });5288 log.debug("thunk({d}) : {f}", .{ thunk_index, thunk.fmt(macho_file) });
5319 }5289 }
5320}5290}
53215291
src/link/MachO/Archive.zig+25-58
...@@ -29,7 +29,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File...@@ -29,7 +29,7 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
29 pos += @sizeOf(ar_hdr);29 pos += @sizeOf(ar_hdr);
3030
31 if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {31 if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {
32 return diags.failParse(path, "invalid header delimiter: expected '{s}', found '{s}'", .{32 return diags.failParse(path, "invalid header delimiter: expected '{f}', found '{f}'", .{
33 std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),33 std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
34 });34 });
35 }35 }
...@@ -71,53 +71,29 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File...@@ -71,53 +71,29 @@ pub fn unpack(self: *Archive, macho_file: *MachO, path: Path, handle_index: File
71 .mtime = hdr.date() catch 0,71 .mtime = hdr.date() catch 0,
72 };72 };
7373
74 log.debug("extracting object '{}' from archive '{}'", .{ object.path, path });74 log.debug("extracting object '{f}' from archive '{f}'", .{ object.path, path });
7575
76 try self.objects.append(gpa, object);76 try self.objects.append(gpa, object);
77 }77 }
78}78}
7979
80pub fn writeHeader(80pub fn writeHeader(
81 bw: *std.io.BufferedWriter,
81 object_name: []const u8,82 object_name: []const u8,
82 object_size: usize,83 object_size: usize,
83 format: Format,84 format: Format,
84 writer: anytype,85) anyerror!void {
85) !void {86 var hdr: ar_hdr = undefined;
86 var hdr: ar_hdr = .{87 @memset(mem.asBytes(&hdr), ' ');
87 .ar_name = undefined,88 inline for (@typeInfo(ar_hdr).@"struct".fields) |field| @field(hdr, field.name)[0] = '0';
88 .ar_date = undefined,
89 .ar_uid = undefined,
90 .ar_gid = undefined,
91 .ar_mode = undefined,
92 .ar_size = undefined,
93 .ar_fmag = undefined,
94 };
95 @memset(mem.asBytes(&hdr), 0x20);
96 inline for (@typeInfo(ar_hdr).@"struct".fields) |field| {
97 var stream = std.io.fixedBufferStream(&@field(hdr, field.name));
98 stream.writer().print("0", .{}) catch unreachable;
99 }
100 @memcpy(&hdr.ar_fmag, ARFMAG);89 @memcpy(&hdr.ar_fmag, ARFMAG);
101
102 const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format));90 const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format));
91 _ = std.fmt.bufPrint(&hdr.ar_name, "#1/{d}", .{object_name_len}) catch unreachable;
103 const total_object_size = object_size + object_name_len;92 const total_object_size = object_size + object_name_len;
10493 _ = std.fmt.bufPrint(&hdr.ar_size, "{d}", .{total_object_size}) catch unreachable;
105 {94 try bw.writeStruct(hdr);
106 var stream = std.io.fixedBufferStream(&hdr.ar_name);95 try bw.writeAll(object_name);
107 stream.writer().print("#1/{d}", .{object_name_len}) catch unreachable;96 try bw.splatByteAll(0, object_name_len - object_name.len);
108 }
109 {
110 var stream = std.io.fixedBufferStream(&hdr.ar_size);
111 stream.writer().print("{d}", .{total_object_size}) catch unreachable;
112 }
113
114 try writer.writeAll(mem.asBytes(&hdr));
115 try writer.print("{s}\x00", .{object_name});
116
117 const padding = object_name_len - object_name.len - 1;
118 if (padding > 0) {
119 try writer.writeByteNTimes(0, padding);
120 }
121}97}
12298
123// Archive files start with the ARMAG identifying string. Then follows a99// Archive files start with the ARMAG identifying string. Then follows a
...@@ -201,12 +177,12 @@ pub const ArSymtab = struct {...@@ -201,12 +177,12 @@ pub const ArSymtab = struct {
201 return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);177 return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);
202 }178 }
203179
204 pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: anytype) !void {180 pub fn write(ar: ArSymtab, bw: *std.io.BufferedWriter, format: Format, macho_file: *MachO) anyerror!void {
205 const ptr_width = ptrWidth(format);181 const ptr_width = ptrWidth(format);
206 // Header182 // Header
207 try writeHeader(SYMDEF, ar.size(format), format, writer);183 try writeHeader(bw, SYMDEF, ar.size(format), format);
208 // Symtab size184 // Symtab size
209 try writeInt(format, ar.entries.items.len * 2 * ptr_width, writer);185 try writeInt(bw, format, ar.entries.items.len * 2 * ptr_width);
210 // Symtab entries186 // Symtab entries
211 for (ar.entries.items) |entry| {187 for (ar.entries.items) |entry| {
212 const file_off = switch (macho_file.getFile(entry.file).?) {188 const file_off = switch (macho_file.getFile(entry.file).?) {
...@@ -215,19 +191,16 @@ pub const ArSymtab = struct {...@@ -215,19 +191,16 @@ pub const ArSymtab = struct {
215 else => unreachable,191 else => unreachable,
216 };192 };
217 // Name offset193 // Name offset
218 try writeInt(format, entry.off, writer);194 try writeInt(bw, format, entry.off);
219 // File offset195 // File offset
220 try writeInt(format, file_off, writer);196 try writeInt(bw, format, file_off);
221 }197 }
222 // Strtab size198 // Strtab size
223 const strtab_size = mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);199 const strtab_size = mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);
224 const padding = strtab_size - ar.strtab.buffer.items.len;200 try writeInt(bw, format, strtab_size);
225 try writeInt(format, strtab_size, writer);
226 // Strtab201 // Strtab
227 try writer.writeAll(ar.strtab.buffer.items);202 try bw.writeAll(ar.strtab.buffer.items);
228 if (padding > 0) {203 try bw.splatByteAll(0, strtab_size - ar.strtab.buffer.items.len);
229 try writer.writeByteNTimes(0, padding);
230 }
231 }204 }
232205
233 const FormatContext = struct {206 const FormatContext = struct {
...@@ -239,20 +212,14 @@ pub const ArSymtab = struct {...@@ -239,20 +212,14 @@ pub const ArSymtab = struct {
239 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };212 return .{ .data = .{ .ar = ar, .macho_file = macho_file } };
240 }213 }
241214
242 fn format2(215 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
243 ctx: FormatContext,
244 comptime unused_fmt_string: []const u8,
245 options: std.fmt.FormatOptions,
246 writer: anytype,
247 ) !void {
248 _ = unused_fmt_string;216 _ = unused_fmt_string;
249 _ = options;
250 const ar = ctx.ar;217 const ar = ctx.ar;
251 const macho_file = ctx.macho_file;218 const macho_file = ctx.macho_file;
252 for (ar.entries.items, 0..) |entry, i| {219 for (ar.entries.items, 0..) |entry, i| {
253 const name = ar.strtab.getAssumeExists(entry.off);220 const name = ar.strtab.getAssumeExists(entry.off);
254 const file = macho_file.getFile(entry.file).?;221 const file = macho_file.getFile(entry.file).?;
255 try writer.print(" {d}: {s} in file({d})({})\n", .{ i, name, entry.file, file.fmtPath() });222 try bw.print(" {d}: {s} in file({d})({f})\n", .{ i, name, entry.file, file.fmtPath() });
256 }223 }
257 }224 }
258225
...@@ -282,10 +249,10 @@ pub fn ptrWidth(format: Format) usize {...@@ -282,10 +249,10 @@ pub fn ptrWidth(format: Format) usize {
282 };249 };
283}250}
284251
285pub fn writeInt(format: Format, value: u64, writer: anytype) !void {252pub fn writeInt(bw: *std.io.BufferedWriter, format: Format, value: u64) anyerror!void {
286 switch (format) {253 switch (format) {
287 .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little),254 .p32 => try bw.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little),
288 .p64 => try writer.writeInt(u64, value, .little),255 .p64 => try bw.writeInt(u64, value, .little),
289 }256 }
290}257}
291258
src/link/MachO/Atom.zig+59-67
...@@ -580,8 +580,10 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -580,8 +580,10 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
580580
581 relocs_log.debug("{x}: {s}", .{ self.value, name });581 relocs_log.debug("{x}: {s}", .{ self.value, name });
582582
583 var bw: std.io.BufferedWriter = undefined;
584 bw.initFixed(buffer);
585
583 var has_error = false;586 var has_error = false;
584 var stream = std.io.fixedBufferStream(buffer);
585 var i: usize = 0;587 var i: usize = 0;
586 while (i < relocs.len) : (i += 1) {588 while (i < relocs.len) : (i += 1) {
587 const rel = relocs[i];589 const rel = relocs[i];
...@@ -592,30 +594,28 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -592,30 +594,28 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
592 if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;594 if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;
593 }595 }
594596
595 try stream.seekTo(rel_offset);597 bw.end = std.math.cast(usize, rel_offset) orelse return error.Overflow;
596 self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| {598 self.resolveRelocInner(rel, subtractor, buffer, macho_file, &bw) catch |err| switch (@as(ResolveError, @errorCast(err))) {
597 switch (err) {599 error.RelaxFail => {
598 error.RelaxFail => {600 const target = switch (rel.tag) {
599 const target = switch (rel.tag) {601 .@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file),
600 .@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file),602 .local => rel.getTargetAtom(self, macho_file).getName(macho_file),
601 .local => rel.getTargetAtom(self, macho_file).getName(macho_file),603 };
602 };604 try macho_file.reportParseError2(
603 try macho_file.reportParseError2(605 file.getIndex(),
604 file.getIndex(),606 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {f}, target {s}",
605 "{s}: 0x{x}: 0x{x}: failed to relax relocation: type {}, target {s}",607 .{
606 .{608 name,
607 name,609 self.getAddress(macho_file),
608 self.getAddress(macho_file),610 rel.offset,
609 rel.offset,611 rel.fmtPretty(macho_file.getTarget().cpu.arch),
610 rel.fmtPretty(macho_file.getTarget().cpu.arch),612 target,
611 target,613 },
612 },614 );
613 );615 has_error = true;
614 has_error = true;616 },
615 },617 error.RelaxFailUnexpectedInstruction => has_error = true,
616 error.RelaxFailUnexpectedInstruction => has_error = true,618 else => |e| return e,
617 else => |e| return e,
618 }
619 };619 };
620 }620 }
621621
...@@ -638,8 +638,8 @@ fn resolveRelocInner(...@@ -638,8 +638,8 @@ fn resolveRelocInner(
638 subtractor: ?Relocation,638 subtractor: ?Relocation,
639 code: []u8,639 code: []u8,
640 macho_file: *MachO,640 macho_file: *MachO,
641 writer: anytype,641 bw: *std.io.BufferedWriter,
642) ResolveError!void {642) anyerror!void {
643 const t = &macho_file.base.comp.root_mod.resolved_target.result;643 const t = &macho_file.base.comp.root_mod.resolved_target.result;
644 const cpu_arch = t.cpu.arch;644 const cpu_arch = t.cpu.arch;
645 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;645 const rel_offset = math.cast(usize, rel.offset - self.off) orelse return error.Overflow;
...@@ -653,7 +653,7 @@ fn resolveRelocInner(...@@ -653,7 +653,7 @@ fn resolveRelocInner(
653 const divExact = struct {653 const divExact = struct {
654 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {654 fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 {
655 return math.divExact(u12, num, den) catch {655 return math.divExact(u12, num, den) catch {
656 try ctx.reportParseError2(atom.getFile(ctx).getIndex(), "{s}: unexpected remainder when resolving {s} at offset 0x{x}", .{656 try ctx.reportParseError2(atom.getFile(ctx).getIndex(), "{s}: unexpected remainder when resolving {f} at offset 0x{x}", .{
657 atom.getName(ctx),657 atom.getName(ctx),
658 r.fmtPretty(ctx.getTarget().cpu.arch),658 r.fmtPretty(ctx.getTarget().cpu.arch),
659 r.offset,659 r.offset,
...@@ -664,14 +664,14 @@ fn resolveRelocInner(...@@ -664,14 +664,14 @@ fn resolveRelocInner(
664 }.divExact;664 }.divExact;
665665
666 switch (rel.tag) {666 switch (rel.tag) {
667 .local => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] atom({d})", .{667 .local => relocs_log.debug(" {x}<+{d}>: {f}: [=> {x}] atom({d})", .{
668 P,668 P,
669 rel_offset,669 rel_offset,
670 rel.fmtPretty(cpu_arch),670 rel.fmtPretty(cpu_arch),
671 S + A - SUB,671 S + A - SUB,
672 rel.getTargetAtom(self, macho_file).atom_index,672 rel.getTargetAtom(self, macho_file).atom_index,
673 }),673 }),
674 .@"extern" => relocs_log.debug(" {x}<+{d}>: {}: [=> {x}] G({x}) ({s})", .{674 .@"extern" => relocs_log.debug(" {x}<+{d}>: {f}: [=> {x}] G({x}) ({s})", .{
675 P,675 P,
676 rel_offset,676 rel_offset,
677 rel.fmtPretty(cpu_arch),677 rel.fmtPretty(cpu_arch),
...@@ -690,14 +690,14 @@ fn resolveRelocInner(...@@ -690,14 +690,14 @@ fn resolveRelocInner(
690 if (rel.tag == .@"extern") {690 if (rel.tag == .@"extern") {
691 const sym = rel.getTargetSymbol(self, macho_file);691 const sym = rel.getTargetSymbol(self, macho_file);
692 if (sym.isTlvInit(macho_file)) {692 if (sym.isTlvInit(macho_file)) {
693 try writer.writeInt(u64, @intCast(S - TLS), .little);693 try bw.writeInt(u64, @intCast(S - TLS), .little);
694 return;694 return;
695 }695 }
696 if (sym.flags.import) return;696 if (sym.flags.import) return;
697 }697 }
698 try writer.writeInt(u64, @bitCast(S + A - SUB), .little);698 try bw.writeInt(u64, @bitCast(S + A - SUB), .little);
699 } else if (rel.meta.length == 2) {699 } else if (rel.meta.length == 2) {
700 try writer.writeInt(u32, @bitCast(@as(i32, @truncate(S + A - SUB))), .little);700 try bw.writeInt(u32, @bitCast(@as(i32, @truncate(S + A - SUB))), .little);
701 } else unreachable;701 } else unreachable;
702 },702 },
703703
...@@ -705,7 +705,7 @@ fn resolveRelocInner(...@@ -705,7 +705,7 @@ fn resolveRelocInner(
705 assert(rel.tag == .@"extern");705 assert(rel.tag == .@"extern");
706 assert(rel.meta.length == 2);706 assert(rel.meta.length == 2);
707 assert(rel.meta.pcrel);707 assert(rel.meta.pcrel);
708 try writer.writeInt(i32, @intCast(G + A - P), .little);708 try bw.writeInt(i32, @intCast(G + A - P), .little);
709 },709 },
710710
711 .branch => {711 .branch => {
...@@ -714,7 +714,7 @@ fn resolveRelocInner(...@@ -714,7 +714,7 @@ fn resolveRelocInner(
714 assert(rel.tag == .@"extern");714 assert(rel.tag == .@"extern");
715715
716 switch (cpu_arch) {716 switch (cpu_arch) {
717 .x86_64 => try writer.writeInt(i32, @intCast(S + A - P), .little),717 .x86_64 => try bw.writeInt(i32, @intCast(S + A - P), .little),
718 .aarch64 => {718 .aarch64 => {
719 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {719 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
720 const thunk = self.getThunk(macho_file);720 const thunk = self.getThunk(macho_file);
...@@ -732,10 +732,10 @@ fn resolveRelocInner(...@@ -732,10 +732,10 @@ fn resolveRelocInner(
732 assert(rel.meta.length == 2);732 assert(rel.meta.length == 2);
733 assert(rel.meta.pcrel);733 assert(rel.meta.pcrel);
734 if (rel.getTargetSymbol(self, macho_file).getSectionFlags().has_got) {734 if (rel.getTargetSymbol(self, macho_file).getSectionFlags().has_got) {
735 try writer.writeInt(i32, @intCast(G + A - P), .little);735 try bw.writeInt(i32, @intCast(G + A - P), .little);
736 } else {736 } else {
737 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);737 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);
738 try writer.writeInt(i32, @intCast(S + A - P), .little);738 try bw.writeInt(i32, @intCast(S + A - P), .little);
739 }739 }
740 },740 },
741741
...@@ -746,17 +746,17 @@ fn resolveRelocInner(...@@ -746,17 +746,17 @@ fn resolveRelocInner(
746 const sym = rel.getTargetSymbol(self, macho_file);746 const sym = rel.getTargetSymbol(self, macho_file);
747 if (sym.getSectionFlags().tlv_ptr) {747 if (sym.getSectionFlags().tlv_ptr) {
748 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));748 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
749 try writer.writeInt(i32, @intCast(S_ + A - P), .little);749 try bw.writeInt(i32, @intCast(S_ + A - P), .little);
750 } else {750 } else {
751 try x86_64.relaxTlv(code[rel_offset - 3 ..], t);751 try x86_64.relaxTlv(code[rel_offset - 3 ..], t);
752 try writer.writeInt(i32, @intCast(S + A - P), .little);752 try bw.writeInt(i32, @intCast(S + A - P), .little);
753 }753 }
754 },754 },
755755
756 .signed, .signed1, .signed2, .signed4 => {756 .signed, .signed1, .signed2, .signed4 => {
757 assert(rel.meta.length == 2);757 assert(rel.meta.length == 2);
758 assert(rel.meta.pcrel);758 assert(rel.meta.pcrel);
759 try writer.writeInt(i32, @intCast(S + A - P), .little);759 try bw.writeInt(i32, @intCast(S + A - P), .little);
760 },760 },
761761
762 .page,762 .page,
...@@ -808,7 +808,7 @@ fn resolveRelocInner(...@@ -808,7 +808,7 @@ fn resolveRelocInner(
808 2 => try divExact(self, rel, @truncate(target), 4, macho_file),808 2 => try divExact(self, rel, @truncate(target), 4, macho_file),
809 3 => try divExact(self, rel, @truncate(target), 8, macho_file),809 3 => try divExact(self, rel, @truncate(target), 8, macho_file),
810 };810 };
811 try writer.writeInt(u32, inst.toU32(), .little);811 try bw.writeInt(u32, inst.toU32(), .little);
812 }812 }
813 },813 },
814814
...@@ -886,7 +886,7 @@ fn resolveRelocInner(...@@ -886,7 +886,7 @@ fn resolveRelocInner(
886 .sf = @as(u1, @truncate(reg_info.size)),886 .sf = @as(u1, @truncate(reg_info.size)),
887 },887 },
888 };888 };
889 try writer.writeInt(u32, inst.toU32(), .little);889 try bw.writeInt(u32, inst.toU32(), .little);
890 },890 },
891 }891 }
892}892}
...@@ -900,19 +900,19 @@ const x86_64 = struct {...@@ -900,19 +900,19 @@ const x86_64 = struct {
900 switch (old_inst.encoding.mnemonic) {900 switch (old_inst.encoding.mnemonic) {
901 .mov => {901 .mov => {
902 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;902 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;
903 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });903 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
904 encode(&.{inst}, code) catch return error.RelaxFail;904 encode(&.{inst}, code) catch return error.RelaxFail;
905 },905 },
906 else => |x| {906 else => |x| {
907 var err = try diags.addErrorWithNotes(2);907 var err = try diags.addErrorWithNotes(2);
908 try err.addMsg("{s}: 0x{x}: 0x{x}: failed to relax relocation of type {}", .{908 try err.addMsg("{s}: 0x{x}: 0x{x}: failed to relax relocation of type {f}", .{
909 self.getName(macho_file),909 self.getName(macho_file),
910 self.getAddress(macho_file),910 self.getAddress(macho_file),
911 rel.offset,911 rel.offset,
912 rel.fmtPretty(.x86_64),912 rel.fmtPretty(.x86_64),
913 });913 });
914 err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});914 err.addNote("expected .mov instruction but found .{s}", .{@tagName(x)});
915 err.addNote("while parsing {}", .{self.getFile(macho_file).fmtPath()});915 err.addNote("while parsing {f}", .{self.getFile(macho_file).fmtPath()});
916 return error.RelaxFailUnexpectedInstruction;916 return error.RelaxFailUnexpectedInstruction;
917 },917 },
918 }918 }
...@@ -924,7 +924,7 @@ const x86_64 = struct {...@@ -924,7 +924,7 @@ const x86_64 = struct {
924 switch (old_inst.encoding.mnemonic) {924 switch (old_inst.encoding.mnemonic) {
925 .mov => {925 .mov => {
926 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;926 const inst = Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t) catch return error.RelaxFail;
927 relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });927 relocs_log.debug(" relaxing {f} => {f}", .{ old_inst.encoding, inst.encoding });
928 encode(&.{inst}, code) catch return error.RelaxFail;928 encode(&.{inst}, code) catch return error.RelaxFail;
929 },929 },
930 else => return error.RelaxFail,930 else => return error.RelaxFail,
...@@ -938,11 +938,9 @@ const x86_64 = struct {...@@ -938,11 +938,9 @@ const x86_64 = struct {
938 }938 }
939939
940 fn encode(insts: []const Instruction, code: []u8) !void {940 fn encode(insts: []const Instruction, code: []u8) !void {
941 var stream = std.io.fixedBufferStream(code);941 var bw: std.io.BufferedWriter = undefined;
942 const writer = stream.writer();942 bw.initFixed(code);
943 for (insts) |inst| {943 for (insts) |inst| try inst.encode(&bw, .{});
944 try inst.encode(writer, .{});
945 }
946 }944 }
947945
948 const bits = @import("../../arch/x86_64/bits.zig");946 const bits = @import("../../arch/x86_64/bits.zig");
...@@ -1003,7 +1001,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1003,7 +1001,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1003 }1001 }
10041002
1005 switch (rel.tag) {1003 switch (rel.tag) {
1006 .local => relocs_log.debug(" {}: [{x} => {d}({s},{s})] + {x}", .{1004 .local => relocs_log.debug(" {f}: [{x} => {d}({s},{s})] + {x}", .{
1007 rel.fmtPretty(cpu_arch),1005 rel.fmtPretty(cpu_arch),
1008 r_address,1006 r_address,
1009 r_symbolnum,1007 r_symbolnum,
...@@ -1011,7 +1009,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r...@@ -1011,7 +1009,7 @@ pub fn writeRelocs(self: Atom, macho_file: *MachO, code: []u8, buffer: []macho.r
1011 macho_file.sections.items(.header)[r_symbolnum - 1].sectName(),1009 macho_file.sections.items(.header)[r_symbolnum - 1].sectName(),
1012 addend,1010 addend,
1013 }),1011 }),
1014 .@"extern" => relocs_log.debug(" {}: [{x} => {d}({s})] + {x}", .{1012 .@"extern" => relocs_log.debug(" {f}: [{x} => {d}({s})] + {x}", .{
1015 rel.fmtPretty(cpu_arch),1013 rel.fmtPretty(cpu_arch),
1016 r_address,1014 r_address,
1017 r_symbolnum,1015 r_symbolnum,
...@@ -1142,33 +1140,27 @@ const FormatContext = struct {...@@ -1142,33 +1140,27 @@ const FormatContext = struct {
1142 macho_file: *MachO,1140 macho_file: *MachO,
1143};1141};
11441142
1145fn format2(1143fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1146 ctx: FormatContext,
1147 comptime unused_fmt_string: []const u8,
1148 options: std.fmt.FormatOptions,
1149 writer: anytype,
1150) !void {
1151 _ = options;
1152 _ = unused_fmt_string;1144 _ = unused_fmt_string;
1153 const atom = ctx.atom;1145 const atom = ctx.atom;
1154 const macho_file = ctx.macho_file;1146 const macho_file = ctx.macho_file;
1155 const file = atom.getFile(macho_file);1147 const file = atom.getFile(macho_file);
1156 try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{1148 try bw.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : nreloc({d}) : thunk({d})", .{
1157 atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),1149 atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
1158 atom.out_n_sect, atom.alignment, atom.size,1150 atom.out_n_sect, atom.alignment, atom.size,
1159 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,1151 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,
1160 });1152 });
1161 if (!atom.isAlive()) try writer.writeAll(" : [*]");1153 if (!atom.isAlive()) try bw.writeAll(" : [*]");
1162 if (atom.getUnwindRecords(macho_file).len > 0) {1154 if (atom.getUnwindRecords(macho_file).len > 0) {
1163 try writer.writeAll(" : unwind{ ");1155 try bw.writeAll(" : unwind{ ");
1164 const extra = atom.getExtra(macho_file);1156 const extra = atom.getExtra(macho_file);
1165 for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| {1157 for (atom.getUnwindRecords(macho_file), extra.unwind_index..) |index, i| {
1166 const rec = file.object.getUnwindRecord(index);1158 const rec = file.object.getUnwindRecord(index);
1167 try writer.print("{d}", .{index});1159 try bw.print("{d}", .{index});
1168 if (!rec.alive) try writer.writeAll("([*])");1160 if (!rec.alive) try bw.writeAll("([*])");
1169 if (i < extra.unwind_index + extra.unwind_count - 1) try writer.writeAll(", ");1161 if (i < extra.unwind_index + extra.unwind_count - 1) try bw.writeAll(", ");
1170 }1162 }
1171 try writer.writeAll(" }");1163 try bw.writeAll(" }");
1172 }1164 }
1173}1165}
11741166
src/link/MachO/CodeSignature.zig+13-9
...@@ -247,7 +247,7 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void {...@@ -247,7 +247,7 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void {
247pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void {247pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void {
248 const file = try fs.cwd().openFile(path, .{});248 const file = try fs.cwd().openFile(path, .{});
249 defer file.close();249 defer file.close();
250 const inner = try file.readToEndAlloc(allocator, std.math.maxInt(u32));250 const inner = try file.readToEndAlloc(allocator, .unlimited);
251 self.entitlements = .{ .inner = inner };251 self.entitlements = .{ .inner = inner };
252}252}
253253
...@@ -304,10 +304,12 @@ pub fn writeAdhocSignature(...@@ -304,10 +304,12 @@ pub fn writeAdhocSignature(
304 var hash: [hash_size]u8 = undefined;304 var hash: [hash_size]u8 = undefined;
305305
306 if (self.requirements) |*req| {306 if (self.requirements) |*req| {
307 var buf = std.ArrayList(u8).init(allocator);307 var aw: std.io.AllocatingWriter = undefined;
308 defer buf.deinit();308 aw.init(allocator);
309 try req.write(buf.writer());309 defer aw.deinit();
310 Sha256.hash(buf.items, &hash, .{});310
311 try req.write(&aw.buffered_writer);
312 Sha256.hash(aw.getWritten(), &hash, .{});
311 self.code_directory.addSpecialHash(req.slotType(), hash);313 self.code_directory.addSpecialHash(req.slotType(), hash);
312314
313 try blobs.append(.{ .requirements = req });315 try blobs.append(.{ .requirements = req });
...@@ -316,10 +318,12 @@ pub fn writeAdhocSignature(...@@ -316,10 +318,12 @@ pub fn writeAdhocSignature(
316 }318 }
317319
318 if (self.entitlements) |*ents| {320 if (self.entitlements) |*ents| {
319 var buf = std.ArrayList(u8).init(allocator);321 var aw: std.io.AllocatingWriter = undefined;
320 defer buf.deinit();322 aw.init(allocator);
321 try ents.write(buf.writer());323 defer aw.deinit();
322 Sha256.hash(buf.items, &hash, .{});324
325 try ents.write(&aw.buffered_writer);
326 Sha256.hash(aw.getWritten(), &hash, .{});
323 self.code_directory.addSpecialHash(ents.slotType(), hash);327 self.code_directory.addSpecialHash(ents.slotType(), hash);
324328
325 try blobs.append(.{ .entitlements = ents });329 try blobs.append(.{ .entitlements = ents });
src/link/MachO/DebugSymbols.zig+12-16
...@@ -269,18 +269,15 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {...@@ -269,18 +269,15 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void {
269269
270fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {270fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } {
271 const gpa = self.allocator;271 const gpa = self.allocator;
272 const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self);272 var bw: std.io.BufferedWriter = undefined;
273 const buffer = try gpa.alloc(u8, needed_size);273 bw.initFixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeDsym(macho_file, self)));
274 defer gpa.free(buffer);274 defer gpa.free(bw.buffer);
275
276 var stream = std.io.fixedBufferStream(buffer);
277 const writer = stream.writer();
278275
279 var ncmds: usize = 0;276 var ncmds: usize = 0;
280277
281 // UUID comes first presumably to speed up lookup by the consumer like lldb.278 // UUID comes first presumably to speed up lookup by the consumer like lldb.
282 @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid);279 @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid);
283 try writer.writeStruct(self.uuid_cmd);280 try bw.writeStruct(self.uuid_cmd);
284 ncmds += 1;281 ncmds += 1;
285282
286 // Segment and section load commands283 // Segment and section load commands
...@@ -293,11 +290,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u...@@ -293,11 +290,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u
293 var out_seg = seg;290 var out_seg = seg;
294 out_seg.fileoff = 0;291 out_seg.fileoff = 0;
295 out_seg.filesize = 0;292 out_seg.filesize = 0;
296 try writer.writeStruct(out_seg);293 try bw.writeStruct(out_seg);
297 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {294 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
298 var out_header = header;295 var out_header = header;
299 out_header.offset = 0;296 out_header.offset = 0;
300 try writer.writeStruct(out_header);297 try bw.writeStruct(out_header);
301 }298 }
302 sect_id += seg.nsects;299 sect_id += seg.nsects;
303 }300 }
...@@ -306,23 +303,22 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u...@@ -306,23 +303,22 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u
306 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.303 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
307 sect_id = 0;304 sect_id = 0;
308 for (self.segments.items) |seg| {305 for (self.segments.items) |seg| {
309 try writer.writeStruct(seg);306 try bw.writeStruct(seg);
310 for (self.sections.items[sect_id..][0..seg.nsects]) |header| {307 for (self.sections.items[sect_id..][0..seg.nsects]) |header| {
311 try writer.writeStruct(header);308 try bw.writeStruct(header);
312 }309 }
313 sect_id += seg.nsects;310 sect_id += seg.nsects;
314 }311 }
315 ncmds += self.segments.items.len;312 ncmds += self.segments.items.len;
316 }313 }
317314
318 try writer.writeStruct(self.symtab_cmd);315 try bw.writeStruct(self.symtab_cmd);
319 ncmds += 1;316 ncmds += 1;
320317
321 assert(stream.pos == needed_size);318 assert(bw.end == bw.buffer.len);
322319 try self.file.?.pwriteAll(bw.buffer, @sizeOf(macho.mach_header_64));
323 try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
324320
325 return .{ ncmds, buffer.len };321 return .{ ncmds, bw.end };
326}322}
327323
328fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {324fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
src/link/MachO/Dwarf.zig+20-30
...@@ -81,7 +81,7 @@ pub const InfoReader = struct {...@@ -81,7 +81,7 @@ pub const InfoReader = struct {
81 .dwarf64 => 12,81 .dwarf64 => 12,
82 } + cuh_length;82 } + cuh_length;
83 while (p.pos < end_pos) {83 while (p.pos < end_pos) {
84 const di_code = try p.readUleb128(u64);84 const di_code = try p.readLeb128(u64);
85 if (di_code == 0) return error.UnexpectedEndOfFile;85 if (di_code == 0) return error.UnexpectedEndOfFile;
86 if (di_code == code) return;86 if (di_code == code) return;
8787
...@@ -174,14 +174,14 @@ pub const InfoReader = struct {...@@ -174,14 +174,14 @@ pub const InfoReader = struct {
174 dw.FORM.block1 => try p.readByte(),174 dw.FORM.block1 => try p.readByte(),
175 dw.FORM.block2 => try p.readInt(u16),175 dw.FORM.block2 => try p.readInt(u16),
176 dw.FORM.block4 => try p.readInt(u32),176 dw.FORM.block4 => try p.readInt(u32),
177 dw.FORM.block => try p.readUleb128(u64),177 dw.FORM.block => try p.readLeb128(u64),
178 else => unreachable,178 else => unreachable,
179 };179 };
180 return p.readNBytes(len);180 return p.readNBytes(len);
181 }181 }
182182
183 pub fn readExprLoc(p: *InfoReader) ![]const u8 {183 pub fn readExprLoc(p: *InfoReader) ![]const u8 {
184 const len: u64 = try p.readUleb128(u64);184 const len: u64 = try p.readLeb128(u64);
185 return p.readNBytes(len);185 return p.readNBytes(len);
186 }186 }
187187
...@@ -191,8 +191,8 @@ pub const InfoReader = struct {...@@ -191,8 +191,8 @@ pub const InfoReader = struct {
191 dw.FORM.data2, dw.FORM.ref2 => try p.readInt(u16),191 dw.FORM.data2, dw.FORM.ref2 => try p.readInt(u16),
192 dw.FORM.data4, dw.FORM.ref4 => try p.readInt(u32),192 dw.FORM.data4, dw.FORM.ref4 => try p.readInt(u32),
193 dw.FORM.data8, dw.FORM.ref8, dw.FORM.ref_sig8 => try p.readInt(u64),193 dw.FORM.data8, dw.FORM.ref8, dw.FORM.ref_sig8 => try p.readInt(u64),
194 dw.FORM.udata, dw.FORM.ref_udata => try p.readUleb128(u64),194 dw.FORM.udata, dw.FORM.ref_udata => try p.readLeb128(u64),
195 dw.FORM.sdata => @bitCast(try p.readIleb128(i64)),195 dw.FORM.sdata => @bitCast(try p.readLeb128(i64)),
196 else => return error.UnhandledConstantForm,196 else => return error.UnhandledConstantForm,
197 };197 };
198 }198 }
...@@ -203,7 +203,7 @@ pub const InfoReader = struct {...@@ -203,7 +203,7 @@ pub const InfoReader = struct {
203 dw.FORM.strx2, dw.FORM.addrx2 => try p.readInt(u16),203 dw.FORM.strx2, dw.FORM.addrx2 => try p.readInt(u16),
204 dw.FORM.strx3, dw.FORM.addrx3 => error.UnhandledForm,204 dw.FORM.strx3, dw.FORM.addrx3 => error.UnhandledForm,
205 dw.FORM.strx4, dw.FORM.addrx4 => try p.readInt(u32),205 dw.FORM.strx4, dw.FORM.addrx4 => try p.readInt(u32),
206 dw.FORM.strx, dw.FORM.addrx => try p.readUleb128(u64),206 dw.FORM.strx, dw.FORM.addrx => try p.readLeb128(u64),
207 else => return error.UnhandledIndexForm,207 else => return error.UnhandledIndexForm,
208 };208 };
209 }209 }
...@@ -272,20 +272,11 @@ pub const InfoReader = struct {...@@ -272,20 +272,11 @@ pub const InfoReader = struct {
272 };272 };
273 }273 }
274274
275 pub fn readUleb128(p: *InfoReader, comptime Type: type) !Type {275 pub fn readLeb128(p: *InfoReader, comptime Type: type) !Type {
276 var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]);276 var br: std.io.BufferedReader = undefined;
277 var creader = std.io.countingReader(stream.reader());277 br.initFixed(p.bytes()[p.pos..]);
278 const value: Type = try leb.readUleb128(Type, creader.reader());278 defer p.pos += br.seek;
279 p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow;279 return br.takeLeb128(Type);
280 return value;
281 }
282
283 pub fn readIleb128(p: *InfoReader, comptime Type: type) !Type {
284 var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]);
285 var creader = std.io.countingReader(stream.reader());
286 const value: Type = try leb.readIleb128(Type, creader.reader());
287 p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow;
288 return value;
289 }280 }
290281
291 pub fn seekTo(p: *InfoReader, off: u64) !void {282 pub fn seekTo(p: *InfoReader, off: u64) !void {
...@@ -307,10 +298,10 @@ pub const AbbrevReader = struct {...@@ -307,10 +298,10 @@ pub const AbbrevReader = struct {
307298
308 pub fn readDecl(p: *AbbrevReader) !?AbbrevDecl {299 pub fn readDecl(p: *AbbrevReader) !?AbbrevDecl {
309 const pos = p.pos;300 const pos = p.pos;
310 const code = try p.readUleb128(Code);301 const code = try p.readLeb128(Code);
311 if (code == 0) return null;302 if (code == 0) return null;
312303
313 const tag = try p.readUleb128(Tag);304 const tag = try p.readLeb128(Tag);
314 const has_children = (try p.readByte()) > 0;305 const has_children = (try p.readByte()) > 0;
315 return .{306 return .{
316 .code = code,307 .code = code,
...@@ -323,8 +314,8 @@ pub const AbbrevReader = struct {...@@ -323,8 +314,8 @@ pub const AbbrevReader = struct {
323314
324 pub fn readAttr(p: *AbbrevReader) !?AbbrevAttr {315 pub fn readAttr(p: *AbbrevReader) !?AbbrevAttr {
325 const pos = p.pos;316 const pos = p.pos;
326 const at = try p.readUleb128(At);317 const at = try p.readLeb128(At);
327 const form = try p.readUleb128(Form);318 const form = try p.readLeb128(Form);
328 return if (at == 0 and form == 0) null else .{319 return if (at == 0 and form == 0) null else .{
329 .at = at,320 .at = at,
330 .form = form,321 .form = form,
...@@ -339,12 +330,11 @@ pub const AbbrevReader = struct {...@@ -339,12 +330,11 @@ pub const AbbrevReader = struct {
339 return p.bytes()[p.pos];330 return p.bytes()[p.pos];
340 }331 }
341332
342 pub fn readUleb128(p: *AbbrevReader, comptime Type: type) !Type {333 pub fn readLeb128(p: *AbbrevReader, comptime Type: type) !Type {
343 var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]);334 var br: std.io.BufferedReader = undefined;
344 var creader = std.io.countingReader(stream.reader());335 br.initFixed(p.bytes()[p.pos..]);
345 const value: Type = try leb.readUleb128(Type, creader.reader());336 defer p.pos += br.seek;
346 p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow;337 return br.takeLeb128(Type);
347 return value;
348 }338 }
349339
350 pub fn seekTo(p: *AbbrevReader, off: u64) !void {340 pub fn seekTo(p: *AbbrevReader, off: u64) !void {
src/link/MachO/Dylib.zig+26-72
...@@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -61,7 +61,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
61 const file = macho_file.getFileHandle(self.file_handle);61 const file = macho_file.getFileHandle(self.file_handle);
62 const offset = self.offset;62 const offset = self.offset;
6363
64 log.debug("parsing dylib from binary: {}", .{@as(Path, self.path)});64 log.debug("parsing dylib from binary: {f}", .{@as(Path, self.path)});
6565
66 var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined;66 var header_buffer: [@sizeOf(macho.mach_header_64)]u8 = undefined;
67 {67 {
...@@ -140,7 +140,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -140,7 +140,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
140140
141 if (self.platform) |platform| {141 if (self.platform) |platform| {
142 if (!macho_file.platform.eqlTarget(platform)) {142 if (!macho_file.platform.eqlTarget(platform)) {
143 try macho_file.reportParseError2(self.index, "invalid platform: {}", .{143 try macho_file.reportParseError2(self.index, "invalid platform: {f}", .{
144 platform.fmtTarget(macho_file.getTarget().cpu.arch),144 platform.fmtTarget(macho_file.getTarget().cpu.arch),
145 });145 });
146 return error.InvalidTarget;146 return error.InvalidTarget;
...@@ -148,7 +148,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -148,7 +148,7 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
148 // TODO: this can cause the CI to fail so I'm commenting this check out so that148 // TODO: this can cause the CI to fail so I'm commenting this check out so that
149 // I can work out the rest of the changes first149 // I can work out the rest of the changes first
150 // if (macho_file.platform.version.order(platform.version) == .lt) {150 // if (macho_file.platform.version.order(platform.version) == .lt) {
151 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {}: {} < {}", .{151 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {f}: {f} < {f}", .{
152 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),152 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),
153 // macho_file.platform.version,153 // macho_file.platform.version,
154 // platform.version,154 // platform.version,
...@@ -158,46 +158,6 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {...@@ -158,46 +158,6 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void {
158 }158 }
159}159}
160160
161const TrieIterator = struct {
162 data: []const u8,
163 pos: usize = 0,
164
165 fn getStream(it: *TrieIterator) std.io.FixedBufferStream([]const u8) {
166 return std.io.fixedBufferStream(it.data[it.pos..]);
167 }
168
169 fn readUleb128(it: *TrieIterator) !u64 {
170 var stream = it.getStream();
171 var creader = std.io.countingReader(stream.reader());
172 const reader = creader.reader();
173 const value = try std.leb.readUleb128(u64, reader);
174 it.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow;
175 return value;
176 }
177
178 fn readString(it: *TrieIterator) ![:0]const u8 {
179 var stream = it.getStream();
180 const reader = stream.reader();
181
182 var count: usize = 0;
183 while (true) : (count += 1) {
184 const byte = try reader.readByte();
185 if (byte == 0) break;
186 }
187
188 const str = @as([*:0]const u8, @ptrCast(it.data.ptr + it.pos))[0..count :0];
189 it.pos += count + 1;
190 return str;
191 }
192
193 fn readByte(it: *TrieIterator) !u8 {
194 var stream = it.getStream();
195 const value = try stream.reader().readByte();
196 it.pos += 1;
197 return value;
198 }
199};
200
201pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Export.Flags) !void {161pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Export.Flags) !void {
202 try self.exports.append(allocator, .{162 try self.exports.append(allocator, .{
203 .name = try self.addString(allocator, name),163 .name = try self.addString(allocator, name),
...@@ -207,16 +167,16 @@ pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Ex...@@ -207,16 +167,16 @@ pub fn addExport(self: *Dylib, allocator: Allocator, name: []const u8, flags: Ex
207167
208fn parseTrieNode(168fn parseTrieNode(
209 self: *Dylib,169 self: *Dylib,
210 it: *TrieIterator,170 br: *std.io.BufferedReader,
211 allocator: Allocator,171 allocator: Allocator,
212 arena: Allocator,172 arena: Allocator,
213 prefix: []const u8,173 prefix: []const u8,
214) !void {174) !void {
215 const tracy = trace(@src());175 const tracy = trace(@src());
216 defer tracy.end();176 defer tracy.end();
217 const size = try it.readUleb128();177 const size = try br.takeLeb128(u64);
218 if (size > 0) {178 if (size > 0) {
219 const flags = try it.readUleb128();179 const flags = try br.takeLeb128(u8);
220 const kind = flags & macho.EXPORT_SYMBOL_FLAGS_KIND_MASK;180 const kind = flags & macho.EXPORT_SYMBOL_FLAGS_KIND_MASK;
221 const out_flags = Export.Flags{181 const out_flags = Export.Flags{
222 .abs = kind == macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE,182 .abs = kind == macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE,
...@@ -224,29 +184,28 @@ fn parseTrieNode(...@@ -224,29 +184,28 @@ fn parseTrieNode(
224 .weak = flags & macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION != 0,184 .weak = flags & macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION != 0,
225 };185 };
226 if (flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT != 0) {186 if (flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT != 0) {
227 _ = try it.readUleb128(); // dylib ordinal187 _ = try br.takeLeb128(u64); // dylib ordinal
228 const name = try it.readString();188 const name = try br.takeSentinel(0);
229 try self.addExport(allocator, if (name.len > 0) name else prefix, out_flags);189 try self.addExport(allocator, if (name.len > 0) name else prefix, out_flags);
230 } else if (flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER != 0) {190 } else if (flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER != 0) {
231 _ = try it.readUleb128(); // stub offset191 _ = try br.takeLeb128(u64); // stub offset
232 _ = try it.readUleb128(); // resolver offset192 _ = try br.takeLeb128(u64); // resolver offset
233 try self.addExport(allocator, prefix, out_flags);193 try self.addExport(allocator, prefix, out_flags);
234 } else {194 } else {
235 _ = try it.readUleb128(); // VM offset195 _ = try br.takeLeb128(u64); // VM offset
236 try self.addExport(allocator, prefix, out_flags);196 try self.addExport(allocator, prefix, out_flags);
237 }197 }
238 }198 }
239199
240 const nedges = try it.readByte();200 const nedges = try br.takeByte();
241
242 for (0..nedges) |_| {201 for (0..nedges) |_| {
243 const label = try it.readString();202 const label = try br.takeSentinel(0);
244 const off = try it.readUleb128();203 const off = try br.takeLeb128(usize);
245 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });204 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
246 const curr = it.pos;205 const seek = br.seek;
247 it.pos = math.cast(usize, off) orelse return error.Overflow;206 br.seek = off;
248 try self.parseTrieNode(it, allocator, arena, prefix_label);207 try self.parseTrieNode(br, allocator, arena, prefix_label);
249 it.pos = curr;208 br.seek = seek;
250 }209 }
251}210}
252211
...@@ -257,8 +216,9 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {...@@ -257,8 +216,9 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {
257 var arena = std.heap.ArenaAllocator.init(gpa);216 var arena = std.heap.ArenaAllocator.init(gpa);
258 defer arena.deinit();217 defer arena.deinit();
259218
260 var it: TrieIterator = .{ .data = data };219 var br: std.io.BufferedReader = undefined;
261 try self.parseTrieNode(&it, gpa, arena.allocator(), "");220 br.initFixed(data);
221 try self.parseTrieNode(&br, gpa, arena.allocator(), "");
262}222}
263223
264fn parseTbd(self: *Dylib, macho_file: *MachO) !void {224fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
...@@ -267,7 +227,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void {...@@ -267,7 +227,7 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
267227
268 const gpa = macho_file.base.comp.gpa;228 const gpa = macho_file.base.comp.gpa;
269229
270 log.debug("parsing dylib from stub: {}", .{self.path});230 log.debug("parsing dylib from stub: {f}", .{self.path});
271231
272 const file = macho_file.getFileHandle(self.file_handle);232 const file = macho_file.getFileHandle(self.file_handle);
273 var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| {233 var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| {
...@@ -716,24 +676,18 @@ const FormatContext = struct {...@@ -716,24 +676,18 @@ const FormatContext = struct {
716 macho_file: *MachO,676 macho_file: *MachO,
717};677};
718678
719fn formatSymtab(679fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
720 ctx: FormatContext,
721 comptime unused_fmt_string: []const u8,
722 options: std.fmt.FormatOptions,
723 writer: anytype,
724) !void {
725 _ = unused_fmt_string;680 _ = unused_fmt_string;
726 _ = options;
727 const dylib = ctx.dylib;681 const dylib = ctx.dylib;
728 const macho_file = ctx.macho_file;682 const macho_file = ctx.macho_file;
729 try writer.writeAll(" globals\n");683 try bw.writeAll(" globals\n");
730 for (dylib.symbols.items, 0..) |sym, i| {684 for (dylib.symbols.items, 0..) |sym, i| {
731 const ref = dylib.getSymbolRef(@intCast(i), macho_file);685 const ref = dylib.getSymbolRef(@intCast(i), macho_file);
732 if (ref.getFile(macho_file) == null) {686 if (ref.getFile(macho_file) == null) {
733 // TODO any better way of handling this?687 // TODO any better way of handling this?
734 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});688 try bw.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
735 } else {689 } else {
736 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});690 try bw.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
737 }691 }
738 }692 }
739}693}
src/link/MachO/InternalObject.zig+8-20
...@@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil...@@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil
261261
262 sect.offset = @intCast(self.objc_methnames.items.len);262 sect.offset = @intCast(self.objc_methnames.items.len);
263 try self.objc_methnames.ensureUnusedCapacity(gpa, methname.len + 1);263 try self.objc_methnames.ensureUnusedCapacity(gpa, methname.len + 1);
264 self.objc_methnames.writer(gpa).print("{s}\x00", .{methname}) catch unreachable;264 self.objc_methnames.print(gpa, "{s}\x00", .{methname}) catch unreachable;
265265
266 const name_str = try self.addString(gpa, "ltmp");266 const name_str = try self.addString(gpa, "ltmp");
267 const sym_index = try self.addSymbol(gpa);267 const sym_index = try self.addSymbol(gpa);
...@@ -848,18 +848,12 @@ pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(for...@@ -848,18 +848,12 @@ pub fn fmtAtoms(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(for
848 } };848 } };
849}849}
850850
851fn formatAtoms(851fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
852 ctx: FormatContext,
853 comptime unused_fmt_string: []const u8,
854 options: std.fmt.FormatOptions,
855 writer: anytype,
856) !void {
857 _ = unused_fmt_string;852 _ = unused_fmt_string;
858 _ = options;853 try bw.writeAll(" atoms\n");
859 try writer.writeAll(" atoms\n");
860 for (ctx.self.getAtoms()) |atom_index| {854 for (ctx.self.getAtoms()) |atom_index| {
861 const atom = ctx.self.getAtom(atom_index) orelse continue;855 const atom = ctx.self.getAtom(atom_index) orelse continue;
862 try writer.print(" {}\n", .{atom.fmt(ctx.macho_file)});856 try bw.print(" {f}\n", .{atom.fmt(ctx.macho_file)});
863 }857 }
864}858}
865859
...@@ -870,24 +864,18 @@ pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(fo...@@ -870,24 +864,18 @@ pub fn fmtSymtab(self: *InternalObject, macho_file: *MachO) std.fmt.Formatter(fo
870 } };864 } };
871}865}
872866
873fn formatSymtab(867fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
874 ctx: FormatContext,
875 comptime unused_fmt_string: []const u8,
876 options: std.fmt.FormatOptions,
877 writer: anytype,
878) !void {
879 _ = unused_fmt_string;868 _ = unused_fmt_string;
880 _ = options;
881 const macho_file = ctx.macho_file;869 const macho_file = ctx.macho_file;
882 const self = ctx.self;870 const self = ctx.self;
883 try writer.writeAll(" symbols\n");871 try bw.writeAll(" symbols\n");
884 for (self.symbols.items, 0..) |sym, i| {872 for (self.symbols.items, 0..) |sym, i| {
885 const ref = self.getSymbolRef(@intCast(i), macho_file);873 const ref = self.getSymbolRef(@intCast(i), macho_file);
886 if (ref.getFile(macho_file) == null) {874 if (ref.getFile(macho_file) == null) {
887 // TODO any better way of handling this?875 // TODO any better way of handling this?
888 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});876 try bw.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
889 } else {877 } else {
890 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});878 try bw.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
891 }879 }
892 }880 }
893}881}
src/link/MachO/Object.zig+39-92
...@@ -72,7 +72,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -72,7 +72,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
72 const tracy = trace(@src());72 const tracy = trace(@src());
73 defer tracy.end();73 defer tracy.end();
7474
75 log.debug("parsing {}", .{self.fmtPath()});75 log.debug("parsing {f}", .{self.fmtPath()});
7676
77 const gpa = macho_file.base.comp.gpa;77 const gpa = macho_file.base.comp.gpa;
78 const handle = macho_file.getFileHandle(self.file_handle);78 const handle = macho_file.getFileHandle(self.file_handle);
...@@ -239,7 +239,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -239,7 +239,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
239239
240 if (self.platform) |platform| {240 if (self.platform) |platform| {
241 if (!macho_file.platform.eqlTarget(platform)) {241 if (!macho_file.platform.eqlTarget(platform)) {
242 try macho_file.reportParseError2(self.index, "invalid platform: {}", .{242 try macho_file.reportParseError2(self.index, "invalid platform: {f}", .{
243 platform.fmtTarget(cpu_arch),243 platform.fmtTarget(cpu_arch),
244 });244 });
245 return error.InvalidTarget;245 return error.InvalidTarget;
...@@ -247,7 +247,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -247,7 +247,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
247 // TODO: this causes the CI to fail so I'm commenting this check out so that247 // TODO: this causes the CI to fail so I'm commenting this check out so that
248 // I can work out the rest of the changes first248 // I can work out the rest of the changes first
249 // if (macho_file.platform.version.order(platform.version) == .lt) {249 // if (macho_file.platform.version.order(platform.version) == .lt) {
250 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {}: {} < {}", .{250 // try macho_file.reportParseError2(self.index, "object file built for newer platform: {f}: {f} < {f}", .{
251 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),251 // macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),
252 // macho_file.platform.version,252 // macho_file.platform.version,
253 // platform.version,253 // platform.version,
...@@ -1065,7 +1065,8 @@ fn initEhFrameRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fi...@@ -1065,7 +1065,8 @@ fn initEhFrameRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fi
1065 }1065 }
1066 }1066 }
10671067
1068 var it = eh_frame.Iterator{ .data = self.eh_frame_data.items };1068 var it: eh_frame.Iterator = undefined;
1069 it.br.initFixed(self.eh_frame_data.items);
1069 while (try it.next()) |rec| {1070 while (try it.next()) |rec| {
1070 switch (rec.tag) {1071 switch (rec.tag) {
1071 .cie => try self.cies.append(allocator, .{1072 .cie => try self.cies.append(allocator, .{
...@@ -1694,11 +1695,11 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void {...@@ -1694,11 +1695,11 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void {
1694 };1695 };
1695}1696}
16961697
1697pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {1698pub fn writeAr(self: Object, bw: *std.io.BufferedWriter, ar_format: Archive.Format, macho_file: *MachO) !void {
1698 // Header1699 // Header
1699 const size = try macho_file.cast(usize, self.output_ar_state.size);1700 const size = try macho_file.cast(usize, self.output_ar_state.size);
1700 const basename = std.fs.path.basename(self.path.sub_path);1701 const basename = std.fs.path.basename(self.path.sub_path);
1701 try Archive.writeHeader(basename, size, ar_format, writer);1702 try Archive.writeHeader(bw, basename, size, ar_format);
1702 // Data1703 // Data
1703 const file = macho_file.getFileHandle(self.file_handle);1704 const file = macho_file.getFileHandle(self.file_handle);
1704 // TODO try using copyRangeAll1705 // TODO try using copyRangeAll
...@@ -1707,7 +1708,7 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ...@@ -1707,7 +1708,7 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ
1707 defer gpa.free(data);1708 defer gpa.free(data);
1708 const amt = try file.preadAll(data, self.offset);1709 const amt = try file.preadAll(data, self.offset);
1709 if (amt != size) return error.InputOutput;1710 if (amt != size) return error.InputOutput;
1710 try writer.writeAll(data);1711 try bw.writeAll(data);
1711}1712}
17121713
1713pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {1714pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {
...@@ -1861,7 +1862,7 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void {...@@ -1861,7 +1862,7 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void {
1861 }1862 }
1862 gpa.free(sections_data);1863 gpa.free(sections_data);
1863 }1864 }
1864 @memset(sections_data, &[0]u8{});1865 @memset(sections_data, &.{});
1865 const file = macho_file.getFileHandle(self.file_handle);1866 const file = macho_file.getFileHandle(self.file_handle);
18661867
1867 for (headers, 0..) |header, n_sect| {1868 for (headers, 0..) |header, n_sect| {
...@@ -2512,16 +2513,10 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_...@@ -2512,16 +2513,10 @@ pub fn readSectionData(self: Object, allocator: Allocator, file: File.Handle, n_
2512 return data;2513 return data;
2513}2514}
25142515
2515pub fn format(2516pub fn format(self: *Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2516 self: *Object,
2517 comptime unused_fmt_string: []const u8,
2518 options: std.fmt.FormatOptions,
2519 writer: anytype,
2520) !void {
2521 _ = self;2517 _ = self;
2518 _ = bw;
2522 _ = unused_fmt_string;2519 _ = unused_fmt_string;
2523 _ = options;
2524 _ = writer;
2525 @compileError("do not format objects directly");2520 @compileError("do not format objects directly");
2526}2521}
25272522
...@@ -2537,20 +2532,14 @@ pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms...@@ -2537,20 +2532,14 @@ pub fn fmtAtoms(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatAtoms
2537 } };2532 } };
2538}2533}
25392534
2540fn formatAtoms(2535fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2541 ctx: FormatContext,
2542 comptime unused_fmt_string: []const u8,
2543 options: std.fmt.FormatOptions,
2544 writer: anytype,
2545) !void {
2546 _ = unused_fmt_string;2536 _ = unused_fmt_string;
2547 _ = options;
2548 const object = ctx.object;2537 const object = ctx.object;
2549 const macho_file = ctx.macho_file;2538 const macho_file = ctx.macho_file;
2550 try writer.writeAll(" atoms\n");2539 try bw.writeAll(" atoms\n");
2551 for (object.getAtoms()) |atom_index| {2540 for (object.getAtoms()) |atom_index| {
2552 const atom = object.getAtom(atom_index) orelse continue;2541 const atom = object.getAtom(atom_index) orelse continue;
2553 try writer.print(" {}\n", .{atom.fmt(macho_file)});2542 try bw.print(" {f}\n", .{atom.fmt(macho_file)});
2554 }2543 }
2555}2544}
25562545
...@@ -2561,18 +2550,12 @@ pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies)...@@ -2561,18 +2550,12 @@ pub fn fmtCies(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatCies)
2561 } };2550 } };
2562}2551}
25632552
2564fn formatCies(2553fn formatCies(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2565 ctx: FormatContext,
2566 comptime unused_fmt_string: []const u8,
2567 options: std.fmt.FormatOptions,
2568 writer: anytype,
2569) !void {
2570 _ = unused_fmt_string;2554 _ = unused_fmt_string;
2571 _ = options;
2572 const object = ctx.object;2555 const object = ctx.object;
2573 try writer.writeAll(" cies\n");2556 try bw.writeAll(" cies\n");
2574 for (object.cies.items, 0..) |cie, i| {2557 for (object.cies.items, 0..) |cie, i| {
2575 try writer.print(" cie({d}) : {}\n", .{ i, cie.fmt(ctx.macho_file) });2558 try bw.print(" cie({d}) : {f}\n", .{ i, cie.fmt(ctx.macho_file) });
2576 }2559 }
2577}2560}
25782561
...@@ -2583,18 +2566,12 @@ pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes)...@@ -2583,18 +2566,12 @@ pub fn fmtFdes(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatFdes)
2583 } };2566 } };
2584}2567}
25852568
2586fn formatFdes(2569fn formatFdes(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2587 ctx: FormatContext,
2588 comptime unused_fmt_string: []const u8,
2589 options: std.fmt.FormatOptions,
2590 writer: anytype,
2591) !void {
2592 _ = unused_fmt_string;2570 _ = unused_fmt_string;
2593 _ = options;
2594 const object = ctx.object;2571 const object = ctx.object;
2595 try writer.writeAll(" fdes\n");2572 try bw.writeAll(" fdes\n");
2596 for (object.fdes.items, 0..) |fde, i| {2573 for (object.fdes.items, 0..) |fde, i| {
2597 try writer.print(" fde({d}) : {}\n", .{ i, fde.fmt(ctx.macho_file) });2574 try bw.print(" fde({d}) : {f}\n", .{ i, fde.fmt(ctx.macho_file) });
2598 }2575 }
2599}2576}
26002577
...@@ -2605,19 +2582,13 @@ pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(for...@@ -2605,19 +2582,13 @@ pub fn fmtUnwindRecords(self: *Object, macho_file: *MachO) std.fmt.Formatter(for
2605 } };2582 } };
2606}2583}
26072584
2608fn formatUnwindRecords(2585fn formatUnwindRecords(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2609 ctx: FormatContext,
2610 comptime unused_fmt_string: []const u8,
2611 options: std.fmt.FormatOptions,
2612 writer: anytype,
2613) !void {
2614 _ = unused_fmt_string;2586 _ = unused_fmt_string;
2615 _ = options;
2616 const object = ctx.object;2587 const object = ctx.object;
2617 const macho_file = ctx.macho_file;2588 const macho_file = ctx.macho_file;
2618 try writer.writeAll(" unwind records\n");2589 try bw.writeAll(" unwind records\n");
2619 for (object.unwind_records_indexes.items) |rec| {2590 for (object.unwind_records_indexes.items) |rec| {
2620 try writer.print(" rec({d}) : {}\n", .{ rec, object.getUnwindRecord(rec).fmt(macho_file) });2591 try bw.print(" rec({d}) : {f}\n", .{ rec, object.getUnwindRecord(rec).fmt(macho_file) });
2621 }2592 }
2622}2593}
26232594
...@@ -2628,34 +2599,28 @@ pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymt...@@ -2628,34 +2599,28 @@ pub fn fmtSymtab(self: *Object, macho_file: *MachO) std.fmt.Formatter(formatSymt
2628 } };2599 } };
2629}2600}
26302601
2631fn formatSymtab(2602fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2632 ctx: FormatContext,
2633 comptime unused_fmt_string: []const u8,
2634 options: std.fmt.FormatOptions,
2635 writer: anytype,
2636) !void {
2637 _ = unused_fmt_string;2603 _ = unused_fmt_string;
2638 _ = options;
2639 const object = ctx.object;2604 const object = ctx.object;
2640 const macho_file = ctx.macho_file;2605 const macho_file = ctx.macho_file;
2641 try writer.writeAll(" symbols\n");2606 try bw.writeAll(" symbols\n");
2642 for (object.symbols.items, 0..) |sym, i| {2607 for (object.symbols.items, 0..) |sym, i| {
2643 const ref = object.getSymbolRef(@intCast(i), macho_file);2608 const ref = object.getSymbolRef(@intCast(i), macho_file);
2644 if (ref.getFile(macho_file) == null) {2609 if (ref.getFile(macho_file) == null) {
2645 // TODO any better way of handling this?2610 // TODO any better way of handling this?
2646 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});2611 try bw.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
2647 } else {2612 } else {
2648 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});2613 try bw.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
2649 }2614 }
2650 }2615 }
2651 for (object.stab_files.items) |sf| {2616 for (object.stab_files.items) |sf| {
2652 try writer.print(" stabs({s},{s},{s})\n", .{2617 try bw.print(" stabs({s},{s},{s})\n", .{
2653 sf.getCompDir(object.*),2618 sf.getCompDir(object.*),
2654 sf.getTuName(object.*),2619 sf.getTuName(object.*),
2655 sf.getOsoPath(object.*),2620 sf.getOsoPath(object.*),
2656 });2621 });
2657 for (sf.stabs.items) |stab| {2622 for (sf.stabs.items) |stab| {
2658 try writer.print(" {}", .{stab.fmt(object.*)});2623 try bw.print(" {f}", .{stab.fmt(object.*)});
2659 }2624 }
2660 }2625 }
2661}2626}
...@@ -2664,20 +2629,14 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {...@@ -2664,20 +2629,14 @@ pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) {
2664 return .{ .data = self };2629 return .{ .data = self };
2665}2630}
26662631
2667fn formatPath(2632fn formatPath(object: Object, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2668 object: Object,
2669 comptime unused_fmt_string: []const u8,
2670 options: std.fmt.FormatOptions,
2671 writer: anytype,
2672) !void {
2673 _ = unused_fmt_string;2633 _ = unused_fmt_string;
2674 _ = options;
2675 if (object.in_archive) |ar| {2634 if (object.in_archive) |ar| {
2676 try writer.print("{}({s})", .{2635 try bw.print("{f}({s})", .{
2677 @as(Path, ar.path), object.path.basename(),2636 ar.path, object.path.basename(),
2678 });2637 });
2679 } else {2638 } else {
2680 try writer.print("{}", .{@as(Path, object.path)});2639 try bw.print("{f}", .{object.path});
2681 }2640 }
2682}2641}
26832642
...@@ -2731,16 +2690,10 @@ const StabFile = struct {...@@ -2731,16 +2690,10 @@ const StabFile = struct {
2731 return object.symbols.items[index];2690 return object.symbols.items[index];
2732 }2691 }
27332692
2734 pub fn format(2693 pub fn format(stab: Stab, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2735 stab: Stab,
2736 comptime unused_fmt_string: []const u8,
2737 options: std.fmt.FormatOptions,
2738 writer: anytype,
2739 ) !void {
2740 _ = stab;2694 _ = stab;
2695 _ = bw;
2741 _ = unused_fmt_string;2696 _ = unused_fmt_string;
2742 _ = options;
2743 _ = writer;
2744 @compileError("do not format stabs directly");2697 @compileError("do not format stabs directly");
2745 }2698 }
27462699
...@@ -2750,22 +2703,16 @@ const StabFile = struct {...@@ -2750,22 +2703,16 @@ const StabFile = struct {
2750 return .{ .data = .{ stab, object } };2703 return .{ .data = .{ stab, object } };
2751 }2704 }
27522705
2753 fn format2(2706 fn format2(ctx: StabFormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
2754 ctx: StabFormatContext,
2755 comptime unused_fmt_string: []const u8,
2756 options: std.fmt.FormatOptions,
2757 writer: anytype,
2758 ) !void {
2759 _ = unused_fmt_string;2707 _ = unused_fmt_string;
2760 _ = options;
2761 const stab, const object = ctx;2708 const stab, const object = ctx;
2762 const sym = stab.getSymbol(object).?;2709 const sym = stab.getSymbol(object).?;
2763 if (stab.is_func) {2710 if (stab.is_func) {
2764 try writer.print("func({d})", .{stab.index.?});2711 try bw.print("func({d})", .{stab.index.?});
2765 } else if (sym.visibility == .global) {2712 } else if (sym.visibility == .global) {
2766 try writer.print("gsym({d})", .{stab.index.?});2713 try bw.print("gsym({d})", .{stab.index.?});
2767 } else {2714 } else {
2768 try writer.print("stsym({d})", .{stab.index.?});2715 try bw.print("stsym({d})", .{stab.index.?});
2769 }2716 }
2770 }2717 }
2771 };2718 };
src/link/MachO/Relocation.zig+3-10
...@@ -76,16 +76,10 @@ pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatt...@@ -76,16 +76,10 @@ pub fn fmtPretty(rel: Relocation, cpu_arch: std.Target.Cpu.Arch) std.fmt.Formatt
76 return .{ .data = .{ rel, cpu_arch } };76 return .{ .data = .{ rel, cpu_arch } };
77}77}
7878
79fn formatPretty(79fn formatPretty(ctx: FormatCtx, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
80 ctx: FormatCtx,
81 comptime unused_fmt_string: []const u8,
82 options: std.fmt.FormatOptions,
83 writer: anytype,
84) !void {
85 _ = options;
86 _ = unused_fmt_string;80 _ = unused_fmt_string;
87 const rel, const cpu_arch = ctx;81 const rel, const cpu_arch = ctx;
88 const str = switch (rel.type) {82 try bw.writeAll(switch (rel.type) {
89 .signed => "X86_64_RELOC_SIGNED",83 .signed => "X86_64_RELOC_SIGNED",
90 .signed1 => "X86_64_RELOC_SIGNED_1",84 .signed1 => "X86_64_RELOC_SIGNED_1",
91 .signed2 => "X86_64_RELOC_SIGNED_2",85 .signed2 => "X86_64_RELOC_SIGNED_2",
...@@ -118,8 +112,7 @@ fn formatPretty(...@@ -118,8 +112,7 @@ fn formatPretty(
118 .aarch64 => "ARM64_RELOC_UNSIGNED",112 .aarch64 => "ARM64_RELOC_UNSIGNED",
119 else => unreachable,113 else => unreachable,
120 },114 },
121 };115 });
122 try writer.writeAll(str);
123}116}
124117
125pub const Type = enum {118pub const Type = enum {
src/link/MachO/Symbol.zig+14-26
...@@ -286,16 +286,10 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo...@@ -286,16 +286,10 @@ pub fn setOutputSym(symbol: Symbol, macho_file: *MachO, out: *macho.nlist_64) vo
286 }286 }
287}287}
288288
289pub fn format(289pub fn format(symbol: Symbol, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
290 symbol: Symbol,
291 comptime unused_fmt_string: []const u8,
292 options: std.fmt.FormatOptions,
293 writer: anytype,
294) !void {
295 _ = symbol;290 _ = symbol;
291 _ = bw;
296 _ = unused_fmt_string;292 _ = unused_fmt_string;
297 _ = options;
298 _ = writer;
299 @compileError("do not format symbols directly");293 @compileError("do not format symbols directly");
300}294}
301295
...@@ -311,26 +305,20 @@ pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) {...@@ -311,26 +305,20 @@ pub fn fmt(symbol: Symbol, macho_file: *MachO) std.fmt.Formatter(format2) {
311 } };305 } };
312}306}
313307
314fn format2(308fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
315 ctx: FormatContext,
316 comptime unused_fmt_string: []const u8,
317 options: std.fmt.FormatOptions,
318 writer: anytype,
319) !void {
320 _ = options;
321 _ = unused_fmt_string;309 _ = unused_fmt_string;
322 const symbol = ctx.symbol;310 const symbol = ctx.symbol;
323 try writer.print("%{d} : {s} : @{x}", .{311 try bw.print("%{d} : {s} : @{x}", .{
324 symbol.nlist_idx,312 symbol.nlist_idx,
325 symbol.getName(ctx.macho_file),313 symbol.getName(ctx.macho_file),
326 symbol.getAddress(.{}, ctx.macho_file),314 symbol.getAddress(.{}, ctx.macho_file),
327 });315 });
328 if (symbol.getFile(ctx.macho_file)) |file| {316 if (symbol.getFile(ctx.macho_file)) |file| {
329 if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) {317 if (symbol.getOutputSectionIndex(ctx.macho_file) != 0) {
330 try writer.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)});318 try bw.print(" : sect({d})", .{symbol.getOutputSectionIndex(ctx.macho_file)});
331 }319 }
332 if (symbol.getAtom(ctx.macho_file)) |atom| {320 if (symbol.getAtom(ctx.macho_file)) |atom| {
333 try writer.print(" : atom({d})", .{atom.atom_index});321 try bw.print(" : atom({d})", .{atom.atom_index});
334 }322 }
335 var buf: [3]u8 = .{'_'} ** 3;323 var buf: [3]u8 = .{'_'} ** 3;
336 if (symbol.flags.@"export") buf[0] = 'E';324 if (symbol.flags.@"export") buf[0] = 'E';
...@@ -340,16 +328,16 @@ fn format2(...@@ -340,16 +328,16 @@ fn format2(
340 .hidden => buf[2] = 'H',328 .hidden => buf[2] = 'H',
341 .global => buf[2] = 'G',329 .global => buf[2] = 'G',
342 }330 }
343 try writer.print(" : {s}", .{&buf});331 try bw.print(" : {s}", .{&buf});
344 if (symbol.flags.weak) try writer.writeAll(" : weak");332 if (symbol.flags.weak) try bw.writeAll(" : weak");
345 if (symbol.isSymbolStab(ctx.macho_file)) try writer.writeAll(" : stab");333 if (symbol.isSymbolStab(ctx.macho_file)) try bw.writeAll(" : stab");
346 switch (file) {334 switch (file) {
347 .zig_object => |x| try writer.print(" : zig_object({d})", .{x.index}),335 .zig_object => |x| try bw.print(" : zig_object({d})", .{x.index}),
348 .internal => |x| try writer.print(" : internal({d})", .{x.index}),336 .internal => |x| try bw.print(" : internal({d})", .{x.index}),
349 .object => |x| try writer.print(" : object({d})", .{x.index}),337 .object => |x| try bw.print(" : object({d})", .{x.index}),
350 .dylib => |x| try writer.print(" : dylib({d})", .{x.index}),338 .dylib => |x| try bw.print(" : dylib({d})", .{x.index}),
351 }339 }
352 } else try writer.writeAll(" : unresolved");340 } else try bw.writeAll(" : unresolved");
353}341}
354342
355pub const Flags = packed struct {343pub const Flags = packed struct {
src/link/MachO/Thunk.zig+9-21
...@@ -20,16 +20,16 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {...@@ -20,16 +20,16 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {
20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;
21}21}
2222
23pub fn write(thunk: Thunk, macho_file: *MachO, writer: anytype) !void {23pub fn write(thunk: Thunk, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
24 for (thunk.symbols.keys(), 0..) |ref, i| {24 for (thunk.symbols.keys(), 0..) |ref, i| {
25 const sym = ref.getSymbol(macho_file).?;25 const sym = ref.getSymbol(macho_file).?;
26 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;26 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;
27 const taddr = sym.getAddress(.{}, macho_file);27 const taddr = sym.getAddress(.{}, macho_file);
28 const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr));28 const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr));
29 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);29 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
30 const off: u12 = @truncate(taddr);30 const off: u12 = @truncate(taddr);
31 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);31 try bw.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);
32 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);32 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
33 }33 }
34}34}
3535
...@@ -61,16 +61,10 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {...@@ -61,16 +61,10 @@ pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {
61 }61 }
62}62}
6363
64pub fn format(64pub fn format(thunk: Thunk, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
65 thunk: Thunk,
66 comptime unused_fmt_string: []const u8,
67 options: std.fmt.FormatOptions,
68 writer: anytype,
69) !void {
70 _ = thunk;65 _ = thunk;
66 _ = bw;
71 _ = unused_fmt_string;67 _ = unused_fmt_string;
72 _ = options;
73 _ = writer;
74 @compileError("do not format Thunk directly");68 @compileError("do not format Thunk directly");
75}69}
7670
...@@ -86,20 +80,14 @@ const FormatContext = struct {...@@ -86,20 +80,14 @@ const FormatContext = struct {
86 macho_file: *MachO,80 macho_file: *MachO,
87};81};
8882
89fn format2(83fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
90 ctx: FormatContext,
91 comptime unused_fmt_string: []const u8,
92 options: std.fmt.FormatOptions,
93 writer: anytype,
94) !void {
95 _ = options;
96 _ = unused_fmt_string;84 _ = unused_fmt_string;
97 const thunk = ctx.thunk;85 const thunk = ctx.thunk;
98 const macho_file = ctx.macho_file;86 const macho_file = ctx.macho_file;
99 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size() });87 try bw.print("@{x} : size({x})\n", .{ thunk.value, thunk.size() });
100 for (thunk.symbols.keys()) |ref| {88 for (thunk.symbols.keys()) |ref| {
101 const sym = ref.getSymbol(macho_file).?;89 const sym = ref.getSymbol(macho_file).?;
102 try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.getName(macho_file), sym.value });90 try bw.print(" {f} : {s} : @{x}\n", .{ ref, sym.getName(macho_file), sym.value });
103 }91 }
104}92}
10593
src/link/MachO/UnwindInfo.zig+32-68
...@@ -133,7 +133,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -133,7 +133,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
133 for (info.records.items) |ref| {133 for (info.records.items) |ref| {
134 const rec = ref.getUnwindRecord(macho_file);134 const rec = ref.getUnwindRecord(macho_file);
135 const atom = rec.getAtom(macho_file);135 const atom = rec.getAtom(macho_file);
136 log.debug("@{x}-{x} : {s} : rec({d}) : object({d}) : {}", .{136 log.debug("@{x}-{x} : {s} : rec({d}) : object({d}) : {f}", .{
137 rec.getAtomAddress(macho_file),137 rec.getAtomAddress(macho_file),
138 rec.getAtomAddress(macho_file) + rec.length,138 rec.getAtomAddress(macho_file) + rec.length,
139 atom.getName(macho_file),139 atom.getName(macho_file),
...@@ -202,7 +202,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -202,7 +202,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
202 if (i >= max_common_encodings) break;202 if (i >= max_common_encodings) break;
203 if (slice[i].count < 2) continue;203 if (slice[i].count < 2) continue;
204 info.appendCommonEncoding(slice[i].enc);204 info.appendCommonEncoding(slice[i].enc);
205 log.debug("adding common encoding: {d} => {}", .{ i, slice[i].enc });205 log.debug("adding common encoding: {d} => {f}", .{ i, slice[i].enc });
206 }206 }
207 }207 }
208208
...@@ -255,7 +255,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -255,7 +255,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
255 page.kind = .compressed;255 page.kind = .compressed;
256 }256 }
257257
258 log.debug("{}", .{page.fmt(info.*)});258 log.debug("{f}", .{page.fmt(info.*)});
259259
260 try info.pages.append(gpa, page);260 try info.pages.append(gpa, page);
261 }261 }
...@@ -289,13 +289,10 @@ pub fn calcSize(info: UnwindInfo) usize {...@@ -289,13 +289,10 @@ pub fn calcSize(info: UnwindInfo) usize {
289 return total_size;289 return total_size;
290}290}
291291
292pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {292pub fn write(info: UnwindInfo, macho_file: *MachO, bw: *std.io.BufferedWriter) anyerror!void {
293 const seg = macho_file.getTextSegment();293 const seg = macho_file.getTextSegment();
294 const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?];294 const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?];
295295
296 var stream = std.io.fixedBufferStream(buffer);
297 const writer = stream.writer();
298
299 const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header);296 const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header);
300 const common_encodings_count: u32 = info.common_encodings_count;297 const common_encodings_count: u32 = info.common_encodings_count;
301 const personalities_offset: u32 = common_encodings_offset + common_encodings_count * @sizeOf(u32);298 const personalities_offset: u32 = common_encodings_offset + common_encodings_count * @sizeOf(u32);
...@@ -303,7 +300,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -303,7 +300,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
303 const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32);300 const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32);
304 const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1));301 const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1));
305302
306 try writer.writeStruct(macho.unwind_info_section_header{303 try bw.writeStruct(macho.unwind_info_section_header{
307 .commonEncodingsArraySectionOffset = common_encodings_offset,304 .commonEncodingsArraySectionOffset = common_encodings_offset,
308 .commonEncodingsArrayCount = common_encodings_count,305 .commonEncodingsArrayCount = common_encodings_count,
309 .personalityArraySectionOffset = personalities_offset,306 .personalityArraySectionOffset = personalities_offset,
...@@ -312,11 +309,11 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -312,11 +309,11 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
312 .indexCount = indexes_count,309 .indexCount = indexes_count,
313 });310 });
314311
315 try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));312 try bw.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
316313
317 for (info.personalities[0..info.personalities_count]) |ref| {314 for (info.personalities[0..info.personalities_count]) |ref| {
318 const sym = ref.getSymbol(macho_file).?;315 const sym = ref.getSymbol(macho_file).?;
319 try writer.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little);316 try bw.writeInt(u32, @intCast(sym.getGotAddress(macho_file) - seg.vmaddr), .little);
320 }317 }
321318
322 const pages_base_offset = @as(u32, @intCast(header.size - (info.pages.items.len * second_level_page_bytes)));319 const pages_base_offset = @as(u32, @intCast(header.size - (info.pages.items.len * second_level_page_bytes)));
...@@ -325,7 +322,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -325,7 +322,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
325 for (info.pages.items, 0..) |page, i| {322 for (info.pages.items, 0..) |page, i| {
326 assert(page.count > 0);323 assert(page.count > 0);
327 const rec = info.records.items[page.start].getUnwindRecord(macho_file);324 const rec = info.records.items[page.start].getUnwindRecord(macho_file);
328 try writer.writeStruct(macho.unwind_info_section_header_index_entry{325 try bw.writeStruct(macho.unwind_info_section_header_index_entry{
329 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),326 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),
330 .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)),327 .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)),
331 .lsdaIndexArraySectionOffset = lsda_base_offset +328 .lsdaIndexArraySectionOffset = lsda_base_offset +
...@@ -335,7 +332,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -335,7 +332,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
335332
336 const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file);333 const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file);
337 const sentinel_address = @as(u32, @intCast(last_rec.getAtomAddress(macho_file) + last_rec.length - seg.vmaddr));334 const sentinel_address = @as(u32, @intCast(last_rec.getAtomAddress(macho_file) + last_rec.length - seg.vmaddr));
338 try writer.writeStruct(macho.unwind_info_section_header_index_entry{335 try bw.writeStruct(macho.unwind_info_section_header_index_entry{
339 .functionOffset = sentinel_address,336 .functionOffset = sentinel_address,
340 .secondLevelPagesSectionOffset = 0,337 .secondLevelPagesSectionOffset = 0,
341 .lsdaIndexArraySectionOffset = lsda_base_offset +338 .lsdaIndexArraySectionOffset = lsda_base_offset +
...@@ -344,23 +341,20 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -344,23 +341,20 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
344341
345 for (info.lsdas.items) |index| {342 for (info.lsdas.items) |index| {
346 const rec = info.records.items[index].getUnwindRecord(macho_file);343 const rec = info.records.items[index].getUnwindRecord(macho_file);
347 try writer.writeStruct(macho.unwind_info_section_header_lsda_index_entry{344 try bw.writeStruct(macho.unwind_info_section_header_lsda_index_entry{
348 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),345 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),
349 .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)),346 .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)),
350 });347 });
351 }348 }
352349
353 for (info.pages.items) |page| {350 for (info.pages.items) |page| {
354 const start = stream.pos;351 const start = bw.count;
355 try page.write(info, macho_file, writer);352 try page.write(info, macho_file, bw);
356 const nwritten = stream.pos - start;353 const nwritten = bw.count - start;
357 if (nwritten < second_level_page_bytes) {354 try bw.splatByteAll(0, math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow);
358 const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow;
359 try writer.writeByteNTimes(0, padding);
360 }
361 }355 }
362356
363 @memset(buffer[stream.pos..], 0);357 @memset(bw.unusedCapacitySlice(), 0);
364}358}
365359
366fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 {360fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 {
...@@ -455,15 +449,9 @@ pub const Encoding = extern struct {...@@ -455,15 +449,9 @@ pub const Encoding = extern struct {
455 return enc.enc == other.enc;449 return enc.enc == other.enc;
456 }450 }
457451
458 pub fn format(452 pub fn format(enc: Encoding, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
459 enc: Encoding,
460 comptime unused_fmt_string: []const u8,
461 options: std.fmt.FormatOptions,
462 writer: anytype,
463 ) !void {
464 _ = unused_fmt_string;453 _ = unused_fmt_string;
465 _ = options;454 try bw.print("0x{x:0>8}", .{enc.enc});
466 try writer.print("0x{x:0>8}", .{enc.enc});
467 }455 }
468};456};
469457
...@@ -517,16 +505,10 @@ pub const Record = struct {...@@ -517,16 +505,10 @@ pub const Record = struct {
517 return lsda.getAddress(macho_file) + rec.lsda_offset;505 return lsda.getAddress(macho_file) + rec.lsda_offset;
518 }506 }
519507
520 pub fn format(508 pub fn format(rec: Record, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
521 rec: Record,
522 comptime unused_fmt_string: []const u8,
523 options: std.fmt.FormatOptions,
524 writer: anytype,
525 ) !void {
526 _ = rec;509 _ = rec;
510 _ = bw;
527 _ = unused_fmt_string;511 _ = unused_fmt_string;
528 _ = options;
529 _ = writer;
530 @compileError("do not format UnwindInfo.Records directly");512 @compileError("do not format UnwindInfo.Records directly");
531 }513 }
532514
...@@ -542,22 +524,16 @@ pub const Record = struct {...@@ -542,22 +524,16 @@ pub const Record = struct {
542 macho_file: *MachO,524 macho_file: *MachO,
543 };525 };
544526
545 fn format2(527 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
546 ctx: FormatContext,
547 comptime unused_fmt_string: []const u8,
548 options: std.fmt.FormatOptions,
549 writer: anytype,
550 ) !void {
551 _ = unused_fmt_string;528 _ = unused_fmt_string;
552 _ = options;
553 const rec = ctx.rec;529 const rec = ctx.rec;
554 const macho_file = ctx.macho_file;530 const macho_file = ctx.macho_file;
555 try writer.print("{x} : len({x})", .{531 try bw.print("{x} : len({x})", .{
556 rec.enc.enc, rec.length,532 rec.enc.enc, rec.length,
557 });533 });
558 if (rec.enc.isDwarf(macho_file)) try writer.print(" : fde({d})", .{rec.fde});534 if (rec.enc.isDwarf(macho_file)) try bw.print(" : fde({d})", .{rec.fde});
559 try writer.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)});535 try bw.print(" : {s}", .{rec.getAtom(macho_file).getName(macho_file)});
560 if (!rec.alive) try writer.writeAll(" : [*]");536 if (!rec.alive) try bw.writeAll(" : [*]");
561 }537 }
562538
563 pub const Index = u32;539 pub const Index = u32;
...@@ -613,16 +589,10 @@ const Page = struct {...@@ -613,16 +589,10 @@ const Page = struct {
613 return null;589 return null;
614 }590 }
615591
616 fn format(592 fn format(page: *const Page, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
617 page: *const Page,
618 comptime unused_format_string: []const u8,
619 options: std.fmt.FormatOptions,
620 writer: anytype,
621 ) !void {
622 _ = page;593 _ = page;
594 _ = bw;
623 _ = unused_format_string;595 _ = unused_format_string;
624 _ = options;
625 _ = writer;
626 @compileError("do not format Page directly; use page.fmt()");596 @compileError("do not format Page directly; use page.fmt()");
627 }597 }
628598
...@@ -631,23 +601,17 @@ const Page = struct {...@@ -631,23 +601,17 @@ const Page = struct {
631 info: UnwindInfo,601 info: UnwindInfo,
632 };602 };
633603
634 fn format2(604 fn format2(ctx: FormatPageContext, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
635 ctx: FormatPageContext,
636 comptime unused_format_string: []const u8,
637 options: std.fmt.FormatOptions,
638 writer: anytype,
639 ) @TypeOf(writer).Error!void {
640 _ = options;
641 _ = unused_format_string;605 _ = unused_format_string;
642 try writer.writeAll("Page:\n");606 try bw.writeAll("Page:\n");
643 try writer.print(" kind: {s}\n", .{@tagName(ctx.page.kind)});607 try bw.print(" kind: {s}\n", .{@tagName(ctx.page.kind)});
644 try writer.print(" entries: {d} - {d}\n", .{608 try bw.print(" entries: {d} - {d}\n", .{
645 ctx.page.start,609 ctx.page.start,
646 ctx.page.start + ctx.page.count,610 ctx.page.start + ctx.page.count,
647 });611 });
648 try writer.print(" encodings (count = {d})\n", .{ctx.page.page_encodings_count});612 try bw.print(" encodings (count = {d})\n", .{ctx.page.page_encodings_count});
649 for (ctx.page.page_encodings[0..ctx.page.page_encodings_count], 0..) |enc, i| {613 for (ctx.page.page_encodings[0..ctx.page.page_encodings_count], 0..) |enc, i| {
650 try writer.print(" {d}: {}\n", .{ ctx.info.common_encodings_count + i, enc });614 try bw.print(" {d}: {f}\n", .{ ctx.info.common_encodings_count + i, enc });
651 }615 }
652 }616 }
653617
src/link/MachO/ZigObject.zig+16-30
...@@ -317,12 +317,12 @@ pub fn updateArSize(self: *ZigObject) void {...@@ -317,12 +317,12 @@ pub fn updateArSize(self: *ZigObject) void {
317 self.output_ar_state.size = self.data.items.len;317 self.output_ar_state.size = self.data.items.len;
318}318}
319319
320pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !void {320pub fn writeAr(self: ZigObject, bw: *std.io.BufferedWriter, ar_format: Archive.Format) anyerror!void {
321 // Header321 // Header
322 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;322 const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow;
323 try Archive.writeHeader(self.basename, size, ar_format, writer);323 try Archive.writeHeader(bw, self.basename, size, ar_format);
324 // Data324 // Data
325 try writer.writeAll(self.data.items);325 try bw.writeAll(self.data.items);
326}326}
327327
328pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void {328pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void {
...@@ -618,7 +618,7 @@ pub fn getNavVAddr(...@@ -618,7 +618,7 @@ pub fn getNavVAddr(
618 const zcu = pt.zcu;618 const zcu = pt.zcu;
619 const ip = &zcu.intern_pool;619 const ip = &zcu.intern_pool;
620 const nav = ip.getNav(nav_index);620 const nav = ip.getNav(nav_index);
621 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });621 log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
622 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(622 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
623 macho_file,623 macho_file,
624 nav.name.toSlice(ip),624 nav.name.toSlice(ip),
...@@ -884,7 +884,6 @@ pub fn updateNav(...@@ -884,7 +884,6 @@ pub fn updateNav(
884 defer debug_wip_nav.deinit();884 defer debug_wip_nav.deinit();
885 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {885 dwarf.finishWipNav(pt, nav_index, &debug_wip_nav) catch |err| switch (err) {
886 error.OutOfMemory => return error.OutOfMemory,886 error.OutOfMemory => return error.OutOfMemory,
887 error.Overflow => return error.Overflow,
888 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),887 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
889 };888 };
890 }889 }
...@@ -921,7 +920,6 @@ pub fn updateNav(...@@ -921,7 +920,6 @@ pub fn updateNav(
921920
922 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {921 if (debug_wip_nav) |*wip_nav| self.dwarf.?.finishWipNav(pt, nav_index, wip_nav) catch |err| switch (err) {
923 error.OutOfMemory => return error.OutOfMemory,922 error.OutOfMemory => return error.OutOfMemory,
924 error.Overflow => return error.Overflow,
925 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),923 else => |e| return macho_file.base.cgFail(nav_index, "failed to finish dwarf nav: {s}", .{@errorName(e)}),
926 };924 };
927 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);925 } else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
...@@ -943,7 +941,7 @@ fn updateNavCode(...@@ -943,7 +941,7 @@ fn updateNavCode(
943 const ip = &zcu.intern_pool;941 const ip = &zcu.intern_pool;
944 const nav = ip.getNav(nav_index);942 const nav = ip.getNav(nav_index);
945943
946 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });944 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
947945
948 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;946 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
949 const required_alignment = switch (pt.navAlignment(nav_index)) {947 const required_alignment = switch (pt.navAlignment(nav_index)) {
...@@ -981,7 +979,7 @@ fn updateNavCode(...@@ -981,7 +979,7 @@ fn updateNavCode(
981 if (need_realloc) {979 if (need_realloc) {
982 atom.grow(macho_file) catch |err|980 atom.grow(macho_file) catch |err|
983 return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});981 return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});
984 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });982 log.debug("growing {f} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });
985 if (old_vaddr != atom.value) {983 if (old_vaddr != atom.value) {
986 sym.value = 0;984 sym.value = 0;
987 nlist.n_value = 0;985 nlist.n_value = 0;
...@@ -1023,7 +1021,7 @@ fn updateTlv(...@@ -1023,7 +1021,7 @@ fn updateTlv(
1023 const ip = &pt.zcu.intern_pool;1021 const ip = &pt.zcu.intern_pool;
1024 const nav = ip.getNav(nav_index);1022 const nav = ip.getNav(nav_index);
10251023
1026 log.debug("updateTlv {} (0x{x})", .{ nav.fqn.fmt(ip), nav_index });1024 log.debug("updateTlv {f} (0x{x})", .{ nav.fqn.fmt(ip), nav_index });
10271025
1028 // 1. Lower TLV initializer1026 // 1. Lower TLV initializer
1029 const init_sym_index = try self.createTlvInitializer(1027 const init_sym_index = try self.createTlvInitializer(
...@@ -1351,7 +1349,7 @@ fn updateLazySymbol(...@@ -1351,7 +1349,7 @@ fn updateLazySymbol(
1351 defer code_buffer.deinit(gpa);1349 defer code_buffer.deinit(gpa);
13521350
1353 const name_str = blk: {1351 const name_str = blk: {
1354 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1352 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1355 @tagName(lazy_sym.kind),1353 @tagName(lazy_sym.kind),
1356 Type.fromInterned(lazy_sym.ty).fmt(pt),1354 Type.fromInterned(lazy_sym.ty).fmt(pt),
1357 });1355 });
...@@ -1430,7 +1428,7 @@ pub fn deleteExport(...@@ -1430,7 +1428,7 @@ pub fn deleteExport(
1430 } orelse return;1428 } orelse return;
1431 const nlist_index = metadata.@"export"(self, name.toSlice(&zcu.intern_pool)) orelse return;1429 const nlist_index = metadata.@"export"(self, name.toSlice(&zcu.intern_pool)) orelse return;
14321430
1433 log.debug("deleting export '{}'", .{name.fmt(&zcu.intern_pool)});1431 log.debug("deleting export '{f}'", .{name.fmt(&zcu.intern_pool)});
14341432
1435 const nlist = &self.symtab.items(.nlist)[nlist_index.*];1433 const nlist = &self.symtab.items(.nlist)[nlist_index.*];
1436 self.symtab.items(.size)[nlist_index.*] = 0;1434 self.symtab.items(.size)[nlist_index.*] = 0;
...@@ -1690,24 +1688,18 @@ const FormatContext = struct {...@@ -1690,24 +1688,18 @@ const FormatContext = struct {
1690 macho_file: *MachO,1688 macho_file: *MachO,
1691};1689};
16921690
1693fn formatSymtab(1691fn formatSymtab(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1694 ctx: FormatContext,
1695 comptime unused_fmt_string: []const u8,
1696 options: std.fmt.FormatOptions,
1697 writer: anytype,
1698) !void {
1699 _ = unused_fmt_string;1692 _ = unused_fmt_string;
1700 _ = options;1693 try bw.writeAll(" symbols\n");
1701 try writer.writeAll(" symbols\n");
1702 const self = ctx.self;1694 const self = ctx.self;
1703 const macho_file = ctx.macho_file;1695 const macho_file = ctx.macho_file;
1704 for (self.symbols.items, 0..) |sym, i| {1696 for (self.symbols.items, 0..) |sym, i| {
1705 const ref = self.getSymbolRef(@intCast(i), macho_file);1697 const ref = self.getSymbolRef(@intCast(i), macho_file);
1706 if (ref.getFile(macho_file) == null) {1698 if (ref.getFile(macho_file) == null) {
1707 // TODO any better way of handling this?1699 // TODO any better way of handling this?
1708 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});1700 try bw.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
1709 } else {1701 } else {
1710 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});1702 try bw.print(" {f}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
1711 }1703 }
1712 }1704 }
1713}1705}
...@@ -1719,20 +1711,14 @@ pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatAt...@@ -1719,20 +1711,14 @@ pub fn fmtAtoms(self: *ZigObject, macho_file: *MachO) std.fmt.Formatter(formatAt
1719 } };1711 } };
1720}1712}
17211713
1722fn formatAtoms(1714fn formatAtoms(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
1723 ctx: FormatContext,
1724 comptime unused_fmt_string: []const u8,
1725 options: std.fmt.FormatOptions,
1726 writer: anytype,
1727) !void {
1728 _ = unused_fmt_string;1715 _ = unused_fmt_string;
1729 _ = options;
1730 const self = ctx.self;1716 const self = ctx.self;
1731 const macho_file = ctx.macho_file;1717 const macho_file = ctx.macho_file;
1732 try writer.writeAll(" atoms\n");1718 try bw.writeAll(" atoms\n");
1733 for (self.getAtoms()) |atom_index| {1719 for (self.getAtoms()) |atom_index| {
1734 const atom = self.getAtom(atom_index) orelse continue;1720 const atom = self.getAtom(atom_index) orelse continue;
1735 try writer.print(" {}\n", .{atom.fmt(macho_file)});1721 try bw.print(" {f}\n", .{atom.fmt(macho_file)});
1736 }1722 }
1737}1723}
17381724
src/link/MachO/dead_strip.zig+3-9
...@@ -117,7 +117,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {...@@ -117,7 +117,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
117fn markLive(atom: *Atom, macho_file: *MachO) void {117fn markLive(atom: *Atom, macho_file: *MachO) void {
118 assert(atom.visited.load(.seq_cst));118 assert(atom.visited.load(.seq_cst));
119 atom.setAlive(true);119 atom.setAlive(true);
120 track_live_log.debug("{}marking live atom({d},{s})", .{120 track_live_log.debug("{f}marking live atom({d},{s})", .{
121 track_live_level,121 track_live_level,
122 atom.atom_index,122 atom.atom_index,
123 atom.getName(macho_file),123 atom.getName(macho_file),
...@@ -196,15 +196,9 @@ const Level = struct {...@@ -196,15 +196,9 @@ const Level = struct {
196 self.value += 1;196 self.value += 1;
197 }197 }
198198
199 pub fn format(199 pub fn format(self: *const @This(), bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
200 self: *const @This(),
201 comptime unused_fmt_string: []const u8,
202 options: std.fmt.FormatOptions,
203 writer: anytype,
204 ) !void {
205 _ = unused_fmt_string;200 _ = unused_fmt_string;
206 _ = options;201 try bw.splatByteAll(' ', self.value);
207 try writer.writeByteNTimes(' ', self.value);
208 }202 }
209};203};
210204
src/link/MachO/dyld_info/Rebase.zig+45-45
...@@ -3,7 +3,7 @@ buffer: std.ArrayListUnmanaged(u8) = .empty,...@@ -3,7 +3,7 @@ buffer: std.ArrayListUnmanaged(u8) = .empty,
33
4pub const Entry = struct {4pub const Entry = struct {
5 offset: u64,5 offset: u64,
6 segment_id: u8,6 segment_id: u4,
77
8 pub fn lessThan(ctx: void, entry: Entry, other: Entry) bool {8 pub fn lessThan(ctx: void, entry: Entry, other: Entry) bool {
9 _ = ctx;9 _ = ctx;
...@@ -110,33 +110,35 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {...@@ -110,33 +110,35 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
110fn finalize(rebase: *Rebase, gpa: Allocator) !void {110fn finalize(rebase: *Rebase, gpa: Allocator) !void {
111 if (rebase.entries.items.len == 0) return;111 if (rebase.entries.items.len == 0) return;
112112
113 const writer = rebase.buffer.writer(gpa);113 var aw: std.io.AllocatingWriter = undefined;
114 const bw = aw.fromArrayList(gpa, &rebase.buffer);
115 defer rebase.buffer = aw.toArrayList();
114116
115 log.debug("rebase opcodes", .{});117 log.debug("rebase opcodes", .{});
116118
117 std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan);119 std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan);
118120
119 try setTypePointer(writer);121 try setTypePointer(bw);
120122
121 var start: usize = 0;123 var start: usize = 0;
122 var seg_id: ?u8 = null;124 var seg_id: ?u8 = null;
123 for (rebase.entries.items, 0..) |entry, i| {125 for (rebase.entries.items, 0..) |entry, i| {
124 if (seg_id != null and seg_id.? == entry.segment_id) continue;126 if (seg_id != null and seg_id.? == entry.segment_id) continue;
125 try finalizeSegment(rebase.entries.items[start..i], writer);127 try finalizeSegment(rebase.entries.items[start..i], bw);
126 seg_id = entry.segment_id;128 seg_id = entry.segment_id;
127 start = i;129 start = i;
128 }130 }
129131
130 try finalizeSegment(rebase.entries.items[start..], writer);132 try finalizeSegment(rebase.entries.items[start..], bw);
131 try done(writer);133 try done(bw);
132}134}
133135
134fn finalizeSegment(entries: []const Entry, writer: anytype) !void {136fn finalizeSegment(entries: []const Entry, bw: *std.io.BufferedWriter) anyerror!void {
135 if (entries.len == 0) return;137 if (entries.len == 0) return;
136138
137 const segment_id = entries[0].segment_id;139 const segment_id = entries[0].segment_id;
138 var offset = entries[0].offset;140 var offset = entries[0].offset;
139 try setSegmentOffset(segment_id, offset, writer);141 try setSegmentOffset(segment_id, offset, bw);
140142
141 var count: usize = 0;143 var count: usize = 0;
142 var skip: u64 = 0;144 var skip: u64 = 0;
...@@ -155,7 +157,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {...@@ -155,7 +157,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {
155 .start => {157 .start => {
156 if (offset < current_offset) {158 if (offset < current_offset) {
157 const delta = current_offset - offset;159 const delta = current_offset - offset;
158 try addAddr(delta, writer);160 try addAddr(delta, bw);
159 offset += delta;161 offset += delta;
160 }162 }
161 state = .times;163 state = .times;
...@@ -175,7 +177,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {...@@ -175,7 +177,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {
175 offset += skip;177 offset += skip;
176 i -= 1;178 i -= 1;
177 } else {179 } else {
178 try rebaseTimes(count, writer);180 try rebaseTimes(count, bw);
179 state = .start;181 state = .start;
180 i -= 1;182 i -= 1;
181 }183 }
...@@ -184,9 +186,9 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {...@@ -184,9 +186,9 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {
184 if (current_offset < offset) {186 if (current_offset < offset) {
185 count -= 1;187 count -= 1;
186 if (count == 1) {188 if (count == 1) {
187 try rebaseAddAddr(skip, writer);189 try rebaseAddAddr(skip, bw);
188 } else {190 } else {
189 try rebaseTimesSkip(count, skip, writer);191 try rebaseTimesSkip(count, skip, bw);
190 }192 }
191 state = .start;193 state = .start;
192 offset = offset - (@sizeOf(u64) + skip);194 offset = offset - (@sizeOf(u64) + skip);
...@@ -199,7 +201,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {...@@ -199,7 +201,7 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {
199 count += 1;201 count += 1;
200 offset += @sizeOf(u64) + skip;202 offset += @sizeOf(u64) + skip;
201 } else {203 } else {
202 try rebaseTimesSkip(count, skip, writer);204 try rebaseTimesSkip(count, skip, bw);
203 state = .start;205 state = .start;
204 i -= 1;206 i -= 1;
205 }207 }
...@@ -210,68 +212,66 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {...@@ -210,68 +212,66 @@ fn finalizeSegment(entries: []const Entry, writer: anytype) !void {
210 switch (state) {212 switch (state) {
211 .start => unreachable,213 .start => unreachable,
212 .times => {214 .times => {
213 try rebaseTimes(count, writer);215 try rebaseTimes(count, bw);
214 },216 },
215 .times_skip => {217 .times_skip => {
216 try rebaseTimesSkip(count, skip, writer);218 try rebaseTimesSkip(count, skip, bw);
217 },219 },
218 }220 }
219}221}
220222
221fn setTypePointer(writer: anytype) !void {223fn setTypePointer(bw: *std.io.BufferedWriter) anyerror!void {
222 log.debug(">>> set type: {d}", .{macho.REBASE_TYPE_POINTER});224 log.debug(">>> set type: {d}", .{macho.REBASE_TYPE_POINTER});
223 try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.REBASE_TYPE_POINTER)));225 try bw.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.REBASE_TYPE_POINTER)));
224}226}
225227
226fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void {228fn setSegmentOffset(segment_id: u4, offset: u64, bw: *std.io.BufferedWriter) anyerror!void {
227 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });229 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
228 try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));230 try bw.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));
229 try std.leb.writeUleb128(writer, offset);231 try bw.writeLeb128(offset);
230}232}
231233
232fn rebaseAddAddr(addr: u64, writer: anytype) !void {234fn rebaseAddAddr(addr: u64, bw: *std.io.BufferedWriter) anyerror!void {
233 log.debug(">>> rebase with add: {x}", .{addr});235 log.debug(">>> rebase with add: {x}", .{addr});
234 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);236 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);
235 try std.leb.writeUleb128(writer, addr);237 try bw.writeLeb128(addr);
236}238}
237239
238fn rebaseTimes(count: usize, writer: anytype) !void {240fn rebaseTimes(count: usize, bw: *std.io.BufferedWriter) anyerror!void {
239 log.debug(">>> rebase with count: {d}", .{count});241 log.debug(">>> rebase with count: {d}", .{count});
240 if (count <= 0xf) {242 if (count <= 0xf) {
241 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @as(u4, @truncate(count)));243 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @as(u4, @truncate(count)));
242 } else {244 } else {
243 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES);245 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
244 try std.leb.writeUleb128(writer, count);246 try bw.writeLeb128(count);
245 }247 }
246}248}
247249
248fn rebaseTimesSkip(count: usize, skip: u64, writer: anytype) !void {250fn rebaseTimesSkip(count: usize, skip: u64, bw: *std.io.BufferedWriter) anyerror!void {
249 log.debug(">>> rebase with count: {d} and skip: {x}", .{ count, skip });251 log.debug(">>> rebase with count: {d} and skip: {x}", .{ count, skip });
250 try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);252 try bw.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);
251 try std.leb.writeUleb128(writer, count);253 try bw.writeLeb128(count);
252 try std.leb.writeUleb128(writer, skip);254 try bw.writeLeb128(skip);
253}255}
254256
255fn addAddr(addr: u64, writer: anytype) !void {257fn addAddr(addr: u64, bw: *std.io.BufferedWriter) anyerror!void {
256 log.debug(">>> add: {x}", .{addr});258 log.debug(">>> add: {x}", .{addr});
257 if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) {259 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {
258 const imm = @divExact(addr, @sizeOf(u64));260 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(
259 if (imm <= 0xf) {261 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED | imm_scaled,
260 try writer.writeByte(macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED | @as(u4, @truncate(imm)));262 );
261 return;263 } else |_| {}
262 }264 try bw.writeByte(macho.REBASE_OPCODE_ADD_ADDR_ULEB);
263 }265 try bw.writeLeb128(addr);
264 try writer.writeByte(macho.REBASE_OPCODE_ADD_ADDR_ULEB);
265 try std.leb.writeUleb128(writer, addr);
266}266}
267267
268fn done(writer: anytype) !void {268fn done(bw: *std.io.BufferedWriter) anyerror!void {
269 log.debug(">>> done", .{});269 log.debug(">>> done", .{});
270 try writer.writeByte(macho.REBASE_OPCODE_DONE);270 try bw.writeByte(macho.REBASE_OPCODE_DONE);
271}271}
272272
273pub fn write(rebase: Rebase, writer: anytype) !void {273pub fn write(rebase: Rebase, bw: *std.io.BufferedWriter) anyerror!void {
274 try writer.writeAll(rebase.buffer.items);274 try bw.writeAll(rebase.buffer.items);
275}275}
276276
277test "rebase - no entries" {277test "rebase - no entries" {
src/link/MachO/dyld_info/Trie.zig+32-35
...@@ -31,7 +31,7 @@...@@ -31,7 +31,7 @@
3131
32/// The root node of the trie.32/// The root node of the trie.
33root: ?Node.Index = null,33root: ?Node.Index = null,
34buffer: std.ArrayListUnmanaged(u8) = .empty,34buffer: []u8 = &.{},
35nodes: std.MultiArrayList(Node) = .{},35nodes: std.MultiArrayList(Node) = .{},
36edges: std.ArrayListUnmanaged(Edge) = .empty,36edges: std.ArrayListUnmanaged(Edge) = .empty,
3737
...@@ -123,7 +123,7 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {...@@ -123,7 +123,7 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {
123123
124 try self.finalize(gpa);124 try self.finalize(gpa);
125125
126 macho_file.dyld_info_cmd.export_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));126 macho_file.dyld_info_cmd.export_size = mem.alignForward(u32, @intCast(self.buffer.len), @alignOf(u64));
127}127}
128128
129/// Finalizes this trie for writing to a byte stream.129/// Finalizes this trie for writing to a byte stream.
...@@ -164,9 +164,12 @@ fn finalize(self: *Trie, allocator: Allocator) !void {...@@ -164,9 +164,12 @@ fn finalize(self: *Trie, allocator: Allocator) !void {
164 }164 }
165 }165 }
166166
167 try self.buffer.ensureTotalCapacityPrecise(allocator, size);167 assert(self.buffer.len == 0);
168 self.buffer = try allocator.alloc(u8, size);
169 var bw: std.io.BufferedWriter = undefined;
170 bw.initFixed(self.buffer);
168 for (ordered_nodes.items) |node_index| {171 for (ordered_nodes.items) |node_index| {
169 try self.writeNode(node_index, self.buffer.writer(allocator));172 try self.writeNode(node_index, &bw);
170 }173 }
171}174}
172175
...@@ -181,17 +184,20 @@ const FinalizeNodeResult = struct {...@@ -181,17 +184,20 @@ const FinalizeNodeResult = struct {
181184
182/// Updates offset of this node in the output byte stream.185/// Updates offset of this node in the output byte stream.
183fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {186fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !FinalizeNodeResult {
184 var stream = std.io.countingWriter(std.io.null_writer);187 var buf: [1024]u8 = undefined;
185 const writer = stream.writer();188 var bw: std.io.BufferedWriter = .{
189 .unbuffered_writer = .null,
190 .buffer = &buf,
191 };
186 const slice = self.nodes.slice();192 const slice = self.nodes.slice();
187193
188 var node_size: u32 = 0;194 var node_size: u32 = 0;
189 if (slice.items(.is_terminal)[node_index]) {195 if (slice.items(.is_terminal)[node_index]) {
190 const export_flags = slice.items(.export_flags)[node_index];196 const export_flags = slice.items(.export_flags)[node_index];
191 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];197 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];
192 try leb.writeULEB128(writer, export_flags);198 try bw.writeLeb128(export_flags);
193 try leb.writeULEB128(writer, vmaddr_offset);199 try bw.writeLeb128(vmaddr_offset);
194 try leb.writeULEB128(writer, stream.bytes_written);200 try bw.writeLeb128(bw.count);
195 } else {201 } else {
196 node_size += 1; // 0x0 for non-terminal nodes202 node_size += 1; // 0x0 for non-terminal nodes
197 }203 }
...@@ -201,13 +207,13 @@ fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !Final...@@ -201,13 +207,13 @@ fn finalizeNode(self: *Trie, node_index: Node.Index, offset_in_trie: u32) !Final
201 const edge = &self.edges.items[edge_index];207 const edge = &self.edges.items[edge_index];
202 const next_node_offset = slice.items(.trie_offset)[edge.node];208 const next_node_offset = slice.items(.trie_offset)[edge.node];
203 node_size += @intCast(edge.label.len + 1);209 node_size += @intCast(edge.label.len + 1);
204 try leb.writeULEB128(writer, next_node_offset);210 try bw.writeLeb128(next_node_offset);
205 }211 }
206212
207 const trie_offset = slice.items(.trie_offset)[node_index];213 const trie_offset = slice.items(.trie_offset)[node_index];
208 const updated = offset_in_trie != trie_offset;214 const updated = offset_in_trie != trie_offset;
209 slice.items(.trie_offset)[node_index] = offset_in_trie;215 slice.items(.trie_offset)[node_index] = offset_in_trie;
210 node_size += @intCast(stream.bytes_written);216 node_size += @intCast(bw.count);
211217
212 return .{ .node_size = node_size, .updated = updated };218 return .{ .node_size = node_size, .updated = updated };
213}219}
...@@ -223,12 +229,11 @@ pub fn deinit(self: *Trie, allocator: Allocator) void {...@@ -223,12 +229,11 @@ pub fn deinit(self: *Trie, allocator: Allocator) void {
223 }229 }
224 self.nodes.deinit(allocator);230 self.nodes.deinit(allocator);
225 self.edges.deinit(allocator);231 self.edges.deinit(allocator);
226 self.buffer.deinit(allocator);232 allocator.free(self.buffer);
227}233}
228234
229pub fn write(self: Trie, writer: anytype) !void {235pub fn write(self: Trie, bw: *std.io.BufferedWriter) anyerror!void {
230 if (self.buffer.items.len == 0) return;236 try bw.writeAll(self.buffer);
231 try writer.writeAll(self.buffer.items);
232}237}
233238
234/// Writes this node to a byte stream.239/// Writes this node to a byte stream.
...@@ -237,7 +242,7 @@ pub fn write(self: Trie, writer: anytype) !void {...@@ -237,7 +242,7 @@ pub fn write(self: Trie, writer: anytype) !void {
237/// iterate over `Trie.ordered_nodes` and call this method on each node.242/// iterate over `Trie.ordered_nodes` and call this method on each node.
238/// This is one of the requirements of the MachO.243/// This is one of the requirements of the MachO.
239/// Panics if `finalize` was not called before calling this method.244/// Panics if `finalize` was not called before calling this method.
240fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void {245fn writeNode(self: *Trie, node_index: Node.Index, bw: *std.io.BufferedWriter) !void {
241 const slice = self.nodes.slice();246 const slice = self.nodes.slice();
242 const edges = slice.items(.edges)[node_index];247 const edges = slice.items(.edges)[node_index];
243 const is_terminal = slice.items(.is_terminal)[node_index];248 const is_terminal = slice.items(.is_terminal)[node_index];
...@@ -245,36 +250,28 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void {...@@ -245,36 +250,28 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void {
245 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];250 const vmaddr_offset = slice.items(.vmaddr_offset)[node_index];
246251
247 if (is_terminal) {252 if (is_terminal) {
248 // Terminal node info: encode export flags and vmaddr offset of this symbol.253 const start = bw.count;
249 var info_buf: [@sizeOf(u64) * 2]u8 = undefined;
250 var info_stream = std.io.fixedBufferStream(&info_buf);
251 // TODO Implement for special flags.254 // TODO Implement for special flags.
252 assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and255 assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and
253 export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0);256 export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0);
254 try leb.writeULEB128(info_stream.writer(), export_flags);257 // Terminal node info: encode export flags and vmaddr offset of this symbol.
255 try leb.writeULEB128(info_stream.writer(), vmaddr_offset);258 try bw.writeLeb128(export_flags);
256259 try bw.writeLeb128(vmaddr_offset);
257 // Encode the size of the terminal node info.260 // Encode the size of the terminal node info.
258 var size_buf: [@sizeOf(u64)]u8 = undefined;261 try bw.writeLeb128(bw.count - start);
259 var size_stream = std.io.fixedBufferStream(&size_buf);
260 try leb.writeULEB128(size_stream.writer(), info_stream.pos);
261
262 // Now, write them to the output stream.
263 try writer.writeAll(size_buf[0..size_stream.pos]);
264 try writer.writeAll(info_buf[0..info_stream.pos]);
265 } else {262 } else {
266 // Non-terminal node is delimited by 0 byte.263 // Non-terminal node is delimited by 0 byte.
267 try writer.writeByte(0);264 try bw.writeByte(0);
268 }265 }
269 // Write number of edges (max legal number of edges is 256).266 // Write number of edges (max legal number of edges is 255).
270 try writer.writeByte(@as(u8, @intCast(edges.items.len)));267 try bw.writeByte(@intCast(edges.items.len));
271268
272 for (edges.items) |edge_index| {269 for (edges.items) |edge_index| {
273 const edge = self.edges.items[edge_index];270 const edge = self.edges.items[edge_index];
274 // Write edge label and offset to next node in trie.271 // Write edge label and offset to next node in trie.
275 try writer.writeAll(edge.label);272 try bw.writeAll(edge.label);
276 try writer.writeByte(0);273 try bw.writeByte(0);
277 try leb.writeULEB128(writer, slice.items(.trie_offset)[edge.node]);274 try bw.writeLeb128(slice.items(.trie_offset)[edge.node]);
278 }275 }
279}276}
280277
src/link/MachO/dyld_info/bind.zig+151-184
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1pub const Entry = struct {1pub const Entry = struct {
2 target: MachO.Ref,2 target: MachO.Ref,
3 offset: u64,3 offset: u64,
4 segment_id: u8,4 segment_id: u4,
5 addend: i64,5 addend: i64,
66
7 pub fn lessThan(ctx: *MachO, entry: Entry, other: Entry) bool {7 pub fn lessThan(ctx: *MachO, entry: Entry, other: Entry) bool {
...@@ -20,14 +20,12 @@ pub const Bind = struct {...@@ -20,14 +20,12 @@ pub const Bind = struct {
20 entries: std.ArrayListUnmanaged(Entry) = .empty,20 entries: std.ArrayListUnmanaged(Entry) = .empty,
21 buffer: std.ArrayListUnmanaged(u8) = .empty,21 buffer: std.ArrayListUnmanaged(u8) = .empty,
2222
23 const Self = @This();23 pub fn deinit(bind: *Bind, gpa: Allocator) void {
2424 bind.entries.deinit(gpa);
25 pub fn deinit(self: *Self, gpa: Allocator) void {25 bind.buffer.deinit(gpa);
26 self.entries.deinit(gpa);
27 self.buffer.deinit(gpa);
28 }26 }
2927
30 pub fn updateSize(self: *Self, macho_file: *MachO) !void {28 pub fn updateSize(bind: *Bind, macho_file: *MachO) !void {
31 const tracy = trace(@src());29 const tracy = trace(@src());
32 defer tracy.end();30 defer tracy.end();
3331
...@@ -56,15 +54,12 @@ pub const Bind = struct {...@@ -56,15 +54,12 @@ pub const Bind = struct {
56 const addend = rel.addend + rel.getRelocAddend(cpu_arch);54 const addend = rel.addend + rel.getRelocAddend(cpu_arch);
57 const sym = rel.getTargetSymbol(atom.*, macho_file);55 const sym = rel.getTargetSymbol(atom.*, macho_file);
58 if (sym.isTlvInit(macho_file)) continue;56 if (sym.isTlvInit(macho_file)) continue;
59 const entry = Entry{57 if (sym.flags.import or (!(sym.flags.@"export" and sym.flags.weak) and sym.flags.interposable)) (try bind.entries.addOne(gpa)).* = .{
60 .target = rel.getTargetSymbolRef(atom.*, macho_file),58 .target = rel.getTargetSymbolRef(atom.*, macho_file),
61 .offset = atom_addr + rel_offset - seg.vmaddr,59 .offset = atom_addr + rel_offset - seg.vmaddr,
62 .segment_id = seg_id,60 .segment_id = seg_id,
63 .addend = addend,61 .addend = addend,
64 };62 };
65 if (sym.flags.import or (!(sym.flags.@"export" and sym.flags.weak) and sym.flags.interposable)) {
66 try self.entries.append(gpa, entry);
67 }
68 }63 }
69 }64 }
70 }65 }
...@@ -75,15 +70,12 @@ pub const Bind = struct {...@@ -75,15 +70,12 @@ pub const Bind = struct {
75 for (macho_file.got.symbols.items, 0..) |ref, idx| {70 for (macho_file.got.symbols.items, 0..) |ref, idx| {
76 const sym = ref.getSymbol(macho_file).?;71 const sym = ref.getSymbol(macho_file).?;
77 const addr = macho_file.got.getAddress(@intCast(idx), macho_file);72 const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
78 const entry = Entry{73 if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
79 .target = ref,74 .target = ref,
80 .offset = addr - seg.vmaddr,75 .offset = addr - seg.vmaddr,
81 .segment_id = seg_id,76 .segment_id = seg_id,
82 .addend = 0,77 .addend = 0,
83 };78 };
84 if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) {
85 try self.entries.append(gpa, entry);
86 }
87 }79 }
88 }80 }
8981
...@@ -94,15 +86,12 @@ pub const Bind = struct {...@@ -94,15 +86,12 @@ pub const Bind = struct {
94 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {86 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
95 const sym = ref.getSymbol(macho_file).?;87 const sym = ref.getSymbol(macho_file).?;
96 const addr = sect.addr + idx * @sizeOf(u64);88 const addr = sect.addr + idx * @sizeOf(u64);
97 const bind_entry = Entry{89 if (sym.flags.import and sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
98 .target = ref,90 .target = ref,
99 .offset = addr - seg.vmaddr,91 .offset = addr - seg.vmaddr,
100 .segment_id = seg_id,92 .segment_id = seg_id,
101 .addend = 0,93 .addend = 0,
102 };94 };
103 if (sym.flags.import and sym.flags.weak) {
104 try self.entries.append(gpa, bind_entry);
105 }
106 }95 }
107 }96 }
10897
...@@ -113,49 +102,48 @@ pub const Bind = struct {...@@ -113,49 +102,48 @@ pub const Bind = struct {
113 for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {102 for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
114 const sym = ref.getSymbol(macho_file).?;103 const sym = ref.getSymbol(macho_file).?;
115 const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);104 const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
116 const entry = Entry{105 if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
117 .target = ref,106 .target = ref,
118 .offset = addr - seg.vmaddr,107 .offset = addr - seg.vmaddr,
119 .segment_id = seg_id,108 .segment_id = seg_id,
120 .addend = 0,109 .addend = 0,
121 };110 };
122 if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) {
123 try self.entries.append(gpa, entry);
124 }
125 }111 }
126 }112 }
127113
128 try self.finalize(gpa, macho_file);114 try bind.finalize(gpa, macho_file);
129 macho_file.dyld_info_cmd.bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));115 macho_file.dyld_info_cmd.bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
130 }116 }
131117
132 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {118 fn finalize(bind: *Bind, gpa: Allocator, ctx: *MachO) !void {
133 if (self.entries.items.len == 0) return;119 if (bind.entries.items.len == 0) return;
134120
135 const writer = self.buffer.writer(gpa);121 var aw: std.io.AllocatingWriter = undefined;
122 const bw = aw.fromArrayList(gpa, &bind.buffer);
123 defer bind.buffer = aw.toArrayList();
136124
137 log.debug("bind opcodes", .{});125 log.debug("bind opcodes", .{});
138126
139 std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);127 std.mem.sort(Entry, bind.entries.items, ctx, Entry.lessThan);
140128
141 var start: usize = 0;129 var start: usize = 0;
142 var seg_id: ?u8 = null;130 var seg_id: ?u8 = null;
143 for (self.entries.items, 0..) |entry, i| {131 for (bind.entries.items, 0..) |entry, i| {
144 if (seg_id != null and seg_id.? == entry.segment_id) continue;132 if (seg_id != null and seg_id.? == entry.segment_id) continue;
145 try finalizeSegment(self.entries.items[start..i], ctx, writer);133 try finalizeSegment(bind.entries.items[start..i], ctx, bw);
146 seg_id = entry.segment_id;134 seg_id = entry.segment_id;
147 start = i;135 start = i;
148 }136 }
149137
150 try finalizeSegment(self.entries.items[start..], ctx, writer);138 try finalizeSegment(bind.entries.items[start..], ctx, bw);
151 try done(writer);139 try done(bw);
152 }140 }
153141
154 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {142 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *std.io.BufferedWriter) anyerror!void {
155 if (entries.len == 0) return;143 if (entries.len == 0) return;
156144
157 const seg_id = entries[0].segment_id;145 const seg_id = entries[0].segment_id;
158 try setSegmentOffset(seg_id, 0, writer);146 try setSegmentOffset(seg_id, 0, bw);
159147
160 var offset: u64 = 0;148 var offset: u64 = 0;
161 var addend: i64 = 0;149 var addend: i64 = 0;
...@@ -175,15 +163,15 @@ pub const Bind = struct {...@@ -175,15 +163,15 @@ pub const Bind = struct {
175 if (target == null or !target.?.eql(current.target)) {163 if (target == null or !target.?.eql(current.target)) {
176 switch (state) {164 switch (state) {
177 .start => {},165 .start => {},
178 .bind_single => try doBind(writer),166 .bind_single => try doBind(bw),
179 .bind_times_skip => try doBindTimesSkip(count, skip, writer),167 .bind_times_skip => try doBindTimesSkip(count, skip, bw),
180 }168 }
181 state = .start;169 state = .start;
182 target = current.target;170 target = current.target;
183171
184 const sym = current.target.getSymbol(ctx).?;172 const sym = current.target.getSymbol(ctx).?;
185 const name = sym.getName(ctx);173 const name = sym.getName(ctx);
186 const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;174 const flags: u4 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
187 const ordinal: i16 = ord: {175 const ordinal: i16 = ord: {
188 if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;176 if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
189 if (sym.flags.import) {177 if (sym.flags.import) {
...@@ -195,13 +183,13 @@ pub const Bind = struct {...@@ -195,13 +183,13 @@ pub const Bind = struct {
195 break :ord macho.BIND_SPECIAL_DYLIB_SELF;183 break :ord macho.BIND_SPECIAL_DYLIB_SELF;
196 };184 };
197185
198 try setSymbol(name, flags, writer);186 try setSymbol(name, flags, bw);
199 try setTypePointer(writer);187 try setTypePointer(bw);
200 try setDylibOrdinal(ordinal, writer);188 try setDylibOrdinal(ordinal, bw);
201189
202 if (current.addend != addend) {190 if (current.addend != addend) {
203 addend = current.addend;191 addend = current.addend;
204 try setAddend(addend, writer);192 try setAddend(addend, bw);
205 }193 }
206 }194 }
207195
...@@ -210,11 +198,11 @@ pub const Bind = struct {...@@ -210,11 +198,11 @@ pub const Bind = struct {
210 switch (state) {198 switch (state) {
211 .start => {199 .start => {
212 if (current.offset < offset) {200 if (current.offset < offset) {
213 try addAddr(@bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset))), writer);201 try addAddr(@bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset))), bw);
214 offset = offset - (offset - current.offset);202 offset = offset - (offset - current.offset);
215 } else if (current.offset > offset) {203 } else if (current.offset > offset) {
216 const delta = current.offset - offset;204 const delta = current.offset - offset;
217 try addAddr(delta, writer);205 try addAddr(delta, bw);
218 offset += delta;206 offset += delta;
219 }207 }
220 state = .bind_single;208 state = .bind_single;
...@@ -223,7 +211,7 @@ pub const Bind = struct {...@@ -223,7 +211,7 @@ pub const Bind = struct {
223 },211 },
224 .bind_single => {212 .bind_single => {
225 if (current.offset == offset) {213 if (current.offset == offset) {
226 try doBind(writer);214 try doBind(bw);
227 state = .start;215 state = .start;
228 } else if (current.offset > offset) {216 } else if (current.offset > offset) {
229 const delta = current.offset - offset;217 const delta = current.offset - offset;
...@@ -237,9 +225,9 @@ pub const Bind = struct {...@@ -237,9 +225,9 @@ pub const Bind = struct {
237 if (current.offset < offset) {225 if (current.offset < offset) {
238 count -= 1;226 count -= 1;
239 if (count == 1) {227 if (count == 1) {
240 try doBindAddAddr(skip, writer);228 try doBindAddAddr(skip, bw);
241 } else {229 } else {
242 try doBindTimesSkip(count, skip, writer);230 try doBindTimesSkip(count, skip, bw);
243 }231 }
244 state = .start;232 state = .start;
245 offset = offset - (@sizeOf(u64) + skip);233 offset = offset - (@sizeOf(u64) + skip);
...@@ -248,7 +236,7 @@ pub const Bind = struct {...@@ -248,7 +236,7 @@ pub const Bind = struct {
248 count += 1;236 count += 1;
249 offset += @sizeOf(u64) + skip;237 offset += @sizeOf(u64) + skip;
250 } else {238 } else {
251 try doBindTimesSkip(count, skip, writer);239 try doBindTimesSkip(count, skip, bw);
252 state = .start;240 state = .start;
253 i -= 1;241 i -= 1;
254 }242 }
...@@ -258,13 +246,13 @@ pub const Bind = struct {...@@ -258,13 +246,13 @@ pub const Bind = struct {
258246
259 switch (state) {247 switch (state) {
260 .start => unreachable,248 .start => unreachable,
261 .bind_single => try doBind(writer),249 .bind_single => try doBind(bw),
262 .bind_times_skip => try doBindTimesSkip(count, skip, writer),250 .bind_times_skip => try doBindTimesSkip(count, skip, bw),
263 }251 }
264 }252 }
265253
266 pub fn write(self: Self, writer: anytype) !void {254 pub fn write(bind: Bind, bw: *std.io.BufferedWriter) anyerror!void {
267 try writer.writeAll(self.buffer.items);255 try bw.writeAll(bind.buffer.items);
268 }256 }
269};257};
270258
...@@ -272,14 +260,12 @@ pub const WeakBind = struct {...@@ -272,14 +260,12 @@ pub const WeakBind = struct {
272 entries: std.ArrayListUnmanaged(Entry) = .empty,260 entries: std.ArrayListUnmanaged(Entry) = .empty,
273 buffer: std.ArrayListUnmanaged(u8) = .empty,261 buffer: std.ArrayListUnmanaged(u8) = .empty,
274262
275 const Self = @This();263 pub fn deinit(bind: *WeakBind, gpa: Allocator) void {
276264 bind.entries.deinit(gpa);
277 pub fn deinit(self: *Self, gpa: Allocator) void {265 bind.buffer.deinit(gpa);
278 self.entries.deinit(gpa);
279 self.buffer.deinit(gpa);
280 }266 }
281267
282 pub fn updateSize(self: *Self, macho_file: *MachO) !void {268 pub fn updateSize(bind: *WeakBind, macho_file: *MachO) !void {
283 const tracy = trace(@src());269 const tracy = trace(@src());
284 defer tracy.end();270 defer tracy.end();
285271
...@@ -308,15 +294,12 @@ pub const WeakBind = struct {...@@ -308,15 +294,12 @@ pub const WeakBind = struct {
308 const addend = rel.addend + rel.getRelocAddend(cpu_arch);294 const addend = rel.addend + rel.getRelocAddend(cpu_arch);
309 const sym = rel.getTargetSymbol(atom.*, macho_file);295 const sym = rel.getTargetSymbol(atom.*, macho_file);
310 if (sym.isTlvInit(macho_file)) continue;296 if (sym.isTlvInit(macho_file)) continue;
311 const entry = Entry{297 if (!sym.isLocal() and sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
312 .target = rel.getTargetSymbolRef(atom.*, macho_file),298 .target = rel.getTargetSymbolRef(atom.*, macho_file),
313 .offset = atom_addr + rel_offset - seg.vmaddr,299 .offset = atom_addr + rel_offset - seg.vmaddr,
314 .segment_id = seg_id,300 .segment_id = seg_id,
315 .addend = addend,301 .addend = addend,
316 };302 };
317 if (!sym.isLocal() and sym.flags.weak) {
318 try self.entries.append(gpa, entry);
319 }
320 }303 }
321 }304 }
322 }305 }
...@@ -327,15 +310,12 @@ pub const WeakBind = struct {...@@ -327,15 +310,12 @@ pub const WeakBind = struct {
327 for (macho_file.got.symbols.items, 0..) |ref, idx| {310 for (macho_file.got.symbols.items, 0..) |ref, idx| {
328 const sym = ref.getSymbol(macho_file).?;311 const sym = ref.getSymbol(macho_file).?;
329 const addr = macho_file.got.getAddress(@intCast(idx), macho_file);312 const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
330 const entry = Entry{313 if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
331 .target = ref,314 .target = ref,
332 .offset = addr - seg.vmaddr,315 .offset = addr - seg.vmaddr,
333 .segment_id = seg_id,316 .segment_id = seg_id,
334 .addend = 0,317 .addend = 0,
335 };318 };
336 if (sym.flags.weak) {
337 try self.entries.append(gpa, entry);
338 }
339 }319 }
340 }320 }
341321
...@@ -347,15 +327,12 @@ pub const WeakBind = struct {...@@ -347,15 +327,12 @@ pub const WeakBind = struct {
347 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {327 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
348 const sym = ref.getSymbol(macho_file).?;328 const sym = ref.getSymbol(macho_file).?;
349 const addr = sect.addr + idx * @sizeOf(u64);329 const addr = sect.addr + idx * @sizeOf(u64);
350 const bind_entry = Entry{330 if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
351 .target = ref,331 .target = ref,
352 .offset = addr - seg.vmaddr,332 .offset = addr - seg.vmaddr,
353 .segment_id = seg_id,333 .segment_id = seg_id,
354 .addend = 0,334 .addend = 0,
355 };335 };
356 if (sym.flags.weak) {
357 try self.entries.append(gpa, bind_entry);
358 }
359 }336 }
360 }337 }
361338
...@@ -366,49 +343,48 @@ pub const WeakBind = struct {...@@ -366,49 +343,48 @@ pub const WeakBind = struct {
366 for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {343 for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
367 const sym = ref.getSymbol(macho_file).?;344 const sym = ref.getSymbol(macho_file).?;
368 const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);345 const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
369 const entry = Entry{346 if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
370 .target = ref,347 .target = ref,
371 .offset = addr - seg.vmaddr,348 .offset = addr - seg.vmaddr,
372 .segment_id = seg_id,349 .segment_id = seg_id,
373 .addend = 0,350 .addend = 0,
374 };351 };
375 if (sym.flags.weak) {
376 try self.entries.append(gpa, entry);
377 }
378 }352 }
379 }353 }
380354
381 try self.finalize(gpa, macho_file);355 try bind.finalize(gpa, macho_file);
382 macho_file.dyld_info_cmd.weak_bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));356 macho_file.dyld_info_cmd.weak_bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
383 }357 }
384358
385 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {359 fn finalize(bind: *WeakBind, gpa: Allocator, ctx: *MachO) !void {
386 if (self.entries.items.len == 0) return;360 if (bind.entries.items.len == 0) return;
387361
388 const writer = self.buffer.writer(gpa);362 var aw: std.io.AllocatingWriter = undefined;
363 const bw = aw.fromArrayList(gpa, &bind.buffer);
364 defer bind.buffer = aw.toArrayList();
389365
390 log.debug("weak bind opcodes", .{});366 log.debug("weak bind opcodes", .{});
391367
392 std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);368 std.mem.sort(Entry, bind.entries.items, ctx, Entry.lessThan);
393369
394 var start: usize = 0;370 var start: usize = 0;
395 var seg_id: ?u8 = null;371 var seg_id: ?u8 = null;
396 for (self.entries.items, 0..) |entry, i| {372 for (bind.entries.items, 0..) |entry, i| {
397 if (seg_id != null and seg_id.? == entry.segment_id) continue;373 if (seg_id != null and seg_id.? == entry.segment_id) continue;
398 try finalizeSegment(self.entries.items[start..i], ctx, writer);374 try finalizeSegment(bind.entries.items[start..i], ctx, bw);
399 seg_id = entry.segment_id;375 seg_id = entry.segment_id;
400 start = i;376 start = i;
401 }377 }
402378
403 try finalizeSegment(self.entries.items[start..], ctx, writer);379 try finalizeSegment(bind.entries.items[start..], ctx, bw);
404 try done(writer);380 try done(bw);
405 }381 }
406382
407 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {383 fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *std.io.BufferedWriter) anyerror!void {
408 if (entries.len == 0) return;384 if (entries.len == 0) return;
409385
410 const seg_id = entries[0].segment_id;386 const seg_id = entries[0].segment_id;
411 try setSegmentOffset(seg_id, 0, writer);387 try setSegmentOffset(seg_id, 0, bw);
412388
413 var offset: u64 = 0;389 var offset: u64 = 0;
414 var addend: i64 = 0;390 var addend: i64 = 0;
...@@ -428,8 +404,8 @@ pub const WeakBind = struct {...@@ -428,8 +404,8 @@ pub const WeakBind = struct {
428 if (target == null or !target.?.eql(current.target)) {404 if (target == null or !target.?.eql(current.target)) {
429 switch (state) {405 switch (state) {
430 .start => {},406 .start => {},
431 .bind_single => try doBind(writer),407 .bind_single => try doBind(bw),
432 .bind_times_skip => try doBindTimesSkip(count, skip, writer),408 .bind_times_skip => try doBindTimesSkip(count, skip, bw),
433 }409 }
434 state = .start;410 state = .start;
435 target = current.target;411 target = current.target;
...@@ -438,12 +414,12 @@ pub const WeakBind = struct {...@@ -438,12 +414,12 @@ pub const WeakBind = struct {
438 const name = sym.getName(ctx);414 const name = sym.getName(ctx);
439 const flags: u8 = 0; // TODO NON_WEAK_DEFINITION415 const flags: u8 = 0; // TODO NON_WEAK_DEFINITION
440416
441 try setSymbol(name, flags, writer);417 try setSymbol(name, flags, bw);
442 try setTypePointer(writer);418 try setTypePointer(bw);
443419
444 if (current.addend != addend) {420 if (current.addend != addend) {
445 addend = current.addend;421 addend = current.addend;
446 try setAddend(addend, writer);422 try setAddend(addend, bw);
447 }423 }
448 }424 }
449425
...@@ -452,11 +428,11 @@ pub const WeakBind = struct {...@@ -452,11 +428,11 @@ pub const WeakBind = struct {
452 switch (state) {428 switch (state) {
453 .start => {429 .start => {
454 if (current.offset < offset) {430 if (current.offset < offset) {
455 try addAddr(@as(u64, @bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset)))), writer);431 try addAddr(@as(u64, @bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset)))), bw);
456 offset = offset - (offset - current.offset);432 offset = offset - (offset - current.offset);
457 } else if (current.offset > offset) {433 } else if (current.offset > offset) {
458 const delta = current.offset - offset;434 const delta = current.offset - offset;
459 try addAddr(delta, writer);435 try addAddr(delta, bw);
460 offset += delta;436 offset += delta;
461 }437 }
462 state = .bind_single;438 state = .bind_single;
...@@ -465,7 +441,7 @@ pub const WeakBind = struct {...@@ -465,7 +441,7 @@ pub const WeakBind = struct {
465 },441 },
466 .bind_single => {442 .bind_single => {
467 if (current.offset == offset) {443 if (current.offset == offset) {
468 try doBind(writer);444 try doBind(bw);
469 state = .start;445 state = .start;
470 } else if (current.offset > offset) {446 } else if (current.offset > offset) {
471 const delta = current.offset - offset;447 const delta = current.offset - offset;
...@@ -479,9 +455,9 @@ pub const WeakBind = struct {...@@ -479,9 +455,9 @@ pub const WeakBind = struct {
479 if (current.offset < offset) {455 if (current.offset < offset) {
480 count -= 1;456 count -= 1;
481 if (count == 1) {457 if (count == 1) {
482 try doBindAddAddr(skip, writer);458 try doBindAddAddr(skip, bw);
483 } else {459 } else {
484 try doBindTimesSkip(count, skip, writer);460 try doBindTimesSkip(count, skip, bw);
485 }461 }
486 state = .start;462 state = .start;
487 offset = offset - (@sizeOf(u64) + skip);463 offset = offset - (@sizeOf(u64) + skip);
...@@ -490,7 +466,7 @@ pub const WeakBind = struct {...@@ -490,7 +466,7 @@ pub const WeakBind = struct {
490 count += 1;466 count += 1;
491 offset += @sizeOf(u64) + skip;467 offset += @sizeOf(u64) + skip;
492 } else {468 } else {
493 try doBindTimesSkip(count, skip, writer);469 try doBindTimesSkip(count, skip, bw);
494 state = .start;470 state = .start;
495 i -= 1;471 i -= 1;
496 }472 }
...@@ -500,13 +476,13 @@ pub const WeakBind = struct {...@@ -500,13 +476,13 @@ pub const WeakBind = struct {
500476
501 switch (state) {477 switch (state) {
502 .start => unreachable,478 .start => unreachable,
503 .bind_single => try doBind(writer),479 .bind_single => try doBind(bw),
504 .bind_times_skip => try doBindTimesSkip(count, skip, writer),480 .bind_times_skip => try doBindTimesSkip(count, skip, bw),
505 }481 }
506 }482 }
507483
508 pub fn write(self: Self, writer: anytype) !void {484 pub fn write(bind: WeakBind, bw: *std.io.BufferedWriter) anyerror!void {
509 try writer.writeAll(self.buffer.items);485 try bw.writeAll(bind.buffer.items);
510 }486 }
511};487};
512488
...@@ -515,15 +491,13 @@ pub const LazyBind = struct {...@@ -515,15 +491,13 @@ pub const LazyBind = struct {
515 buffer: std.ArrayListUnmanaged(u8) = .empty,491 buffer: std.ArrayListUnmanaged(u8) = .empty,
516 offsets: std.ArrayListUnmanaged(u32) = .empty,492 offsets: std.ArrayListUnmanaged(u32) = .empty,
517493
518 const Self = @This();494 pub fn deinit(bind: *LazyBind, gpa: Allocator) void {
519495 bind.entries.deinit(gpa);
520 pub fn deinit(self: *Self, gpa: Allocator) void {496 bind.buffer.deinit(gpa);
521 self.entries.deinit(gpa);497 bind.offsets.deinit(gpa);
522 self.buffer.deinit(gpa);
523 self.offsets.deinit(gpa);
524 }498 }
525499
526 pub fn updateSize(self: *Self, macho_file: *MachO) !void {500 pub fn updateSize(bind: *LazyBind, macho_file: *MachO) !void {
527 const tracy = trace(@src());501 const tracy = trace(@src());
528 defer tracy.end();502 defer tracy.end();
529503
...@@ -537,36 +511,35 @@ pub const LazyBind = struct {...@@ -537,36 +511,35 @@ pub const LazyBind = struct {
537 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {511 for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
538 const sym = ref.getSymbol(macho_file).?;512 const sym = ref.getSymbol(macho_file).?;
539 const addr = sect.addr + idx * @sizeOf(u64);513 const addr = sect.addr + idx * @sizeOf(u64);
540 const bind_entry = Entry{514 if ((sym.flags.import and !sym.flags.weak) or (sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
541 .target = ref,515 .target = ref,
542 .offset = addr - seg.vmaddr,516 .offset = addr - seg.vmaddr,
543 .segment_id = seg_id,517 .segment_id = seg_id,
544 .addend = 0,518 .addend = 0,
545 };519 };
546 if ((sym.flags.import and !sym.flags.weak) or (sym.flags.interposable and !sym.flags.weak)) {
547 try self.entries.append(gpa, bind_entry);
548 }
549 }520 }
550521
551 try self.finalize(gpa, macho_file);522 try bind.finalize(gpa, macho_file);
552 macho_file.dyld_info_cmd.lazy_bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));523 macho_file.dyld_info_cmd.lazy_bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
553 }524 }
554525
555 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {526 fn finalize(bind: *LazyBind, gpa: Allocator, ctx: *MachO) !void {
556 try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len);527 try bind.offsets.ensureTotalCapacityPrecise(gpa, bind.entries.items.len);
557528
558 const writer = self.buffer.writer(gpa);529 var aw: std.io.AllocatingWriter = undefined;
530 const bw = aw.fromArrayList(gpa, &bind.buffer);
531 defer bind.buffer = aw.toArrayList();
559532
560 log.debug("lazy bind opcodes", .{});533 log.debug("lazy bind opcodes", .{});
561534
562 var addend: i64 = 0;535 var addend: i64 = 0;
563536
564 for (self.entries.items) |entry| {537 for (bind.entries.items) |entry| {
565 self.offsets.appendAssumeCapacity(@intCast(self.buffer.items.len));538 bind.offsets.appendAssumeCapacity(@intCast(bind.buffer.items.len));
566539
567 const sym = entry.target.getSymbol(ctx).?;540 const sym = entry.target.getSymbol(ctx).?;
568 const name = sym.getName(ctx);541 const name = sym.getName(ctx);
569 const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;542 const flags: u4 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
570 const ordinal: i16 = ord: {543 const ordinal: i16 = ord: {
571 if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;544 if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
572 if (sym.flags.import) {545 if (sym.flags.import) {
...@@ -578,109 +551,103 @@ pub const LazyBind = struct {...@@ -578,109 +551,103 @@ pub const LazyBind = struct {
578 break :ord macho.BIND_SPECIAL_DYLIB_SELF;551 break :ord macho.BIND_SPECIAL_DYLIB_SELF;
579 };552 };
580553
581 try setSegmentOffset(entry.segment_id, entry.offset, writer);554 try setSegmentOffset(entry.segment_id, entry.offset, bw);
582 try setSymbol(name, flags, writer);555 try setSymbol(name, flags, bw);
583 try setDylibOrdinal(ordinal, writer);556 try setDylibOrdinal(ordinal, bw);
584557
585 if (entry.addend != addend) {558 if (entry.addend != addend) {
586 try setAddend(entry.addend, writer);559 try setAddend(entry.addend, bw);
587 addend = entry.addend;560 addend = entry.addend;
588 }561 }
589562
590 try doBind(writer);563 try doBind(bw);
591 try done(writer);564 try done(bw);
592 }565 }
593 }566 }
594567
595 pub fn write(self: Self, writer: anytype) !void {568 pub fn write(bind: LazyBind, bw: *std.io.BufferedWriter) anyerror!void {
596 try writer.writeAll(self.buffer.items);569 try bw.writeAll(bind.buffer.items);
597 }570 }
598};571};
599572
600fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void {573fn setSegmentOffset(segment_id: u4, offset: u64, bw: *std.io.BufferedWriter) anyerror!void {
601 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });574 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
602 try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));575 try bw.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segment_id);
603 try std.leb.writeUleb128(writer, offset);576 try bw.writeLeb128(offset);
604}577}
605578
606fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void {579fn setSymbol(name: []const u8, flags: u4, bw: *std.io.BufferedWriter) anyerror!void {
607 log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });580 log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });
608 try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags)));581 try bw.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
609 try writer.writeAll(name);582 try bw.writeAll(name);
610 try writer.writeByte(0);583 try bw.writeByte(0);
611}584}
612585
613fn setTypePointer(writer: anytype) !void {586fn setTypePointer(bw: *std.io.BufferedWriter) anyerror!void {
614 log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});587 log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});
615 try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER)));588 try bw.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.BIND_TYPE_POINTER)));
616}589}
617590
618fn setDylibOrdinal(ordinal: i16, writer: anytype) !void {591fn setDylibOrdinal(ordinal: i16, bw: *std.io.BufferedWriter) anyerror!void {
619 if (ordinal <= 0) {592 switch (ordinal) {
620 switch (ordinal) {593 else => unreachable, // Invalid dylib special binding
621 macho.BIND_SPECIAL_DYLIB_SELF,594 macho.BIND_SPECIAL_DYLIB_SELF,
622 macho.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE,595 macho.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE,
623 macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP,596 macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP,
624 => {},597 => {
625 else => unreachable, // Invalid dylib special binding598 log.debug(">>> set dylib special: {d}", .{ordinal});
626 }599 try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @as(u4, @bitCast(@as(i4, @intCast(ordinal)))));
627 log.debug(">>> set dylib special: {d}", .{ordinal});600 },
628 const cast = @as(u16, @bitCast(ordinal));601 1...std.math.maxInt(i16) => {
629 try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @as(u4, @truncate(cast)));602 log.debug(">>> set dylib ordinal: {d}", .{ordinal});
630 } else {603 if (std.math.cast(u4, ordinal)) |imm| {
631 const cast = @as(u16, @bitCast(ordinal));604 try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | imm);
632 log.debug(">>> set dylib ordinal: {d}", .{ordinal});605 } else {
633 if (cast <= 0xf) {606 try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
634 try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @as(u4, @truncate(cast)));607 try bw.writeUleb128(ordinal);
635 } else {608 }
636 try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);609 },
637 try std.leb.writeUleb128(writer, cast);
638 }
639 }610 }
640}611}
641612
642fn setAddend(addend: i64, writer: anytype) !void {613fn setAddend(addend: i64, bw: *std.io.BufferedWriter) anyerror!void {
643 log.debug(">>> set addend: {x}", .{addend});614 log.debug(">>> set addend: {x}", .{addend});
644 try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);615 try bw.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);
645 try std.leb.writeIleb128(writer, addend);616 try bw.writeLeb128(addend);
646}617}
647618
648fn doBind(writer: anytype) !void {619fn doBind(bw: *std.io.BufferedWriter) anyerror!void {
649 log.debug(">>> bind", .{});620 log.debug(">>> bind", .{});
650 try writer.writeByte(macho.BIND_OPCODE_DO_BIND);621 try bw.writeByte(macho.BIND_OPCODE_DO_BIND);
651}622}
652623
653fn doBindAddAddr(addr: u64, writer: anytype) !void {624fn doBindAddAddr(addr: u64, bw: *std.io.BufferedWriter) anyerror!void {
654 log.debug(">>> bind with add: {x}", .{addr});625 log.debug(">>> bind with add: {x}", .{addr});
655 if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) {626 if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {
656 const imm = @divExact(addr, @sizeOf(u64));627 if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(
657 if (imm <= 0xf) {628 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | imm_scaled,
658 try writer.writeByte(629 );
659 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | @as(u4, @truncate(imm)),630 } else |_| {}
660 );631 try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
661 return;632 try bw.writeLeb128(addr);
662 }
663 }
664 try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
665 try std.leb.writeUleb128(writer, addr);
666}633}
667634
668fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void {635fn doBindTimesSkip(count: usize, skip: u64, bw: *std.io.BufferedWriter) anyerror!void {
669 log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });636 log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });
670 try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);637 try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
671 try std.leb.writeUleb128(writer, count);638 try bw.writeLeb128(count);
672 try std.leb.writeUleb128(writer, skip);639 try bw.writeLeb128(skip);
673}640}
674641
675fn addAddr(addr: u64, writer: anytype) !void {642fn addAddr(addr: u64, bw: *std.io.BufferedWriter) anyerror!void {
676 log.debug(">>> add: {x}", .{addr});643 log.debug(">>> add: {x}", .{addr});
677 try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);644 try bw.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);
678 try std.leb.writeUleb128(writer, addr);645 try bw.writeLeb128(addr);
679}646}
680647
681fn done(writer: anytype) !void {648fn done(bw: *std.io.BufferedWriter) anyerror!void {
682 log.debug(">>> done", .{});649 log.debug(">>> done", .{});
683 try writer.writeByte(macho.BIND_OPCODE_DONE);650 try bw.writeByte(macho.BIND_OPCODE_DONE);
684}651}
685652
686const assert = std.debug.assert;653const assert = std.debug.assert;
src/link/MachO/eh_frame.zig+37-53
...@@ -12,36 +12,34 @@ pub const Cie = struct {...@@ -12,36 +12,34 @@ pub const Cie = struct {
12 const tracy = trace(@src());12 const tracy = trace(@src());
13 defer tracy.end();13 defer tracy.end();
1414
15 const data = cie.getData(macho_file);15 var br: std.io.BufferedReader = undefined;
16 const aug = std.mem.sliceTo(@as([*:0]const u8, @ptrCast(data.ptr + 9)), 0);16 br.initFixed(cie.getData(macho_file));
1717
18 try br.discard(9);
19 const aug = try br.takeSentinel(0);
18 if (aug[0] != 'z') return; // TODO should we error out?20 if (aug[0] != 'z') return; // TODO should we error out?
1921
20 var stream = std.io.fixedBufferStream(data[9 + aug.len + 1 ..]);22 _ = try br.takeLeb128(u64); // code alignment factor
21 var creader = std.io.countingReader(stream.reader());23 _ = try br.takeLeb128(u64); // data alignment factor
22 const reader = creader.reader();24 _ = try br.takeLeb128(u64); // return address register
2325 _ = try br.takeLeb128(u64); // augmentation data length
24 _ = try leb.readUleb128(u64, reader); // code alignment factor
25 _ = try leb.readUleb128(u64, reader); // data alignment factor
26 _ = try leb.readUleb128(u64, reader); // return address register
27 _ = try leb.readUleb128(u64, reader); // augmentation data length
2826
29 for (aug[1..]) |ch| switch (ch) {27 for (aug[1..]) |ch| switch (ch) {
30 'R' => {28 'R' => {
31 const enc = try reader.readByte();29 const enc = try br.takeByte();
32 if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) {30 if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) {
33 @panic("unexpected pointer encoding"); // TODO error31 @panic("unexpected pointer encoding"); // TODO error
34 }32 }
35 },33 },
36 'P' => {34 'P' => {
37 const enc = try reader.readByte();35 const enc = try br.takeByte();
38 if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) {36 if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) {
39 @panic("unexpected personality pointer encoding"); // TODO error37 @panic("unexpected personality pointer encoding"); // TODO error
40 }38 }
41 _ = try reader.readInt(u32, .little); // personality pointer39 _ = try br.takeInt(u32, .little); // personality pointer
42 },40 },
43 'L' => {41 'L' => {
44 const enc = try reader.readByte();42 const enc = try br.takeByte();
45 switch (enc & DW_EH_PE.type_mask) {43 switch (enc & DW_EH_PE.type_mask) {
46 DW_EH_PE.sdata4 => cie.lsda_size = .p32,44 DW_EH_PE.sdata4 => cie.lsda_size = .p32,
47 DW_EH_PE.absptr => cie.lsda_size = .p64,45 DW_EH_PE.absptr => cie.lsda_size = .p64,
...@@ -106,20 +104,14 @@ pub const Cie = struct {...@@ -106,20 +104,14 @@ pub const Cie = struct {
106 macho_file: *MachO,104 macho_file: *MachO,
107 };105 };
108106
109 fn format2(107 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
110 ctx: FormatContext,
111 comptime unused_fmt_string: []const u8,
112 options: std.fmt.FormatOptions,
113 writer: anytype,
114 ) !void {
115 _ = unused_fmt_string;108 _ = unused_fmt_string;
116 _ = options;
117 const cie = ctx.cie;109 const cie = ctx.cie;
118 try writer.print("@{x} : size({x})", .{110 try bw.print("@{x} : size({x})", .{
119 cie.offset,111 cie.offset,
120 cie.getSize(),112 cie.getSize(),
121 });113 });
122 if (!cie.alive) try writer.writeAll(" : [*]");114 if (!cie.alive) try bw.writeAll(" : [*]");
123 }115 }
124116
125 pub const Index = u32;117 pub const Index = u32;
...@@ -148,12 +140,17 @@ pub const Fde = struct {...@@ -148,12 +140,17 @@ pub const Fde = struct {
148 const tracy = trace(@src());140 const tracy = trace(@src());
149 defer tracy.end();141 defer tracy.end();
150142
151 const data = fde.getData(macho_file);
152 const object = fde.getObject(macho_file);143 const object = fde.getObject(macho_file);
153 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];144 const sect = object.sections.items(.header)[object.eh_frame_sect_index.?];
154145
146 var br: std.io.BufferedReader = undefined;
147 br.initFixed(fde.getData(macho_file));
148
149 try br.discard(4);
150 const cie_ptr = try br.takeInt(u32, .little);
151 const pc_begin = try br.takeInt(i64, .little);
152
155 // Parse target atom index153 // Parse target atom index
156 const pc_begin = std.mem.readInt(i64, data[8..][0..8], .little);
157 const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin);154 const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin);
158 fde.atom = object.findAtom(taddr) orelse {155 fde.atom = object.findAtom(taddr) orelse {
159 try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid function reference in FDE", .{156 try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid function reference in FDE", .{
...@@ -165,7 +162,6 @@ pub const Fde = struct {...@@ -165,7 +162,6 @@ pub const Fde = struct {
165 fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file));162 fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file));
166163
167 // Associate with a CIE164 // Associate with a CIE
168 const cie_ptr = std.mem.readInt(u32, data[4..8], .little);
169 const cie_offset = fde.offset + 4 - cie_ptr;165 const cie_offset = fde.offset + 4 - cie_ptr;
170 const cie_index = for (object.cies.items, 0..) |cie, cie_index| {166 const cie_index = for (object.cies.items, 0..) |cie, cie_index| {
171 if (cie.offset == cie_offset) break @as(Cie.Index, @intCast(cie_index));167 if (cie.offset == cie_offset) break @as(Cie.Index, @intCast(cie_index));
...@@ -183,14 +179,12 @@ pub const Fde = struct {...@@ -183,14 +179,12 @@ pub const Fde = struct {
183179
184 // Parse LSDA atom index if any180 // Parse LSDA atom index if any
185 if (cie.lsda_size) |lsda_size| {181 if (cie.lsda_size) |lsda_size| {
186 var stream = std.io.fixedBufferStream(data[24..]);182 try br.discard(8);
187 var creader = std.io.countingReader(stream.reader());183 _ = try br.takeLeb128(u64); // augmentation length
188 const reader = creader.reader();184 fde.lsda_ptr_offset = @intCast(br.seek);
189 _ = try leb.readUleb128(u64, reader); // augmentation length
190 fde.lsda_ptr_offset = @intCast(creader.bytes_read + 24);
191 const lsda_ptr = switch (lsda_size) {185 const lsda_ptr = switch (lsda_size) {
192 .p32 => try reader.readInt(i32, .little),186 .p32 => try br.takeInt(i32, .little),
193 .p64 => try reader.readInt(i64, .little),187 .p64 => try br.takeInt(i64, .little),
194 };188 };
195 const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr);189 const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr);
196 fde.lsda = object.findAtom(lsda_addr) orelse {190 fde.lsda = object.findAtom(lsda_addr) orelse {
...@@ -256,31 +250,24 @@ pub const Fde = struct {...@@ -256,31 +250,24 @@ pub const Fde = struct {
256 macho_file: *MachO,250 macho_file: *MachO,
257 };251 };
258252
259 fn format2(253 fn format2(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
260 ctx: FormatContext,
261 comptime unused_fmt_string: []const u8,
262 options: std.fmt.FormatOptions,
263 writer: anytype,
264 ) !void {
265 _ = unused_fmt_string;254 _ = unused_fmt_string;
266 _ = options;
267 const fde = ctx.fde;255 const fde = ctx.fde;
268 const macho_file = ctx.macho_file;256 const macho_file = ctx.macho_file;
269 try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{257 try bw.print("@{x} : size({x}) : cie({d}) : {s}", .{
270 fde.offset,258 fde.offset,
271 fde.getSize(),259 fde.getSize(),
272 fde.cie,260 fde.cie,
273 fde.getAtom(macho_file).getName(macho_file),261 fde.getAtom(macho_file).getName(macho_file),
274 });262 });
275 if (!fde.alive) try writer.writeAll(" : [*]");263 if (!fde.alive) try bw.writeAll(" : [*]");
276 }264 }
277265
278 pub const Index = u32;266 pub const Index = u32;
279};267};
280268
281pub const Iterator = struct {269pub const Iterator = struct {
282 data: []const u8,270 br: std.io.BufferedReader,
283 pos: u32 = 0,
284271
285 pub const Record = struct {272 pub const Record = struct {
286 tag: enum { fde, cie },273 tag: enum { fde, cie },
...@@ -289,21 +276,18 @@ pub const Iterator = struct {...@@ -289,21 +276,18 @@ pub const Iterator = struct {
289 };276 };
290277
291 pub fn next(it: *Iterator) !?Record {278 pub fn next(it: *Iterator) !?Record {
292 if (it.pos >= it.data.len) return null;279 if (it.br.seek >= it.br.storageBuffer().len) return null;
293
294 var stream = std.io.fixedBufferStream(it.data[it.pos..]);
295 const reader = stream.reader();
296280
297 const size = try reader.readInt(u32, .little);281 const size = try it.br.takeInt(u32, .little);
298 if (size == 0xFFFFFFFF) @panic("DWARF CFI is 32bit on macOS");282 if (size == 0xFFFFFFFF) @panic("DWARF CFI is 32bit on macOS");
299283
300 const id = try reader.readInt(u32, .little);284 const id = try it.br.takeInt(u32, .little);
301 const record = Record{285 const record: Record = .{
302 .tag = if (id == 0) .cie else .fde,286 .tag = if (id == 0) .cie else .fde,
303 .offset = it.pos,287 .offset = @intCast(it.br.seek),
304 .size = size,288 .size = size,
305 };289 };
306 it.pos += size + 4;290 try it.br.discard(size);
307291
308 return record;292 return record;
309 }293 }
src/link/MachO/file.zig+8-14
...@@ -14,19 +14,13 @@ pub const File = union(enum) {...@@ -14,19 +14,13 @@ pub const File = union(enum) {
14 return .{ .data = file };14 return .{ .data = file };
15 }15 }
1616
17 fn formatPath(17 fn formatPath(file: File, bw: *std.io.BufferedWriter, comptime unused_fmt_string: []const u8) anyerror!void {
18 file: File,
19 comptime unused_fmt_string: []const u8,
20 options: std.fmt.FormatOptions,
21 writer: anytype,
22 ) !void {
23 _ = unused_fmt_string;18 _ = unused_fmt_string;
24 _ = options;
25 switch (file) {19 switch (file) {
26 .zig_object => |zo| try writer.writeAll(zo.basename),20 .zig_object => |zo| try bw.writeAll(zo.basename),
27 .internal => try writer.writeAll("internal"),21 .internal => try bw.writeAll("internal"),
28 .object => |x| try writer.print("{}", .{x.fmtPath()}),22 .object => |x| try bw.print("{f}", .{x.fmtPath()}),
29 .dylib => |dl| try writer.print("{}", .{@as(Path, dl.path)}),23 .dylib => |dl| try bw.print("{f}", .{@as(Path, dl.path)}),
30 }24 }
31 }25 }
3226
...@@ -328,11 +322,11 @@ pub const File = union(enum) {...@@ -328,11 +322,11 @@ pub const File = union(enum) {
328 };322 };
329 }323 }
330324
331 pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {325 pub fn writeAr(file: File, bw: *std.io.BufferedWriter, ar_format: Archive.Format, macho_file: *MachO) anyerror!void {
332 return switch (file) {326 return switch (file) {
333 .dylib, .internal => unreachable,327 .dylib, .internal => unreachable,
334 .zig_object => |x| x.writeAr(ar_format, writer),328 .zig_object => |x| x.writeAr(bw, ar_format),
335 .object => |x| x.writeAr(ar_format, macho_file, writer),329 .object => |x| x.writeAr(bw, ar_format, macho_file),
336 };330 };
337 }331 }
338332
src/link/MachO/load_commands.zig+21-30
...@@ -180,23 +180,20 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {...@@ -180,23 +180,20 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {
180 return offset;180 return offset;
181}181}
182182
183pub fn writeDylinkerLC(writer: anytype) !void {183pub fn writeDylinkerLC(bw: *std.io.BufferedWriter) anyerror!void {
184 const name_len = mem.sliceTo(default_dyld_path, 0).len;184 const name_len = mem.sliceTo(default_dyld_path, 0).len;
185 const cmdsize = @as(u32, @intCast(mem.alignForward(185 const cmdsize = @as(u32, @intCast(mem.alignForward(
186 u64,186 u64,
187 @sizeOf(macho.dylinker_command) + name_len,187 @sizeOf(macho.dylinker_command) + name_len,
188 @sizeOf(u64),188 @sizeOf(u64),
189 )));189 )));
190 try writer.writeStruct(macho.dylinker_command{190 try bw.writeStruct(macho.dylinker_command{
191 .cmd = .LOAD_DYLINKER,191 .cmd = .LOAD_DYLINKER,
192 .cmdsize = cmdsize,192 .cmdsize = cmdsize,
193 .name = @sizeOf(macho.dylinker_command),193 .name = @sizeOf(macho.dylinker_command),
194 });194 });
195 try writer.writeAll(mem.sliceTo(default_dyld_path, 0));195 try bw.writeAll(mem.sliceTo(default_dyld_path, 0));
196 const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len;196 try bw.splatByteAll(0, cmdsize - @sizeOf(macho.dylinker_command) - name_len);
197 if (padding > 0) {
198 try writer.writeByteNTimes(0, padding);
199 }
200}197}
201198
202const WriteDylibLCCtx = struct {199const WriteDylibLCCtx = struct {
...@@ -207,14 +204,14 @@ const WriteDylibLCCtx = struct {...@@ -207,14 +204,14 @@ const WriteDylibLCCtx = struct {
207 compatibility_version: u32 = 0x10000,204 compatibility_version: u32 = 0x10000,
208};205};
209206
210pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void {207pub fn writeDylibLC(ctx: WriteDylibLCCtx, bw: *std.io.BufferedWriter) !void {
211 const name_len = ctx.name.len + 1;208 const name_len = ctx.name.len + 1;
212 const cmdsize = @as(u32, @intCast(mem.alignForward(209 const cmdsize: u32 = @intCast(mem.alignForward(
213 u64,210 u64,
214 @sizeOf(macho.dylib_command) + name_len,211 @sizeOf(macho.dylib_command) + name_len,
215 @sizeOf(u64),212 @sizeOf(u64),
216 )));213 ));
217 try writer.writeStruct(macho.dylib_command{214 try bw.writeStruct(macho.dylib_command{
218 .cmd = ctx.cmd,215 .cmd = ctx.cmd,
219 .cmdsize = cmdsize,216 .cmdsize = cmdsize,
220 .dylib = .{217 .dylib = .{
...@@ -224,12 +221,9 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void {...@@ -224,12 +221,9 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void {
224 .compatibility_version = ctx.compatibility_version,221 .compatibility_version = ctx.compatibility_version,
225 },222 },
226 });223 });
227 try writer.writeAll(ctx.name);224 try bw.writeAll(ctx.name);
228 try writer.writeByte(0);225 try bw.writeByte(0);
229 const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len;226 try bw.splatByteAll(0, cmdsize - @sizeOf(macho.dylib_command) - name_len);
230 if (padding > 0) {
231 try writer.writeByteNTimes(0, padding);
232 }
233}227}
234228
235pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {229pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
...@@ -258,26 +252,23 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {...@@ -258,26 +252,23 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
258 }, writer);252 }, writer);
259}253}
260254
261pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void {255pub fn writeRpathLC(bw: *std.io.BufferedWriter, rpath: []const u8) !void {
262 const rpath_len = rpath.len + 1;256 const rpath_len = rpath.len + 1;
263 const cmdsize = @as(u32, @intCast(mem.alignForward(257 const cmdsize = @as(u32, @intCast(mem.alignForward(
264 u64,258 u64,
265 @sizeOf(macho.rpath_command) + rpath_len,259 @sizeOf(macho.rpath_command) + rpath_len,
266 @sizeOf(u64),260 @sizeOf(u64),
267 )));261 )));
268 try writer.writeStruct(macho.rpath_command{262 try bw.writeStruct(macho.rpath_command{
269 .cmdsize = cmdsize,263 .cmdsize = cmdsize,
270 .path = @sizeOf(macho.rpath_command),264 .path = @sizeOf(macho.rpath_command),
271 });265 });
272 try writer.writeAll(rpath);266 try bw.writeAll(rpath);
273 try writer.writeByte(0);267 try bw.writeByte(0);
274 const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len;268 try bw.splatByteAll(0, cmdsize - @sizeOf(macho.rpath_command) - rpath_len);
275 if (padding > 0) {
276 try writer.writeByteNTimes(0, padding);
277 }
278}269}
279270
280pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void {271pub fn writeVersionMinLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) anyerror!void {
281 const cmd: macho.LC = switch (platform.os_tag) {272 const cmd: macho.LC = switch (platform.os_tag) {
282 .macos => .VERSION_MIN_MACOSX,273 .macos => .VERSION_MIN_MACOSX,
283 .ios => .VERSION_MIN_IPHONEOS,274 .ios => .VERSION_MIN_IPHONEOS,
...@@ -285,7 +276,7 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer...@@ -285,7 +276,7 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer
285 .watchos => .VERSION_MIN_WATCHOS,276 .watchos => .VERSION_MIN_WATCHOS,
286 else => unreachable,277 else => unreachable,
287 };278 };
288 try writer.writeAll(mem.asBytes(&macho.version_min_command{279 try bw.writeAll(mem.asBytes(&macho.version_min_command{
289 .cmd = cmd,280 .cmd = cmd,
290 .version = platform.toAppleVersion(),281 .version = platform.toAppleVersion(),
291 .sdk = if (sdk_version) |ver|282 .sdk = if (sdk_version) |ver|
...@@ -295,9 +286,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer...@@ -295,9 +286,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer
295 }));286 }));
296}287}
297288
298pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void {289pub fn writeBuildVersionLC(bw: *std.io.BufferedWriter, platform: MachO.Platform, sdk_version: ?std.SemanticVersion) anyerror!void {
299 const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);290 const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
300 try writer.writeStruct(macho.build_version_command{291 try bw.writeStruct(macho.build_version_command{
301 .cmdsize = cmdsize,292 .cmdsize = cmdsize,
302 .platform = platform.toApplePlatform(),293 .platform = platform.toApplePlatform(),
303 .minos = platform.toAppleVersion(),294 .minos = platform.toAppleVersion(),
...@@ -307,7 +298,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV...@@ -307,7 +298,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV
307 platform.toAppleVersion(),298 platform.toAppleVersion(),
308 .ntools = 1,299 .ntools = 1,
309 });300 });
310 try writer.writeAll(mem.asBytes(&macho.build_tool_version{301 try bw.writeAll(mem.asBytes(&macho.build_tool_version{
311 .tool = .ZIG,302 .tool = .ZIG,
312 .version = 0x0,303 .version = 0x0,
313 }));304 }));
src/link/MachO/relocatable.zig+33-58
...@@ -20,13 +20,13 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -20,13 +20,13 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
20 // the *only* input file over.20 // the *only* input file over.
21 const path = positionals.items[0].path().?;21 const path = positionals.items[0].path().?;
22 const in_file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err|22 const in_file = path.root_dir.handle.openFile(path.sub_path, .{}) catch |err|
23 return diags.fail("failed to open {}: {s}", .{ path, @errorName(err) });23 return diags.fail("failed to open {f}: {s}", .{ path, @errorName(err) });
24 const stat = in_file.stat() catch |err|24 const stat = in_file.stat() catch |err|
25 return diags.fail("failed to stat {}: {s}", .{ path, @errorName(err) });25 return diags.fail("failed to stat {f}: {s}", .{ path, @errorName(err) });
26 const amt = in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size) catch |err|26 const amt = in_file.copyRangeAll(0, macho_file.base.file.?, 0, stat.size) catch |err|
27 return diags.fail("failed to copy range of file {}: {s}", .{ path, @errorName(err) });27 return diags.fail("failed to copy range of file {f}: {s}", .{ path, @errorName(err) });
28 if (amt != stat.size)28 if (amt != stat.size)
29 return diags.fail("unexpected short write in copy range of file {}", .{path});29 return diags.fail("unexpected short write in copy range of file {f}", .{path});
30 return;30 return;
31 }31 }
3232
...@@ -62,12 +62,12 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -62,12 +62,12 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
62 allocateSegment(macho_file);62 allocateSegment(macho_file);
6363
64 if (build_options.enable_logging) {64 if (build_options.enable_logging) {
65 state_log.debug("{}", .{macho_file.dumpState()});65 state_log.debug("{f}", .{macho_file.dumpState()});
66 }66 }
6767
68 try writeSections(macho_file);68 try writeSections(macho_file);
69 sortRelocs(macho_file);69 sortRelocs(macho_file);
70 try writeSectionsToFile(macho_file);70 writeSectionsToFile(macho_file) catch |err| return @errorCast(err);
7171
72 // In order to please Apple ld (and possibly other MachO linkers in the wild),72 // In order to please Apple ld (and possibly other MachO linkers in the wild),
73 // we will now sanitize segment names of Zig-specific segments.73 // we will now sanitize segment names of Zig-specific segments.
...@@ -126,12 +126,12 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -126,12 +126,12 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
126 allocateSegment(macho_file);126 allocateSegment(macho_file);
127127
128 if (build_options.enable_logging) {128 if (build_options.enable_logging) {
129 state_log.debug("{}", .{macho_file.dumpState()});129 state_log.debug("{f}", .{macho_file.dumpState()});
130 }130 }
131131
132 try writeSections(macho_file);132 try writeSections(macho_file);
133 sortRelocs(macho_file);133 sortRelocs(macho_file);
134 try writeSectionsToFile(macho_file);134 writeSectionsToFile(macho_file) catch |err| return @errorCast(err);
135135
136 // In order to please Apple ld (and possibly other MachO linkers in the wild),136 // In order to please Apple ld (and possibly other MachO linkers in the wild),
137 // we will now sanitize segment names of Zig-specific segments.137 // we will now sanitize segment names of Zig-specific segments.
...@@ -202,38 +202,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?...@@ -202,38 +202,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
202 };202 };
203203
204 if (build_options.enable_logging) {204 if (build_options.enable_logging) {
205 state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(macho_file)});205 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
206 }206 }
207207
208 var buffer = std.ArrayList(u8).init(gpa);208 var bw: std.io.BufferedWriter = undefined;
209 defer buffer.deinit();209 bw.initFixed(try gpa.alloc(u8, total_size));
210 try buffer.ensureTotalCapacityPrecise(total_size);210 defer gpa.free(bw.buffer);
211 const writer = buffer.writer();
212211
213 // Write magic212 // Write magic
214 try writer.writeAll(Archive.ARMAG);213 bw.writeAll(Archive.ARMAG) catch unreachable;
215214
216 // Write symtab215 // Write symtab
217 ar_symtab.write(format, macho_file, writer) catch |err| switch (err) {216 ar_symtab.write(&bw, format, macho_file) catch |err| switch (err) {
218 error.OutOfMemory => return error.OutOfMemory,217 error.OutOfMemory => unreachable,
219 else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}),218 else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}),
220 };219 };
221220
222 // Write object files221 // Write object files
223 for (files.items) |index| {222 for (files.items) |index| {
224 const aligned = mem.alignForward(usize, buffer.items.len, 2);223 bw.splatByteAll(0, mem.alignForward(usize, bw.end, 2) - bw.end) catch unreachable;
225 const padding = aligned - buffer.items.len;224 macho_file.getFile(index).?.writeAr(&bw, format, macho_file) catch |err|
226 if (padding > 0) {
227 try writer.writeByteNTimes(0, padding);
228 }
229 macho_file.getFile(index).?.writeAr(format, macho_file, writer) catch |err|
230 return diags.fail("failed to write archive: {s}", .{@errorName(err)});225 return diags.fail("failed to write archive: {s}", .{@errorName(err)});
231 }226 }
232227
233 assert(buffer.items.len == total_size);228 assert(bw.end == bw.buffer.len);
234229 try macho_file.setEndPos(bw.end);
235 try macho_file.setEndPos(total_size);230 try macho_file.pwriteAll(bw.buffer, 0);
236 try macho_file.pwriteAll(buffer.items, 0);
237231
238 if (diags.hasErrors()) return error.LinkFailure;232 if (diags.hasErrors()) return error.LinkFailure;
239}233}
...@@ -689,12 +683,9 @@ fn writeSectionsToFile(macho_file: *MachO) !void {...@@ -689,12 +683,9 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
689683
690fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {684fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struct { usize, usize } {
691 const gpa = macho_file.base.comp.gpa;685 const gpa = macho_file.base.comp.gpa;
692 const needed_size = load_commands.calcLoadCommandsSizeObject(macho_file);686 var bw: std.io.BufferedWriter = undefined;
693 const buffer = try gpa.alloc(u8, needed_size);687 bw.initFixed(try gpa.alloc(u8, load_commands.calcLoadCommandsSizeObject(macho_file)));
694 defer gpa.free(buffer);688 defer gpa.free(bw.buffer);
695
696 var stream = std.io.fixedBufferStream(buffer);
697 const writer = stream.writer();
698689
699 var ncmds: usize = 0;690 var ncmds: usize = 0;
700691
...@@ -702,47 +693,31 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc...@@ -702,47 +693,31 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc
702 {693 {
703 assert(macho_file.segments.items.len == 1);694 assert(macho_file.segments.items.len == 1);
704 const seg = macho_file.segments.items[0];695 const seg = macho_file.segments.items[0];
705 writer.writeStruct(seg) catch |err| switch (err) {696 bw.writeStruct(seg) catch unreachable;
706 error.NoSpaceLeft => unreachable,
707 };
708 for (macho_file.sections.items(.header)) |header| {697 for (macho_file.sections.items(.header)) |header| {
709 writer.writeStruct(header) catch |err| switch (err) {698 bw.writeStruct(header) catch unreachable;
710 error.NoSpaceLeft => unreachable,
711 };
712 }699 }
713 ncmds += 1;700 ncmds += 1;
714 }701 }
715702
716 writer.writeStruct(macho_file.data_in_code_cmd) catch |err| switch (err) {703 bw.writeStruct(macho_file.data_in_code_cmd) catch unreachable;
717 error.NoSpaceLeft => unreachable,
718 };
719 ncmds += 1;704 ncmds += 1;
720 writer.writeStruct(macho_file.symtab_cmd) catch |err| switch (err) {705 bw.writeStruct(macho_file.symtab_cmd) catch unreachable;
721 error.NoSpaceLeft => unreachable,
722 };
723 ncmds += 1;706 ncmds += 1;
724 writer.writeStruct(macho_file.dysymtab_cmd) catch |err| switch (err) {707 bw.writeStruct(macho_file.dysymtab_cmd) catch unreachable;
725 error.NoSpaceLeft => unreachable,
726 };
727 ncmds += 1;708 ncmds += 1;
728709
729 if (macho_file.platform.isBuildVersionCompatible()) {710 if (macho_file.platform.isBuildVersionCompatible()) {
730 load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) {711 load_commands.writeBuildVersionLC(&bw, macho_file.platform, macho_file.sdk_version) catch unreachable;
731 error.NoSpaceLeft => unreachable,
732 };
733 ncmds += 1;712 ncmds += 1;
734 } else {713 } else {
735 load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) {714 load_commands.writeVersionMinLC(&bw, macho_file.platform, macho_file.sdk_version) catch unreachable;
736 error.NoSpaceLeft => unreachable,
737 };
738 ncmds += 1;715 ncmds += 1;
739 }716 }
740717
741 assert(stream.pos == needed_size);718 assert(bw.end == bw.buffer.len);
742719 try macho_file.pwriteAll(bw.buffer, @sizeOf(macho.mach_header_64));
743 try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64));720 return .{ ncmds, bw.end };
744
745 return .{ ncmds, buffer.len };
746}721}
747722
748fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {723fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
src/link/MachO/synthetic.zig+62-70
...@@ -27,13 +27,13 @@ pub const GotSection = struct {...@@ -27,13 +27,13 @@ pub const GotSection = struct {
27 return got.symbols.items.len * @sizeOf(u64);27 return got.symbols.items.len * @sizeOf(u64);
28 }28 }
2929
30 pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void {30 pub fn write(got: GotSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
31 const tracy = trace(@src());31 const tracy = trace(@src());
32 defer tracy.end();32 defer tracy.end();
33 for (got.symbols.items) |ref| {33 for (got.symbols.items) |ref| {
34 const sym = ref.getSymbol(macho_file).?;34 const sym = ref.getSymbol(macho_file).?;
35 const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);35 const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);
36 try writer.writeInt(u64, value, .little);36 try bw.writeInt(u64, value, .little);
37 }37 }
38 }38 }
3939
...@@ -48,15 +48,13 @@ pub const GotSection = struct {...@@ -48,15 +48,13 @@ pub const GotSection = struct {
4848
49 pub fn format2(49 pub fn format2(
50 ctx: FormatCtx,50 ctx: FormatCtx,
51 bw: *std.io.BufferedWriter,
51 comptime unused_fmt_string: []const u8,52 comptime unused_fmt_string: []const u8,
52 options: std.fmt.FormatOptions,
53 writer: anytype,
54 ) !void {53 ) !void {
55 _ = options;
56 _ = unused_fmt_string;54 _ = unused_fmt_string;
57 for (ctx.got.symbols.items, 0..) |ref, i| {55 for (ctx.got.symbols.items, 0..) |ref, i| {
58 const symbol = ref.getSymbol(ctx.macho_file).?;56 const symbol = ref.getSymbol(ctx.macho_file).?;
59 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{57 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
60 i,58 i,
61 symbol.getGotAddress(ctx.macho_file),59 symbol.getGotAddress(ctx.macho_file),
62 ref,60 ref,
...@@ -96,7 +94,7 @@ pub const StubsSection = struct {...@@ -96,7 +94,7 @@ pub const StubsSection = struct {
96 return stubs.symbols.items.len * header.reserved2;94 return stubs.symbols.items.len * header.reserved2;
97 }95 }
9896
99 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void {97 pub fn write(stubs: StubsSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
100 const tracy = trace(@src());98 const tracy = trace(@src());
101 defer tracy.end();99 defer tracy.end();
102 const cpu_arch = macho_file.getTarget().cpu.arch;100 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -108,20 +106,20 @@ pub const StubsSection = struct {...@@ -108,20 +106,20 @@ pub const StubsSection = struct {
108 const target = laptr_sect.addr + idx * @sizeOf(u64);106 const target = laptr_sect.addr + idx * @sizeOf(u64);
109 switch (cpu_arch) {107 switch (cpu_arch) {
110 .x86_64 => {108 .x86_64 => {
111 try writer.writeAll(&.{ 0xff, 0x25 });109 try bw.writeAll(&.{ 0xff, 0x25 });
112 try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);110 try bw.writeInt(i32, @intCast(target - source - 2 - 4), .little);
113 },111 },
114 .aarch64 => {112 .aarch64 => {
115 // TODO relax if possible113 // TODO relax if possible
116 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));114 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
117 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);115 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
118 const off = try math.divExact(u12, @truncate(target), 8);116 const off = try math.divExact(u12, @truncate(target), 8);
119 try writer.writeInt(117 try bw.writeInt(
120 u32,118 u32,
121 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),119 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
122 .little,120 .little,
123 );121 );
124 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);122 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
125 },123 },
126 else => unreachable,124 else => unreachable,
127 }125 }
...@@ -139,15 +137,13 @@ pub const StubsSection = struct {...@@ -139,15 +137,13 @@ pub const StubsSection = struct {
139137
140 pub fn format2(138 pub fn format2(
141 ctx: FormatCtx,139 ctx: FormatCtx,
140 bw: *std.io.BufferedWriter,
142 comptime unused_fmt_string: []const u8,141 comptime unused_fmt_string: []const u8,
143 options: std.fmt.FormatOptions,
144 writer: anytype,
145 ) !void {142 ) !void {
146 _ = options;
147 _ = unused_fmt_string;143 _ = unused_fmt_string;
148 for (ctx.stubs.symbols.items, 0..) |ref, i| {144 for (ctx.stubs.symbols.items, 0..) |ref, i| {
149 const symbol = ref.getSymbol(ctx.macho_file).?;145 const symbol = ref.getSymbol(ctx.macho_file).?;
150 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{146 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
151 i,147 i,
152 symbol.getStubsAddress(ctx.macho_file),148 symbol.getStubsAddress(ctx.macho_file),
153 ref,149 ref,
...@@ -189,11 +185,11 @@ pub const StubsHelperSection = struct {...@@ -189,11 +185,11 @@ pub const StubsHelperSection = struct {
189 return s;185 return s;
190 }186 }
191187
192 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {188 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
193 const tracy = trace(@src());189 const tracy = trace(@src());
194 defer tracy.end();190 defer tracy.end();
195191
196 try stubs_helper.writePreamble(macho_file, writer);192 try stubs_helper.writePreamble(macho_file, bw);
197193
198 const cpu_arch = macho_file.getTarget().cpu.arch;194 const cpu_arch = macho_file.getTarget().cpu.arch;
199 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];195 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
...@@ -209,24 +205,24 @@ pub const StubsHelperSection = struct {...@@ -209,24 +205,24 @@ pub const StubsHelperSection = struct {
209 const target: i64 = @intCast(sect.addr);205 const target: i64 = @intCast(sect.addr);
210 switch (cpu_arch) {206 switch (cpu_arch) {
211 .x86_64 => {207 .x86_64 => {
212 try writer.writeByte(0x68);208 try bw.writeByte(0x68);
213 try writer.writeInt(u32, offset, .little);209 try bw.writeInt(u32, offset, .little);
214 try writer.writeByte(0xe9);210 try bw.writeByte(0xe9);
215 try writer.writeInt(i32, @intCast(target - source - 6 - 4), .little);211 try bw.writeInt(i32, @intCast(target - source - 6 - 4), .little);
216 },212 },
217 .aarch64 => {213 .aarch64 => {
218 const literal = blk: {214 const literal = blk: {
219 const div_res = try std.math.divExact(u64, entry_size - @sizeOf(u32), 4);215 const div_res = try std.math.divExact(u64, entry_size - @sizeOf(u32), 4);
220 break :blk std.math.cast(u18, div_res) orelse return error.Overflow;216 break :blk std.math.cast(u18, div_res) orelse return error.Overflow;
221 };217 };
222 try writer.writeInt(u32, aarch64.Instruction.ldrLiteral(218 try bw.writeInt(u32, aarch64.Instruction.ldrLiteral(
223 .w16,219 .w16,
224 literal,220 literal,
225 ).toU32(), .little);221 ).toU32(), .little);
226 const disp = math.cast(i28, @as(i64, @intCast(target)) - @as(i64, @intCast(source + 4))) orelse222 const disp = math.cast(i28, @as(i64, @intCast(target)) - @as(i64, @intCast(source + 4))) orelse
227 return error.Overflow;223 return error.Overflow;
228 try writer.writeInt(u32, aarch64.Instruction.b(disp).toU32(), .little);224 try bw.writeInt(u32, aarch64.Instruction.b(disp).toU32(), .little);
229 try writer.writeAll(&.{ 0x0, 0x0, 0x0, 0x0 });225 try bw.writeAll(&.{ 0x0, 0x0, 0x0, 0x0 });
230 },226 },
231 else => unreachable,227 else => unreachable,
232 }228 }
...@@ -234,7 +230,7 @@ pub const StubsHelperSection = struct {...@@ -234,7 +230,7 @@ pub const StubsHelperSection = struct {
234 }230 }
235 }231 }
236232
237 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {233 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
238 _ = stubs_helper;234 _ = stubs_helper;
239 const obj = macho_file.getInternalObject().?;235 const obj = macho_file.getInternalObject().?;
240 const cpu_arch = macho_file.getTarget().cpu.arch;236 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -249,21 +245,21 @@ pub const StubsHelperSection = struct {...@@ -249,21 +245,21 @@ pub const StubsHelperSection = struct {
249 };245 };
250 switch (cpu_arch) {246 switch (cpu_arch) {
251 .x86_64 => {247 .x86_64 => {
252 try writer.writeAll(&.{ 0x4c, 0x8d, 0x1d });248 try bw.writeAll(&.{ 0x4c, 0x8d, 0x1d });
253 try writer.writeInt(i32, @intCast(dyld_private_addr - sect.addr - 3 - 4), .little);249 try bw.writeInt(i32, @intCast(dyld_private_addr - sect.addr - 3 - 4), .little);
254 try writer.writeAll(&.{ 0x41, 0x53, 0xff, 0x25 });250 try bw.writeAll(&.{ 0x41, 0x53, 0xff, 0x25 });
255 try writer.writeInt(i32, @intCast(dyld_stub_binder_addr - sect.addr - 11 - 4), .little);251 try bw.writeInt(i32, @intCast(dyld_stub_binder_addr - sect.addr - 11 - 4), .little);
256 try writer.writeByte(0x90);252 try bw.writeByte(0x90);
257 },253 },
258 .aarch64 => {254 .aarch64 => {
259 {255 {
260 // TODO relax if possible256 // TODO relax if possible
261 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr));257 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr));
262 try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);258 try bw.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);
263 const off: u12 = @truncate(dyld_private_addr);259 const off: u12 = @truncate(dyld_private_addr);
264 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);260 try bw.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);
265 }261 }
266 try writer.writeInt(u32, aarch64.Instruction.stp(262 try bw.writeInt(u32, aarch64.Instruction.stp(
267 .x16,263 .x16,
268 .x17,264 .x17,
269 aarch64.Register.sp,265 aarch64.Register.sp,
...@@ -272,15 +268,15 @@ pub const StubsHelperSection = struct {...@@ -272,15 +268,15 @@ pub const StubsHelperSection = struct {
272 {268 {
273 // TODO relax if possible269 // TODO relax if possible
274 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr));270 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr));
275 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);271 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
276 const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);272 const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);
277 try writer.writeInt(u32, aarch64.Instruction.ldr(273 try bw.writeInt(u32, aarch64.Instruction.ldr(
278 .x16,274 .x16,
279 .x16,275 .x16,
280 aarch64.Instruction.LoadStoreOffset.imm(off),276 aarch64.Instruction.LoadStoreOffset.imm(off),
281 ).toU32(), .little);277 ).toU32(), .little);
282 }278 }
283 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);279 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
284 },280 },
285 else => unreachable,281 else => unreachable,
286 }282 }
...@@ -293,7 +289,7 @@ pub const LaSymbolPtrSection = struct {...@@ -293,7 +289,7 @@ pub const LaSymbolPtrSection = struct {
293 return macho_file.stubs.symbols.items.len * @sizeOf(u64);289 return macho_file.stubs.symbols.items.len * @sizeOf(u64);
294 }290 }
295291
296 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: anytype) !void {292 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
297 const tracy = trace(@src());293 const tracy = trace(@src());
298 defer tracy.end();294 defer tracy.end();
299 _ = laptr;295 _ = laptr;
...@@ -304,12 +300,12 @@ pub const LaSymbolPtrSection = struct {...@@ -304,12 +300,12 @@ pub const LaSymbolPtrSection = struct {
304 const sym = ref.getSymbol(macho_file).?;300 const sym = ref.getSymbol(macho_file).?;
305 if (sym.flags.weak) {301 if (sym.flags.weak) {
306 const value = sym.getAddress(.{ .stubs = false }, macho_file);302 const value = sym.getAddress(.{ .stubs = false }, macho_file);
307 try writer.writeInt(u64, @intCast(value), .little);303 try bw.writeInt(u64, @intCast(value), .little);
308 } else {304 } else {
309 const value = sect.addr + StubsHelperSection.preambleSize(cpu_arch) +305 const value = sect.addr + StubsHelperSection.preambleSize(cpu_arch) +
310 StubsHelperSection.entrySize(cpu_arch) * stub_helper_idx;306 StubsHelperSection.entrySize(cpu_arch) * stub_helper_idx;
311 stub_helper_idx += 1;307 stub_helper_idx += 1;
312 try writer.writeInt(u64, @intCast(value), .little);308 try bw.writeInt(u64, @intCast(value), .little);
313 }309 }
314 }310 }
315 }311 }
...@@ -343,16 +339,16 @@ pub const TlvPtrSection = struct {...@@ -343,16 +339,16 @@ pub const TlvPtrSection = struct {
343 return tlv.symbols.items.len * @sizeOf(u64);339 return tlv.symbols.items.len * @sizeOf(u64);
344 }340 }
345341
346 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: anytype) !void {342 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
347 const tracy = trace(@src());343 const tracy = trace(@src());
348 defer tracy.end();344 defer tracy.end();
349345
350 for (tlv.symbols.items) |ref| {346 for (tlv.symbols.items) |ref| {
351 const sym = ref.getSymbol(macho_file).?;347 const sym = ref.getSymbol(macho_file).?;
352 if (sym.flags.import) {348 if (sym.flags.import) {
353 try writer.writeInt(u64, 0, .little);349 try bw.writeInt(u64, 0, .little);
354 } else {350 } else {
355 try writer.writeInt(u64, sym.getAddress(.{}, macho_file), .little);351 try bw.writeInt(u64, sym.getAddress(.{}, macho_file), .little);
356 }352 }
357 }353 }
358 }354 }
...@@ -368,15 +364,13 @@ pub const TlvPtrSection = struct {...@@ -368,15 +364,13 @@ pub const TlvPtrSection = struct {
368364
369 pub fn format2(365 pub fn format2(
370 ctx: FormatCtx,366 ctx: FormatCtx,
367 bw: *std.io.BufferedWriter,
371 comptime unused_fmt_string: []const u8,368 comptime unused_fmt_string: []const u8,
372 options: std.fmt.FormatOptions,
373 writer: anytype,
374 ) !void {369 ) !void {
375 _ = options;
376 _ = unused_fmt_string;370 _ = unused_fmt_string;
377 for (ctx.tlv.symbols.items, 0..) |ref, i| {371 for (ctx.tlv.symbols.items, 0..) |ref, i| {
378 const symbol = ref.getSymbol(ctx.macho_file).?;372 const symbol = ref.getSymbol(ctx.macho_file).?;
379 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{373 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
380 i,374 i,
381 symbol.getTlvPtrAddress(ctx.macho_file),375 symbol.getTlvPtrAddress(ctx.macho_file),
382 ref,376 ref,
...@@ -421,7 +415,7 @@ pub const ObjcStubsSection = struct {...@@ -421,7 +415,7 @@ pub const ObjcStubsSection = struct {
421 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);415 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);
422 }416 }
423417
424 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void {418 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
425 const tracy = trace(@src());419 const tracy = trace(@src());
426 defer tracy.end();420 defer tracy.end();
427421
...@@ -432,18 +426,18 @@ pub const ObjcStubsSection = struct {...@@ -432,18 +426,18 @@ pub const ObjcStubsSection = struct {
432 const addr = objc.getAddress(@intCast(idx), macho_file);426 const addr = objc.getAddress(@intCast(idx), macho_file);
433 switch (macho_file.getTarget().cpu.arch) {427 switch (macho_file.getTarget().cpu.arch) {
434 .x86_64 => {428 .x86_64 => {
435 try writer.writeAll(&.{ 0x48, 0x8b, 0x35 });429 try bw.writeAll(&.{ 0x48, 0x8b, 0x35 });
436 {430 {
437 const target = sym.getObjcSelrefsAddress(macho_file);431 const target = sym.getObjcSelrefsAddress(macho_file);
438 const source = addr;432 const source = addr;
439 try writer.writeInt(i32, @intCast(target - source - 3 - 4), .little);433 try bw.writeInt(i32, @intCast(target - source - 3 - 4), .little);
440 }434 }
441 try writer.writeAll(&.{ 0xff, 0x25 });435 try bw.writeAll(&.{ 0xff, 0x25 });
442 {436 {
443 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;437 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
444 const target = target_sym.getGotAddress(macho_file);438 const target = target_sym.getGotAddress(macho_file);
445 const source = addr + 7;439 const source = addr + 7;
446 try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);440 try bw.writeInt(i32, @intCast(target - source - 2 - 4), .little);
447 }441 }
448 },442 },
449 .aarch64 => {443 .aarch64 => {
...@@ -451,9 +445,9 @@ pub const ObjcStubsSection = struct {...@@ -451,9 +445,9 @@ pub const ObjcStubsSection = struct {
451 const target = sym.getObjcSelrefsAddress(macho_file);445 const target = sym.getObjcSelrefsAddress(macho_file);
452 const source = addr;446 const source = addr;
453 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));447 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
454 try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);448 try bw.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);
455 const off = try math.divExact(u12, @truncate(target), 8);449 const off = try math.divExact(u12, @truncate(target), 8);
456 try writer.writeInt(450 try bw.writeInt(
457 u32,451 u32,
458 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),452 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
459 .little,453 .little,
...@@ -464,18 +458,18 @@ pub const ObjcStubsSection = struct {...@@ -464,18 +458,18 @@ pub const ObjcStubsSection = struct {
464 const target = target_sym.getGotAddress(macho_file);458 const target = target_sym.getGotAddress(macho_file);
465 const source = addr + 2 * @sizeOf(u32);459 const source = addr + 2 * @sizeOf(u32);
466 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));460 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
467 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);461 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
468 const off = try math.divExact(u12, @truncate(target), 8);462 const off = try math.divExact(u12, @truncate(target), 8);
469 try writer.writeInt(463 try bw.writeInt(
470 u32,464 u32,
471 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),465 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
472 .little,466 .little,
473 );467 );
474 }468 }
475 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);469 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
476 try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);470 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
477 try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);471 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
478 try writer.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);472 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);
479 },473 },
480 else => unreachable,474 else => unreachable,
481 }475 }
...@@ -493,15 +487,13 @@ pub const ObjcStubsSection = struct {...@@ -493,15 +487,13 @@ pub const ObjcStubsSection = struct {
493487
494 pub fn format2(488 pub fn format2(
495 ctx: FormatCtx,489 ctx: FormatCtx,
490 bw: *std.io.BufferedWriter,
496 comptime unused_fmt_string: []const u8,491 comptime unused_fmt_string: []const u8,
497 options: std.fmt.FormatOptions,
498 writer: anytype,
499 ) !void {492 ) !void {
500 _ = options;
501 _ = unused_fmt_string;493 _ = unused_fmt_string;
502 for (ctx.objc.symbols.items, 0..) |ref, i| {494 for (ctx.objc.symbols.items, 0..) |ref, i| {
503 const symbol = ref.getSymbol(ctx.macho_file).?;495 const symbol = ref.getSymbol(ctx.macho_file).?;
504 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{496 try bw.print(" {d}@0x{x} => {f}@0x{x} ({s})\n", .{
505 i,497 i,
506 symbol.getObjcStubsAddress(ctx.macho_file),498 symbol.getObjcStubsAddress(ctx.macho_file),
507 ref,499 ref,
...@@ -524,7 +516,7 @@ pub const Indsymtab = struct {...@@ -524,7 +516,7 @@ pub const Indsymtab = struct {
524 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);516 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
525 }517 }
526518
527 pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void {519 pub fn write(ind: Indsymtab, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
528 const tracy = trace(@src());520 const tracy = trace(@src());
529 defer tracy.end();521 defer tracy.end();
530522
...@@ -533,21 +525,21 @@ pub const Indsymtab = struct {...@@ -533,21 +525,21 @@ pub const Indsymtab = struct {
533 for (macho_file.stubs.symbols.items) |ref| {525 for (macho_file.stubs.symbols.items) |ref| {
534 const sym = ref.getSymbol(macho_file).?;526 const sym = ref.getSymbol(macho_file).?;
535 if (sym.getOutputSymtabIndex(macho_file)) |idx| {527 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
536 try writer.writeInt(u32, idx, .little);528 try bw.writeInt(u32, idx, .little);
537 }529 }
538 }530 }
539531
540 for (macho_file.got.symbols.items) |ref| {532 for (macho_file.got.symbols.items) |ref| {
541 const sym = ref.getSymbol(macho_file).?;533 const sym = ref.getSymbol(macho_file).?;
542 if (sym.getOutputSymtabIndex(macho_file)) |idx| {534 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
543 try writer.writeInt(u32, idx, .little);535 try bw.writeInt(u32, idx, .little);
544 }536 }
545 }537 }
546538
547 for (macho_file.stubs.symbols.items) |ref| {539 for (macho_file.stubs.symbols.items) |ref| {
548 const sym = ref.getSymbol(macho_file).?;540 const sym = ref.getSymbol(macho_file).?;
549 if (sym.getOutputSymtabIndex(macho_file)) |idx| {541 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
550 try writer.writeInt(u32, idx, .little);542 try bw.writeInt(u32, idx, .little);
551 }543 }
552 }544 }
553 }545 }
...@@ -601,7 +593,7 @@ pub const DataInCode = struct {...@@ -601,7 +593,7 @@ pub const DataInCode = struct {
601 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;593 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
602 }594 }
603595
604 pub fn write(dice: DataInCode, macho_file: *MachO, writer: anytype) !void {596 pub fn write(dice: DataInCode, macho_file: *MachO, bw: *std.io.BufferedWriter) !void {
605 const base_address = if (!macho_file.base.isRelocatable())597 const base_address = if (!macho_file.base.isRelocatable())
606 macho_file.getTextSegment().vmaddr598 macho_file.getTextSegment().vmaddr
607 else599 else
...@@ -609,7 +601,7 @@ pub const DataInCode = struct {...@@ -609,7 +601,7 @@ pub const DataInCode = struct {
609 for (dice.entries.items) |entry| {601 for (dice.entries.items) |entry| {
610 const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file);602 const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file);
611 const offset = atom_address + entry.offset - base_address;603 const offset = atom_address + entry.offset - base_address;
612 try writer.writeStruct(macho.data_in_code_entry{604 try bw.writeStruct(macho.data_in_code_entry{
613 .offset = @intCast(offset),605 .offset = @intCast(offset),
614 .length = entry.length,606 .length = entry.length,
615 .kind = entry.kind,607 .kind = entry.kind,
src/link/Plan9.zig+60-56
...@@ -202,7 +202,7 @@ pub const Atom = struct {...@@ -202,7 +202,7 @@ pub const Atom = struct {
202/// after every opcode, add the quanta of the instruction size to the pc202/// after every opcode, add the quanta of the instruction size to the pc
203pub const DebugInfoOutput = struct {203pub const DebugInfoOutput = struct {
204 /// the actual opcodes204 /// the actual opcodes
205 dbg_line: std.ArrayList(u8),205 dbg_line: std.ArrayListUnmanaged(u8),
206 /// what line the debuginfo starts on206 /// what line the debuginfo starts on
207 /// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl207 /// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
208 start_line: ?u32,208 start_line: ?u32,
...@@ -336,23 +336,26 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void...@@ -336,23 +336,26 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void
336 };336 };
337 try fn_map_res.value_ptr.functions.put(gpa, nav_index, out);337 try fn_map_res.value_ptr.functions.put(gpa, nav_index, out);
338338
339 var a = std.ArrayList(u8).init(arena);339 var aw: std.io.AllocatingWriter = undefined;
340 errdefer a.deinit();340 aw.init(arena);
341 defer aw.deinit();
342 const bw = &aw.buffered_writer;
343
341 // every 'z' starts with 0344 // every 'z' starts with 0
342 try a.append(0);345 try bw.writeByte(0);
343 // path component value of '/'346 // path component value of '/'
344 try a.writer().writeInt(u16, 1, .big);347 try bw.writeInt(u16, 1, .big);
345348
346 // getting the full file path349 // getting the full file path
347 {350 {
348 const full_path = try file.path.toAbsolute(comp.dirs, gpa);351 const full_path = try file.path.toAbsolute(comp.dirs, gpa);
349 defer gpa.free(full_path);352 defer gpa.free(full_path);
350 try self.addPathComponents(full_path, &a);353 try self.addPathComponents(full_path, bw);
351 }354 }
352355
353 // null terminate356 // null terminate
354 try a.append(0);357 try bw.writeByte(0);
355 const final = try a.toOwnedSlice();358 const final = try aw.toOwnedSlice();
356 self.syms.items[fn_map_res.value_ptr.sym_index - 1] = .{359 self.syms.items[fn_map_res.value_ptr.sym_index - 1] = .{
357 .type = .z,360 .type = .z,
358 .value = 1,361 .value = 1,
...@@ -367,17 +370,17 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void...@@ -367,17 +370,17 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void
367 }370 }
368}371}
369372
370fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !void {373fn addPathComponents(self: *Plan9, path: []const u8, bw: *std.io.BufferedWriter) !void {
371 const gpa = self.base.comp.gpa;374 const gpa = self.base.comp.gpa;
372 const sep = std.fs.path.sep;375 const sep = std.fs.path.sep;
373 var it = std.mem.tokenizeScalar(u8, path, sep);376 var it = std.mem.tokenizeScalar(u8, path, sep);
374 while (it.next()) |component| {377 while (it.next()) |component| {
375 if (self.file_segments.get(component)) |num| {378 if (self.file_segments.get(component)) |num| {
376 try a.writer().writeInt(u16, num, .big);379 try bw.writeInt(u16, num, .big);
377 } else {380 } else {
378 self.file_segments_i += 1;381 self.file_segments_i += 1;
379 try self.file_segments.put(gpa, component, self.file_segments_i);382 try self.file_segments.put(gpa, component, self.file_segments_i);
380 try a.writer().writeInt(u16, self.file_segments_i, .big);383 try bw.writeInt(u16, self.file_segments_i, .big);
381 }384 }
382 }385 }
383}386}
...@@ -402,14 +405,14 @@ pub fn updateFunc(...@@ -402,14 +405,14 @@ pub fn updateFunc(
402 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;405 var code_buffer: std.ArrayListUnmanaged(u8) = .empty;
403 defer code_buffer.deinit(gpa);406 defer code_buffer.deinit(gpa);
404 var dbg_info_output: DebugInfoOutput = .{407 var dbg_info_output: DebugInfoOutput = .{
405 .dbg_line = std.ArrayList(u8).init(gpa),408 .dbg_line = .empty,
406 .start_line = null,409 .start_line = null,
407 .end_line = undefined,410 .end_line = undefined,
408 .pcop_change_index = null,411 .pcop_change_index = null,
409 // we have already checked the target in the linker to make sure it is compatable412 // we have already checked the target in the linker to make sure it is compatable
410 .pc_quanta = aout.getPCQuant(target.cpu.arch) catch unreachable,413 .pc_quanta = aout.getPCQuant(target.cpu.arch) catch unreachable,
411 };414 };
412 defer dbg_info_output.dbg_line.deinit();415 defer dbg_info_output.dbg_line.deinit(gpa);
413416
414 try codegen.emitFunction(417 try codegen.emitFunction(
415 &self.base,418 &self.base,
...@@ -427,7 +430,7 @@ pub fn updateFunc(...@@ -427,7 +430,7 @@ pub fn updateFunc(
427 };430 };
428 const out: FnNavOutput = .{431 const out: FnNavOutput = .{
429 .code = code,432 .code = code,
430 .lineinfo = try dbg_info_output.dbg_line.toOwnedSlice(),433 .lineinfo = try dbg_info_output.dbg_line.toOwnedSlice(gpa),
431 .start_line = dbg_info_output.start_line.?,434 .start_line = dbg_info_output.start_line.?,
432 .end_line = dbg_info_output.end_line,435 .end_line = dbg_info_output.end_line,
433 };436 };
...@@ -445,7 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -445,7 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
445 .func => return,448 .func => return,
446 .variable => |variable| Value.fromInterned(variable.init),449 .variable => |variable| Value.fromInterned(variable.init),
447 .@"extern" => {450 .@"extern" => {
448 log.debug("found extern decl: {}", .{nav.name.fmt(ip)});451 log.debug("found extern decl: {f}", .{nav.name.fmt(ip)});
449 return;452 return;
450 },453 },
451 else => nav_val,454 else => nav_val,
...@@ -524,16 +527,14 @@ fn allocateGotIndex(self: *Plan9) usize {...@@ -524,16 +527,14 @@ fn allocateGotIndex(self: *Plan9) usize {
524 }527 }
525}528}
526529
527pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {530pub fn changeLine(bw: *std.io.Writer, delta_line: i32) !void {
528 if (delta_line > 0 and delta_line < 65) {531 if (delta_line > 0 and delta_line < 65) {
529 const toappend = @as(u8, @intCast(delta_line));532 try bw.writeByte(@intCast(delta_line));
530 try l.append(toappend);
531 } else if (delta_line < 0 and delta_line > -65) {533 } else if (delta_line < 0 and delta_line > -65) {
532 const toadd: u8 = @as(u8, @intCast(-delta_line + 64));534 try bw.writeByte(@intCast(-delta_line + 64));
533 try l.append(toadd);
534 } else if (delta_line != 0) {535 } else if (delta_line != 0) {
535 try l.append(0);536 try bw.writeByte(0);
536 try l.writer().writeInt(i32, delta_line, .big);537 try bw.writeInt(i32, delta_line, .big);
537 }538 }
538}539}
539540
...@@ -645,10 +646,12 @@ pub fn flush(...@@ -645,10 +646,12 @@ pub fn flush(
645 var iovecs_i: usize = 1;646 var iovecs_i: usize = 1;
646 var text_i: u64 = 0;647 var text_i: u64 = 0;
647648
648 var linecountinfo = std.ArrayList(u8).init(gpa);649 var linecountinfo_aw: std.io.AllocatingWriter = undefined;
649 defer linecountinfo.deinit();650 linecountinfo_aw.init(gpa);
651 defer linecountinfo_aw.deinit();
650 // text652 // text
651 {653 {
654 const linecountinfo_bw = &linecountinfo_aw.buffered_writer;
652 var linecount: i64 = -1;655 var linecount: i64 = -1;
653 var it_file = self.fn_nav_table.iterator();656 var it_file = self.fn_nav_table.iterator();
654 while (it_file.next()) |fentry| {657 while (it_file.next()) |fentry| {
...@@ -662,11 +665,11 @@ pub fn flush(...@@ -662,11 +665,11 @@ pub fn flush(
662 // connect the previous decl to the next665 // connect the previous decl to the next
663 const delta_line = @as(i32, @intCast(out.start_line)) - @as(i32, @intCast(linecount));666 const delta_line = @as(i32, @intCast(out.start_line)) - @as(i32, @intCast(linecount));
664667
665 try changeLine(&linecountinfo, delta_line);668 changeLine(linecountinfo_bw, delta_line) catch |err| return @errorCast(err);
666 // TODO change the pc too (maybe?)669 // TODO change the pc too (maybe?)
667670
668 // write out the actual info that was generated in codegen now671 // write out the actual info that was generated in codegen now
669 try linecountinfo.appendSlice(out.lineinfo);672 linecountinfo_bw.writeAll(out.lineinfo) catch |err| return @errorCast(err);
670 linecount = out.end_line;673 linecount = out.end_line;
671 }674 }
672 foff += out.code.len;675 foff += out.code.len;
...@@ -675,7 +678,7 @@ pub fn flush(...@@ -675,7 +678,7 @@ pub fn flush(
675 const off = self.getAddr(text_i, .t);678 const off = self.getAddr(text_i, .t);
676 text_i += out.code.len;679 text_i += out.code.len;
677 atom.offset = off;680 atom.offset = off;
678 log.debug("write text nav 0x{x} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });681 log.debug("write text nav 0x{x} ({f}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ nav_index, nav.name.fmt(&pt.zcu.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });
679 if (!self.sixtyfour_bit) {682 if (!self.sixtyfour_bit) {
680 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian());683 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(off), target.cpu.arch.endian());
681 } else {684 } else {
...@@ -687,11 +690,12 @@ pub fn flush(...@@ -687,11 +690,12 @@ pub fn flush(
687 }690 }
688 }691 }
689 }692 }
690 if (linecountinfo.items.len & 1 == 1) {693 if (linecountinfo_aw.getWritten().len & 1 == 1) {
691 // just a nop to make it even, the plan9 linker does this694 // just a nop to make it even, the plan9 linker does this
692 try linecountinfo.append(129);695 linecountinfo_bw.writeByte(129) catch |err| return @errorCast(err);
693 }696 }
694 }697 }
698 const linecountinfo = linecountinfo_aw.getWritten();
695 // the text lazy symbols699 // the text lazy symbols
696 {700 {
697 var it = self.lazy_syms.iterator();701 var it = self.lazy_syms.iterator();
...@@ -815,25 +819,26 @@ pub fn flush(...@@ -815,25 +819,26 @@ pub fn flush(
815 }819 }
816 }820 }
817 }821 }
818 var sym_buf = std.ArrayList(u8).init(gpa);822 var syms_aw: std.io.AllocatingWriter = undefined;
819 try self.writeSyms(&sym_buf);823 syms_aw.init(gpa);
820 const syms = try sym_buf.toOwnedSlice();824 defer syms_aw.deinit();
821 defer gpa.free(syms);825 self.writeSyms(&syms_aw.buffered_writer) catch |err| return @errorCast(err);
826 const syms = syms_aw.getWritten();
822 assert(2 + self.atomCount() - self.externCount() == iovecs_i); // we didn't write all the decls827 assert(2 + self.atomCount() - self.externCount() == iovecs_i); // we didn't write all the decls
823 iovecs[iovecs_i] = .{ .base = syms.ptr, .len = syms.len };828 iovecs[iovecs_i] = .{ .base = syms.ptr, .len = syms.len };
824 iovecs_i += 1;829 iovecs_i += 1;
825 iovecs[iovecs_i] = .{ .base = linecountinfo.items.ptr, .len = linecountinfo.items.len };830 iovecs[iovecs_i] = .{ .base = linecountinfo.ptr, .len = linecountinfo.len };
826 iovecs_i += 1;831 iovecs_i += 1;
827 // generate the header832 // generate the header
828 self.hdr = .{833 self.hdr = .{
829 .magic = self.magic,834 .magic = self.magic,
830 .text = @as(u32, @intCast(text_i)),835 .text = @intCast(text_i),
831 .data = @as(u32, @intCast(data_i)),836 .data = @intCast(data_i),
832 .syms = @as(u32, @intCast(syms.len)),837 .syms = @intCast(syms.len),
833 .bss = 0,838 .bss = 0,
834 .spsz = 0,839 .spsz = 0,
835 .pcsz = @as(u32, @intCast(linecountinfo.items.len)),840 .pcsz = @intCast(linecountinfo.len),
836 .entry = @as(u32, @intCast(self.entry_val.?)),841 .entry = @intCast(self.entry_val.?),
837 };842 };
838 @memcpy(hdr_slice, self.hdr.toU8s()[0..hdr_size]);843 @memcpy(hdr_slice, self.hdr.toU8s()[0..hdr_size]);
839 // write the fat header for 64 bit entry points844 // write the fat header for 64 bit entry points
...@@ -974,11 +979,11 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -974,11 +979,11 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
974 self.etext_edata_end_atom_indices[2] = atom_idx;979 self.etext_edata_end_atom_indices[2] = atom_idx;
975 }980 }
976 try self.updateFinish(pt, nav_index);981 try self.updateFinish(pt, nav_index);
977 log.debug("seeNav(extern) for {} (got_addr=0x{x})", .{982 log.debug("seeNav(extern) for {f} (got_addr=0x{x})", .{
978 nav.name.fmt(ip),983 nav.name.fmt(ip),
979 self.getAtom(atom_idx).getOffsetTableAddress(self),984 self.getAtom(atom_idx).getOffsetTableAddress(self),
980 });985 });
981 } else log.debug("seeNav for {}", .{nav.name.fmt(ip)});986 } else log.debug("seeNav for {f}", .{nav.name.fmt(ip)});
982 return atom_idx;987 return atom_idx;
983}988}
984989
...@@ -1043,7 +1048,7 @@ fn updateLazySymbolAtom(...@@ -1043,7 +1048,7 @@ fn updateLazySymbolAtom(
1043 defer code_buffer.deinit(gpa);1048 defer code_buffer.deinit(gpa);
10441049
1045 // create the symbol for the name1050 // create the symbol for the name
1046 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{}", .{1051 const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
1047 @tagName(sym.kind),1052 @tagName(sym.kind),
1048 Type.fromInterned(sym.ty).fmt(pt),1053 Type.fromInterned(sym.ty).fmt(pt),
1049 });1054 });
...@@ -1200,17 +1205,16 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {...@@ -1200,17 +1205,16 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
1200 try w.writeByte(0);1205 try w.writeByte(0);
1201}1206}
12021207
1203pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {1208pub fn writeSyms(self: *Plan9, bw: *std.io.BufferedWriter) !void {
1204 const zcu = self.base.comp.zcu.?;1209 const zcu = self.base.comp.zcu.?;
1205 const ip = &zcu.intern_pool;1210 const ip = &zcu.intern_pool;
1206 const writer = buf.writer();
1207 // write __GOT1211 // write __GOT
1208 try self.writeSym(writer, self.syms.items[0]);1212 try self.writeSym(bw, self.syms.items[0]);
1209 // write the f symbols1213 // write the f symbols
1210 {1214 {
1211 var it = self.file_segments.iterator();1215 var it = self.file_segments.iterator();
1212 while (it.next()) |entry| {1216 while (it.next()) |entry| {
1213 try self.writeSym(writer, .{1217 try self.writeSym(bw, .{
1214 .type = .f,1218 .type = .f,
1215 .value = entry.value_ptr.*,1219 .value = entry.value_ptr.*,
1216 .name = entry.key_ptr.*,1220 .name = entry.key_ptr.*,
...@@ -1226,12 +1230,12 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1226,12 +1230,12 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1226 const nav_metadata = self.navs.get(nav_index).?;1230 const nav_metadata = self.navs.get(nav_index).?;
1227 const atom = self.getAtom(nav_metadata.index);1231 const atom = self.getAtom(nav_metadata.index);
1228 const sym = self.syms.items[atom.sym_index.?];1232 const sym = self.syms.items[atom.sym_index.?];
1229 try self.writeSym(writer, sym);1233 try self.writeSym(bw, sym);
1230 if (self.nav_exports.get(nav_index)) |export_indices| {1234 if (self.nav_exports.get(nav_index)) |export_indices| {
1231 for (export_indices) |export_idx| {1235 for (export_indices) |export_idx| {
1232 const exp = export_idx.ptr(zcu);1236 const exp = export_idx.ptr(zcu);
1233 if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {1237 if (nav_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
1234 try self.writeSym(writer, self.syms.items[exp_i]);1238 try self.writeSym(bw, self.syms.items[exp_i]);
1235 }1239 }
1236 }1240 }
1237 }1241 }
...@@ -1244,7 +1248,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1244,7 +1248,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1244 const meta = kv.value_ptr;1248 const meta = kv.value_ptr;
1245 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;1249 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;
1246 const sym = self.syms.items[data_atom.sym_index.?];1250 const sym = self.syms.items[data_atom.sym_index.?];
1247 try self.writeSym(writer, sym);1251 try self.writeSym(bw, sym);
1248 }1252 }
1249 }1253 }
1250 // text symbols are the hardest:1254 // text symbols are the hardest:
...@@ -1255,8 +1259,8 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1255,8 +1259,8 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1255 while (it_file.next()) |fentry| {1259 while (it_file.next()) |fentry| {
1256 var symidx_and_submap = fentry.value_ptr;1260 var symidx_and_submap = fentry.value_ptr;
1257 // write the z symbols1261 // write the z symbols
1258 try self.writeSym(writer, self.syms.items[symidx_and_submap.sym_index - 1]);1262 try self.writeSym(bw, self.syms.items[symidx_and_submap.sym_index - 1]);
1259 try self.writeSym(writer, self.syms.items[symidx_and_submap.sym_index]);1263 try self.writeSym(bw, self.syms.items[symidx_and_submap.sym_index]);
12601264
1261 // write all the decls come from the file of the z symbol1265 // write all the decls come from the file of the z symbol
1262 var submap_it = symidx_and_submap.functions.iterator();1266 var submap_it = symidx_and_submap.functions.iterator();
...@@ -1265,7 +1269,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1265,7 +1269,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1265 const nav_metadata = self.navs.get(nav_index).?;1269 const nav_metadata = self.navs.get(nav_index).?;
1266 const atom = self.getAtom(nav_metadata.index);1270 const atom = self.getAtom(nav_metadata.index);
1267 const sym = self.syms.items[atom.sym_index.?];1271 const sym = self.syms.items[atom.sym_index.?];
1268 try self.writeSym(writer, sym);1272 try self.writeSym(bw, sym);
1269 if (self.nav_exports.get(nav_index)) |export_indices| {1273 if (self.nav_exports.get(nav_index)) |export_indices| {
1270 for (export_indices) |export_idx| {1274 for (export_indices) |export_idx| {
1271 const exp = export_idx.ptr(zcu);1275 const exp = export_idx.ptr(zcu);
...@@ -1273,7 +1277,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1273,7 +1277,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1273 const s = self.syms.items[exp_i];1277 const s = self.syms.items[exp_i];
1274 if (mem.eql(u8, s.name, "_start"))1278 if (mem.eql(u8, s.name, "_start"))
1275 self.entry_val = s.value;1279 self.entry_val = s.value;
1276 try self.writeSym(writer, s);1280 try self.writeSym(bw, s);
1277 }1281 }
1278 }1282 }
1279 }1283 }
...@@ -1286,7 +1290,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1286,7 +1290,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1286 const meta = kv.value_ptr;1290 const meta = kv.value_ptr;
1287 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;1291 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;
1288 const sym = self.syms.items[text_atom.sym_index.?];1292 const sym = self.syms.items[text_atom.sym_index.?];
1289 try self.writeSym(writer, sym);1293 try self.writeSym(bw, sym);
1290 }1294 }
1291 }1295 }
1292 }1296 }
...@@ -1295,7 +1299,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1295,7 +1299,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1295 if (idx) |atom_idx| {1299 if (idx) |atom_idx| {
1296 const atom = self.getAtom(atom_idx);1300 const atom = self.getAtom(atom_idx);
1297 const sym = self.syms.items[atom.sym_index.?];1301 const sym = self.syms.items[atom.sym_index.?];
1298 try self.writeSym(writer, sym);1302 try self.writeSym(bw, sym);
1299 }1303 }
1300 }1304 }
1301}1305}
...@@ -1314,7 +1318,7 @@ pub fn getNavVAddr(...@@ -1314,7 +1318,7 @@ pub fn getNavVAddr(
1314) !u64 {1318) !u64 {
1315 const ip = &pt.zcu.intern_pool;1319 const ip = &pt.zcu.intern_pool;
1316 const nav = ip.getNav(nav_index);1320 const nav = ip.getNav(nav_index);
1317 log.debug("getDeclVAddr for {}", .{nav.name.fmt(ip)});1321 log.debug("getDeclVAddr for {f}", .{nav.name.fmt(ip)});
1318 if (nav.getExtern(ip) != null) {1322 if (nav.getExtern(ip) != null) {
1319 if (nav.name.eqlSlice("etext", ip)) {1323 if (nav.name.eqlSlice("etext", ip)) {
1320 try self.addReloc(reloc_info.parent.atom_index, .{1324 try self.addReloc(reloc_info.parent.atom_index, .{
src/link/SpirV.zig+9-8
...@@ -117,7 +117,7 @@ pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin...@@ -117,7 +117,7 @@ pub fn updateNav(self: *SpirV, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin
117 }117 }
118118
119 const ip = &pt.zcu.intern_pool;119 const ip = &pt.zcu.intern_pool;
120 log.debug("lowering nav {}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });120 log.debug("lowering nav {f}({d})", .{ ip.getNav(nav).fqn.fmt(ip), nav });
121121
122 try self.object.updateNav(pt, nav);122 try self.object.updateNav(pt, nav);
123}123}
...@@ -203,10 +203,11 @@ pub fn flush(...@@ -203,10 +203,11 @@ pub fn flush(
203 // We need to export the list of error names somewhere so that we can pretty-print them in the203 // We need to export the list of error names somewhere so that we can pretty-print them in the
204 // executor. This is not really an important thing though, so we can just dump it in any old204 // executor. This is not really an important thing though, so we can just dump it in any old
205 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.205 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.
206 var error_info = std.ArrayList(u8).init(self.object.gpa);206 var error_info: std.io.AllocatingWriter = undefined;
207 error_info.init(self.object.gpa);
207 defer error_info.deinit();208 defer error_info.deinit();
208209
209 try error_info.appendSlice("zig_errors:");210 error_info.buffered_writer.writeAll("zig_errors:") catch |err| return @errorCast(err);
210 const ip = &self.base.comp.zcu.?.intern_pool;211 const ip = &self.base.comp.zcu.?.intern_pool;
211 for (ip.global_error_set.getNamesFromMainThread()) |name| {212 for (ip.global_error_set.getNamesFromMainThread()) |name| {
212 // Errors can contain pretty much any character - to encode them in a string we must escape213 // Errors can contain pretty much any character - to encode them in a string we must escape
...@@ -214,9 +215,9 @@ pub fn flush(...@@ -214,9 +215,9 @@ pub fn flush(
214 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.215 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
215 // We're using : as separator, which is a reserved character.216 // We're using : as separator, which is a reserved character.
216217
217 try error_info.append(':');218 error_info.buffered_writer.writeByte(':') catch |err| return @errorCast(err);
218 try std.Uri.Component.percentEncode(219 std.Uri.Component.percentEncode(
219 error_info.writer(),220 &error_info.buffered_writer,
220 name.toSlice(ip),221 name.toSlice(ip),
221 struct {222 struct {
222 fn isValidChar(c: u8) bool {223 fn isValidChar(c: u8) bool {
...@@ -226,10 +227,10 @@ pub fn flush(...@@ -226,10 +227,10 @@ pub fn flush(
226 };227 };
227 }228 }
228 }.isValidChar,229 }.isValidChar,
229 );230 ) catch |err| return @errorCast(err);
230 }231 }
231 try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{232 try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{
232 .extension = error_info.items,233 .extension = error_info.getWritten(),
233 });234 });
234235
235 const module = try spv.finalize(arena);236 const module = try spv.finalize(arena);
src/link/SpirV/deduplicate.zig+1-1
...@@ -110,7 +110,7 @@ const ModuleInfo = struct {...@@ -110,7 +110,7 @@ const ModuleInfo = struct {
110 .TypeDeclaration, .ConstantCreation => {110 .TypeDeclaration, .ConstantCreation => {
111 const entry = try entities.getOrPut(result_id);111 const entry = try entities.getOrPut(result_id);
112 if (entry.found_existing) {112 if (entry.found_existing) {
113 log.err("type or constant {} has duplicate definition", .{result_id});113 log.err("type or constant {f} has duplicate definition", .{result_id});
114 return error.DuplicateId;114 return error.DuplicateId;
115 }115 }
116 entry.value_ptr.* = entity;116 entry.value_ptr.* = entity;
src/link/SpirV/lower_invocation_globals.zig+9-9
...@@ -92,7 +92,7 @@ const ModuleInfo = struct {...@@ -92,7 +92,7 @@ const ModuleInfo = struct {
92 const entry_point: ResultId = @enumFromInt(inst.operands[1]);92 const entry_point: ResultId = @enumFromInt(inst.operands[1]);
93 const entry = try entry_points.getOrPut(entry_point);93 const entry = try entry_points.getOrPut(entry_point);
94 if (entry.found_existing) {94 if (entry.found_existing) {
95 log.err("Entry point type {} has duplicate definition", .{entry_point});95 log.err("Entry point type {f} has duplicate definition", .{entry_point});
96 return error.DuplicateId;96 return error.DuplicateId;
97 }97 }
98 },98 },
...@@ -103,7 +103,7 @@ const ModuleInfo = struct {...@@ -103,7 +103,7 @@ const ModuleInfo = struct {
103103
104 const entry = try fn_types.getOrPut(fn_type);104 const entry = try fn_types.getOrPut(fn_type);
105 if (entry.found_existing) {105 if (entry.found_existing) {
106 log.err("Function type {} has duplicate definition", .{fn_type});106 log.err("Function type {f} has duplicate definition", .{fn_type});
107 return error.DuplicateId;107 return error.DuplicateId;
108 }108 }
109109
...@@ -135,7 +135,7 @@ const ModuleInfo = struct {...@@ -135,7 +135,7 @@ const ModuleInfo = struct {
135 },135 },
136 .OpFunction => {136 .OpFunction => {
137 if (maybe_current_function) |current_function| {137 if (maybe_current_function) |current_function| {
138 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});138 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
139 return error.InvalidPhysicalFormat;139 return error.InvalidPhysicalFormat;
140 }140 }
141141
...@@ -154,7 +154,7 @@ const ModuleInfo = struct {...@@ -154,7 +154,7 @@ const ModuleInfo = struct {
154 };154 };
155 const entry = try functions.getOrPut(current_function);155 const entry = try functions.getOrPut(current_function);
156 if (entry.found_existing) {156 if (entry.found_existing) {
157 log.err("Function {} has duplicate definition", .{current_function});157 log.err("Function {f} has duplicate definition", .{current_function});
158 return error.DuplicateId;158 return error.DuplicateId;
159 }159 }
160160
...@@ -162,7 +162,7 @@ const ModuleInfo = struct {...@@ -162,7 +162,7 @@ const ModuleInfo = struct {
162 try callee_store.appendSlice(calls.keys());162 try callee_store.appendSlice(calls.keys());
163163
164 const fn_type = fn_types.get(fn_ty_id) orelse {164 const fn_type = fn_types.get(fn_ty_id) orelse {
165 log.err("Function {} has invalid OpFunction type", .{current_function});165 log.err("Function {f} has invalid OpFunction type", .{current_function});
166 return error.InvalidId;166 return error.InvalidId;
167 };167 };
168168
...@@ -187,7 +187,7 @@ const ModuleInfo = struct {...@@ -187,7 +187,7 @@ const ModuleInfo = struct {
187 }187 }
188188
189 if (maybe_current_function) |current_function| {189 if (maybe_current_function) |current_function| {
190 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});190 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
191 return error.InvalidPhysicalFormat;191 return error.InvalidPhysicalFormat;
192 }192 }
193193
...@@ -222,7 +222,7 @@ const ModuleInfo = struct {...@@ -222,7 +222,7 @@ const ModuleInfo = struct {
222 seen: *std.DynamicBitSetUnmanaged,222 seen: *std.DynamicBitSetUnmanaged,
223 ) !void {223 ) !void {
224 const index = self.functions.getIndex(id) orelse {224 const index = self.functions.getIndex(id) orelse {
225 log.err("function calls invalid function {}", .{id});225 log.err("function calls invalid function {f}", .{id});
226 return error.InvalidId;226 return error.InvalidId;
227 };227 };
228228
...@@ -261,7 +261,7 @@ const ModuleInfo = struct {...@@ -261,7 +261,7 @@ const ModuleInfo = struct {
261 seen: *std.DynamicBitSetUnmanaged,261 seen: *std.DynamicBitSetUnmanaged,
262 ) !void {262 ) !void {
263 const index = self.invocation_globals.getIndex(id) orelse {263 const index = self.invocation_globals.getIndex(id) orelse {
264 log.err("invalid invocation global {}", .{id});264 log.err("invalid invocation global {f}", .{id});
265 return error.InvalidId;265 return error.InvalidId;
266 };266 };
267267
...@@ -276,7 +276,7 @@ const ModuleInfo = struct {...@@ -276,7 +276,7 @@ const ModuleInfo = struct {
276 }276 }
277277
278 const initializer = self.functions.get(info.initializer) orelse {278 const initializer = self.functions.get(info.initializer) orelse {
279 log.err("invocation global {} has invalid initializer {}", .{ id, info.initializer });279 log.err("invocation global {f} has invalid initializer {f}", .{ id, info.initializer });
280 return error.InvalidId;280 return error.InvalidId;
281 };281 };
282282
src/link/SpirV/prune_unused.zig+4-4
...@@ -128,7 +128,7 @@ const ModuleInfo = struct {...@@ -128,7 +128,7 @@ const ModuleInfo = struct {
128 switch (inst.opcode) {128 switch (inst.opcode) {
129 .OpFunction => {129 .OpFunction => {
130 if (maybe_current_function) |current_function| {130 if (maybe_current_function) |current_function| {
131 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});131 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
132 return error.InvalidPhysicalFormat;132 return error.InvalidPhysicalFormat;
133 }133 }
134134
...@@ -145,7 +145,7 @@ const ModuleInfo = struct {...@@ -145,7 +145,7 @@ const ModuleInfo = struct {
145 };145 };
146 const entry = try functions.getOrPut(current_function);146 const entry = try functions.getOrPut(current_function);
147 if (entry.found_existing) {147 if (entry.found_existing) {
148 log.err("Function {} has duplicate definition", .{current_function});148 log.err("Function {f} has duplicate definition", .{current_function});
149 return error.DuplicateId;149 return error.DuplicateId;
150 }150 }
151151
...@@ -163,7 +163,7 @@ const ModuleInfo = struct {...@@ -163,7 +163,7 @@ const ModuleInfo = struct {
163 }163 }
164164
165 if (maybe_current_function) |current_function| {165 if (maybe_current_function) |current_function| {
166 log.err("OpFunction {} does not have an OpFunctionEnd", .{current_function});166 log.err("OpFunction {f} does not have an OpFunctionEnd", .{current_function});
167 return error.InvalidPhysicalFormat;167 return error.InvalidPhysicalFormat;
168 }168 }
169169
...@@ -184,7 +184,7 @@ const AliveMarker = struct {...@@ -184,7 +184,7 @@ const AliveMarker = struct {
184184
185 fn markAlive(self: *AliveMarker, result_id: ResultId) BinaryModule.ParseError!void {185 fn markAlive(self: *AliveMarker, result_id: ResultId) BinaryModule.ParseError!void {
186 const index = self.info.result_id_to_code_offset.getIndex(result_id) orelse {186 const index = self.info.result_id_to_code_offset.getIndex(result_id) orelse {
187 log.err("undefined result-id {}", .{result_id});187 log.err("undefined result-id {f}", .{result_id});
188 return error.InvalidId;188 return error.InvalidId;
189 };189 };
190190
src/link/Wasm.zig+27-34
...@@ -547,7 +547,7 @@ pub const SourceLocation = enum(u32) {...@@ -547,7 +547,7 @@ pub const SourceLocation = enum(u32) {
547 switch (sl.unpack(wasm)) {547 switch (sl.unpack(wasm)) {
548 .none => unreachable,548 .none => unreachable,
549 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),549 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),
550 .object_index => |i| diags.addError("{}: " ++ f, .{i.ptr(wasm).path} ++ args),550 .object_index => |i| diags.addError("{f}: " ++ f, .{i.ptr(wasm).path} ++ args),
551 .source_location_index => @panic("TODO"),551 .source_location_index => @panic("TODO"),
552 }552 }
553 }553 }
...@@ -579,9 +579,9 @@ pub const SourceLocation = enum(u32) {...@@ -579,9 +579,9 @@ pub const SourceLocation = enum(u32) {
579 .object_index => |i| {579 .object_index => |i| {
580 const obj = i.ptr(wasm);580 const obj = i.ptr(wasm);
581 return if (obj.archive_member_name.slice(wasm)) |obj_name|581 return if (obj.archive_member_name.slice(wasm)) |obj_name|
582 try bundle.printString("{} ({s}): {s}", .{ obj.path, std.fs.path.basename(obj_name), msg })582 try bundle.printString("{f} ({s}): {s}", .{ obj.path, std.fs.path.basename(obj_name), msg })
583 else583 else
584 try bundle.printString("{}: {s}", .{ obj.path, msg });584 try bundle.printString("{f}: {s}", .{ obj.path, msg });
585 },585 },
586 .source_location_index => @panic("TODO"),586 .source_location_index => @panic("TODO"),
587 };587 };
...@@ -2087,11 +2087,10 @@ pub const Expr = enum(u32) {...@@ -2087,11 +2087,10 @@ pub const Expr = enum(u32) {
2087 pub const end = @intFromEnum(std.wasm.Opcode.end);2087 pub const end = @intFromEnum(std.wasm.Opcode.end);
20882088
2089 pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {2089 pub fn slice(index: Expr, wasm: *const Wasm) [:end]const u8 {
2090 const start_slice = wasm.string_bytes.items[@intFromEnum(index)..];2090 var br: std.io.BufferedReader = undefined;
2091 const end_pos = Object.exprEndPos(start_slice, 0) catch |err| switch (err) {2091 br.initFixed(wasm.string_bytes.items[@intFromEnum(index)..]);
2092 error.InvalidInitOpcode => unreachable,2092 Object.skipInit(&br) catch unreachable;
2093 };2093 return br.storageBuffer()[0 .. br.seek - 1 :end];
2094 return start_slice[0..end_pos :end];
2095 }2094 }
2096};2095};
20972096
...@@ -2126,32 +2125,26 @@ pub const FunctionType = extern struct {...@@ -2126,32 +2125,26 @@ pub const FunctionType = extern struct {
2126 wasm: *const Wasm,2125 wasm: *const Wasm,
2127 ft: FunctionType,2126 ft: FunctionType,
21282127
2129 pub fn format(2128 pub fn format(self: Formatter, bw: *std.io.BufferedWriter, comptime format_string: []const u8) anyerror!void {
2130 self: Formatter,
2131 comptime format_string: []const u8,
2132 options: std.fmt.FormatOptions,
2133 writer: anytype,
2134 ) !void {
2135 if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self);2129 if (format_string.len != 0) std.fmt.invalidFmtError(format_string, self);
2136 _ = options;
2137 const params = self.ft.params.slice(self.wasm);2130 const params = self.ft.params.slice(self.wasm);
2138 const returns = self.ft.returns.slice(self.wasm);2131 const returns = self.ft.returns.slice(self.wasm);
21392132
2140 try writer.writeByte('(');2133 try bw.writeByte('(');
2141 for (params, 0..) |param, i| {2134 for (params, 0..) |param, i| {
2142 try writer.print("{s}", .{@tagName(param)});2135 try bw.print("{s}", .{@tagName(param)});
2143 if (i + 1 != params.len) {2136 if (i + 1 != params.len) {
2144 try writer.writeAll(", ");2137 try bw.writeAll(", ");
2145 }2138 }
2146 }2139 }
2147 try writer.writeAll(") -> ");2140 try bw.writeAll(") -> ");
2148 if (returns.len == 0) {2141 if (returns.len == 0) {
2149 try writer.writeAll("nil");2142 try bw.writeAll("nil");
2150 } else {2143 } else {
2151 for (returns, 0..) |return_ty, i| {2144 for (returns, 0..) |return_ty, i| {
2152 try writer.print("{s}", .{@tagName(return_ty)});2145 try bw.print("{s}", .{@tagName(return_ty)});
2153 if (i + 1 != returns.len) {2146 if (i + 1 != returns.len) {
2154 try writer.writeAll(", ");2147 try bw.writeAll(", ");
2155 }2148 }
2156 }2149 }
2157 }2150 }
...@@ -2912,10 +2905,9 @@ pub const Feature = packed struct(u8) {...@@ -2912,10 +2905,9 @@ pub const Feature = packed struct(u8) {
2912 @"=",2905 @"=",
2913 };2906 };
29142907
2915 pub fn format(feature: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void {2908 pub fn format(feature: Feature, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
2916 _ = opt;
2917 _ = fmt;2909 _ = fmt;
2918 try writer.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });2910 try bw.print("{s} {s}", .{ @tagName(feature.prefix), @tagName(feature.tag) });
2919 }2911 }
29202912
2921 pub fn lessThan(_: void, a: Feature, b: Feature) bool {2913 pub fn lessThan(_: void, a: Feature, b: Feature) bool {
...@@ -3036,7 +3028,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {...@@ -3036,7 +3028,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
3036}3028}
30373029
3038fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {3030fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3039 log.debug("parseObject {}", .{obj.path});3031 log.debug("parseObject {f}", .{obj.path});
3040 const gpa = wasm.base.comp.gpa;3032 const gpa = wasm.base.comp.gpa;
3041 const gc_sections = wasm.base.gc_sections;3033 const gc_sections = wasm.base.gc_sections;
30423034
...@@ -3046,21 +3038,22 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3046,21 +3038,22 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
3046 const stat = try obj.file.stat();3038 const stat = try obj.file.stat();
3047 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;3039 const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;
30483040
3049 const file_contents = try gpa.alloc(u8, size);3041 var br: std.io.BufferedReader = undefined;
3050 defer gpa.free(file_contents);3042 br.initFixed(try gpa.alloc(u8, size));
3043 defer gpa.free(br.storageBuffer());
30513044
3052 const n = try obj.file.preadAll(file_contents, 0);3045 const n = try obj.file.preadAll(br.storageBuffer(), 0);
3053 if (n != file_contents.len) return error.UnexpectedEndOfFile;3046 if (n != br.storageBuffer().len) return error.UnexpectedEndOfFile;
30543047
3055 var ss: Object.ScratchSpace = .{};3048 var ss: Object.ScratchSpace = .{};
3056 defer ss.deinit(gpa);3049 defer ss.deinit(gpa);
30573050
3058 const object = try Object.parse(wasm, file_contents, obj.path, null, wasm.object_host_name, &ss, obj.must_link, gc_sections);3051 const object = try Object.parse(wasm, &br, obj.path, null, wasm.object_host_name, &ss, obj.must_link, gc_sections);
3059 wasm.objects.appendAssumeCapacity(object);3052 wasm.objects.appendAssumeCapacity(object);
3060}3053}
30613054
3062fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {3055fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
3063 log.debug("parseArchive {}", .{obj.path});3056 log.debug("parseArchive {f}", .{obj.path});
3064 const gpa = wasm.base.comp.gpa;3057 const gpa = wasm.base.comp.gpa;
3065 const gc_sections = wasm.base.gc_sections;3058 const gc_sections = wasm.base.gc_sections;
30663059
...@@ -3196,7 +3189,7 @@ pub fn updateFunc(...@@ -3196,7 +3189,7 @@ pub fn updateFunc(
3196 const is_obj = zcu.comp.config.output_mode == .Obj;3189 const is_obj = zcu.comp.config.output_mode == .Obj;
3197 const target = &zcu.comp.root_mod.resolved_target.result;3190 const target = &zcu.comp.root_mod.resolved_target.result;
3198 const owner_nav = zcu.funcInfo(func_index).owner_nav;3191 const owner_nav = zcu.funcInfo(func_index).owner_nav;
3199 log.debug("updateFunc {}", .{ip.getNav(owner_nav).fqn.fmt(ip)});3192 log.debug("updateFunc {f}", .{ip.getNav(owner_nav).fqn.fmt(ip)});
32003193
3201 // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,3194 // For Wasm, we do not lower the MIR to code just yet. That lowering happens during `flush`,
3202 // after garbage collection, which can affect function and global indexes, which affects the3195 // after garbage collection, which can affect function and global indexes, which affects the
...@@ -4347,7 +4340,7 @@ fn resolveFunctionSynthetic(...@@ -4347,7 +4340,7 @@ fn resolveFunctionSynthetic(
4347 });4340 });
4348 if (import.type != correct_func_type) {4341 if (import.type != correct_func_type) {
4349 const diags = &wasm.base.comp.link_diags;4342 const diags = &wasm.base.comp.link_diags;
4350 return import.source_location.fail(diags, "synthetic function {s} {} imported with incorrect signature {}", .{4343 return import.source_location.fail(diags, "synthetic function {s} {f} imported with incorrect signature {f}", .{
4351 @tagName(res), correct_func_type.fmt(wasm), import.type.fmt(wasm),4344 @tagName(res), correct_func_type.fmt(wasm), import.type.fmt(wasm),
4352 });4345 });
4353 }4346 }
src/link/Wasm/Archive.zig+3-2
...@@ -167,9 +167,10 @@ pub fn parseObject(...@@ -167,9 +167,10 @@ pub fn parseObject(
167 };167 };
168168
169 const object_file_size = try header.parsedSize();169 const object_file_size = try header.parsedSize();
170 const contents = file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size];170 var br: std.io.BufferedReader = undefined;
171 br.initFixed(file_contents[object_offset + @sizeOf(Header) ..][0..object_file_size]);
171172
172 return Object.parse(wasm, contents, path, object_name, host_name, scratch_space, must_link, gc_sections);173 return Object.parse(wasm, &br, path, object_name, host_name, scratch_space, must_link, gc_sections);
173}174}
174175
175const Archive = @This();176const Archive = @This();
src/link/Wasm/Flush.zig+469-554
...@@ -16,7 +16,6 @@ const build_options = @import("build_options");...@@ -16,7 +16,6 @@ const build_options = @import("build_options");
16const std = @import("std");16const std = @import("std");
17const Allocator = std.mem.Allocator;17const Allocator = std.mem.Allocator;
18const mem = std.mem;18const mem = std.mem;
19const leb = std.leb;
20const log = std.log.scoped(.link);19const log = std.log.scoped(.link);
21const assert = std.debug.assert;20const assert = std.debug.assert;
2221
...@@ -557,13 +556,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -557,13 +556,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
557 // Index of the data section. Used to tell relocation table where the section lives.556 // Index of the data section. Used to tell relocation table where the section lives.
558 var data_section_index: ?u32 = null;557 var data_section_index: ?u32 = null;
559558
560 const binary_bytes = &f.binary_bytes;559 assert(f.binary_bytes.items.len == 0);
561 assert(binary_bytes.items.len == 0);560 var aw: std.io.AllocatingWriter = undefined;
561 const bw = aw.fromArrayList(gpa, &f.binary_bytes);
562 defer f.binary_bytes = aw.toArrayList();
562563
563 try binary_bytes.appendSlice(gpa, &std.wasm.magic ++ &std.wasm.version);564 try bw.writeAll(&std.wasm.magic ++ &std.wasm.version);
564 assert(binary_bytes.items.len == 8);
565
566 const binary_writer = binary_bytes.writer(gpa);
567565
568 // Type section.566 // Type section.
569 for (f.function_imports.values()) |id| {567 for (f.function_imports.values()) |id| {
...@@ -573,22 +571,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -573,22 +571,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
573 try f.func_types.put(gpa, function.typeIndex(wasm), {});571 try f.func_types.put(gpa, function.typeIndex(wasm), {});
574 }572 }
575 if (f.func_types.entries.len != 0) {573 if (f.func_types.entries.len != 0) {
576 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);574 const header_offset = try reserveVecSectionHeader(bw);
577 for (f.func_types.keys()) |func_type_index| {575 for (f.func_types.keys()) |func_type_index| {
578 const func_type = func_type_index.ptr(wasm);576 const func_type = func_type_index.ptr(wasm);
579 try leb.writeUleb128(binary_writer, std.wasm.function_type);577 try bw.writeLeb128(std.wasm.function_type);
580 const params = func_type.params.slice(wasm);578 const params = func_type.params.slice(wasm);
581 try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len)));579 try bw.writeLeb128(params.len);
582 for (params) |param_ty| {580 for (params) |param_ty| try bw.writeLeb128(@intFromEnum(param_ty));
583 try leb.writeUleb128(binary_writer, @intFromEnum(param_ty));
584 }
585 const returns = func_type.returns.slice(wasm);581 const returns = func_type.returns.slice(wasm);
586 try leb.writeUleb128(binary_writer, @as(u32, @intCast(returns.len)));582 try bw.writeLeb128(returns.len);
587 for (returns) |ret_ty| {583 for (returns) |ret_ty| try bw.writeLeb128(@intFromEnum(ret_ty));
588 try leb.writeUleb128(binary_writer, @intFromEnum(ret_ty));
589 }
590 }584 }
591 replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(f.func_types.entries.len));585 replaceVecSectionHeader(&aw, header_offset, .type, @intCast(f.func_types.entries.len));
592 section_index += 1;586 section_index += 1;
593 }587 }
594588
...@@ -601,42 +595,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -601,42 +595,42 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
601 // Import section595 // Import section
602 {596 {
603 var total_imports: usize = 0;597 var total_imports: usize = 0;
604 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);598 const header_offset = try reserveVecSectionHeader(bw);
605599
606 for (f.function_imports.values()) |id| {600 for (f.function_imports.values()) |id| {
607 const module_name = id.moduleName(wasm).slice(wasm).?;601 const module_name = id.moduleName(wasm).slice(wasm).?;
608 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));602 try bw.writeLeb128(module_name.len);
609 try binary_writer.writeAll(module_name);603 try bw.writeAll(module_name);
610604
611 const name = id.importName(wasm).slice(wasm);605 const name = id.importName(wasm).slice(wasm);
612 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));606 try bw.writeLeb128(name.len);
613 try binary_writer.writeAll(name);607 try bw.writeAll(name);
614608
615 try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function));609 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
616 const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f);610 const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f);
617 try leb.writeUleb128(binary_writer, @intFromEnum(type_index));611 try bw.writeLeb128(@intFromEnum(type_index));
618 }612 }
619 total_imports += f.function_imports.entries.len;613 total_imports += f.function_imports.entries.len;
620614
621 for (wasm.table_imports.values()) |id| {615 for (wasm.table_imports.values()) |id| {
622 const table_import = id.value(wasm);616 const table_import = id.value(wasm);
623 const module_name = table_import.module_name.slice(wasm);617 const module_name = table_import.module_name.slice(wasm);
624 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));618 try bw.writeLeb128(module_name.len);
625 try binary_writer.writeAll(module_name);619 try bw.writeAll(module_name);
626620
627 const name = table_import.name.slice(wasm);621 const name = table_import.name.slice(wasm);
628 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));622 try bw.writeLeb128(name.len);
629 try binary_writer.writeAll(name);623 try bw.writeAll(name);
630624
631 try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.table));625 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.table));
632 try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to())));626 try bw.writeLeb128(@intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to())));
633 try emitLimits(gpa, binary_bytes, table_import.limits());627 try emitLimits(bw, table_import.limits());
634 }628 }
635 total_imports += wasm.table_imports.entries.len;629 total_imports += wasm.table_imports.entries.len;
636630
637 if (import_memory) {631 if (import_memory) {
638 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;632 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;
639 try emitMemoryImport(wasm, binary_bytes, name, &.{633 try emitMemoryImport(wasm, bw, name, &.{
640 // TODO the import_memory option needs to specify from which module634 // TODO the import_memory option needs to specify from which module
641 .module_name = wasm.object_host_name.unwrap().?,635 .module_name = wasm.object_host_name.unwrap().?,
642 .limits_min = wasm.memories.limits.min,636 .limits_min = wasm.memories.limits.min,
...@@ -650,215 +644,209 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -650,215 +644,209 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
650644
651 for (f.global_imports.values()) |id| {645 for (f.global_imports.values()) |id| {
652 const module_name = id.moduleName(wasm).slice(wasm).?;646 const module_name = id.moduleName(wasm).slice(wasm).?;
653 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));647 try bw.writeLeb128(module_name.len);
654 try binary_writer.writeAll(module_name);648 try bw.writeAll(module_name);
655649
656 const name = id.importName(wasm).slice(wasm);650 const name = id.importName(wasm).slice(wasm);
657 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));651 try bw.writeLeb128(name.len);
658 try binary_writer.writeAll(name);652 try bw.writeAll(name);
659653
660 try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.global));654 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.global));
661 const global_type = id.globalType(wasm);655 const global_type = id.globalType(wasm);
662 try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.Valtype, global_type.valtype)));656 try bw.writeLeb128(@intFromEnum(global_type.valtype));
663 try binary_writer.writeByte(@intFromBool(global_type.mutable));657 try bw.writeByte(@intFromBool(global_type.mutable));
664 }658 }
665 total_imports += f.global_imports.entries.len;659 total_imports += f.global_imports.entries.len;
666660
667 if (total_imports > 0) {661 if (total_imports > 0) {
668 replaceVecSectionHeader(binary_bytes, header_offset, .import, @intCast(total_imports));662 replaceVecSectionHeader(&aw, header_offset, .import, @intCast(total_imports));
669 section_index += 1;663 section_index += 1;
670 } else {664 } else {
671 binary_bytes.shrinkRetainingCapacity(header_offset);665 aw.shrinkRetainingCapacity(header_offset);
672 }666 }
673 }667 }
674668
675 // Function section669 // Function section
676 if (wasm.functions.count() != 0) {670 if (wasm.functions.count() != 0) {
677 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);671 const header_offset = try reserveVecSectionHeader(bw);
678 for (wasm.functions.keys()) |function| {672 for (wasm.functions.keys()) |function| {
679 const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f);673 const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f);
680 try leb.writeUleb128(binary_writer, @intFromEnum(index));674 try bw.writeLeb128(@intFromEnum(index));
681 }675 }
682676
683 replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count()));677 replaceVecSectionHeader(&aw, header_offset, .function, @intCast(wasm.functions.count()));
684 section_index += 1;678 section_index += 1;
685 }679 }
686680
687 // Table section681 // Table section
688 if (wasm.tables.entries.len > 0) {682 if (wasm.tables.entries.len > 0) {
689 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);683 const header_offset = try reserveVecSectionHeader(bw);
690684
691 for (wasm.tables.keys()) |table| {685 for (wasm.tables.keys()) |table| {
692 try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table.refType(wasm))));686 try bw.writeLeb128(@intFromEnum(table.refType(wasm)));
693 try emitLimits(gpa, binary_bytes, table.limits(wasm));687 try emitLimits(bw, table.limits(wasm));
694 }688 }
695689
696 replaceVecSectionHeader(binary_bytes, header_offset, .table, @intCast(wasm.tables.entries.len));690 replaceVecSectionHeader(&aw, header_offset, .table, @intCast(wasm.tables.entries.len));
697 section_index += 1;691 section_index += 1;
698 }692 }
699693
700 // Memory section. wasm currently only supports 1 linear memory segment.694 // Memory section. wasm currently only supports 1 linear memory segment.
701 if (!import_memory) {695 if (!import_memory) {
702 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);696 const header_offset = try reserveVecSectionHeader(bw);
703 try emitLimits(gpa, binary_bytes, wasm.memories.limits);697 try emitLimits(bw, wasm.memories.limits);
704 replaceVecSectionHeader(binary_bytes, header_offset, .memory, 1);698 replaceVecSectionHeader(&aw, header_offset, .memory, 1);
705 section_index += 1;699 section_index += 1;
706 }700 }
707701
708 // Global section.702 // Global section.
709 const globals_len: u32 = @intCast(wasm.globals.entries.len);703 const globals_len: u32 = @intCast(wasm.globals.entries.len);
710 if (globals_len > 0) {704 if (globals_len > 0) {
711 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);705 const header_offset = try reserveVecSectionHeader(bw);
712706
713 for (wasm.globals.keys()) |global_resolution| {707 for (wasm.globals.keys()) |global_resolution| {
714 switch (global_resolution.unpack(wasm)) {708 switch (global_resolution.unpack(wasm)) {
715 .unresolved => unreachable,709 .unresolved => unreachable,
716 .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base),710 .__heap_base => try appendGlobal(bw, false, virtual_addrs.heap_base),
717 .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end),711 .__heap_end => try appendGlobal(bw, false, virtual_addrs.heap_end),
718 .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer),712 .__stack_pointer => try appendGlobal(bw, true, virtual_addrs.stack_pointer),
719 .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)),713 .__tls_align => try appendGlobal(bw, false, @intCast(virtual_addrs.tls_align.toByteUnits().?)),
720 .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?),714 .__tls_base => try appendGlobal(bw, true, virtual_addrs.tls_base.?),
721 .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?),715 .__tls_size => try appendGlobal(bw, false, virtual_addrs.tls_size.?),
722 .object_global => |i| {716 .object_global => |i| {
723 const global = i.ptr(wasm);717 const global = i.ptr(wasm);
724 try binary_bytes.appendSlice(gpa, &.{718 try bw.writeAll(&.{
725 @intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())),719 @intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())),
726 @intFromBool(global.flags.global_type.mutable),720 @intFromBool(global.flags.global_type.mutable),
727 });721 });
728 try emitExpr(wasm, binary_bytes, global.expr);722 try emitExpr(wasm, bw, global.expr);
729 },723 },
730 .nav_exe => unreachable, // Zig source code currently cannot represent this.724 .nav_exe => unreachable, // Zig source code currently cannot represent this.
731 .nav_obj => unreachable, // Zig source code currently cannot represent this.725 .nav_obj => unreachable, // Zig source code currently cannot represent this.
732 }726 }
733 }727 }
734728
735 replaceVecSectionHeader(binary_bytes, header_offset, .global, globals_len);729 replaceVecSectionHeader(&aw, header_offset, .global, globals_len);
736 section_index += 1;730 section_index += 1;
737 }731 }
738732
739 // Export section733 // Export section
740 {734 {
741 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);735 const header_offset = try reserveVecSectionHeader(bw);
742 var exports_len: usize = 0;736 var exports_len: usize = 0;
743737
744 for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| {738 for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| {
745 const name = exp_name.slice(wasm);739 const name = exp_name.slice(wasm);
746 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));740 try bw.writeLeb128(name.len);
747 try binary_bytes.appendSlice(gpa, name);741 try bw.writeAll(name);
748 try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.function));742 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.function));
749 const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index);743 const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index);
750 try leb.writeUleb128(binary_writer, @intFromEnum(func_index));744 try bw.writeLeb128(@intFromEnum(func_index));
751 }745 }
752 exports_len += wasm.function_exports.entries.len;746 exports_len += wasm.function_exports.entries.len;
753747
754 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {748 if (wasm.export_table and f.indirect_function_table.entries.len > 0) {
755 const name = "__indirect_function_table";749 const name = "__indirect_function_table";
756 const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);750 const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
757 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));751 try bw.writeLeb128(name.len);
758 try binary_bytes.appendSlice(gpa, name);752 try bw.writeAll(name);
759 try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.table));753 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.table));
760 try leb.writeUleb128(binary_writer, index);754 try bw.writeLeb128(index);
761 exports_len += 1;755 exports_len += 1;
762 }756 }
763757
764 if (export_memory) {758 if (export_memory) {
765 const name = "memory";759 const name = "memory";
766 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));760 try bw.writeLeb128(name.len);
767 try binary_bytes.appendSlice(gpa, name);761 try bw.writeAll(name);
768 try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory));762 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));
769 try leb.writeUleb128(binary_writer, @as(u32, 0));763 try bw.writeUleb128(0);
770 exports_len += 1;764 exports_len += 1;
771 }765 }
772766
773 for (wasm.global_exports.items) |exp| {767 for (wasm.global_exports.items) |exp| {
774 const name = exp.name.slice(wasm);768 const name = exp.name.slice(wasm);
775 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));769 try bw.writeLeb128(name.len);
776 try binary_bytes.appendSlice(gpa, name);770 try bw.writeAll(name);
777 try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.global));771 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.global));
778 try leb.writeUleb128(binary_writer, @intFromEnum(exp.global_index));772 try bw.writeLeb128(@intFromEnum(exp.global_index));
779 }773 }
780 exports_len += wasm.global_exports.items.len;774 exports_len += wasm.global_exports.items.len;
781775
782 if (exports_len > 0) {776 if (exports_len > 0) {
783 replaceVecSectionHeader(binary_bytes, header_offset, .@"export", @intCast(exports_len));777 replaceVecSectionHeader(&aw, header_offset, .@"export", @intCast(exports_len));
784 section_index += 1;778 section_index += 1;
785 } else {779 } else {
786 binary_bytes.shrinkRetainingCapacity(header_offset);780 aw.shrinkRetainingCapacity(header_offset);
787 }781 }
788 }782 }
789783
790 // start section784 // start section
791 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {785 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {
792 try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @enumFromInt(func_index)));786 try emitStartSection(&aw, .fromFunctionIndex(wasm, @enumFromInt(func_index)));
793 } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {787 } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {
794 try emitStartSection(gpa, binary_bytes, func_index);788 try emitStartSection(&aw, func_index);
795 }789 }
796790
797 // element section791 // element section
798 if (f.indirect_function_table.entries.len > 0) {792 if (f.indirect_function_table.entries.len > 0) {
799 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);793 const header_offset = try reserveVecSectionHeader(bw);
800794
801 // indirect function table elements795 // indirect function table elements
802 const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);796 const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?);
803 // passive with implicit 0-index table or set table index manually797 // passive with implicit 0-index table or set table index manually
804 const flags: u32 = if (table_index == 0) 0x0 else 0x02;798 const flags: u32 = if (table_index == 0) 0x0 else 0x02;
805 try leb.writeUleb128(binary_writer, flags);799 try bw.writeLeb128(flags);
806 if (flags == 0x02) {800 if (flags == 0x02) try bw.writeLeb128(table_index);
807 try leb.writeUleb128(binary_writer, table_index);
808 }
809 // We start at index 1, so unresolved function pointers are invalid801 // We start at index 1, so unresolved function pointers are invalid
810 try emitInit(binary_writer, .{ .i32_const = 1 });802 try emitInit(bw, .{ .i32_const = 1 });
811 if (flags == 0x02) {803 if (flags == 0x02) try bw.writeUleb128(0); // represents funcref
812 try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref804 try bw.writeLeb128(f.indirect_function_table.entries.len);
813 }805 for (f.indirect_function_table.keys()) |func_index| try bw.writeLeb128(@intFromEnum(func_index));
814 try leb.writeUleb128(binary_writer, @as(u32, @intCast(f.indirect_function_table.entries.len)));
815 for (f.indirect_function_table.keys()) |func_index| {
816 try leb.writeUleb128(binary_writer, @intFromEnum(func_index));
817 }
818806
819 replaceVecSectionHeader(binary_bytes, header_offset, .element, 1);807 replaceVecSectionHeader(&aw, header_offset, .element, 1);
820 section_index += 1;808 section_index += 1;
821 }809 }
822810
823 // When the shared-memory option is enabled, we *must* emit the 'data count' section.811 // When the shared-memory option is enabled, we *must* emit the 'data count' section.
824 if (f.data_segment_groups.items.len > 0) {812 if (f.data_segment_groups.items.len > 0) {
825 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);813 const header_offset = try reserveVecSectionHeader(bw);
826 replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));814 replaceVecSectionHeader(&aw, header_offset, .data_count, @intCast(f.data_segment_groups.items.len));
827 }815 }
828816
829 // Code section.817 // Code section.
830 if (wasm.functions.count() != 0) {818 if (wasm.functions.count() != 0) {
831 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);819 const header_offset = try reserveVecSectionHeader(bw);
832820
833 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {821 for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) {
834 .unresolved => unreachable,822 .unresolved => unreachable,
835 .__wasm_apply_global_tls_relocs => @panic("TODO lower __wasm_apply_global_tls_relocs"),823 .__wasm_apply_global_tls_relocs => @panic("TODO lower __wasm_apply_global_tls_relocs"),
836 .__wasm_call_ctors => {824 .__wasm_call_ctors => {
837 const code_start = try reserveSize(gpa, binary_bytes);825 const code_start = try reserveSizeHeader(bw);
838 defer replaceSize(binary_bytes, code_start);826 defer replaceSizeHeader(&aw, code_start);
839 try emitCallCtorsFunction(wasm, binary_bytes);827 try emitCallCtorsFunction(wasm, bw);
840 },828 },
841 .__wasm_init_memory => {829 .__wasm_init_memory => {
842 const code_start = try reserveSize(gpa, binary_bytes);830 const code_start = try reserveSizeHeader(bw);
843 defer replaceSize(binary_bytes, code_start);831 defer replaceSizeHeader(&aw, code_start);
844 try emitInitMemoryFunction(wasm, binary_bytes, &virtual_addrs);832 try emitInitMemoryFunction(wasm, bw, &virtual_addrs);
845 },833 },
846 .__wasm_init_tls => {834 .__wasm_init_tls => {
847 const code_start = try reserveSize(gpa, binary_bytes);835 const code_start = try reserveSizeHeader(bw);
848 defer replaceSize(binary_bytes, code_start);836 defer replaceSizeHeader(&aw, code_start);
849 try emitInitTlsFunction(wasm, binary_bytes);837 try emitInitTlsFunction(wasm, bw);
850 },838 },
851 .object_function => |i| {839 .object_function => |i| {
852 const ptr = i.ptr(wasm);840 const ptr = i.ptr(wasm);
853 const code = ptr.code.slice(wasm);841 const code = ptr.code.slice(wasm);
854 try leb.writeUleb128(binary_writer, code.len);842 try bw.writeLeb128(code.len);
855 const code_start = binary_bytes.items.len;843 const code_start = bw.count;
856 try binary_bytes.appendSlice(gpa, code);844 try bw.writeAll(code);
857 if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);845 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
858 },846 },
859 .zcu_func => |i| {847 .zcu_func => |i| {
860 const code_start = try reserveSize(gpa, binary_bytes);848 const code_start = try reserveSizeHeader(bw);
861 defer replaceSize(binary_bytes, code_start);849 defer replaceSizeHeader(&aw, code_start);
862850
863 log.debug("lowering function code for '{s}'", .{resolution.name(wasm).?});851 log.debug("lowering function code for '{s}'", .{resolution.name(wasm).?});
864852
...@@ -867,7 +855,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -867,7 +855,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
867 const ip_index = i.key(wasm).*;855 const ip_index = i.key(wasm).*;
868 switch (ip.indexToKey(ip_index)) {856 switch (ip.indexToKey(ip_index)) {
869 .enum_type => {857 .enum_type => {
870 try emitTagNameFunction(wasm, binary_bytes, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);858 try emitTagNameFunction(wasm, bw, f.data_segments.get(.__zig_tag_name_table).?, i.value(wasm).tag_name.table_index, ip_index);
871 },859 },
872 else => {860 else => {
873 const func = i.value(wasm).function;861 const func = i.value(wasm).function;
...@@ -882,13 +870,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -882,13 +870,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
882 .func_tys = undefined,870 .func_tys = undefined,
883 .error_name_table_ref_count = undefined,871 .error_name_table_ref_count = undefined,
884 };872 };
885 try mir.lower(wasm, binary_bytes);873 try mir.lower(wasm, bw);
886 },874 },
887 }875 }
888 },876 },
889 };877 };
890878
891 replaceVecSectionHeader(binary_bytes, header_offset, .code, @intCast(wasm.functions.entries.len));879 replaceVecSectionHeader(&aw, header_offset, .code, @intCast(wasm.functions.entries.len));
892 code_section_index = section_index;880 code_section_index = section_index;
893 section_index += 1;881 section_index += 1;
894 }882 }
...@@ -924,7 +912,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -924,7 +912,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
924912
925 // Data section.913 // Data section.
926 if (f.data_segment_groups.items.len != 0) {914 if (f.data_segment_groups.items.len != 0) {
927 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);915 const header_offset = try reserveVecSectionHeader(bw);
928916
929 var group_index: u32 = 0;917 var group_index: u32 = 0;
930 var segment_offset: u32 = 0;918 var segment_offset: u32 = 0;
...@@ -932,7 +920,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -932,7 +920,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
932 var group_end_addr = f.data_segment_groups.items[group_index].end_addr;920 var group_end_addr = f.data_segment_groups.items[group_index].end_addr;
933 for (segment_ids, segment_vaddrs) |segment_id, segment_vaddr| {921 for (segment_ids, segment_vaddrs) |segment_id, segment_vaddr| {
934 if (segment_vaddr >= group_end_addr) {922 if (segment_vaddr >= group_end_addr) {
935 try binary_bytes.appendNTimes(gpa, 0, group_end_addr - group_start_addr - segment_offset);923 try bw.splatByteAll(0, group_end_addr - group_start_addr - segment_offset);
936 group_index += 1;924 group_index += 1;
937 if (group_index >= f.data_segment_groups.items.len) {925 if (group_index >= f.data_segment_groups.items.len) {
938 // All remaining segments are zero.926 // All remaining segments are zero.
...@@ -946,12 +934,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -946,12 +934,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
946 const group_size = group_end_addr - group_start_addr;934 const group_size = group_end_addr - group_start_addr;
947 log.debug("emit data section group, {d} bytes", .{group_size});935 log.debug("emit data section group, {d} bytes", .{group_size});
948 const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active;936 const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active;
949 try leb.writeUleb128(binary_writer, @intFromEnum(flags));937 try bw.writeLeb128(@intFromEnum(flags));
950 // Passive segments are initialized at runtime.938 // Passive segments are initialized at runtime.
951 if (flags != .passive) {939 if (flags != .passive) try emitInit(bw, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) });
952 try emitInit(binary_writer, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) });940 try bw.writeLeb128(group_size);
953 }
954 try leb.writeUleb128(binary_writer, group_size);
955 }941 }
956 if (segment_id.isEmpty(wasm)) {942 if (segment_id.isEmpty(wasm)) {
957 // It counted for virtual memory but it does not go into the binary.943 // It counted for virtual memory but it does not go into the binary.
...@@ -960,62 +946,62 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -960,62 +946,62 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
960946
961 // Padding for alignment.947 // Padding for alignment.
962 const needed_offset = segment_vaddr - group_start_addr;948 const needed_offset = segment_vaddr - group_start_addr;
963 try binary_bytes.appendNTimes(gpa, 0, needed_offset - segment_offset);949 try bw.splatByteAll(0, needed_offset - segment_offset);
964 segment_offset = needed_offset;950 segment_offset = needed_offset;
965951
966 const code_start = binary_bytes.items.len;952 const code_start = bw.count;
967 append: {953 append: {
968 const code = switch (segment_id.unpack(wasm)) {954 const code = switch (segment_id.unpack(wasm)) {
969 .__heap_base => {955 .__heap_base => {
970 mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_base, .little);956 try bw.writeInt(u32, virtual_addrs.heap_base, .little);
971 break :append;957 break :append;
972 },958 },
973 .__heap_end => {959 .__heap_end => {
974 mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_end, .little);960 try bw.writeInt(u32, virtual_addrs.heap_end, .little);
975 break :append;961 break :append;
976 },962 },
977 .__zig_error_names => {963 .__zig_error_names => {
978 try binary_bytes.appendSlice(gpa, wasm.error_name_bytes.items);964 try bw.writeAll(wasm.error_name_bytes.items);
979 break :append;965 break :append;
980 },966 },
981 .__zig_error_name_table => {967 .__zig_error_name_table => {
982 if (is_obj) @panic("TODO error name table reloc");968 if (is_obj) @panic("TODO error name table reloc");
983 const base = f.data_segments.get(.__zig_error_names).?;969 const base = f.data_segments.get(.__zig_error_names).?;
984 if (!is64) {970 if (!is64) {
985 try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);971 try emitTagNameTable(bw, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);
986 } else {972 } else {
987 try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);973 try emitTagNameTable(bw, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);
988 }974 }
989 break :append;975 break :append;
990 },976 },
991 .__zig_tag_names => {977 .__zig_tag_names => {
992 try binary_bytes.appendSlice(gpa, wasm.tag_name_bytes.items);978 try bw.writeAll(wasm.tag_name_bytes.items);
993 break :append;979 break :append;
994 },980 },
995 .__zig_tag_name_table => {981 .__zig_tag_name_table => {
996 if (is_obj) @panic("TODO tag name table reloc");982 if (is_obj) @panic("TODO tag name table reloc");
997 const base = f.data_segments.get(.__zig_tag_names).?;983 const base = f.data_segments.get(.__zig_tag_names).?;
998 if (!is64) {984 if (!is64) {
999 try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);985 try emitTagNameTable(bw, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32);
1000 } else {986 } else {
1001 try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64);987 try emitTagNameTable(bw, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u64);
1002 }988 }
1003 break :append;989 break :append;
1004 },990 },
1005 .object => |i| {991 .object => |i| {
1006 const ptr = i.ptr(wasm);992 const ptr = i.ptr(wasm);
1007 try binary_bytes.appendSlice(gpa, ptr.payload.slice(wasm));993 try bw.writeAll(ptr.payload.slice(wasm));
1008 if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm);994 if (!is_obj) applyRelocs(aw.getWritten()[code_start..], ptr.offset, ptr.relocations(wasm), wasm);
1009 break :append;995 break :append;
1010 },996 },
1011 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code,997 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code,
1012 };998 };
1013 try binary_bytes.appendSlice(gpa, code.slice(wasm));999 try bw.writeAll(code.slice(wasm));
1014 }1000 }
1015 segment_offset += @intCast(binary_bytes.items.len - code_start);1001 segment_offset += @intCast(bw.count - code_start);
1016 }1002 }
10171003
1018 replaceVecSectionHeader(binary_bytes, header_offset, .data, @intCast(f.data_segment_groups.items.len));1004 replaceVecSectionHeader(&aw, header_offset, .data, @intCast(f.data_segment_groups.items.len));
1019 data_section_index = section_index;1005 data_section_index = section_index;
1020 section_index += 1;1006 section_index += 1;
1021 }1007 }
...@@ -1023,7 +1009,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1023,7 +1009,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1023 if (is_obj) {1009 if (is_obj) {
1024 @panic("TODO emit link section for object file and emit modified relocations");1010 @panic("TODO emit link section for object file and emit modified relocations");
1025 } else if (comp.config.debug_format != .strip) {1011 } else if (comp.config.debug_format != .strip) {
1026 try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes);1012 try emitNameSection(wasm, &aw, f.data_segment_groups.items);
1027 }1013 }
10281014
1029 if (comp.config.debug_format != .strip) {1015 if (comp.config.debug_format != .strip) {
...@@ -1033,17 +1019,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1033,17 +1019,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1033 .none => {},1019 .none => {},
1034 .fast => {1020 .fast => {
1035 var id: [16]u8 = undefined;1021 var id: [16]u8 = undefined;
1036 std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});1022 std.crypto.hash.sha3.TurboShake128(null).hash(bw.getWritten(), &id, .{});
1037 var uuid: [36]u8 = undefined;1023 var uuid: [36]u8 = undefined;
1038 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{1024 _ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{
1039 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],1025 id[0..4], id[4..6], id[6..8], id[8..10], id[10..],
1040 });1026 });
1041 try emitBuildIdSection(gpa, binary_bytes, &uuid);1027 try emitBuildIdSection(&aw, &uuid);
1042 },1028 },
1043 .hexstring => |hs| {1029 .hexstring => |hs| {
1044 var buffer: [32 * 2]u8 = undefined;1030 var buffer: [32 * 2]u8 = undefined;
1045 const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable;1031 const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable;
1046 try emitBuildIdSection(gpa, binary_bytes, str);1032 try emitBuildIdSection(&aw, str);
1047 },1033 },
1048 else => |mode| {1034 else => |mode| {
1049 var err = try diags.addErrorWithNotes(0);1035 var err = try diags.addErrorWithNotes(0);
...@@ -1054,14 +1040,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1054,14 +1040,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1054 var debug_bytes = std.ArrayList(u8).init(gpa);1040 var debug_bytes = std.ArrayList(u8).init(gpa);
1055 defer debug_bytes.deinit();1041 defer debug_bytes.deinit();
10561042
1057 try emitProducerSection(gpa, binary_bytes);1043 try emitProducerSection(&aw);
1058 try emitFeaturesSection(gpa, binary_bytes, target);1044 try emitFeaturesSection(&aw, target);
1059 }1045 }
10601046
1061 // Finally, write the entire binary into the file.1047 // Finally, write the entire binary into the file.
1062 const file = wasm.base.file.?;1048 const file = wasm.base.file.?;
1063 try file.pwriteAll(binary_bytes.items, 0);1049 const contents = aw.getWritten();
1064 try file.setEndPos(binary_bytes.items.len);1050 try file.setEndPos(contents.len);
1051 try file.pwriteAll(contents, 0);
1065}1052}
10661053
1067const VirtualAddrs = struct {1054const VirtualAddrs = struct {
...@@ -1076,170 +1063,155 @@ const VirtualAddrs = struct {...@@ -1076,170 +1063,155 @@ const VirtualAddrs = struct {
10761063
1077fn emitNameSection(1064fn emitNameSection(
1078 wasm: *Wasm,1065 wasm: *Wasm,
1066 aw: *std.io.AllocatingWriter,
1079 data_segment_groups: []const DataSegmentGroup,1067 data_segment_groups: []const DataSegmentGroup,
1080 binary_bytes: *std.ArrayListUnmanaged(u8),1068) anyerror!void {
1081) !void {
1082 const f = &wasm.flush_buffer;1069 const f = &wasm.flush_buffer;
1083 const comp = wasm.base.comp;1070 const bw = &aw.buffered_writer;
1084 const gpa = comp.gpa;1071 const header_offset = try reserveSectionHeader(bw);
1072 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
10851073
1086 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1074 const section_name = "name";
1087 defer writeCustomSectionHeader(binary_bytes, header_offset);1075 try bw.writeLeb128(section_name.len);
10881076 try bw.writeAll(section_name);
1089 const name_name = "name";
1090 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, name_name.len));
1091 try binary_bytes.appendSlice(gpa, name_name);
10921077
1093 {1078 {
1094 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1079 const sub_header_offset = try reserveSectionHeader(bw);
1095 defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.function));1080 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.function));
1096
1097 const total_functions: u32 = @intCast(f.function_imports.entries.len + wasm.functions.entries.len);
1098 try leb.writeUleb128(binary_bytes.writer(gpa), total_functions);
10991081
1082 try bw.writeLeb128(f.function_imports.entries.len + wasm.functions.entries.len);
1100 for (f.function_imports.keys(), 0..) |name_index, function_index| {1083 for (f.function_imports.keys(), 0..) |name_index, function_index| {
1101 const name = name_index.slice(wasm);1084 const name = name_index.slice(wasm);
1102 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index)));1085 try bw.writeLeb128(function_index);
1103 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1086 try bw.writeLeb128(name.len);
1104 try binary_bytes.appendSlice(gpa, name);1087 try bw.writeAll(name);
1105 }1088 }
1106 for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| {1089 for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| {
1107 const name = resolution.name(wasm).?;1090 const name = resolution.name(wasm).?;
1108 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index)));1091 try bw.writeLeb128(function_index);
1109 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1092 try bw.writeLeb128(name.len);
1110 try binary_bytes.appendSlice(gpa, name);1093 try bw.writeAll(name);
1111 }1094 }
1112 }1095 }
11131096
1114 {1097 {
1115 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1098 const sub_header_offset = try reserveSectionHeader(bw);
1116 defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.global));1099 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.global));
1117
1118 const total_globals: u32 = @intCast(f.global_imports.entries.len + wasm.globals.entries.len);
1119 try leb.writeUleb128(binary_bytes.writer(gpa), total_globals);
11201100
1101 try bw.writeLeb128(f.global_imports.entries.len + wasm.globals.entries.len);
1121 for (f.global_imports.keys(), 0..) |name_index, global_index| {1102 for (f.global_imports.keys(), 0..) |name_index, global_index| {
1122 const name = name_index.slice(wasm);1103 const name = name_index.slice(wasm);
1123 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index)));1104 try bw.writeLeb128(global_index);
1124 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1105 try bw.writeLeb128(name.len);
1125 try binary_bytes.appendSlice(gpa, name);1106 try bw.writeAll(name);
1126 }1107 }
1127 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {1108 for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| {
1128 const name = resolution.name(wasm).?;1109 const name = resolution.name(wasm).?;
1129 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index)));1110 try bw.writeLeb128(global_index);
1130 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1111 try bw.writeLeb128(name.len);
1131 try binary_bytes.appendSlice(gpa, name);1112 try bw.writeAll(name);
1132 }1113 }
1133 }1114 }
11341115
1135 {1116 {
1136 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1117 const sub_header_offset = try reserveSectionHeader(bw);
1137 defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.data_segment));1118 defer replaceSectionHeader(aw, sub_header_offset, @intFromEnum(std.wasm.NameSubsection.data_segment));
11381119
1139 const total_data_segments: u32 = @intCast(data_segment_groups.len);1120 try bw.writeLeb128(data_segment_groups.len);
1140 try leb.writeUleb128(binary_bytes.writer(gpa), total_data_segments);1121 for (data_segment_groups, 0..) |group, group_index| {
1141
1142 for (data_segment_groups, 0..) |group, i| {
1143 const name, _ = splitSegmentName(group.first_segment.name(wasm));1122 const name, _ = splitSegmentName(group.first_segment.name(wasm));
1144 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(i)));1123 try bw.writeLeb128(group_index);
1145 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1124 try bw.writeLeb128(name.len);
1146 try binary_bytes.appendSlice(gpa, name);1125 try bw.writeAll(name);
1147 }1126 }
1148 }1127 }
1149}1128}
11501129
1151fn emitFeaturesSection(1130fn emitFeaturesSection(aw: *std.io.AllocatingWriter, target: *const std.Target) anyerror!void {
1152 gpa: Allocator,
1153 binary_bytes: *std.ArrayListUnmanaged(u8),
1154 target: *const std.Target,
1155) Allocator.Error!void {
1156 const feature_count = target.cpu.features.count();1131 const feature_count = target.cpu.features.count();
1157 if (feature_count == 0) return;1132 if (feature_count == 0) return;
11581133
1159 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1134 const bw = &aw.buffered_writer;
1160 defer writeCustomSectionHeader(binary_bytes, header_offset);1135 const header_offset = try reserveSectionHeader(bw);
11611136 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
1162 const writer = binary_bytes.writer(gpa);
1163 const target_features = "target_features";
1164 try leb.writeUleb128(writer, @as(u32, @intCast(target_features.len)));
1165 try writer.writeAll(target_features);
11661137
1167 try leb.writeUleb128(writer, @as(u32, @intCast(feature_count)));1138 const section_name = "target_features";
1139 try bw.writeLeb128(section_name.len);
1140 try bw.writeAll(section_name);
11681141
1142 try bw.writeLeb128(feature_count);
1169 var safety_count = feature_count;1143 var safety_count = feature_count;
1170 for (target.cpu.arch.allFeaturesList(), 0..) |*feature, i| {1144 for (target.cpu.arch.allFeaturesList(), 0..) |*feature, i| {
1171 if (!target.cpu.has(.wasm, @as(std.Target.wasm.Feature, @enumFromInt(i)))) continue;1145 if (!target.cpu.has(.wasm, @as(std.Target.wasm.Feature, @enumFromInt(i)))) continue;
1172 safety_count -= 1;1146 safety_count -= 1;
11731147
1174 try leb.writeUleb128(writer, @as(u32, '+'));1148 try bw.writeUleb128('+');
1175 // Depends on llvm_name for the hyphenated version that matches wasm tooling conventions.1149 // Depends on llvm_name for the hyphenated version that matches wasm tooling conventions.
1176 const name = feature.llvm_name.?;1150 const name = feature.llvm_name.?;
1177 try leb.writeUleb128(writer, @as(u32, @intCast(name.len)));1151 try bw.writeLeb128(name.len);
1178 try writer.writeAll(name);1152 try bw.writeAll(name);
1179 }1153 }
1180 assert(safety_count == 0);1154 assert(safety_count == 0);
1181}1155}
11821156
1183fn emitBuildIdSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8), build_id: []const u8) !void {1157fn emitBuildIdSection(aw: *std.io.AllocatingWriter, build_id: []const u8) !void {
1184 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1158 const bw = &aw.buffered_writer;
1185 defer writeCustomSectionHeader(binary_bytes, header_offset);1159 const header_offset = try reserveSectionHeader(bw);
1160 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
11861161
1187 const writer = binary_bytes.writer(gpa);1162 const section_name = "build_id";
1188 const hdr_build_id = "build_id";1163 try bw.writeLeb128(section_name.len);
1189 try leb.writeUleb128(writer, @as(u32, @intCast(hdr_build_id.len)));1164 try bw.writeAll(section_name);
1190 try writer.writeAll(hdr_build_id);
11911165
1192 try leb.writeUleb128(writer, @as(u32, 1));1166 try bw.writeUleb128(1);
1193 try leb.writeUleb128(writer, @as(u32, @intCast(build_id.len)));1167 try bw.writeLeb128(build_id.len);
1194 try writer.writeAll(build_id);1168 try bw.writeAll(build_id);
1195}1169}
11961170
1197fn emitProducerSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8)) !void {1171fn emitProducerSection(aw: *std.io.AllocatingWriter) !void {
1198 const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1172 const bw = &aw.buffered_writer;
1199 defer writeCustomSectionHeader(binary_bytes, header_offset);1173 const header_offset = try reserveSectionHeader(bw);
12001174 defer replaceSectionHeader(aw, header_offset, @intFromEnum(std.wasm.Section.custom));
1201 const writer = binary_bytes.writer(gpa);
1202 const producers = "producers";
1203 try leb.writeUleb128(writer, @as(u32, @intCast(producers.len)));
1204 try writer.writeAll(producers);
12051175
1206 try leb.writeUleb128(writer, @as(u32, 2)); // 2 fields: Language + processed-by1176 const section_name = "producers";
1177 try bw.writeLeb128(section_name.len);
1178 try bw.writeAll(section_name);
12071179
1208 // language field1180 try bw.writeUleb128(2); // 2 fields: language + processed-by
1209 {1181 {
1210 const language = "language";1182 const field_name = "language";
1211 try leb.writeUleb128(writer, @as(u32, @intCast(language.len)));1183 try bw.writeLeb128(field_name.len);
1212 try writer.writeAll(language);1184 try bw.writeAll(field_name);
12131185
1214 // field_value_count (TODO: Parse object files for producer sections to detect their language)1186 // field_value_count (TODO: Parse object files for producer sections to detect their language)
1215 try leb.writeUleb128(writer, @as(u32, 1));1187 try bw.writeUleb128(1);
12161188
1217 // versioned name1189 // versioned name
1218 {1190 {
1219 try leb.writeUleb128(writer, @as(u32, 3)); // len of "Zig"1191 const field_value = "Zig";
1220 try writer.writeAll("Zig");1192 try bw.writeLeb128(field_value.len);
1193 try bw.writeAll(field_value);
12211194
1222 try leb.writeUleb128(writer, @as(u32, @intCast(build_options.version.len)));1195 try bw.writeLeb128(build_options.version.len);
1223 try writer.writeAll(build_options.version);1196 try bw.writeAll(build_options.version);
1224 }1197 }
1225 }1198 }
1226
1227 // processed-by field
1228 {1199 {
1229 const processed_by = "processed-by";1200 const field_name = "processed-by";
1230 try leb.writeUleb128(writer, @as(u32, @intCast(processed_by.len)));1201 try bw.writeLeb128(field_name.len);
1231 try writer.writeAll(processed_by);1202 try bw.writeAll(field_name);
12321203
1233 // field_value_count (TODO: Parse object files for producer sections to detect other used tools)1204 // field_value_count (TODO: Parse object files for producer sections to detect other used tools)
1234 try leb.writeUleb128(writer, @as(u32, 1));1205 try bw.writeUleb128(1);
12351206
1236 // versioned name1207 // versioned name
1237 {1208 {
1238 try leb.writeUleb128(writer, @as(u32, 3)); // len of "Zig"1209 const field_value = "Zig";
1239 try writer.writeAll("Zig");1210 try bw.writeLeb128(field_value.len);
1211 try bw.writeAll(field_value);
12401212
1241 try leb.writeUleb128(writer, @as(u32, @intCast(build_options.version.len)));1213 try bw.writeLeb128(build_options.version.len);
1242 try writer.writeAll(build_options.version);1214 try bw.writeAll(build_options.version);
1243 }1215 }
1244 }1216 }
1245}1217}
...@@ -1277,170 +1249,133 @@ fn wantSegmentMerge(...@@ -1277,170 +1249,133 @@ fn wantSegmentMerge(
1277}1249}
12781250
1279/// section id + fixed leb contents size + fixed leb vector length1251/// section id + fixed leb contents size + fixed leb vector length
1280const section_header_reserve_size = 1 + 5 + 5;1252const vec_section_header_size = section_header_size + size_header_size;
1281const section_header_size = 5 + 1;
12821253
1283fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 {1254fn reserveVecSectionHeader(bw: *std.io.BufferedWriter) anyerror!u32 {
1284 try bytes.appendNTimes(gpa, 0, section_header_reserve_size);1255 const offset = bw.count;
1285 return @intCast(bytes.items.len - section_header_reserve_size);1256 _ = try bw.writableSlice(vec_section_header_size);
1257 bw.advance(vec_section_header_size);
1258 return @intCast(offset);
1286}1259}
12871260
1288fn replaceVecSectionHeader(1261fn replaceVecSectionHeader(
1289 bytes: *std.ArrayListUnmanaged(u8),1262 aw: *std.io.AllocatingWriter,
1290 offset: u32,1263 offset: u32,
1291 section: std.wasm.Section,1264 section: std.wasm.Section,
1292 n_items: u32,1265 n_items: u32,
1293) void {1266) void {
1294 const size: u32 = @intCast(bytes.items.len - offset - section_header_reserve_size + uleb128size(n_items));1267 const header = aw.getWritten()[offset..][0..vec_section_header_size];
1295 var buf: [section_header_reserve_size]u8 = undefined;1268 header[0] = @intFromEnum(section);
1296 var fbw = std.io.fixedBufferStream(&buf);1269 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.buffered_writer.count - offset - section_header_size));
1297 const w = fbw.writer();1270 std.leb.writeUnsignedFixed(5, header[6..], n_items);
1298 w.writeByte(@intFromEnum(section)) catch unreachable;
1299 leb.writeUleb128(w, size) catch unreachable;
1300 leb.writeUleb128(w, n_items) catch unreachable;
1301 bytes.replaceRangeAssumeCapacity(offset, section_header_reserve_size, fbw.getWritten());
1302}1271}
13031272
1304fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 {1273const section_header_size = 1 + size_header_size;
1305 try bytes.appendNTimes(gpa, 0, section_header_size);
1306 return @intCast(bytes.items.len - section_header_size);
1307}
13081274
1309fn writeCustomSectionHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32) void {1275fn reserveSectionHeader(bw: *std.io.BufferedWriter) anyerror!u32 {
1310 return replaceHeader(bytes, offset, 0); // 0 = 'custom' section1276 const offset = bw.count;
1277 _ = try bw.writableSlice(section_header_size);
1278 bw.advance(section_header_size);
1279 return @intCast(offset);
1311}1280}
13121281
1313fn replaceHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32, tag: u8) void {1282fn replaceSectionHeader(aw: *std.io.AllocatingWriter, offset: u32, section: u8) void {
1314 const size: u32 = @intCast(bytes.items.len - offset - section_header_size);1283 const header = aw.getWritten()[offset..][0..section_header_size];
1315 var buf: [section_header_size]u8 = undefined;1284 header[0] = section;
1316 var fbw = std.io.fixedBufferStream(&buf);1285 std.leb.writeUnsignedFixed(5, header[1..6], @intCast(aw.buffered_writer.count - offset - section_header_size));
1317 const w = fbw.writer();
1318 w.writeByte(tag) catch unreachable;
1319 leb.writeUleb128(w, size) catch unreachable;
1320 bytes.replaceRangeAssumeCapacity(offset, section_header_size, fbw.getWritten());
1321}1286}
13221287
1323const max_size_encoding = 5;1288const size_header_size = 5;
13241289
1325fn reserveSize(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 {1290fn reserveSizeHeader(bw: *std.io.BufferedWriter) anyerror!u32 {
1326 try bytes.appendNTimes(gpa, 0, max_size_encoding);1291 const offset = bw.count;
1327 return @intCast(bytes.items.len - max_size_encoding);1292 _ = try bw.writableSlice(size_header_size);
1293 bw.advance(size_header_size);
1294 return @intCast(offset);
1328}1295}
13291296
1330fn replaceSize(bytes: *std.ArrayListUnmanaged(u8), offset: u32) void {1297fn replaceSizeHeader(aw: *std.io.AllocatingWriter, offset: u32) void {
1331 const size: u32 = @intCast(bytes.items.len - offset - max_size_encoding);1298 const header = aw.getWritten()[offset..][0..size_header_size];
1332 var buf: [max_size_encoding]u8 = undefined;1299 std.leb.writeUnsignedFixed(5, header[0..5], @intCast(aw.buffered_writer.count - offset - size_header_size));
1333 var fbw = std.io.fixedBufferStream(&buf);
1334 leb.writeUleb128(fbw.writer(), size) catch unreachable;
1335 bytes.replaceRangeAssumeCapacity(offset, max_size_encoding, fbw.getWritten());
1336}1300}
13371301
1338fn emitLimits(1302fn emitLimits(bw: *std.io.BufferedWriter, limits: std.wasm.Limits) anyerror!void {
1339 gpa: Allocator,1303 try bw.writeByte(@bitCast(limits.flags));
1340 binary_bytes: *std.ArrayListUnmanaged(u8),1304 try bw.writeLeb128(limits.min);
1341 limits: std.wasm.Limits,1305 if (limits.flags.has_max) try bw.writeLeb128(limits.max);
1342) Allocator.Error!void {
1343 try binary_bytes.append(gpa, @bitCast(limits.flags));
1344 try leb.writeUleb128(binary_bytes.writer(gpa), limits.min);
1345 if (limits.flags.has_max) try leb.writeUleb128(binary_bytes.writer(gpa), limits.max);
1346}1306}
13471307
1348fn emitMemoryImport(1308fn emitMemoryImport(
1349 wasm: *Wasm,1309 wasm: *Wasm,
1350 binary_bytes: *std.ArrayListUnmanaged(u8),1310 bw: *std.io.BufferedWriter,
1351 name_index: String,1311 name_index: String,
1352 memory_import: *const Wasm.MemoryImport,1312 memory_import: *const Wasm.MemoryImport,
1353) Allocator.Error!void {1313) anyerror!void {
1354 const gpa = wasm.base.comp.gpa;
1355 const module_name = memory_import.module_name.slice(wasm);1314 const module_name = memory_import.module_name.slice(wasm);
1356 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len)));1315 try bw.writeLeb128(module_name.len);
1357 try binary_bytes.appendSlice(gpa, module_name);1316 try bw.writeAll(module_name);
13581317
1359 const name = name_index.slice(wasm);1318 const name = name_index.slice(wasm);
1360 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1319 try bw.writeLeb128(name.len);
1361 try binary_bytes.appendSlice(gpa, name);1320 try bw.writeAll(name);
13621321
1363 try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory));1322 try bw.writeByte(@intFromEnum(std.wasm.ExternalKind.memory));
1364 try emitLimits(gpa, binary_bytes, memory_import.limits());1323 try emitLimits(bw, memory_import.limits());
1365}1324}
13661325
1367pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void {1326pub fn emitInit(bw: *std.io.BufferedWriter, init_expr: std.wasm.InitExpression) anyerror!void {
1368 switch (init_expr) {1327 switch (init_expr) {
1369 .i32_const => |val| {1328 inline else => |val, tag| {
1370 try writer.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));1329 try bw.writeByte(@intFromEnum(@field(std.wasm.Opcode, @tagName(tag))));
1371 try leb.writeIleb128(writer, val);1330 switch (@typeInfo(@TypeOf(val))) {
1372 },1331 .int => try bw.writeLeb128(val),
1373 .i64_const => |val| {1332 .float => |float| try bw.writeInt(
1374 try writer.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));1333 @Type(.{ .int = .{ .signedness = .unsigned, .bits = float.bits } }),
1375 try leb.writeIleb128(writer, val);1334 @bitCast(val),
1376 },1335 .little,
1377 .f32_const => |val| {1336 ),
1378 try writer.writeByte(@intFromEnum(std.wasm.Opcode.f32_const));1337 else => comptime unreachable,
1379 try writer.writeInt(u32, @bitCast(val), .little);1338 }
1380 },
1381 .f64_const => |val| {
1382 try writer.writeByte(@intFromEnum(std.wasm.Opcode.f64_const));
1383 try writer.writeInt(u64, @bitCast(val), .little);
1384 },
1385 .global_get => |val| {
1386 try writer.writeByte(@intFromEnum(std.wasm.Opcode.global_get));
1387 try leb.writeUleb128(writer, val);
1388 },1339 },
1389 }1340 }
1390 try writer.writeByte(@intFromEnum(std.wasm.Opcode.end));1341 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1391}1342}
13921343
1393pub fn emitExpr(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), expr: Wasm.Expr) Allocator.Error!void {1344pub fn emitExpr(wasm: *const Wasm, bw: *std.io.BufferedWriter, expr: Wasm.Expr) anyerror!void {
1394 const gpa = wasm.base.comp.gpa;
1395 const slice = expr.slice(wasm);1345 const slice = expr.slice(wasm);
1396 try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode1346 try bw.writeAll(slice[0 .. slice.len + 1]); // +1 to include end opcode
1397}1347}
13981348
1399fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.ArrayList(u8)) !void {1349fn emitSegmentInfo(wasm: *Wasm, aw: *std.io.BufferedWriter) anyerror!void {
1400 const gpa = wasm.base.comp.gpa;1350 const bw = &aw.buffered_writer;
1401 const writer = binary_bytes.writer(gpa);1351 const header_offset = try reserveSectionHeader(bw);
1402 try leb.writeUleb128(writer, @intFromEnum(Wasm.SubsectionType.segment_info));1352 defer replaceSectionHeader(aw, header_offset, @intFromEnum(Wasm.SubsectionType.segment_info));
1403 const segment_offset = binary_bytes.items.len;
14041353
1405 try leb.writeUleb128(writer, @as(u32, @intCast(wasm.segment_info.count())));1354 try bw.writeLeb128(wasm.segment_info.count());
1406 for (wasm.segment_info.values()) |segment_info| {1355 for (wasm.segment_info.values()) |segment_info| {
1407 log.debug("Emit segment: {s} align({d}) flags({b})", .{1356 log.debug("Emit segment: {s} align({d}) flags({b})", .{
1408 segment_info.name,1357 segment_info.name,
1409 segment_info.alignment,1358 segment_info.alignment,
1410 segment_info.flags,1359 segment_info.flags,
1411 });1360 });
1412 try leb.writeUleb128(writer, @as(u32, @intCast(segment_info.name.len)));1361 try bw.writeLeb128(segment_info.name.len);
1413 try writer.writeAll(segment_info.name);1362 try bw.writeAll(segment_info.name);
1414 try leb.writeUleb128(writer, segment_info.alignment.toLog2Units());1363 try bw.writeLeb128(segment_info.alignment.toLog2Units());
1415 try leb.writeUleb128(writer, segment_info.flags);1364 try bw.writeLeb128(segment_info.flags);
1416 }1365 }
1417
1418 var buf: [5]u8 = undefined;
1419 leb.writeUnsignedFixed(5, &buf, @as(u32, @intCast(binary_bytes.items.len - segment_offset)));
1420 try binary_bytes.insertSlice(segment_offset, &buf);
1421}
1422
1423fn uleb128size(x: u32) u32 {
1424 var value = x;
1425 var size: u32 = 0;
1426 while (value != 0) : (size += 1) value >>= 7;
1427 return size;
1428}1366}
14291367
1430fn emitTagNameTable(1368fn emitTagNameTable(
1431 gpa: Allocator,1369 bw: *std.io.BufferedWriter,
1432 code: *std.ArrayListUnmanaged(u8),
1433 tag_name_offs: []const u32,1370 tag_name_offs: []const u32,
1434 tag_name_bytes: []const u8,1371 tag_name_bytes: []const u8,
1435 base: u32,1372 base: u32,
1436 comptime Int: type,1373 comptime Int: type,
1437) error{OutOfMemory}!void {1374) anyerror!void {
1438 const ptr_size_bytes = @divExact(@bitSizeOf(Int), 8);
1439 try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len);
1440 for (tag_name_offs) |off| {1375 for (tag_name_offs) |off| {
1441 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);1376 const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?);
1442 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little);1377 try bw.writeInt(Int, base + off, .little);
1443 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little);1378 try bw.writeInt(Int, name_len, .little);
1444 }1379 }
1445}1380}
14461381
...@@ -1525,11 +1460,11 @@ fn reloc_u64_table_index(code: []u8, i: IndirectFunctionTableIndex) void {...@@ -1525,11 +1460,11 @@ fn reloc_u64_table_index(code: []u8, i: IndirectFunctionTableIndex) void {
1525}1460}
15261461
1527fn reloc_sleb_table_index(code: []u8, i: IndirectFunctionTableIndex) void {1462fn reloc_sleb_table_index(code: []u8, i: IndirectFunctionTableIndex) void {
1528 leb.writeSignedFixed(5, code[0..5], i.toAbi());1463 std.leb.writeSignedFixed(5, code[0..5], i.toAbi());
1529}1464}
15301465
1531fn reloc_sleb64_table_index(code: []u8, i: IndirectFunctionTableIndex) void {1466fn reloc_sleb64_table_index(code: []u8, i: IndirectFunctionTableIndex) void {
1532 leb.writeSignedFixed(11, code[0..11], i.toAbi());1467 std.leb.writeSignedFixed(11, code[0..11], i.toAbi());
1533}1468}
15341469
1535fn reloc_u32_function(code: []u8, function: Wasm.OutputFunctionIndex) void {1470fn reloc_u32_function(code: []u8, function: Wasm.OutputFunctionIndex) void {
...@@ -1537,7 +1472,7 @@ fn reloc_u32_function(code: []u8, function: Wasm.OutputFunctionIndex) void {...@@ -1537,7 +1472,7 @@ fn reloc_u32_function(code: []u8, function: Wasm.OutputFunctionIndex) void {
1537}1472}
15381473
1539fn reloc_leb_function(code: []u8, function: Wasm.OutputFunctionIndex) void {1474fn reloc_leb_function(code: []u8, function: Wasm.OutputFunctionIndex) void {
1540 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(function));1475 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(function));
1541}1476}
15421477
1543fn reloc_u32_global(code: []u8, global: Wasm.GlobalIndex) void {1478fn reloc_u32_global(code: []u8, global: Wasm.GlobalIndex) void {
...@@ -1545,7 +1480,7 @@ fn reloc_u32_global(code: []u8, global: Wasm.GlobalIndex) void {...@@ -1545,7 +1480,7 @@ fn reloc_u32_global(code: []u8, global: Wasm.GlobalIndex) void {
1545}1480}
15461481
1547fn reloc_leb_global(code: []u8, global: Wasm.GlobalIndex) void {1482fn reloc_leb_global(code: []u8, global: Wasm.GlobalIndex) void {
1548 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(global));1483 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(global));
1549}1484}
15501485
1551const RelocAddr = struct {1486const RelocAddr = struct {
...@@ -1581,35 +1516,31 @@ fn reloc_u64_addr(code: []u8, ra: RelocAddr) void {...@@ -1581,35 +1516,31 @@ fn reloc_u64_addr(code: []u8, ra: RelocAddr) void {
1581}1516}
15821517
1583fn reloc_leb_addr(code: []u8, ra: RelocAddr) void {1518fn reloc_leb_addr(code: []u8, ra: RelocAddr) void {
1584 leb.writeUnsignedFixed(5, code[0..5], ra.addr);1519 std.leb.writeUnsignedFixed(5, code[0..5], ra.addr);
1585}1520}
15861521
1587fn reloc_leb64_addr(code: []u8, ra: RelocAddr) void {1522fn reloc_leb64_addr(code: []u8, ra: RelocAddr) void {
1588 leb.writeUnsignedFixed(11, code[0..11], ra.addr);1523 std.leb.writeUnsignedFixed(11, code[0..11], ra.addr);
1589}1524}
15901525
1591fn reloc_sleb_addr(code: []u8, ra: RelocAddr) void {1526fn reloc_sleb_addr(code: []u8, ra: RelocAddr) void {
1592 leb.writeSignedFixed(5, code[0..5], ra.addr);1527 std.leb.writeSignedFixed(5, code[0..5], ra.addr);
1593}1528}
15941529
1595fn reloc_sleb64_addr(code: []u8, ra: RelocAddr) void {1530fn reloc_sleb64_addr(code: []u8, ra: RelocAddr) void {
1596 leb.writeSignedFixed(11, code[0..11], ra.addr);1531 std.leb.writeSignedFixed(11, code[0..11], ra.addr);
1597}1532}
15981533
1599fn reloc_leb_table(code: []u8, table: Wasm.TableIndex) void {1534fn reloc_leb_table(code: []u8, table: Wasm.TableIndex) void {
1600 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(table));1535 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(table));
1601}1536}
16021537
1603fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void {1538fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void {
1604 leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));1539 std.leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index));
1605}1540}
16061541
1607fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {1542fn emitCallCtorsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) anyerror!void {
1608 const gpa = wasm.base.comp.gpa;1543 try bw.writeUleb128(0); // no locals
1609
1610 try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1);
1611 appendReservedUleb32(binary_bytes, 0); // no locals
1612
1613 for (wasm.object_init_funcs.items) |init_func| {1544 for (wasm.object_init_funcs.items) |init_func| {
1614 const func = init_func.function_index.ptr(wasm);1545 const func = init_func.function_index.ptr(wasm);
1615 if (!func.object_index.ptr(wasm).is_included) continue;1546 if (!func.object_index.ptr(wasm).is_included) continue;
...@@ -1617,25 +1548,18 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanage...@@ -1617,25 +1548,18 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanage
1617 const n_returns = ty.returns.slice(wasm).len;1548 const n_returns = ty.returns.slice(wasm).len;
16181549
1619 // Call function by its function index1550 // Call function by its function index
1620 try binary_bytes.ensureUnusedCapacity(gpa, 1 + 5 + n_returns + 1);
1621 const call_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);1551 const call_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);
1622 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));1552 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));
1623 appendReservedUleb32(binary_bytes, @intFromEnum(call_index));1553 try bw.writeLeb128(@intFromEnum(call_index));
16241554
1625 // drop all returned values from the stack as __wasm_call_ctors has no return value1555 // drop all returned values from the stack as __wasm_call_ctors has no return value
1626 binary_bytes.appendNTimesAssumeCapacity(@intFromEnum(std.wasm.Opcode.drop), n_returns);1556 try bw.splatByteAll(@intFromEnum(std.wasm.Opcode.drop), n_returns);
1627 }1557 }
16281558 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end function body
1629 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); // end function body
1630}1559}
16311560
1632fn emitInitMemoryFunction(1561fn emitInitMemoryFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter, virtual_addrs: *const VirtualAddrs) anyerror!void {
1633 wasm: *const Wasm,
1634 binary_bytes: *std.ArrayListUnmanaged(u8),
1635 virtual_addrs: *const VirtualAddrs,
1636) Allocator.Error!void {
1637 const comp = wasm.base.comp;1562 const comp = wasm.base.comp;
1638 const gpa = comp.gpa;
1639 const shared_memory = comp.config.shared_memory;1563 const shared_memory = comp.config.shared_memory;
16401564
1641 // Passive segments are used to avoid memory being reinitialized on each1565 // Passive segments are used to avoid memory being reinitialized on each
...@@ -1645,39 +1569,40 @@ fn emitInitMemoryFunction(...@@ -1645,39 +1569,40 @@ fn emitInitMemoryFunction(
1645 // function.1569 // function.
1646 assert(wasm.any_passive_inits);1570 assert(wasm.any_passive_inits);
16471571
1648 try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1);1572 try bw.writeUleb128(0); // no locals
1649 appendReservedUleb32(binary_bytes, 0); // no locals
16501573
1651 if (virtual_addrs.init_memory_flag) |flag_address| {1574 if (virtual_addrs.init_memory_flag) |flag_address| {
1652 assert(shared_memory);1575 assert(shared_memory);
1653 try binary_bytes.ensureUnusedCapacity(gpa, 2 * 3 + 6 * 3 + 1 + 6 * 3 + 1 + 5 * 4 + 1 + 1);
1654 // destination blocks1576 // destination blocks
1655 // based on values we jump to corresponding label1577 // based on values we jump to corresponding label
1656 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); // $drop1578 try bw.writeAll(&.{
1657 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));1579 @intFromEnum(std.wasm.Opcode.block), // $drop
16581580 @intFromEnum(std.wasm.BlockType.empty),
1659 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); // $wait1581 @intFromEnum(std.wasm.Opcode.block), // $wait
1660 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));1582 @intFromEnum(std.wasm.BlockType.empty),
16611583 @intFromEnum(std.wasm.Opcode.block), // $init
1662 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); // $init1584 @intFromEnum(std.wasm.BlockType.empty),
1663 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));1585 });
16641586
1665 // atomically check1587 // atomically check
1666 appendReservedI32Const(binary_bytes, flag_address);1588 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1667 appendReservedI32Const(binary_bytes, 0);1589 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));
1668 appendReservedI32Const(binary_bytes, 1);1590 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1669 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix));1591 try bw.writeSleb128(0);
1670 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_rmw_cmpxchg));1592 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1671 appendReservedUleb32(binary_bytes, 2); // alignment1593 try bw.writeSleb128(1);
1672 appendReservedUleb32(binary_bytes, 0); // offset1594 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1595 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_rmw_cmpxchg));
1596 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1597 try bw.writeUleb128(0); // offset
16731598
1674 // based on the value from the atomic check, jump to the label.1599 // based on the value from the atomic check, jump to the label.
1675 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_table));1600 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br_table));
1676 appendReservedUleb32(binary_bytes, 2); // length of the table (we have 3 blocks but because of the mandatory default the length is 2).1601 try bw.writeUleb128(3 - 1); // length of the table (we have 3 blocks but because of the mandatory default the length is 2).
1677 appendReservedUleb32(binary_bytes, 0); // $init1602 try bw.writeUleb128(0); // $init
1678 appendReservedUleb32(binary_bytes, 1); // $wait1603 try bw.writeUleb128(1); // $wait
1679 appendReservedUleb32(binary_bytes, 2); // $drop1604 try bw.writeUleb128(2); // $drop
1680 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1605 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1681 }1606 }
16821607
1683 const segment_groups = wasm.flush_buffer.data_segment_groups.items;1608 const segment_groups = wasm.flush_buffer.data_segment_groups.items;
...@@ -1690,74 +1615,82 @@ fn emitInitMemoryFunction(...@@ -1690,74 +1615,82 @@ fn emitInitMemoryFunction(
1690 const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end));1615 const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end));
1691 const segment_size: u32 = group.end_addr - start_addr;1616 const segment_size: u32 = group.end_addr - start_addr;
16921617
1693 try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 5 + 6 + 6 + 1 + 6 * 2 + 1 + 1);
1694
1695 // For passive BSS segments we can simply issue a memory.fill(0). For1618 // For passive BSS segments we can simply issue a memory.fill(0). For
1696 // non-BSS segments we do a memory.init. Both instructions take as1619 // non-BSS segments we do a memory.init. Both instructions take as
1697 // their first argument the destination address.1620 // their first argument the destination address.
1698 appendReservedI32Const(binary_bytes, start_addr);1621 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1622 try bw.writeLeb128(@as(i32, @bitCast(start_addr)));
16991623
1700 if (shared_memory and segment.isTls(wasm)) {1624 if (shared_memory and segment.isTls(wasm)) {
1701 // When we initialize the TLS segment we also set the `__tls_base`1625 // When we initialize the TLS segment we also set the `__tls_base`
1702 // global. This allows the runtime to use this static copy of the1626 // global. This allows the runtime to use this static copy of the
1703 // TLS data for the first/main thread.1627 // TLS data for the first/main thread.
1704 appendReservedI32Const(binary_bytes, start_addr);1628 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1705 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));1629 try bw.writeLeb128(@as(i32, @bitCast(start_addr)));
1706 appendReservedUleb32(binary_bytes, virtual_addrs.tls_base.?);1630 try bw.writeByte(@intFromEnum(std.wasm.Opcode.global_set));
1631 try bw.writeLeb128(virtual_addrs.tls_base.?);
1707 }1632 }
17081633
1709 appendReservedI32Const(binary_bytes, 0);1634 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1710 appendReservedI32Const(binary_bytes, segment_size);1635 try bw.writeSleb128(0);
1711 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.misc_prefix));1636 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1637 try bw.writeLeb128(@as(i32, @bitCast(segment_size)));
1638 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
1712 if (segment.isBss(wasm)) {1639 if (segment.isBss(wasm)) {
1713 // fill bss segment with zeroes1640 // fill bss segment with zeroes
1714 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.MiscOpcode.memory_fill));1641 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_fill));
1715 } else {1642 } else {
1716 // initialize the segment1643 // initialize the segment
1717 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.MiscOpcode.memory_init));1644 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));
1718 appendReservedUleb32(binary_bytes, @intCast(segment_index));1645 try bw.writeLeb128(segment_index);
1719 }1646 }
1720 binary_bytes.appendAssumeCapacity(0); // memory index immediate1647 try bw.writeByte(0); // memory index immediate
1721 }1648 }
17221649
1723 if (virtual_addrs.init_memory_flag) |flag_address| {1650 if (virtual_addrs.init_memory_flag) |flag_address| {
1724 assert(shared_memory);1651 assert(shared_memory);
1725 try binary_bytes.ensureUnusedCapacity(gpa, 6 + 6 + 1 + 3 * 5 + 6 + 1 + 5 + 1 + 3 * 5 + 1 + 1 + 5 + 1 + 6 * 2 + 1 + 5 + 1 + 3 * 5 + 1 + 1 + 1);1652
1726 // we set the init memory flag to value '2'1653 // we set the init memory flag to value '2'
1727 appendReservedI32Const(binary_bytes, flag_address);1654 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1728 appendReservedI32Const(binary_bytes, 2);1655 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));
1729 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix));1656 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1730 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_store));1657 try bw.writeSleb128(2);
1731 appendReservedUleb32(binary_bytes, @as(u32, 2)); // alignment1658 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1732 appendReservedUleb32(binary_bytes, @as(u32, 0)); // offset1659 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.i32_atomic_store));
1660 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1661 try bw.writeUleb128(0); // offset
17331662
1734 // notify any waiters for segment initialization completion1663 // notify any waiters for segment initialization completion
1735 appendReservedI32Const(binary_bytes, flag_address);1664 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1736 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));1665 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));
1737 leb.writeIleb128(binary_bytes.fixedWriter(), @as(i32, -1)) catch unreachable; // number of waiters1666 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1738 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix));1667 try bw.writeSleb128(-1); // number of waiters
1739 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_notify));1668
1740 appendReservedUleb32(binary_bytes, @as(u32, 2)); // alignment1669 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1741 appendReservedUleb32(binary_bytes, @as(u32, 0)); // offset1670 try bw.writeLeb128(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_notify));
1742 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.drop));1671 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1672 try bw.writeUleb128(0); // offset
1673 try bw.writeByte(@intFromEnum(std.wasm.Opcode.drop));
17431674
1744 // branch and drop segments1675 // branch and drop segments
1745 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br));1676 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br));
1746 appendReservedUleb32(binary_bytes, @as(u32, 1));1677 try bw.writeUleb128(1);
17471678
1748 // wait for thread to initialize memory segments1679 // wait for thread to initialize memory segments
1749 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); // end $wait1680 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $wait
1750 appendReservedI32Const(binary_bytes, flag_address);1681 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1751 appendReservedI32Const(binary_bytes, 1); // expected flag value1682 try bw.writeLeb128(@as(i32, @bitCast(flag_address)));
1752 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const));1683 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1753 leb.writeIleb128(binary_bytes.fixedWriter(), @as(i64, -1)) catch unreachable; // timeout1684 try bw.writeSleb128(1); // expected flag value
1754 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix));1685 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));
1755 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_wait32));1686 try bw.writeSleb128(-1); // timeout
1756 appendReservedUleb32(binary_bytes, @as(u32, 2)); // alignment1687 try bw.writeByte(@intFromEnum(std.wasm.Opcode.atomics_prefix));
1757 appendReservedUleb32(binary_bytes, @as(u32, 0)); // offset1688 try bw.writeByte(@intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_wait32));
1758 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.drop));1689 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
17591690 try bw.writeUleb128(0); // offset
1760 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); // end $drop1691 try bw.writeByte(@intFromEnum(std.wasm.Opcode.drop));
1692
1693 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end)); // end $drop
1761 }1694 }
17621695
1763 for (segment_groups, 0..) |group, segment_index| {1696 for (segment_groups, 0..) |group, segment_index| {
...@@ -1768,26 +1701,20 @@ fn emitInitMemoryFunction(...@@ -1768,26 +1701,20 @@ fn emitInitMemoryFunction(
1768 // during the initialization of each thread (__wasm_init_tls).1701 // during the initialization of each thread (__wasm_init_tls).
1769 if (shared_memory and segment.isTls(wasm)) continue;1702 if (shared_memory and segment.isTls(wasm)) continue;
17701703
1771 try binary_bytes.ensureUnusedCapacity(gpa, 1 + 5 + 5 + 1);1704 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
17721705 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.data_drop));
1773 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.misc_prefix));1706 try bw.writeLeb128(segment_index);
1774 appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.MiscOpcode.data_drop));
1775 appendReservedUleb32(binary_bytes, @intCast(segment_index));
1776 }1707 }
17771708
1778 // End of the function body1709 // End of the function body
1779 binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1710 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1780}1711}
17811712
1782fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!void {1713fn emitInitTlsFunction(wasm: *const Wasm, bw: *std.io.BufferedWriter) anyerror!void {
1783 const comp = wasm.base.comp;1714 const comp = wasm.base.comp;
1784 const gpa = comp.gpa;
1785
1786 assert(comp.config.shared_memory);1715 assert(comp.config.shared_memory);
17871716
1788 try bytes.ensureUnusedCapacity(gpa, 5 * 10 + 8);1717 try bw.writeUleb128(0); // no locals
1789
1790 appendReservedUleb32(bytes, 0); // no locals
17911718
1792 // If there's a TLS segment, initialize it during runtime using the bulk-memory feature1719 // If there's a TLS segment, initialize it during runtime using the bulk-memory feature
1793 // TLS segment is always the first one due to how we sort the data segments.1720 // TLS segment is always the first one due to how we sort the data segments.
...@@ -1796,36 +1723,35 @@ fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Al...@@ -1796,36 +1723,35 @@ fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Al
1796 const start_addr = wasm.flush_buffer.data_segments.values()[0];1723 const start_addr = wasm.flush_buffer.data_segments.values()[0];
1797 const end_addr = wasm.flush_buffer.data_segment_groups.items[0].end_addr;1724 const end_addr = wasm.flush_buffer.data_segment_groups.items[0].end_addr;
1798 const group_size = end_addr - start_addr;1725 const group_size = end_addr - start_addr;
1799 const data_segment_index = 0;1726 const data_segment_index: u32 = 0;
18001727
1801 const param_local: u32 = 0;1728 const param_local: u32 = 0;
18021729
1803 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1730 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1804 appendReservedUleb32(bytes, param_local);1731 try bw.writeLeb128(param_local);
18051732
1806 const tls_base_global_index: Wasm.GlobalIndex = @enumFromInt(wasm.globals.getIndex(.__tls_base).?);1733 const tls_base_global_index: Wasm.GlobalIndex = @enumFromInt(wasm.globals.getIndex(.__tls_base).?);
1807 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set));1734 try bw.writeByte(@intFromEnum(std.wasm.Opcode.global_set));
1808 appendReservedUleb32(bytes, @intFromEnum(tls_base_global_index));1735 try bw.writeLeb128(@intFromEnum(tls_base_global_index));
18091736
1810 // load stack values for the bulk-memory operation1737 // load stack values for the bulk-memory operation
1811 {1738 {
1812 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1739 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1813 appendReservedUleb32(bytes, param_local);1740 try bw.writeLeb128(param_local);
18141741
1815 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));1742 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1816 appendReservedUleb32(bytes, 0); //segment offset1743 try bw.writeSleb128(0); // segment offset
18171744
1818 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));1745 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1819 appendReservedUleb32(bytes, group_size); //segment offset1746 try bw.writeLeb128(@as(i32, @bitCast(group_size))); // segment offset
1820 }1747 }
18211748
1822 // perform the bulk-memory operation to initialize the data segment1749 // perform the bulk-memory operation to initialize the data segment
1823 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.misc_prefix));1750 try bw.writeByte(@intFromEnum(std.wasm.Opcode.misc_prefix));
1824 appendReservedUleb32(bytes, @intFromEnum(std.wasm.MiscOpcode.memory_init));1751 try bw.writeLeb128(@intFromEnum(std.wasm.MiscOpcode.memory_init));
1825 // segment immediate1752 // segment immediate
1826 appendReservedUleb32(bytes, data_segment_index);1753 try bw.writeLeb128(data_segment_index);
1827 // memory index immediate (always 0)1754 try bw.writeByte(0); // memory index immediate
1828 appendReservedUleb32(bytes, 0);
1829 }1755 }
18301756
1831 // If we have to perform any TLS relocations, call the corresponding function1757 // If we have to perform any TLS relocations, call the corresponding function
...@@ -1833,56 +1759,59 @@ fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Al...@@ -1833,56 +1759,59 @@ fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Al
1833 // generated by the linker.1759 // generated by the linker.
1834 if (wasm.functions.getIndex(.__wasm_apply_global_tls_relocs)) |function_index| {1760 if (wasm.functions.getIndex(.__wasm_apply_global_tls_relocs)) |function_index| {
1835 const output_function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex(wasm, @enumFromInt(function_index));1761 const output_function_index: Wasm.OutputFunctionIndex = .fromFunctionIndex(wasm, @enumFromInt(function_index));
1836 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.call));1762 try bw.writeByte(@intFromEnum(std.wasm.Opcode.call));
1837 appendReservedUleb32(bytes, @intFromEnum(output_function_index));1763 try bw.writeLeb128(@intFromEnum(output_function_index));
1838 }1764 }
18391765
1840 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1766 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1841}1767}
18421768
1843fn emitStartSection(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8), i: Wasm.OutputFunctionIndex) !void {1769fn emitStartSection(aw: *std.io.AllocatingWriter, i: Wasm.OutputFunctionIndex) !void {
1844 const header_offset = try reserveVecSectionHeader(gpa, bytes);1770 const header_offset = try reserveVecSectionHeader(&aw.buffered_writer);
1845 replaceVecSectionHeader(bytes, header_offset, .start, @intFromEnum(i));1771 defer replaceVecSectionHeader(aw, header_offset, .start, @intFromEnum(i));
1846}1772}
18471773
1848fn emitTagNameFunction(1774fn emitTagNameFunction(
1849 wasm: *Wasm,1775 wasm: *Wasm,
1850 code: *std.ArrayListUnmanaged(u8),1776 bw: *std.io.BufferedWriter,
1851 table_base_addr: u32,1777 table_base_addr: u32,
1852 table_index: u32,1778 table_index: u32,
1853 enum_type_ip: InternPool.Index,1779 enum_type_ip: InternPool.Index,
1854) !void {1780) !void {
1855 const comp = wasm.base.comp;1781 const comp = wasm.base.comp;
1856 const gpa = comp.gpa;
1857 const diags = &comp.link_diags;1782 const diags = &comp.link_diags;
1858 const zcu = comp.zcu.?;1783 const zcu = comp.zcu.?;
1859 const ip = &zcu.intern_pool;1784 const ip = &zcu.intern_pool;
1860 const enum_type = ip.loadEnumType(enum_type_ip);1785 const enum_type = ip.loadEnumType(enum_type_ip);
1861 const tag_values = enum_type.values.get(ip);1786 const tag_values = enum_type.values.get(ip);
18621787
1863 try code.ensureUnusedCapacity(gpa, 7 * 5 + 6 + 1 * 6);1788 try bw.writeUleb128(0); // no locals
1864 appendReservedUleb32(code, 0); // no locals
18651789
1866 const slice_abi_size = 8;1790 const slice_abi_size: u32 = 8;
1867 const encoded_alignment = @ctz(@as(u32, 4));
1868 if (tag_values.len == 0) {1791 if (tag_values.len == 0) {
1869 // Then it's auto-numbered and therefore a direct table lookup.1792 // Then it's auto-numbered and therefore a direct table lookup.
1870 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1793 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1871 appendReservedUleb32(code, 0);1794 try bw.writeUleb128(0);
18721795
1873 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1796 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1874 appendReservedUleb32(code, 1);1797 try bw.writeUleb128(1);
18751798
1876 appendReservedI32Const(code, slice_abi_size);1799 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1877 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_mul));1800 if (std.math.isPowerOfTwo(slice_abi_size)) {
1801 try bw.writeLeb128(@as(i32, @bitCast(@as(u32, std.math.log2_int(u32, slice_abi_size)))));
1802 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_shl));
1803 } else {
1804 try bw.writeLeb128(@as(i32, @bitCast(slice_abi_size)));
1805 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_mul));
1806 }
18781807
1879 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load));1808 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));
1880 appendReservedUleb32(code, encoded_alignment);1809 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1881 appendReservedUleb32(code, table_base_addr + table_index * 8);1810 try bw.writeLeb128(table_base_addr + slice_abi_size * table_index);
18821811
1883 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store));1812 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));
1884 appendReservedUleb32(code, encoded_alignment);1813 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1885 appendReservedUleb32(code, 0);1814 try bw.writeUleb128(0);
1886 } else {1815 } else {
1887 const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);1816 const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);
1888 const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {1817 const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {
...@@ -1891,94 +1820,80 @@ fn emitTagNameFunction(...@@ -1891,94 +1820,80 @@ fn emitTagNameFunction(
1891 else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),1820 else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),
1892 };1821 };
18931822
1894 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1823 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1895 appendReservedUleb32(code, 0);1824 try bw.writeUleb128(0);
18961825
1897 // Outer block that computes table offset.1826 // Outer block that computes table offset.
1898 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));1827 try bw.writeByte(@intFromEnum(std.wasm.Opcode.block));
1899 code.appendAssumeCapacity(@intFromEnum(outer_block_type));1828 try bw.writeByte(@intFromEnum(outer_block_type));
19001829
1901 for (tag_values, 0..) |tag_value, tag_index| {1830 for (tag_values, 0..) |tag_value, tag_index| {
1902 // block for this if case1831 // block for this if case
1903 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));1832 try bw.writeByte(@intFromEnum(std.wasm.Opcode.block));
1904 code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));1833 try bw.writeByte(@intFromEnum(std.wasm.BlockType.empty));
19051834
1906 // Tag value whose name should be returned.1835 // Tag value whose name should be returned.
1907 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));1836 try bw.writeByte(@intFromEnum(std.wasm.Opcode.local_get));
1908 appendReservedUleb32(code, 1);1837 try bw.writeUleb128(1);
19091838
1910 const val: Zcu.Value = .fromInterned(tag_value);1839 const val: Zcu.Value = .fromInterned(tag_value);
1911 switch (outer_block_type) {1840 switch (outer_block_type) {
1912 .i32 => {1841 .i32 => {
1913 const x: u32 = switch (int_info.signedness) {1842 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1914 .signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))),1843 try bw.writeLeb128(@as(i32, switch (int_info.signedness) {
1915 .unsigned => @intCast(val.toUnsignedInt(zcu)),1844 .signed => @intCast(val.toSignedInt(zcu)),
1916 };1845 .unsigned => @bitCast(@as(u32, @intCast(val.toUnsignedInt(zcu)))),
1917 appendReservedI32Const(code, x);1846 }));
1918 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne));1847 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_ne));
1919 },1848 },
1920 .i64 => {1849 .i64 => {
1921 const x: u64 = switch (int_info.signedness) {1850 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_const));
1922 .signed => @bitCast(val.toSignedInt(zcu)),1851 try bw.writeLeb128(@as(i64, switch (int_info.signedness) {
1923 .unsigned => val.toUnsignedInt(zcu),1852 .signed => val.toSignedInt(zcu),
1924 };1853 .unsigned => @bitCast(val.toUnsignedInt(zcu)),
1925 appendReservedI64Const(code, x);1854 }));
1926 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne));1855 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_ne));
1927 },1856 },
1928 else => unreachable,1857 else => unreachable,
1929 }1858 }
19301859
1931 // if they're not equal, break out of current branch1860 // if they're not equal, break out of current branch
1932 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if));1861 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br_if));
1933 appendReservedUleb32(code, 0);1862 try bw.writeUleb128(0);
19341863
1935 // Put the table offset of the result on the stack.1864 // Put the table offset of the result on the stack.
1936 appendReservedI32Const(code, @intCast(tag_index * slice_abi_size));1865 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i32_const));
1866 try bw.writeLeb128(@as(i32, @bitCast(@as(u32, @intCast(slice_abi_size * tag_index)))));
19371867
1938 // break outside blocks1868 // break outside blocks
1939 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br));1869 try bw.writeByte(@intFromEnum(std.wasm.Opcode.br));
1940 appendReservedUleb32(code, 1);1870 try bw.writeUleb128(1);
19411871
1942 // end the block for this case1872 // end the block for this case
1943 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1873 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1944 }1874 }
1945 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable"));1875 try bw.writeByte(@intFromEnum(std.wasm.Opcode.@"unreachable"));
1946 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1876 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
19471877
1948 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load));1878 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_load));
1949 appendReservedUleb32(code, encoded_alignment);1879 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1950 appendReservedUleb32(code, table_base_addr + table_index * 8);1880 try bw.writeLeb128(table_base_addr + slice_abi_size * table_index);
19511881
1952 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store));1882 try bw.writeByte(@intFromEnum(std.wasm.Opcode.i64_store));
1953 appendReservedUleb32(code, encoded_alignment);1883 try bw.writeLeb128(comptime Alignment.@"4".toLog2Units());
1954 appendReservedUleb32(code, 0);1884 try bw.writeUleb128(0);
1955 }1885 }
19561886
1957 // End of the function body1887 // End of the function body
1958 code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1888 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1959}
1960
1961/// Writes an unsigned 32-bit integer as a LEB128-encoded 'i32.const' value.
1962fn appendReservedI32Const(bytes: *std.ArrayListUnmanaged(u8), val: u32) void {
1963 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));
1964 leb.writeIleb128(bytes.fixedWriter(), @as(i32, @bitCast(val))) catch unreachable;
1965}
1966
1967/// Writes an unsigned 64-bit integer as a LEB128-encoded 'i64.const' value.
1968fn appendReservedI64Const(bytes: *std.ArrayListUnmanaged(u8), val: u64) void {
1969 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const));
1970 leb.writeIleb128(bytes.fixedWriter(), @as(i64, @bitCast(val))) catch unreachable;
1971}
1972
1973fn appendReservedUleb32(bytes: *std.ArrayListUnmanaged(u8), val: u32) void {
1974 leb.writeUleb128(bytes.fixedWriter(), val) catch unreachable;
1975}1889}
19761890
1977fn appendGlobal(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8), mutable: u8, val: u32) Allocator.Error!void {1891fn appendGlobal(bw: *std.io.BufferedWriter, mutable: bool, val: u32) anyerror!void {
1978 try bytes.ensureUnusedCapacity(gpa, 9);1892 try bw.writeAll(&.{
1979 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Valtype.i32));1893 @intFromEnum(std.wasm.Valtype.i32),
1980 bytes.appendAssumeCapacity(mutable);1894 @intFromBool(mutable),
1981 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const));1895 @intFromEnum(std.wasm.Opcode.i32_const),
1982 appendReservedUleb32(bytes, val);1896 });
1983 bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));1897 try bw.writeLeb128(val);
1898 try bw.writeByte(@intFromEnum(std.wasm.Opcode.end));
1984}1899}
src/link/Wasm/Object.zig+263-323
...@@ -252,7 +252,7 @@ pub const ScratchSpace = struct {...@@ -252,7 +252,7 @@ pub const ScratchSpace = struct {
252252
253pub fn parse(253pub fn parse(
254 wasm: *Wasm,254 wasm: *Wasm,
255 bytes: []const u8,255 br: *std.io.BufferedReader,
256 path: Path,256 path: Path,
257 archive_member_name: ?[]const u8,257 archive_member_name: ?[]const u8,
258 host_name: Wasm.OptionalString,258 host_name: Wasm.OptionalString,
...@@ -264,13 +264,9 @@ pub fn parse(...@@ -264,13 +264,9 @@ pub fn parse(
264 const gpa = comp.gpa;264 const gpa = comp.gpa;
265 const diags = &comp.link_diags;265 const diags = &comp.link_diags;
266266
267 var pos: usize = 0;267 if (!std.mem.eql(u8, try br.takeArray(std.wasm.magic.len), &std.wasm.magic)) return error.BadObjectMagic;
268268
269 if (!std.mem.eql(u8, bytes[0..std.wasm.magic.len], &std.wasm.magic)) return error.BadObjectMagic;269 const version = try br.takeInt(u32, .little);
270 pos += std.wasm.magic.len;
271
272 const version = std.mem.readInt(u32, bytes[pos..][0..4], .little);
273 pos += 4;
274270
275 const data_segment_start: u32 = @intCast(wasm.object_data_segments.items.len);271 const data_segment_start: u32 = @intCast(wasm.object_data_segments.items.len);
276 const custom_segment_start: u32 = @intCast(wasm.object_custom_segments.entries.len);272 const custom_segment_start: u32 = @intCast(wasm.object_custom_segments.entries.len);
...@@ -298,200 +294,187 @@ pub fn parse(...@@ -298,200 +294,187 @@ pub fn parse(
298 var code_section_index: ?Wasm.ObjectSectionIndex = null;294 var code_section_index: ?Wasm.ObjectSectionIndex = null;
299 var global_section_index: ?Wasm.ObjectSectionIndex = null;295 var global_section_index: ?Wasm.ObjectSectionIndex = null;
300 var data_section_index: ?Wasm.ObjectSectionIndex = null;296 var data_section_index: ?Wasm.ObjectSectionIndex = null;
301 while (pos < bytes.len) : (wasm.object_total_sections += 1) {297 while (br.takeEnum(std.wasm.Section, .little)) |section_tag| : (wasm.object_total_sections += 1) {
302 const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections);298 const section_index: Wasm.ObjectSectionIndex = @enumFromInt(wasm.object_total_sections);
303299
304 const section_tag: std.wasm.Section = @enumFromInt(bytes[pos]);300 const len = try br.takeLeb128(u32);
305 pos += 1;301 const section_end = br.seek + len;
306
307 const len, pos = readLeb(u32, bytes, pos);
308 const section_end = pos + len;
309 switch (section_tag) {302 switch (section_tag) {
310 .custom => {303 .custom => {
311 const section_name, pos = readBytes(bytes, pos);304 const section_name = try br.take(try br.takeLeb128(u32));
312 if (std.mem.eql(u8, section_name, "linking")) {305 if (std.mem.eql(u8, section_name, "linking")) {
313 saw_linking_section = true;306 saw_linking_section = true;
314 const section_version, pos = readLeb(u32, bytes, pos);307 const section_version = try br.takeLeb128(u32);
315 log.debug("link meta data version: {d}", .{section_version});308 log.debug("link meta data version: {d}", .{section_version});
316 if (section_version != 2) return error.UnsupportedVersion;309 if (section_version != 2) return error.UnsupportedVersion;
317 while (pos < section_end) {310 while (br.seek < section_end) {
318 const sub_type, pos = readLeb(u8, bytes, pos);311 const sub_type = try br.takeEnum(SubsectionType, .little);
319 log.debug("found subsection: {s}", .{@tagName(@as(SubsectionType, @enumFromInt(sub_type)))});312 log.debug("found subsection: {s}", .{@tagName(sub_type)});
320 const payload_len, pos = readLeb(u32, bytes, pos);313 const payload_len = try br.takeLeb128(u32);
321 if (payload_len == 0) break;314 if (payload_len == 0) break;
322315
323 const count, pos = readLeb(u32, bytes, pos);316 const count = try br.takeLeb128(u32);
324317 switch (sub_type) {
325 switch (@as(SubsectionType, @enumFromInt(sub_type))) {318 .segment_info => for (try ss.segment_info.addManyAsSlice(gpa, count)) |*segment| {
326 .segment_info => {319 const name = try br.take(try br.takeLeb128(u32));
327 for (try ss.segment_info.addManyAsSlice(gpa, count)) |*segment| {320 const alignment: Alignment = .fromLog2Units(try br.takeLeb128(u32));
328 const name, pos = readBytes(bytes, pos);321 const flags: SegmentInfo.Flags = @bitCast(try br.takeLeb128(u32));
329 const alignment, pos = readLeb(u32, bytes, pos);322 const tls = flags.tls or
330 const flags_u32, pos = readLeb(u32, bytes, pos);323 // Supports legacy object files that specified
331 const flags: SegmentInfo.Flags = @bitCast(flags_u32);324 // being TLS by the name instead of the TLS flag.
332 const tls = flags.tls or325 std.mem.startsWith(u8, name, ".tdata") or
333 // Supports legacy object files that specified326 std.mem.startsWith(u8, name, ".tbss");
334 // being TLS by the name instead of the TLS flag.327 has_tls = has_tls or tls;
335 std.mem.startsWith(u8, name, ".tdata") or328 segment.* = .{
336 std.mem.startsWith(u8, name, ".tbss");329 .name = try wasm.internString(name),
337 has_tls = has_tls or tls;330 .flags = .{
338 segment.* = .{331 .strings = flags.strings,
339 .name = try wasm.internString(name),332 .tls = tls,
340 .flags = .{333 .alignment = alignment,
341 .strings = flags.strings,334 .retain = flags.retain,
342 .tls = tls,335 },
343 .alignment = @enumFromInt(alignment),336 };
344 .retain = flags.retain,
345 },
346 };
347 }
348 },337 },
349 .init_funcs => {338 .init_funcs => for (try wasm.object_init_funcs.addManyAsSlice(gpa, count)) |*func| {
350 for (try wasm.object_init_funcs.addManyAsSlice(gpa, count)) |*func| {339 const priority = try br.takeLeb128(u32);
351 const priority, pos = readLeb(u32, bytes, pos);340 const symbol_index = try br.takeLeb128(u32);
352 const symbol_index, pos = readLeb(u32, bytes, pos);341 if (symbol_index > ss.symbol_table.items.len)
353 if (symbol_index > ss.symbol_table.items.len)342 return diags.failParse(path, "init_funcs before symbol table", .{});
354 return diags.failParse(path, "init_funcs before symbol table", .{});343 const sym = &ss.symbol_table.items[symbol_index];
355 const sym = &ss.symbol_table.items[symbol_index];344 if (sym.pointee != .function) {
356 if (sym.pointee != .function) {345 return diags.failParse(path, "init_func symbol '{s}' not a function", .{
357 return diags.failParse(path, "init_func symbol '{s}' not a function", .{346 sym.name.slice(wasm).?,
358 sym.name.slice(wasm).?,347 });
359 });348 } else if (sym.flags.undefined) {
360 } else if (sym.flags.undefined) {349 return diags.failParse(path, "init_func symbol '{s}' is an import", .{
361 return diags.failParse(path, "init_func symbol '{s}' is an import", .{350 sym.name.slice(wasm).?,
362 sym.name.slice(wasm).?,351 });
363 });
364 }
365 func.* = .{
366 .priority = priority,
367 .function_index = sym.pointee.function,
368 };
369 }352 }
353 func.* = .{
354 .priority = priority,
355 .function_index = sym.pointee.function,
356 };
370 },357 },
371 .comdat_info => {358 .comdat_info => for (try wasm.object_comdats.addManyAsSlice(gpa, count)) |*comdat| {
372 for (try wasm.object_comdats.addManyAsSlice(gpa, count)) |*comdat| {359 const name = try br.take(try br.takeLeb128(u32));
373 const name, pos = readBytes(bytes, pos);360 const flags = try br.takeLeb128(u32);
374 const flags, pos = readLeb(u32, bytes, pos);361 if (flags != 0) return error.UnexpectedComdatFlags;
375 if (flags != 0) return error.UnexpectedComdatFlags;362 const symbol_count = try br.takeLeb128(u32);
376 const symbol_count, pos = readLeb(u32, bytes, pos);363 const start_off: u32 = @intCast(wasm.object_comdat_symbols.len);
377 const start_off: u32 = @intCast(wasm.object_comdat_symbols.len);364 try wasm.object_comdat_symbols.ensureUnusedCapacity(gpa, symbol_count);
378 try wasm.object_comdat_symbols.ensureUnusedCapacity(gpa, symbol_count);365 for (0..symbol_count) |_| {
379 for (0..symbol_count) |_| {366 const kind = try br.takeEnum(Wasm.Comdat.Symbol.Type, .little);
380 const kind, pos = readEnum(Wasm.Comdat.Symbol.Type, bytes, pos);367 const index = try br.takeLeb128(u32);
381 const index, pos = readLeb(u32, bytes, pos);368 if (true) @panic("TODO rebase index depending on kind");
382 if (true) @panic("TODO rebase index depending on kind");369 wasm.object_comdat_symbols.appendAssumeCapacity(.{
383 wasm.object_comdat_symbols.appendAssumeCapacity(.{370 .kind = kind,
384 .kind = kind,371 .index = index,
385 .index = index,372 });
386 });
387 }
388 comdat.* = .{
389 .name = try wasm.internString(name),
390 .flags = flags,
391 .symbols = .{
392 .off = start_off,
393 .len = @intCast(wasm.object_comdat_symbols.len - start_off),
394 },
395 };
396 }373 }
374 comdat.* = .{
375 .name = try wasm.internString(name),
376 .flags = flags,
377 .symbols = .{
378 .off = start_off,
379 .len = @intCast(wasm.object_comdat_symbols.len - start_off),
380 },
381 };
397 },382 },
398 .symbol_table => {383 .symbol_table => for (try ss.symbol_table.addManyAsSlice(gpa, count)) |*symbol| {
399 for (try ss.symbol_table.addManyAsSlice(gpa, count)) |*symbol| {384 const tag = try br.takeEnum(Symbol.Tag, .little);
400 const tag, pos = readEnum(Symbol.Tag, bytes, pos);385 const flags: Wasm.SymbolFlags = @bitCast(try br.takeLeb128(u32));
401 const flags, pos = readLeb(u32, bytes, pos);386 symbol.* = .{
402 symbol.* = .{387 .flags = flags,
403 .flags = @bitCast(flags),388 .name = .none,
404 .name = .none,389 .pointee = undefined,
405 .pointee = undefined,390 };
406 };391 symbol.flags.initZigSpecific(must_link, gc_sections);
407 symbol.flags.initZigSpecific(must_link, gc_sections);392
408393 switch (tag) {
409 switch (tag) {394 .data => {
410 .data => {395 const name = try br.take(try br.takeLeb128(u32));
411 const name, pos = readBytes(bytes, pos);396 const interned_name = try wasm.internString(name);
412 const interned_name = try wasm.internString(name);397 symbol.name = interned_name.toOptional();
413 symbol.name = interned_name.toOptional();398 if (symbol.flags.undefined) {
414 if (symbol.flags.undefined) {399 symbol.pointee = .data_import;
415 symbol.pointee = .data_import;400 } else {
401 const segment_index = try br.takeLeb128(u32);
402 const segment_offset = try br.takeLeb128(u32);
403 const size = try br.takeLeb128(u32);
404 try wasm.object_datas.append(gpa, .{
405 .segment = @enumFromInt(data_segment_start + segment_index),
406 .offset = segment_offset,
407 .size = size,
408 .name = interned_name,
409 .flags = symbol.flags,
410 });
411 symbol.pointee = .{
412 .data = @enumFromInt(wasm.object_datas.items.len - 1),
413 };
414 }
415 },
416 .section => {
417 const local_section = try br.takeLeb128(u32);
418 const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section);
419 symbol.pointee = .{ .section = section };
420 },
421
422 .function => {
423 const local_index = try br.takeLeb128(u32);
424 if (symbol.flags.undefined) {
425 const function_import: ScratchSpace.FuncImportIndex = @enumFromInt(local_index);
426 symbol.pointee = .{ .function_import = function_import };
427 if (symbol.flags.explicit_name) {
428 const name = try br.take(try br.takeLeb128(u32));
429 symbol.name = (try wasm.internString(name)).toOptional();
416 } else {430 } else {
417 const segment_index, pos = readLeb(u32, bytes, pos);431 symbol.name = function_import.ptr(ss).name.toOptional();
418 const segment_offset, pos = readLeb(u32, bytes, pos);
419 const size, pos = readLeb(u32, bytes, pos);
420 try wasm.object_datas.append(gpa, .{
421 .segment = @enumFromInt(data_segment_start + segment_index),
422 .offset = segment_offset,
423 .size = size,
424 .name = interned_name,
425 .flags = symbol.flags,
426 });
427 symbol.pointee = .{
428 .data = @enumFromInt(wasm.object_datas.items.len - 1),
429 };
430 }432 }
431 },433 } else {
432 .section => {434 symbol.pointee = .{ .function = @enumFromInt(functions_start + (local_index - ss.func_imports.items.len)) };
433 const local_section, pos = readLeb(u32, bytes, pos);435 const name = try br.take(try br.takeLeb128(u32));
434 const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section);436 symbol.name = (try wasm.internString(name)).toOptional();
435 symbol.pointee = .{ .section = section };437 }
436 },438 },
437439 .global => {
438 .function => {440 const local_index = try br.takeLeb128(u32);
439 const local_index, pos = readLeb(u32, bytes, pos);441 if (symbol.flags.undefined) {
440 if (symbol.flags.undefined) {442 const global_import: ScratchSpace.GlobalImportIndex = @enumFromInt(local_index);
441 const function_import: ScratchSpace.FuncImportIndex = @enumFromInt(local_index);443 symbol.pointee = .{ .global_import = global_import };
442 symbol.pointee = .{ .function_import = function_import };444 if (symbol.flags.explicit_name) {
443 if (symbol.flags.explicit_name) {445 const name = try br.take(try br.takeLeb128(u32));
444 const name, pos = readBytes(bytes, pos);
445 symbol.name = (try wasm.internString(name)).toOptional();
446 } else {
447 symbol.name = function_import.ptr(ss).name.toOptional();
448 }
449 } else {
450 symbol.pointee = .{ .function = @enumFromInt(functions_start + (local_index - ss.func_imports.items.len)) };
451 const name, pos = readBytes(bytes, pos);
452 symbol.name = (try wasm.internString(name)).toOptional();446 symbol.name = (try wasm.internString(name)).toOptional();
453 }
454 },
455 .global => {
456 const local_index, pos = readLeb(u32, bytes, pos);
457 if (symbol.flags.undefined) {
458 const global_import: ScratchSpace.GlobalImportIndex = @enumFromInt(local_index);
459 symbol.pointee = .{ .global_import = global_import };
460 if (symbol.flags.explicit_name) {
461 const name, pos = readBytes(bytes, pos);
462 symbol.name = (try wasm.internString(name)).toOptional();
463 } else {
464 symbol.name = global_import.ptr(ss).name.toOptional();
465 }
466 } else {447 } else {
467 symbol.pointee = .{ .global = @enumFromInt(globals_start + (local_index - ss.global_imports.items.len)) };448 symbol.name = global_import.ptr(ss).name.toOptional();
468 const name, pos = readBytes(bytes, pos);
469 symbol.name = (try wasm.internString(name)).toOptional();
470 }449 }
471 },450 } else {
472 .table => {451 symbol.pointee = .{ .global = @enumFromInt(globals_start + (local_index - ss.global_imports.items.len)) };
473 const local_index, pos = readLeb(u32, bytes, pos);452 const name = try br.take(try br.takeLeb128(u32));
474 if (symbol.flags.undefined) {453 symbol.name = (try wasm.internString(name)).toOptional();
475 table_import_symbol_count += 1;454 }
476 const table_import: ScratchSpace.TableImportIndex = @enumFromInt(local_index);455 },
477 symbol.pointee = .{ .table_import = table_import };456 .table => {
478 if (symbol.flags.explicit_name) {457 const local_index = try br.takeLeb128(u32);
479 const name, pos = readBytes(bytes, pos);458 if (symbol.flags.undefined) {
480 symbol.name = (try wasm.internString(name)).toOptional();459 table_import_symbol_count += 1;
481 } else {460 const table_import: ScratchSpace.TableImportIndex = @enumFromInt(local_index);
482 symbol.name = table_import.ptr(ss).name.toOptional();461 symbol.pointee = .{ .table_import = table_import };
483 }462 if (symbol.flags.explicit_name) {
484 } else {463 const name = try br.take(try br.takeLeb128(u32));
485 symbol.pointee = .{ .table = @enumFromInt(tables_start + (local_index - ss.table_imports.items.len)) };
486 const name, pos = readBytes(bytes, pos);
487 symbol.name = (try wasm.internString(name)).toOptional();464 symbol.name = (try wasm.internString(name)).toOptional();
465 } else {
466 symbol.name = table_import.ptr(ss).name.toOptional();
488 }467 }
489 },468 } else {
490 else => {469 symbol.pointee = .{ .table = @enumFromInt(tables_start + (local_index - ss.table_imports.items.len)) };
491 log.debug("unrecognized symbol type tag: {x}", .{@intFromEnum(tag)});470 const name = try br.take(try br.takeLeb128(u32));
492 return error.UnrecognizedSymbolType;471 symbol.name = (try wasm.internString(name)).toOptional();
493 },472 }
494 }473 },
474 else => {
475 log.debug("unrecognized symbol type tag: {x}", .{@intFromEnum(tag)});
476 return error.UnrecognizedSymbolType;
477 },
495 }478 }
496 },479 },
497 }480 }
...@@ -504,8 +487,8 @@ pub fn parse(...@@ -504,8 +487,8 @@ pub fn parse(
504 // which section they apply to, and must be sequenced in487 // which section they apply to, and must be sequenced in
505 // the module after that section."488 // the module after that section."
506 // "Relocation sections can only target code, data and custom sections."489 // "Relocation sections can only target code, data and custom sections."
507 const local_section, pos = readLeb(u32, bytes, pos);490 const local_section = try br.takeLeb128(u32);
508 const count, pos = readLeb(u32, bytes, pos);491 const count = try br.takeLeb128(u32);
509 const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section);492 const section: Wasm.ObjectSectionIndex = @enumFromInt(local_section_index_base + local_section);
510493
511 log.debug("found {d} relocations for section={d}", .{ count, section });494 log.debug("found {d} relocations for section={d}", .{ count, section });
...@@ -513,10 +496,9 @@ pub fn parse(...@@ -513,10 +496,9 @@ pub fn parse(
513 var prev_offset: u32 = 0;496 var prev_offset: u32 = 0;
514 try wasm.object_relocations.ensureUnusedCapacity(gpa, count);497 try wasm.object_relocations.ensureUnusedCapacity(gpa, count);
515 for (0..count) |_| {498 for (0..count) |_| {
516 const tag: RelocationType = @enumFromInt(bytes[pos]);499 const tag = try br.takeEnum(RelocationType, .little);
517 pos += 1;500 const offset = try br.takeLeb128(u32);
518 const offset, pos = readLeb(u32, bytes, pos);501 const index = try br.takeLeb128(u32);
519 const index, pos = readLeb(u32, bytes, pos);
520502
521 if (offset < prev_offset)503 if (offset < prev_offset)
522 return diags.failParse(path, "relocation entries not sorted by offset", .{});504 return diags.failParse(path, "relocation entries not sorted by offset", .{});
...@@ -537,7 +519,7 @@ pub fn parse(...@@ -537,7 +519,7 @@ pub fn parse(
537 .memory_addr_locrel_i32,519 .memory_addr_locrel_i32,
538 .memory_addr_tls_sleb64,520 .memory_addr_tls_sleb64,
539 => {521 => {
540 const addend: i32, pos = readLeb(i32, bytes, pos);522 const addend = try br.takeLeb128(i32);
541 wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) {523 wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) {
542 .data => |data| .{524 .data => |data| .{
543 .tag = .fromType(tag),525 .tag = .fromType(tag),
...@@ -555,7 +537,7 @@ pub fn parse(...@@ -555,7 +537,7 @@ pub fn parse(
555 });537 });
556 },538 },
557 .function_offset_i32, .function_offset_i64 => {539 .function_offset_i32, .function_offset_i64 => {
558 const addend: i32, pos = readLeb(i32, bytes, pos);540 const addend = try br.takeLeb128(i32);
559 wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) {541 wasm.object_relocations.appendAssumeCapacity(switch (sym.pointee) {
560 .function => .{542 .function => .{
561 .tag = .fromType(tag),543 .tag = .fromType(tag),
...@@ -573,7 +555,7 @@ pub fn parse(...@@ -573,7 +555,7 @@ pub fn parse(
573 });555 });
574 },556 },
575 .section_offset_i32 => {557 .section_offset_i32 => {
576 const addend: i32, pos = readLeb(i32, bytes, pos);558 const addend = try br.takeLeb128(i32);
577 wasm.object_relocations.appendAssumeCapacity(.{559 wasm.object_relocations.appendAssumeCapacity(.{
578 .tag = .section_offset_i32,560 .tag = .section_offset_i32,
579 .offset = offset,561 .offset = offset,
...@@ -658,10 +640,9 @@ pub fn parse(...@@ -658,10 +640,9 @@ pub fn parse(
658 .len = count,640 .len = count,
659 });641 });
660 } else if (std.mem.eql(u8, section_name, "target_features")) {642 } else if (std.mem.eql(u8, section_name, "target_features")) {
661 opt_features, pos = try parseFeatures(wasm, bytes, pos, path);643 opt_features = try parseFeatures(wasm, br, path);
662 } else if (std.mem.startsWith(u8, section_name, ".debug")) {644 } else if (std.mem.startsWith(u8, section_name, ".debug")) {
663 const debug_content = bytes[pos..section_end];645 const debug_content = try br.take(len);
664 pos = section_end;
665646
666 const data_off: u32 = @intCast(wasm.string_bytes.items.len);647 const data_off: u32 = @intCast(wasm.string_bytes.items.len);
667 try wasm.string_bytes.appendSlice(gpa, debug_content);648 try wasm.string_bytes.appendSlice(gpa, debug_content);
...@@ -669,23 +650,20 @@ pub fn parse(...@@ -669,23 +650,20 @@ pub fn parse(
669 try wasm.object_custom_segments.put(gpa, section_index, .{650 try wasm.object_custom_segments.put(gpa, section_index, .{
670 .payload = .{651 .payload = .{
671 .off = @enumFromInt(data_off),652 .off = @enumFromInt(data_off),
672 .len = @intCast(debug_content.len),653 .len = @intCast(len),
673 },654 },
674 .flags = .{},655 .flags = .{},
675 .section_name = try wasm.internString(section_name),656 .section_name = try wasm.internString(section_name),
676 });657 });
677 } else {658 } else br.seek = section_end;
678 pos = section_end;
679 }
680 },659 },
681 .type => {660 .type => {
682 const func_types_len, pos = readLeb(u32, bytes, pos);661 const func_types_len = try br.takeLeb128(u32);
683 for (try ss.func_types.addManyAsSlice(gpa, func_types_len)) |*func_type| {662 for (try ss.func_types.addManyAsSlice(gpa, func_types_len)) |*func_type| {
684 if (bytes[pos] != std.wasm.function_type) return error.ExpectedFuncType;663 if (try br.takeByte() != std.wasm.function_type) return error.ExpectedFuncType;
685 pos += 1;
686664
687 const params, pos = readBytes(bytes, pos);665 const params = try br.take(try br.takeLeb128(u32));
688 const returns, pos = readBytes(bytes, pos);666 const returns = try br.take(try br.takeLeb128(u32));
689 func_type.* = try wasm.addFuncType(.{667 func_type.* = try wasm.addFuncType(.{
690 .params = .fromString(try wasm.internString(params)),668 .params = .fromString(try wasm.internString(params)),
691 .returns = .fromString(try wasm.internString(returns)),669 .returns = .fromString(try wasm.internString(returns)),
...@@ -693,16 +671,16 @@ pub fn parse(...@@ -693,16 +671,16 @@ pub fn parse(
693 }671 }
694 },672 },
695 .import => {673 .import => {
696 const imports_len, pos = readLeb(u32, bytes, pos);674 const imports_len = try br.takeLeb128(u32);
697 for (0..imports_len) |_| {675 for (0..imports_len) |_| {
698 const module_name, pos = readBytes(bytes, pos);676 const module_name = try br.take(try br.takeLeb128(u32));
699 const name, pos = readBytes(bytes, pos);677 const name = try br.take(try br.takeLeb128(u32));
700 const kind, pos = readEnum(std.wasm.ExternalKind, bytes, pos);678 const kind = try br.takeEnum(std.wasm.ExternalKind, .little);
701 const interned_module_name = try wasm.internString(module_name);679 const interned_module_name = try wasm.internString(module_name);
702 const interned_name = try wasm.internString(name);680 const interned_name = try wasm.internString(name);
703 switch (kind) {681 switch (kind) {
704 .function => {682 .function => {
705 const function, pos = readLeb(u32, bytes, pos);683 const function = try br.takeLeb128(u32);
706 try ss.func_imports.append(gpa, .{684 try ss.func_imports.append(gpa, .{
707 .module_name = interned_module_name,685 .module_name = interned_module_name,
708 .name = interned_name,686 .name = interned_name,
...@@ -710,7 +688,7 @@ pub fn parse(...@@ -710,7 +688,7 @@ pub fn parse(
710 });688 });
711 },689 },
712 .memory => {690 .memory => {
713 const limits, pos = readLimits(bytes, pos);691 const limits = try readLimits(br);
714 const gop = try wasm.object_memory_imports.getOrPut(gpa, interned_name);692 const gop = try wasm.object_memory_imports.getOrPut(gpa, interned_name);
715 if (gop.found_existing) {693 if (gop.found_existing) {
716 if (gop.value_ptr.module_name != interned_module_name) {694 if (gop.value_ptr.module_name != interned_module_name) {
...@@ -736,9 +714,12 @@ pub fn parse(...@@ -736,9 +714,12 @@ pub fn parse(
736 }714 }
737 },715 },
738 .global => {716 .global => {
739 const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);717 const valtype = try br.takeEnum(std.wasm.Valtype, .little);
740 const mutable = bytes[pos] == 0x01;718 const mutable = switch (try br.takeByte()) {
741 pos += 1;719 0 => false,
720 1 => true,
721 else => return error.InvalidMutability,
722 };
742 try ss.global_imports.append(gpa, .{723 try ss.global_imports.append(gpa, .{
743 .name = interned_name,724 .name = interned_name,
744 .valtype = valtype,725 .valtype = valtype,
...@@ -747,8 +728,8 @@ pub fn parse(...@@ -747,8 +728,8 @@ pub fn parse(
747 });728 });
748 },729 },
749 .table => {730 .table => {
750 const ref_type, pos = readEnum(std.wasm.RefType, bytes, pos);731 const ref_type = try br.takeEnum(std.wasm.RefType, .little);
751 const limits, pos = readLimits(bytes, pos);732 const limits = try readLimits(br);
752 try ss.table_imports.append(gpa, .{733 try ss.table_imports.append(gpa, .{
753 .name = interned_name,734 .name = interned_name,
754 .module_name = interned_module_name,735 .module_name = interned_module_name,
...@@ -763,17 +744,16 @@ pub fn parse(...@@ -763,17 +744,16 @@ pub fn parse(
763 }744 }
764 },745 },
765 .function => {746 .function => {
766 const functions_len, pos = readLeb(u32, bytes, pos);747 const functions_len = try br.takeLeb128(u32);
767 for (try ss.func_type_indexes.addManyAsSlice(gpa, functions_len)) |*func_type_index| {748 for (try ss.func_type_indexes.addManyAsSlice(gpa, functions_len)) |*func_type_index| {
768 const i, pos = readLeb(u32, bytes, pos);749 func_type_index.* = @enumFromInt(try br.takeLeb128(u32));
769 func_type_index.* = @enumFromInt(i);
770 }750 }
771 },751 },
772 .table => {752 .table => {
773 const tables_len, pos = readLeb(u32, bytes, pos);753 const tables_len = try br.takeLeb128(u32);
774 for (try wasm.object_tables.addManyAsSlice(gpa, tables_len)) |*table| {754 for (try wasm.object_tables.addManyAsSlice(gpa, tables_len)) |*table| {
775 const ref_type, pos = readEnum(std.wasm.RefType, bytes, pos);755 const ref_type = try br.takeEnum(std.wasm.RefType, .little);
776 const limits, pos = readLimits(bytes, pos);756 const limits = try readLimits(br);
777 table.* = .{757 table.* = .{
778 .name = .none,758 .name = .none,
779 .module_name = .none,759 .module_name = .none,
...@@ -788,9 +768,9 @@ pub fn parse(...@@ -788,9 +768,9 @@ pub fn parse(
788 }768 }
789 },769 },
790 .memory => {770 .memory => {
791 const memories_len, pos = readLeb(u32, bytes, pos);771 const memories_len = try br.takeLeb128(u32);
792 for (try wasm.object_memories.addManyAsSlice(gpa, memories_len)) |*memory| {772 for (try wasm.object_memories.addManyAsSlice(gpa, memories_len)) |*memory| {
793 const limits, pos = readLimits(bytes, pos);773 const limits = try readLimits(br);
794 memory.* = .{774 memory.* = .{
795 .name = .none,775 .name = .none,
796 .flags = .{776 .flags = .{
...@@ -807,14 +787,17 @@ pub fn parse(...@@ -807,14 +787,17 @@ pub fn parse(
807 return diags.failParse(path, "object has more than one global section", .{});787 return diags.failParse(path, "object has more than one global section", .{});
808 global_section_index = section_index;788 global_section_index = section_index;
809789
810 const section_start = pos;790 const section_start = br.seek;
811 const globals_len, pos = readLeb(u32, bytes, pos);791 const globals_len = try br.takeLeb128(u32);
812 for (try wasm.object_globals.addManyAsSlice(gpa, globals_len)) |*global| {792 for (try wasm.object_globals.addManyAsSlice(gpa, globals_len)) |*global| {
813 const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);793 const valtype = try br.takeEnum(std.wasm.Valtype, .little);
814 const mutable = bytes[pos] == 0x01;794 const mutable = switch (try br.takeByte()) {
815 pos += 1;795 0 => false,
816 const init_start = pos;796 1 => true,
817 const expr, pos = try readInit(wasm, bytes, pos);797 else => return error.InvalidMutability,
798 };
799 const init_start = br.seek;
800 const expr = try readInit(wasm, br);
818 global.* = .{801 global.* = .{
819 .name = .none,802 .name = .none,
820 .flags = .{803 .flags = .{
...@@ -826,20 +809,19 @@ pub fn parse(...@@ -826,20 +809,19 @@ pub fn parse(
826 .expr = expr,809 .expr = expr,
827 .object_index = object_index,810 .object_index = object_index,
828 .offset = @intCast(init_start - section_start),811 .offset = @intCast(init_start - section_start),
829 .size = @intCast(pos - init_start),812 .size = @intCast(br.seek - init_start),
830 };813 };
831 }814 }
832 },815 },
833 .@"export" => {816 .@"export" => {
834 const exports_len, pos = readLeb(u32, bytes, pos);817 const exports_len = try br.takeLeb128(u32);
835 // Read into scratch space, and then later add this data as if818 // Read into scratch space, and then later add this data as if
836 // it were extra symbol table entries, but allow merging with819 // it were extra symbol table entries, but allow merging with
837 // existing symbol table data if the name matches.820 // existing symbol table data if the name matches.
838 for (try ss.exports.addManyAsSlice(gpa, exports_len)) |*exp| {821 for (try ss.exports.addManyAsSlice(gpa, exports_len)) |*exp| {
839 const name, pos = readBytes(bytes, pos);822 const name = try br.take(try br.takeLeb128(u32));
840 const kind: std.wasm.ExternalKind = @enumFromInt(bytes[pos]);823 const kind = try br.takeEnum(std.wasm.ExternalKind, .little);
841 pos += 1;824 const index = try br.takeLeb128(u32);
842 const index, pos = readLeb(u32, bytes, pos);
843 exp.* = .{825 exp.* = .{
844 .name = try wasm.internString(name),826 .name = try wasm.internString(name),
845 .pointee = switch (kind) {827 .pointee = switch (kind) {
...@@ -852,25 +834,24 @@ pub fn parse(...@@ -852,25 +834,24 @@ pub fn parse(
852 }834 }
853 },835 },
854 .start => {836 .start => {
855 const index, pos = readLeb(u32, bytes, pos);837 const index = try br.takeLeb128(u32);
856 start_function = @enumFromInt(functions_start + index);838 start_function = @enumFromInt(functions_start + index);
857 },839 },
858 .element => {840 .element => {
859 log.warn("unimplemented: element section in {} {?s}", .{ path, archive_member_name });841 log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name });
860 pos = section_end;842 br.seek = section_end;
861 },843 },
862 .code => {844 .code => {
863 if (code_section_index != null)845 if (code_section_index != null)
864 return diags.failParse(path, "object has more than one code section", .{});846 return diags.failParse(path, "object has more than one code section", .{});
865 code_section_index = section_index;847 code_section_index = section_index;
866848
867 const start = pos;849 const start = br.seek;
868 const count, pos = readLeb(u32, bytes, pos);850 const count = try br.takeLeb128(u32);
869 for (try wasm.object_functions.addManyAsSlice(gpa, count)) |*elem| {851 for (try wasm.object_functions.addManyAsSlice(gpa, count)) |*elem| {
870 const code_len, pos = readLeb(u32, bytes, pos);852 const code_len = try br.takeLeb128(u32);
871 const offset: u32 = @intCast(pos - start);853 const offset: u32 = @intCast(br.seek - start);
872 const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..code_len]);854 const payload = try wasm.addRelocatableDataPayload(try br.take(code_len));
873 pos += code_len;
874 elem.* = .{855 elem.* = .{
875 .flags = .{}, // populated from symbol table856 .flags = .{}, // populated from symbol table
876 .name = .none, // populated from symbol table857 .name = .none, // populated from symbol table
...@@ -886,20 +867,19 @@ pub fn parse(...@@ -886,20 +867,19 @@ pub fn parse(
886 return diags.failParse(path, "object has more than one data section", .{});867 return diags.failParse(path, "object has more than one data section", .{});
887 data_section_index = section_index;868 data_section_index = section_index;
888869
889 const section_start = pos;870 const section_start = br.seek;
890 const count, pos = readLeb(u32, bytes, pos);871 const count = try br.takeLeb128(u32);
891 for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| {872 for (try wasm.object_data_segments.addManyAsSlice(gpa, count)) |*elem| {
892 const flags, pos = readEnum(DataSegmentFlags, bytes, pos);873 const flags: DataSegmentFlags = @enumFromInt(try br.takeLeb128(u32));
893 if (flags == .active_memidx) {874 if (flags == .active_memidx) {
894 const memidx, pos = readLeb(u32, bytes, pos);875 const memidx = try br.takeLeb128(u32);
895 if (memidx != 0) return diags.failParse(path, "data section uses mem index {d}", .{memidx});876 if (memidx != 0) return diags.failParse(path, "data section uses mem index {d}", .{memidx});
896 }877 }
897 //const expr, pos = if (flags != .passive) try readInit(wasm, bytes, pos) else .{ .none, pos };878 //const expr = if (flags != .passive) try readInit(wasm, br) else .none;
898 if (flags != .passive) pos = try skipInit(bytes, pos);879 if (flags != .passive) try skipInit(br);
899 const data_len, pos = readLeb(u32, bytes, pos);880 const data_len = try br.takeLeb128(u32);
900 const segment_start = pos;881 const segment_start = br.seek;
901 const payload = try wasm.addRelocatableDataPayload(bytes[pos..][0..data_len]);882 const payload = try wasm.addRelocatableDataPayload(try br.take(data_len));
902 pos += data_len;
903 elem.* = .{883 elem.* = .{
904 .payload = payload,884 .payload = payload,
905 .name = .none, // Populated from segment_info885 .name = .none, // Populated from segment_info
...@@ -911,10 +891,10 @@ pub fn parse(...@@ -911,10 +891,10 @@ pub fn parse(
911 };891 };
912 }892 }
913 },893 },
914 else => pos = section_end,894 else => br.seek = section_end,
915 }895 }
916 if (pos != section_end) return error.MalformedSection;896 if (br.seek != section_end) return error.MalformedSection;
917 }897 } else |_| {}
918 if (!saw_linking_section) return error.MissingLinkingSection;898 if (!saw_linking_section) return error.MissingLinkingSection;
919899
920 const cpu = comp.root_mod.resolved_target.result.cpu;900 const cpu = comp.root_mod.resolved_target.result.cpu;
...@@ -984,10 +964,10 @@ pub fn parse(...@@ -984,10 +964,10 @@ pub fn parse(
984 if (gop.value_ptr.type != fn_ty_index) {964 if (gop.value_ptr.type != fn_ty_index) {
985 var err = try diags.addErrorWithNotes(2);965 var err = try diags.addErrorWithNotes(2);
986 try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)});966 try err.addMsg("symbol '{s}' mismatching function signatures", .{name.slice(wasm)});
987 gop.value_ptr.source_location.addNote(&err, "imported as {} here", .{967 gop.value_ptr.source_location.addNote(&err, "imported as {f} here", .{
988 gop.value_ptr.type.fmt(wasm),968 gop.value_ptr.type.fmt(wasm),
989 });969 });
990 source_location.addNote(&err, "imported as {} here", .{fn_ty_index.fmt(wasm)});970 source_location.addNote(&err, "imported as {f} here", .{fn_ty_index.fmt(wasm)});
991 continue;971 continue;
992 }972 }
993 if (gop.value_ptr.module_name != ptr.module_name.toOptional()) {973 if (gop.value_ptr.module_name != ptr.module_name.toOptional()) {
...@@ -1155,11 +1135,11 @@ pub fn parse(...@@ -1155,11 +1135,11 @@ pub fn parse(
1155 if (gop.value_ptr.type != ptr.type_index) {1135 if (gop.value_ptr.type != ptr.type_index) {
1156 var err = try diags.addErrorWithNotes(2);1136 var err = try diags.addErrorWithNotes(2);
1157 try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)});1137 try err.addMsg("function signature mismatch: {s}", .{name.slice(wasm)});
1158 gop.value_ptr.source_location.addNote(&err, "exported as {} here", .{1138 gop.value_ptr.source_location.addNote(&err, "exported as {f} here", .{
1159 ptr.type_index.fmt(wasm),1139 ptr.type_index.fmt(wasm),
1160 });1140 });
1161 const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported";1141 const word = if (gop.value_ptr.resolution == .unresolved) "imported" else "exported";
1162 source_location.addNote(&err, "{s} as {} here", .{ word, gop.value_ptr.type.fmt(wasm) });1142 source_location.addNote(&err, "{s} as {f} here", .{ word, gop.value_ptr.type.fmt(wasm) });
1163 continue;1143 continue;
1164 }1144 }
1165 if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {1145 if (gop.value_ptr.resolution == .unresolved or gop.value_ptr.flags.binding == .weak) {
...@@ -1176,8 +1156,8 @@ pub fn parse(...@@ -1176,8 +1156,8 @@ pub fn parse(
1176 }1156 }
1177 var err = try diags.addErrorWithNotes(2);1157 var err = try diags.addErrorWithNotes(2);
1178 try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});1158 try err.addMsg("symbol collision: {s}", .{name.slice(wasm)});
1179 gop.value_ptr.source_location.addNote(&err, "exported as {} here", .{ptr.type_index.fmt(wasm)});1159 gop.value_ptr.source_location.addNote(&err, "exported as {f} here", .{ptr.type_index.fmt(wasm)});
1180 source_location.addNote(&err, "exported as {} here", .{gop.value_ptr.type.fmt(wasm)});1160 source_location.addNote(&err, "exported as {f} here", .{gop.value_ptr.type.fmt(wasm)});
1181 continue;1161 continue;
1182 } else {1162 } else {
1183 gop.value_ptr.* = .{1163 gop.value_ptr.* = .{
...@@ -1422,27 +1402,21 @@ pub fn parse(...@@ -1422,27 +1402,21 @@ pub fn parse(
1422/// Based on the "features" custom section, parses it into a list of1402/// Based on the "features" custom section, parses it into a list of
1423/// features that tell the linker what features were enabled and may be mandatory1403/// features that tell the linker what features were enabled and may be mandatory
1424/// to be able to link.1404/// to be able to link.
1425fn parseFeatures(1405fn parseFeatures(wasm: *Wasm, br: *std.io.BufferedReader, path: Path) anyerror!Wasm.Feature.Set {
1426 wasm: *Wasm,
1427 bytes: []const u8,
1428 start_pos: usize,
1429 path: Path,
1430) error{ OutOfMemory, LinkFailure }!struct { Wasm.Feature.Set, usize } {
1431 const gpa = wasm.base.comp.gpa;1406 const gpa = wasm.base.comp.gpa;
1432 const diags = &wasm.base.comp.link_diags;1407 const diags = &wasm.base.comp.link_diags;
1433 const features_len, var pos = readLeb(u32, bytes, start_pos);1408 const features_len = try br.takeLeb128(u32);
1434 // This temporary allocation could be avoided by using the string_bytes buffer as a scratch space.1409 // This temporary allocation could be avoided by using the string_bytes buffer as a scratch space.
1435 const feature_buffer = try gpa.alloc(Wasm.Feature, features_len);1410 const feature_buffer = try gpa.alloc(Wasm.Feature, features_len);
1436 defer gpa.free(feature_buffer);1411 defer gpa.free(feature_buffer);
1437 for (feature_buffer) |*feature| {1412 for (feature_buffer) |*feature| {
1438 const prefix: Wasm.Feature.Prefix = switch (bytes[pos]) {1413 const prefix: Wasm.Feature.Prefix = switch (try br.takeByte()) {
1439 '-' => .@"-",1414 '-' => .@"-",
1440 '+' => .@"+",1415 '+' => .@"+",
1441 '=' => .@"=",1416 '=' => .@"=",
1442 else => |b| return diags.failParse(path, "invalid feature prefix: 0x{x}", .{b}),1417 else => |b| return diags.failParse(path, "invalid feature prefix: 0x{x}", .{b}),
1443 };1418 };
1444 pos += 1;1419 const name = try br.take(try br.takeLeb128(u32));
1445 const name, pos = readBytes(bytes, pos);
1446 const tag = std.meta.stringToEnum(Wasm.Feature.Tag, name) orelse {1420 const tag = std.meta.stringToEnum(Wasm.Feature.Tag, name) orelse {
1447 return diags.failParse(path, "unrecognized wasm feature in object: {s}", .{name});1421 return diags.failParse(path, "unrecognized wasm feature in object: {s}", .{name});
1448 };1422 };
...@@ -1453,68 +1427,34 @@ fn parseFeatures(...@@ -1453,68 +1427,34 @@ fn parseFeatures(
1453 }1427 }
1454 std.mem.sortUnstable(Wasm.Feature, feature_buffer, {}, Wasm.Feature.lessThan);1428 std.mem.sortUnstable(Wasm.Feature, feature_buffer, {}, Wasm.Feature.lessThan);
14551429
1456 return .{1430 return .fromString(try wasm.internString(@ptrCast(feature_buffer)));
1457 .fromString(try wasm.internString(@ptrCast(feature_buffer))),
1458 pos,
1459 };
1460}1431}
14611432
1462fn readLeb(comptime T: type, bytes: []const u8, pos: usize) struct { T, usize } {1433fn readLimits(br: *std.io.BufferedReader) anyerror!std.wasm.Limits {
1463 var fbr: std.io.FixedBufferStream = .{ .buffer = bytes[pos..] };1434 const flags: std.wasm.Limits.Flags = @bitCast(try br.takeByte());
1435 const min = try br.takeLeb128(u32);
1436 const max = if (flags.has_max) try br.takeLeb128(u32) else 0;
1464 return .{1437 return .{
1465 switch (@typeInfo(T).int.signedness) {
1466 .signed => std.leb.readIleb128(T, fbr.reader()) catch unreachable,
1467 .unsigned => std.leb.readUleb128(T, fbr.reader()) catch unreachable,
1468 },
1469 pos + fbr.pos,
1470 };
1471}
1472
1473fn readBytes(bytes: []const u8, start_pos: usize) struct { []const u8, usize } {
1474 const len, const pos = readLeb(u32, bytes, start_pos);
1475 return .{
1476 bytes[pos..][0..len],
1477 pos + len,
1478 };
1479}
1480
1481fn readEnum(comptime T: type, bytes: []const u8, pos: usize) struct { T, usize } {
1482 const Tag = @typeInfo(T).@"enum".tag_type;
1483 const int, const new_pos = readLeb(Tag, bytes, pos);
1484 return .{ @enumFromInt(int), new_pos };
1485}
1486
1487fn readLimits(bytes: []const u8, start_pos: usize) struct { std.wasm.Limits, usize } {
1488 const flags: std.wasm.Limits.Flags = @bitCast(bytes[start_pos]);
1489 const min, const max_pos = readLeb(u32, bytes, start_pos + 1);
1490 const max, const end_pos = if (flags.has_max) readLeb(u32, bytes, max_pos) else .{ 0, max_pos };
1491 return .{ .{
1492 .flags = flags,1438 .flags = flags,
1493 .min = min,1439 .min = min,
1494 .max = max,1440 .max = max,
1495 }, end_pos };1441 };
1496}1442}
14971443
1498fn readInit(wasm: *Wasm, bytes: []const u8, pos: usize) !struct { Wasm.Expr, usize } {1444fn readInit(wasm: *Wasm, br: *std.io.BufferedReader) anyerror!Wasm.Expr {
1499 const end_pos = try skipInit(bytes, pos); // one after the end opcode1445 const start = br.seek;
1500 return .{ try wasm.addExpr(bytes[pos..end_pos]), end_pos };1446 try skipInit(br); // one after the end opcode
1447 return wasm.addExpr(br.storageBuffer()[start..br.seek]);
1501}1448}
15021449
1503pub fn exprEndPos(bytes: []const u8, pos: usize) error{InvalidInitOpcode}!usize {1450pub fn skipInit(br: *std.io.BufferedReader) anyerror!void {
1504 const opcode = bytes[pos];1451 switch (try br.takeEnum(std.wasm.Opcode, .little)) {
1505 return switch (@as(std.wasm.Opcode, @enumFromInt(opcode))) {1452 .i32_const => _ = try br.takeLeb128(i32),
1506 .i32_const => readLeb(i32, bytes, pos + 1)[1],1453 .i64_const => _ = try br.takeLeb128(i64),
1507 .i64_const => readLeb(i64, bytes, pos + 1)[1],1454 .f32_const => try br.discard(5),
1508 .f32_const => pos + 5,1455 .f64_const => try br.discard(9),
1509 .f64_const => pos + 9,1456 .global_get => _ = try br.takeLeb128(u32),
1510 .global_get => readLeb(u32, bytes, pos + 1)[1],
1511 else => return error.InvalidInitOpcode,1457 else => return error.InvalidInitOpcode,
1512 };1458 }
1513}1459 if (try br.takeEnum(std.wasm.Opcode, .little) != .end) return error.InitExprMissingEnd;
1514
1515fn skipInit(bytes: []const u8, pos: usize) !usize {
1516 const end_pos = try exprEndPos(bytes, pos);
1517 const op, const final_pos = readEnum(std.wasm.Opcode, bytes, end_pos);
1518 if (op != .end) return error.InitExprMissingEnd;
1519 return final_pos;
1520}1460}
src/link/aarch64.zig+3-3
...@@ -4,7 +4,7 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {...@@ -4,7 +4,7 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
4}4}
55
6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
7 var inst = Instruction{7 var inst: Instruction = .{
8 .add_subtract_immediate = mem.bytesToValue(@FieldType(8 .add_subtract_immediate = mem.bytesToValue(@FieldType(
9 Instruction,9 Instruction,
10 @tagName(Instruction.add_subtract_immediate),10 @tagName(Instruction.add_subtract_immediate),
...@@ -33,7 +33,7 @@ pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i21 {...@@ -33,7 +33,7 @@ pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i21 {
33}33}
3434
35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
36 var inst = Instruction{36 var inst: Instruction = .{
37 .pc_relative_address = mem.bytesToValue(@FieldType(37 .pc_relative_address = mem.bytesToValue(@FieldType(
38 Instruction,38 Instruction,
39 @tagName(Instruction.pc_relative_address),39 @tagName(Instruction.pc_relative_address),
...@@ -45,7 +45,7 @@ pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {...@@ -45,7 +45,7 @@ pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
45}45}
4646
47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
48 var inst = Instruction{48 var inst: Instruction = .{
49 .unconditional_branch_immediate = mem.bytesToValue(@FieldType(49 .unconditional_branch_immediate = mem.bytesToValue(@FieldType(
50 Instruction,50 Instruction,
51 @tagName(Instruction.unconditional_branch_immediate),51 @tagName(Instruction.unconditional_branch_immediate),
src/link/riscv.zig+22-24
...@@ -1,52 +1,50 @@...@@ -1,52 +1,50 @@
1pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytype) void {1pub fn writeSetSub6(comptime op: enum { set, sub }, addend: anytype, bw: *std.io.BufferedWriter) anyerror!void {
2 const mask: u8 = 0b11_000000;2 const mask: u8 = 0b11_000000;
3 const actual: i8 = @truncate(addend);3 const actual: i8 = @truncate(addend);
4 var value: u8 = mem.readInt(u8, code, .little);4 const old_value = (try bw.writableSlice(1))[0];
5 switch (op) {5 const new_value = (old_value & mask) | (@as(u8, switch (op) {
6 .set => value = (value & mask) | @as(u8, @bitCast(actual & ~mask)),6 .set => @bitCast(actual),
7 .sub => value = (value & mask) | (@as(u8, @bitCast(@as(i8, @bitCast(value)) -| actual)) & ~mask),7 .sub => @bitCast(@as(i8, @bitCast(old_value)) -| actual),
8 }8 }) & ~mask);
9 mem.writeInt(u8, code, value, .little);9 try bw.writeByte(new_value);
10}10}
1111
12pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void {12pub fn writeSetSubUleb(comptime op: enum { set, sub }, addend: i64, bw: *std.io.BufferedWriter) anyerror!void {
13 switch (op) {13 switch (op) {
14 .set => try overwriteUleb(stream, @intCast(addend)),14 .set => try overwriteUleb(@intCast(addend), bw),
15 .sub => {15 .sub => {
16 const position = try stream.getPos();16 var br: std.io.BufferedReader = undefined;
17 const value: u64 = try std.leb.readUleb128(u64, stream.reader());17 br.initFixed(try bw.writableSlice(1));
18 try stream.seekTo(position);18 const old_value = try br.takeLeb128(u64);
19 try overwriteUleb(stream, value -% @as(u64, @intCast(addend)));19 try overwriteUleb(old_value -% @as(u64, @intCast(addend)), bw);
20 },20 },
21 }21 }
22}22}
2323
24fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void {24fn overwriteUleb(new_value: u64, bw: *std.io.BufferedWriter) anyerror!void {
25 var value: u64 = addend;25 var value: u64 = new_value;
26 const writer = stream.writer();
27
28 while (true) {26 while (true) {
29 const byte = stream.buffer[stream.pos];27 const byte = (try bw.writableSlice(1))[0];
28 try bw.writeByte((byte & 0x80) | @as(u7, @truncate(value)));
30 if (byte & 0x80 == 0) break;29 if (byte & 0x80 == 0) break;
31 try writer.writeByte(0x80 | @as(u8, @truncate(value & 0x7f)));
32 value >>= 7;30 value >>= 7;
33 }31 }
34 stream.buffer[stream.pos] = @truncate(value & 0x7f);
35}32}
3633
37pub fn writeAddend(34pub fn writeAddend(
38 comptime Int: type,35 comptime Int: type,
39 comptime op: enum { add, sub },36 comptime op: enum { add, sub },
40 code: *[@typeInfo(Int).int.bits / 8]u8,
41 value: anytype,37 value: anytype,
42) void {38 bw: *std.io.BufferedWriter,
43 var V: Int = mem.readInt(Int, code, .little);39) anyerror!void {
40 const n = @divExact(@bitSizeOf(Int), 8);
41 var V: Int = mem.readInt(Int, (try bw.writableSlice(n))[0..n], .little);
44 const addend: Int = @truncate(value);42 const addend: Int = @truncate(value);
45 switch (op) {43 switch (op) {
46 .add => V +|= addend, // TODO: I think saturating arithmetic is correct here44 .add => V +|= addend, // TODO: I think saturating arithmetic is correct here
47 .sub => V -|= addend,45 .sub => V -|= addend,
48 }46 }
49 mem.writeInt(Int, code, V, .little);47 try bw.writeInt(Int, V, .little);
50}48}
5149
52pub fn writeInstU(code: *[4]u8, value: u32) void {50pub fn writeInstU(code: *[4]u8, value: u32) void {
src/link/table_section.zig+3-9
...@@ -39,17 +39,11 @@ pub fn TableSection(comptime Entry: type) type {...@@ -39,17 +39,11 @@ pub fn TableSection(comptime Entry: type) type {
39 return self.entries.items.len;39 return self.entries.items.len;
40 }40 }
4141
42 pub fn format(42 pub fn format(self: Self, bw: *std.io.BufferedWriter, comptime unused_format_string: []const u8) anyerror!void {
43 self: Self,
44 comptime unused_format_string: []const u8,
45 options: std.fmt.FormatOptions,
46 writer: anytype,
47 ) !void {
48 _ = options;
49 comptime assert(unused_format_string.len == 0);43 comptime assert(unused_format_string.len == 0);
50 try writer.writeAll("TableSection:\n");44 try bw.writeAll("TableSection:\n");
51 for (self.entries.items, 0..) |entry, i| {45 for (self.entries.items, 0..) |entry, i| {
52 try writer.print(" {d} => {}\n", .{ i, entry });46 try bw.print(" {d} => {}\n", .{ i, entry });
53 }47 }
54 }48 }
5549
src/main.zig+43-64
...@@ -66,7 +66,7 @@ pub fn wasi_cwd() std.os.wasi.fd_t {...@@ -66,7 +66,7 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
66const fatal = std.process.fatal;66const fatal = std.process.fatal;
6767
68/// This can be global since stdout is a singleton.68/// This can be global since stdout is a singleton.
69var stdout_buffer: [4096]u8 = undefined;69var stdio_buffer: [4096]u8 = undefined;
7070
71/// Shaming all the locations that inappropriately use an O(N) search algorithm.71/// Shaming all the locations that inappropriately use an O(N) search algorithm.
72/// Please delete this and fix the compilation errors!72/// Please delete this and fix the compilation errors!
...@@ -5477,7 +5477,7 @@ fn jitCmd(...@@ -5477,7 +5477,7 @@ fn jitCmd(
5477 defer comp.destroy();5477 defer comp.destroy();
54785478
5479 if (options.server) {5479 if (options.server) {
5480 var server = std.zig.Server{5480 var server: std.zig.Server = .{
5481 .out = fs.File.stdout(),5481 .out = fs.File.stdout(),
5482 .in = undefined, // won't be receiving messages5482 .in = undefined, // won't be receiving messages
5483 .receive_fifo = undefined, // won't be receiving messages5483 .receive_fifo = undefined, // won't be receiving messages
...@@ -5672,7 +5672,7 @@ const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true,...@@ -5672,7 +5672,7 @@ const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true,
5672/// Initialize the arguments from a Response File. "*.rsp"5672/// Initialize the arguments from a Response File. "*.rsp"
5673fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile {5673fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile {
5674 const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit5674 const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit
5675 const cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes);5675 const cmd_line = try fs.cwd().readFileAlloc(resp_file_path, allocator, .limited(max_bytes));
5676 errdefer allocator.free(cmd_line);5676 errdefer allocator.free(cmd_line);
56775677
5678 return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line);5678 return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line);
...@@ -6061,11 +6061,7 @@ fn cmdAstCheck(...@@ -6061,11 +6061,7 @@ fn cmdAstCheck(
60616061
6062 const tree = try Ast.parse(arena, source, mode);6062 const tree = try Ast.parse(arena, source, mode);
60636063
6064 var bw: std.io.BufferedWriter = .{6064 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6065 .unbuffered_writer = fs.File.stdout().writer(),
6066 .buffer = &stdout_buffer,
6067 };
6068
6069 switch (mode) {6065 switch (mode) {
6070 .zig => {6066 .zig => {
6071 const zir = try AstGen.generate(arena, tree);6067 const zir = try AstGen.generate(arena, tree);
...@@ -6109,7 +6105,7 @@ fn cmdAstCheck(...@@ -6109,7 +6105,7 @@ fn cmdAstCheck(
6109 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6105 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6110 zir.string_bytes.len * @sizeOf(u8);6106 zir.string_bytes.len * @sizeOf(u8);
6111 // zig fmt: off6107 // zig fmt: off
6112 try bw.print(6108 try stdout_bw.print(
6113 \\# Source bytes: {Bi}6109 \\# Source bytes: {Bi}
6114 \\# Tokens: {} ({Bi})6110 \\# Tokens: {} ({Bi})
6115 \\# AST Nodes: {} ({Bi})6111 \\# AST Nodes: {} ({Bi})
...@@ -6130,8 +6126,8 @@ fn cmdAstCheck(...@@ -6130,8 +6126,8 @@ fn cmdAstCheck(
6130 // zig fmt: on6126 // zig fmt: on
6131 }6127 }
61326128
6133 try @import("print_zir.zig").renderAsText(arena, tree, zir, &bw);6129 try @import("print_zir.zig").renderAsText(arena, tree, zir, &stdout_bw);
6134 try bw.flush();6130 try stdout_bw.flush();
61356131
6136 if (zir.hasCompileErrors()) {6132 if (zir.hasCompileErrors()) {
6137 process.exit(1);6133 process.exit(1);
...@@ -6158,8 +6154,8 @@ fn cmdAstCheck(...@@ -6158,8 +6154,8 @@ fn cmdAstCheck(
6158 fatal("-t option only available in builds of zig with debug extensions", .{});6154 fatal("-t option only available in builds of zig with debug extensions", .{});
6159 }6155 }
61606156
6161 try @import("print_zoir.zig").renderToWriter(zoir, arena, &bw);6157 try @import("print_zoir.zig").renderToWriter(zoir, arena, &stdout_bw);
6162 try bw.flush();6158 try stdout_bw.flush();
6163 return cleanExit();6159 return cleanExit();
6164 },6160 },
6165 }6161 }
...@@ -6187,8 +6183,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {...@@ -6187,8 +6183,7 @@ fn cmdDetectCpu(args: []const []const u8) !void {
6187 const arg = args[i];6183 const arg = args[i];
6188 if (mem.startsWith(u8, arg, "-")) {6184 if (mem.startsWith(u8, arg, "-")) {
6189 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6185 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6190 const stdout = fs.File.stdout().writer();6186 try fs.File.stdout().writeAll(detect_cpu_usage);
6191 try stdout.writeAll(detect_cpu_usage);
6192 return cleanExit();6187 return cleanExit();
6193 } else if (mem.eql(u8, arg, "--llvm")) {6188 } else if (mem.eql(u8, arg, "--llvm")) {
6194 use_llvm = true;6189 use_llvm = true;
...@@ -6280,13 +6275,10 @@ fn detectNativeCpuWithLLVM(...@@ -6280,13 +6275,10 @@ fn detectNativeCpuWithLLVM(
6280}6275}
62816276
6282fn printCpu(cpu: std.Target.Cpu) !void {6277fn printCpu(cpu: std.Target.Cpu) !void {
6283 var bw: std.io.BufferedWriter = .{6278 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6284 .unbuffered_writer = fs.File.stdout().writer(),
6285 .buffer = &stdout_buffer,
6286 };
62876279
6288 if (cpu.model.llvm_name) |llvm_name| {6280 if (cpu.model.llvm_name) |llvm_name| {
6289 try bw.print("{s}\n", .{llvm_name});6281 try stdout_bw.print("{s}\n", .{llvm_name});
6290 }6282 }
62916283
6292 const all_features = cpu.arch.allFeaturesList();6284 const all_features = cpu.arch.allFeaturesList();
...@@ -6295,10 +6287,10 @@ fn printCpu(cpu: std.Target.Cpu) !void {...@@ -6295,10 +6287,10 @@ fn printCpu(cpu: std.Target.Cpu) !void {
6295 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);6287 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
6296 const is_enabled = cpu.features.isEnabled(index);6288 const is_enabled = cpu.features.isEnabled(index);
6297 const plus_or_minus = "-+"[@intFromBool(is_enabled)];6289 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
6298 try bw.print("{c}{s}\n", .{ plus_or_minus, llvm_name });6290 try stdout_bw.print("{c}{s}\n", .{ plus_or_minus, llvm_name });
6299 }6291 }
63006292
6301 try bw.flush();6293 try stdout_bw.flush();
6302}6294}
63036295
6304fn cmdDumpLlvmInts(6296fn cmdDumpLlvmInts(
...@@ -6331,16 +6323,13 @@ fn cmdDumpLlvmInts(...@@ -6331,16 +6323,13 @@ fn cmdDumpLlvmInts(
6331 const dl = tm.createTargetDataLayout();6323 const dl = tm.createTargetDataLayout();
6332 const context = llvm.Context.create();6324 const context = llvm.Context.create();
63336325
6334 var bw = io.bufferedWriter(fs.File.stdout().writer());6326 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6335 const stdout = bw.writer();
6336
6337 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {6327 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
6338 const int_type = context.intType(bits);6328 const int_type = context.intType(bits);
6339 const alignment = dl.abiAlignmentOfType(int_type);6329 const alignment = dl.abiAlignmentOfType(int_type);
6340 try stdout.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment });6330 try stdout_bw.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment });
6341 }6331 }
63426332 try stdout_bw.flush();
6343 try bw.flush();
63446333
6345 return cleanExit();6334 return cleanExit();
6346}6335}
...@@ -6363,11 +6352,7 @@ fn cmdDumpZir(...@@ -6363,11 +6352,7 @@ fn cmdDumpZir(
63636352
6364 const zir = try Zcu.loadZirCache(arena, f);6353 const zir = try Zcu.loadZirCache(arena, f);
63656354
6366 var bw: std.io.BufferedWriter = .{6355 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6367 .unbuffered_writer = fs.File.stdout().writer(),
6368 .buffer = &stdout_buffer,
6369 };
6370
6371 {6356 {
6372 const instruction_bytes = zir.instructions.len *6357 const instruction_bytes = zir.instructions.len *
6373 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include6358 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
...@@ -6377,7 +6362,7 @@ fn cmdDumpZir(...@@ -6377,7 +6362,7 @@ fn cmdDumpZir(
6377 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6362 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6378 zir.string_bytes.len * @sizeOf(u8);6363 zir.string_bytes.len * @sizeOf(u8);
6379 // zig fmt: off6364 // zig fmt: off
6380 try bw.print(6365 try stdout_bw.print(
6381 \\# Total ZIR bytes: {Bi}6366 \\# Total ZIR bytes: {Bi}
6382 \\# Instructions: {d} ({Bi})6367 \\# Instructions: {d} ({Bi})
6383 \\# String Table Bytes: {Bi}6368 \\# String Table Bytes: {Bi}
...@@ -6392,8 +6377,8 @@ fn cmdDumpZir(...@@ -6392,8 +6377,8 @@ fn cmdDumpZir(
6392 // zig fmt: on6377 // zig fmt: on
6393 }6378 }
63946379
6395 try @import("print_zir.zig").renderAsText(arena, null, zir, &bw);6380 try @import("print_zir.zig").renderAsText(arena, null, zir, &stdout_bw);
6396 try bw.flush();6381 try stdout_bw.flush();
6397}6382}
63986383
6399/// This is only enabled for debug builds.6384/// This is only enabled for debug builds.
...@@ -6451,21 +6436,18 @@ fn cmdChangelist(...@@ -6451,21 +6436,18 @@ fn cmdChangelist(
6451 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6436 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6452 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);6437 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
64536438
6454 var bw: std.io.BufferedWriter = .{6439 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6455 .unbuffered_writer = fs.File.stdout().writer(),
6456 .buffer = &stdout_buffer,
6457 };
6458 {6440 {
6459 try bw.print("Instruction mappings:\n", .{});6441 try stdout_bw.print("Instruction mappings:\n", .{});
6460 var it = inst_map.iterator();6442 var it = inst_map.iterator();
6461 while (it.next()) |entry| {6443 while (it.next()) |entry| {
6462 try bw.print(" %{d} => %{d}\n", .{6444 try stdout_bw.print(" %{d} => %{d}\n", .{
6463 @intFromEnum(entry.key_ptr.*),6445 @intFromEnum(entry.key_ptr.*),
6464 @intFromEnum(entry.value_ptr.*),6446 @intFromEnum(entry.value_ptr.*),
6465 });6447 });
6466 }6448 }
6467 }6449 }
6468 try bw.flush();6450 try stdout_bw.flush();
6469}6451}
64706452
6471fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {6453fn eatIntPrefix(arg: []const u8, base: u8) []const u8 {
...@@ -6800,8 +6782,7 @@ fn cmdFetch(...@@ -6800,8 +6782,7 @@ fn cmdFetch(
6800 const arg = args[i];6782 const arg = args[i];
6801 if (mem.startsWith(u8, arg, "-")) {6783 if (mem.startsWith(u8, arg, "-")) {
6802 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {6784 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6803 const stdout = fs.File.stdout().writer();6785 try fs.File.stdout().writeAll(usage_fetch);
6804 try stdout.writeAll(usage_fetch);
6805 return cleanExit();6786 return cleanExit();
6806 } else if (mem.eql(u8, arg, "--global-cache-dir")) {6787 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
6807 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});6788 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
...@@ -6914,7 +6895,9 @@ fn cmdFetch(...@@ -6914,7 +6895,9 @@ fn cmdFetch(
69146895
6915 const name = switch (save) {6896 const name = switch (save) {
6916 .no => {6897 .no => {
6917 try fs.File.stdout().writer().print("{s}\n", .{package_hash_slice});6898 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
6899 try stdout_bw.print("{s}\n", .{package_hash_slice});
6900 try stdout_bw.flush();
6918 return cleanExit();6901 return cleanExit();
6919 },6902 },
6920 .yes, .exact => |name| name: {6903 .yes, .exact => |name| name: {
...@@ -6950,7 +6933,7 @@ fn cmdFetch(...@@ -6950,7 +6933,7 @@ fn cmdFetch(
6950 var saved_path_or_url = path_or_url;6933 var saved_path_or_url = path_or_url;
69516934
6952 if (fetch.latest_commit) |latest_commit| resolved: {6935 if (fetch.latest_commit) |latest_commit| resolved: {
6953 const latest_commit_hex = try std.fmt.allocPrint(arena, "{}", .{latest_commit});6936 const latest_commit_hex = try std.fmt.allocPrint(arena, "{f}", .{latest_commit});
69546937
6955 var uri = try std.Uri.parse(path_or_url);6938 var uri = try std.Uri.parse(path_or_url);
69566939
...@@ -6963,7 +6946,7 @@ fn cmdFetch(...@@ -6963,7 +6946,7 @@ fn cmdFetch(
6963 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });6946 std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex });
69646947
6965 // include the original refspec in a query parameter, could be used to check for updates6948 // include the original refspec in a query parameter, could be used to check for updates
6966 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={%}", .{fragment}) };6949 uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f%}", .{fragment}) };
6967 } else {6950 } else {
6968 std.log.info("resolved to commit {s}", .{latest_commit_hex});6951 std.log.info("resolved to commit {s}", .{latest_commit_hex});
6969 }6952 }
...@@ -6972,22 +6955,22 @@ fn cmdFetch(...@@ -6972,22 +6955,22 @@ fn cmdFetch(
6972 uri.fragment = .{ .raw = latest_commit_hex };6955 uri.fragment = .{ .raw = latest_commit_hex };
69736956
6974 switch (save) {6957 switch (save) {
6975 .yes => saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri}),6958 .yes => saved_path_or_url = try std.fmt.allocPrint(arena, "{f}", .{uri}),
6976 .no, .exact => {}, // keep the original URL6959 .no, .exact => {}, // keep the original URL
6977 }6960 }
6978 }6961 }
69796962
6980 const new_node_init = try std.fmt.allocPrint(arena,6963 const new_node_init = try std.fmt.allocPrint(arena,
6981 \\.{{6964 \\.{{
6982 \\ .url = "{}",6965 \\ .url = "{f}",
6983 \\ .hash = "{}",6966 \\ .hash = "{f}",
6984 \\ }}6967 \\ }}
6985 , .{6968 , .{
6986 std.zig.fmtEscapes(saved_path_or_url),6969 std.zig.fmtEscapes(saved_path_or_url),
6987 std.zig.fmtEscapes(package_hash_slice),6970 std.zig.fmtEscapes(package_hash_slice),
6988 });6971 });
69896972
6990 const new_node_text = try std.fmt.allocPrint(arena, ".{p_} = {s},\n", .{6973 const new_node_text = try std.fmt.allocPrint(arena, ".{fp_} = {s},\n", .{
6991 std.zig.fmtId(name), new_node_init,6974 std.zig.fmtId(name), new_node_init,
6992 });6975 });
69936976
...@@ -7014,12 +6997,12 @@ fn cmdFetch(...@@ -7014,12 +6997,12 @@ fn cmdFetch(
70146997
7015 const location_replace = try std.fmt.allocPrint(6998 const location_replace = try std.fmt.allocPrint(
7016 arena,6999 arena,
7017 "\"{}\"",7000 "\"{f}\"",
7018 .{std.zig.fmtEscapes(saved_path_or_url)},7001 .{std.zig.fmtEscapes(saved_path_or_url)},
7019 );7002 );
7020 const hash_replace = try std.fmt.allocPrint(7003 const hash_replace = try std.fmt.allocPrint(
7021 arena,7004 arena,
7022 "\"{}\"",7005 "\"{f}\"",
7023 .{std.zig.fmtEscapes(package_hash_slice)},7006 .{std.zig.fmtEscapes(package_hash_slice)},
7024 );7007 );
70257008
...@@ -7047,15 +7030,11 @@ fn cmdFetch(...@@ -7047,15 +7030,11 @@ fn cmdFetch(
7047 fatal("unable to create {s} file: {s}", .{ Package.Manifest.basename, err });7030 fatal("unable to create {s} file: {s}", .{ Package.Manifest.basename, err });
7048 };7031 };
7049 defer file.close();7032 defer file.close();
7050 var buffer: [4096]u8 = undefined;7033 var stdout_bw = fs.File.stdout().writer().buffered(&stdio_buffer);
7051 var bw: std.io.BufferedWriter = .{7034 ast.render(gpa, &stdout_bw, fixups) catch |err| fatal("failed to render AST to {s}: {s}", .{
7052 .unbuffered_writer = file.writer(),
7053 .buffer = &buffer,
7054 };
7055 ast.render(gpa, &bw, fixups) catch |err| fatal("failed to render AST to {s}: {s}", .{
7056 Package.Manifest.basename, err,7035 Package.Manifest.basename, err,
7057 });7036 });
7058 bw.flush() catch |err| fatal("failed to flush {s}: {s}", .{ Package.Manifest.basename, err });7037 stdout_bw.flush() catch |err| fatal("failed to flush {s}: {s}", .{ Package.Manifest.basename, err });
7059 return cleanExit();7038 return cleanExit();
7060}7039}
70617040
...@@ -7208,9 +7187,9 @@ fn loadManifest(...@@ -7208,9 +7187,9 @@ fn loadManifest(
7208) !struct { Package.Manifest, Ast } {7187) !struct { Package.Manifest, Ast } {
7209 const manifest_bytes = while (true) {7188 const manifest_bytes = while (true) {
7210 break options.dir.readFileAllocOptions(7189 break options.dir.readFileAllocOptions(
7211 arena,
7212 Package.Manifest.basename,7190 Package.Manifest.basename,
7213 Package.Manifest.max_bytes,7191 arena,
7192 .limited(Package.Manifest.max_bytes),
7214 null,7193 null,
7215 .@"1",7194 .@"1",
7216 0,7195 0,
...@@ -7287,7 +7266,7 @@ const Templates = struct {...@@ -7287,7 +7266,7 @@ const Templates = struct {
7287 }7266 }
72887267
7289 const max_bytes = 10 * 1024 * 1024;7268 const max_bytes = 10 * 1024 * 1024;
7290 const contents = templates.dir.readFileAlloc(arena, template_path, max_bytes) catch |err| {7269 const contents = templates.dir.readFileAlloc(template_path, arena, .limited(max_bytes)) catch |err| {
7291 fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) });7270 fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) });
7292 };7271 };
7293 templates.buffer.clearRetainingCapacity();7272 templates.buffer.clearRetainingCapacity();
src/print_targets.zig+4-4
...@@ -27,9 +27,9 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)...@@ -27,9 +27,9 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)
27 defer zig_lib_directory.handle.close();27 defer zig_lib_directory.handle.close();
2828
29 const abilists_contents = zig_lib_directory.handle.readFileAlloc(29 const abilists_contents = zig_lib_directory.handle.readFileAlloc(
30 arena,
31 glibc.abilists_path,30 glibc.abilists_path,
32 glibc.abilists_max_size,31 arena,
32 .limited(glibc.abilists_max_size),
33 ) catch |err| switch (err) {33 ) catch |err| switch (err) {
34 error.OutOfMemory => return error.OutOfMemory,34 error.OutOfMemory => return error.OutOfMemory,
35 else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),35 else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),
...@@ -37,7 +37,7 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)...@@ -37,7 +37,7 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)
3737
38 const glibc_abi = try glibc.loadMetaData(arena, abilists_contents);38 const glibc_abi = try glibc.loadMetaData(arena, abilists_contents);
3939
40 var sz = std.zon.stringify.serializer(output, .{});40 var sz: std.zon.stringify.Serializer = .{ .writer = output };
4141
42 {42 {
43 var root_obj = try sz.beginStruct(.{});43 var root_obj = try sz.beginStruct(.{});
...@@ -60,7 +60,7 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)...@@ -60,7 +60,7 @@ fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target)
60 {60 {
61 var glibc_obj = try root_obj.beginTupleField("glibc", .{});61 var glibc_obj = try root_obj.beginTupleField("glibc", .{});
62 for (glibc_abi.all_versions) |ver| {62 for (glibc_abi.all_versions) |ver| {
63 const tmp = try std.fmt.allocPrint(arena, "{}", .{ver});63 const tmp = try std.fmt.allocPrint(arena, "{f}", .{ver});
64 try glibc_obj.field(tmp, .{});64 try glibc_obj.field(tmp, .{});
65 }65 }
66 try glibc_obj.end();66 try glibc_obj.end();
src/print_value.zig+113-124
...@@ -20,16 +20,10 @@ pub const FormatContext = struct {...@@ -20,16 +20,10 @@ pub const FormatContext = struct {
20 depth: u8,20 depth: u8,
21};21};
2222
23pub fn formatSema(23pub fn formatSema(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
24 ctx: FormatContext,
25 comptime fmt: []const u8,
26 options: std.fmt.Options,
27 writer: *std.io.BufferedWriter,
28) anyerror!void {
29 _ = options;
30 const sema = ctx.opt_sema.?;24 const sema = ctx.opt_sema.?;
31 comptime std.debug.assert(fmt.len == 0);25 comptime std.debug.assert(fmt.len == 0);
32 return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) {26 return print(ctx.val, bw, ctx.depth, ctx.pt, sema) catch |err| switch (err) {
33 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function27 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
34 error.ComptimeBreak, error.ComptimeReturn => unreachable,28 error.ComptimeBreak, error.ComptimeReturn => unreachable,
35 error.AnalysisFail => unreachable, // TODO: re-evaluate when we use `sema` more fully29 error.AnalysisFail => unreachable, // TODO: re-evaluate when we use `sema` more fully
...@@ -37,16 +31,10 @@ pub fn formatSema(...@@ -37,16 +31,10 @@ pub fn formatSema(
37 };31 };
38}32}
3933
40pub fn format(34pub fn format(ctx: FormatContext, bw: *std.io.BufferedWriter, comptime fmt: []const u8) anyerror!void {
41 ctx: FormatContext,
42 comptime fmt: []const u8,
43 options: std.fmt.Options,
44 writer: *std.io.BufferedWriter,
45) anyerror!void {
46 _ = options;
47 std.debug.assert(ctx.opt_sema == null);35 std.debug.assert(ctx.opt_sema == null);
48 comptime std.debug.assert(fmt.len == 0);36 comptime std.debug.assert(fmt.len == 0);
49 return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) {37 return print(ctx.val, bw, ctx.depth, ctx.pt, null) catch |err| switch (err) {
50 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function38 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
51 error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable,39 error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable,
52 else => |e| return e,40 else => |e| return e,
...@@ -55,7 +43,7 @@ pub fn format(...@@ -55,7 +43,7 @@ pub fn format(
5543
56pub fn print(44pub fn print(
57 val: Value,45 val: Value,
58 writer: *std.io.BufferedWriter,46 bw: *std.io.BufferedWriter,
59 level: u8,47 level: u8,
60 pt: Zcu.PerThread,48 pt: Zcu.PerThread,
61 opt_sema: ?*Sema,49 opt_sema: ?*Sema,
...@@ -79,61 +67,62 @@ pub fn print(...@@ -79,61 +67,62 @@ pub fn print(
79 .func_type,67 .func_type,
80 .error_set_type,68 .error_set_type,
81 .inferred_error_set_type,69 .inferred_error_set_type,
82 => try Type.print(val.toType(), writer, pt),70 => try Type.print(val.toType(), bw, pt),
83 .undef => try writer.writeAll("undefined"),71 .undef => try bw.writeAll("undefined"),
84 .simple_value => |simple_value| switch (simple_value) {72 .simple_value => |simple_value| switch (simple_value) {
85 .void => try writer.writeAll("{}"),73 .void => try bw.writeAll("{}"),
86 .empty_tuple => try writer.writeAll(".{}"),74 .empty_tuple => try bw.writeAll(".{}"),
87 else => try writer.writeAll(@tagName(simple_value)),75 else => try bw.writeAll(@tagName(simple_value)),
88 },76 },
89 .variable => try writer.writeAll("(variable)"),77 .variable => try bw.writeAll("(variable)"),
90 .@"extern" => |e| try writer.print("(extern '{}')", .{e.name.fmt(ip)}),78 .@"extern" => |e| try bw.print("(extern '{f}')", .{e.name.fmt(ip)}),
91 .func => |func| try writer.print("(function '{}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),79 .func => |func| try bw.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),
92 .int => |int| switch (int.storage) {80 .int => |int| switch (int.storage) {
93 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),81 inline .u64, .i64 => |x| try bw.print("{d}", .{x}),
82 .big_int => |x| try bw.print("{f}", .{x}),
94 .lazy_align => |ty| if (opt_sema != null) {83 .lazy_align => |ty| if (opt_sema != null) {
95 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);84 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);
96 try writer.print("{}", .{a.toByteUnits() orelse 0});85 try bw.print("{}", .{a.toByteUnits() orelse 0});
97 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(pt)}),86 } else try bw.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
98 .lazy_size => |ty| if (opt_sema != null) {87 .lazy_size => |ty| if (opt_sema != null) {
99 const s = try Type.fromInterned(ty).abiSizeSema(pt);88 const s = try Type.fromInterned(ty).abiSizeSema(pt);
100 try writer.print("{}", .{s});89 try bw.print("{}", .{s});
101 } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(pt)}),90 } else try bw.print("@sizeOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
102 },91 },
103 .err => |err| try writer.print("error.{}", .{92 .err => |err| try bw.print("error.{f}", .{
104 err.name.fmt(ip),93 err.name.fmt(ip),
105 }),94 }),
106 .error_union => |error_union| switch (error_union.val) {95 .error_union => |error_union| switch (error_union.val) {
107 .err_name => |err_name| try writer.print("error.{}", .{96 .err_name => |err_name| try bw.print("error.{f}", .{
108 err_name.fmt(ip),97 err_name.fmt(ip),
109 }),98 }),
110 .payload => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),99 .payload => |payload| try print(Value.fromInterned(payload), bw, level, pt, opt_sema),
111 },100 },
112 .enum_literal => |enum_literal| try writer.print(".{}", .{101 .enum_literal => |enum_literal| try bw.print(".{f}", .{
113 enum_literal.fmt(ip),102 enum_literal.fmt(ip),
114 }),103 }),
115 .enum_tag => |enum_tag| {104 .enum_tag => |enum_tag| {
116 const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());105 const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());
117 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {106 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
118 return writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});107 return bw.print(".{fi}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
119 }108 }
120 if (level == 0) {109 if (level == 0) {
121 return writer.writeAll("@enumFromInt(...)");110 return bw.writeAll("@enumFromInt(...)");
122 }111 }
123 try writer.writeAll("@enumFromInt(");112 try bw.writeAll("@enumFromInt(");
124 try print(Value.fromInterned(enum_tag.int), writer, level - 1, pt, opt_sema);113 try print(Value.fromInterned(enum_tag.int), bw, level - 1, pt, opt_sema);
125 try writer.writeAll(")");114 try bw.writeAll(")");
126 },115 },
127 .empty_enum_value => try writer.writeAll("(empty enum value)"),116 .empty_enum_value => try bw.writeAll("(empty enum value)"),
128 .float => |float| switch (float.storage) {117 .float => |float| switch (float.storage) {
129 inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}),118 inline else => |x| try bw.print("{d}", .{@as(f64, @floatCast(x))}),
130 },119 },
131 .slice => |slice| {120 .slice => |slice| {
132 if (ip.isUndef(slice.ptr)) {121 if (ip.isUndef(slice.ptr)) {
133 if (slice.len == .zero_usize) {122 if (slice.len == .zero_usize) {
134 return writer.writeAll("&.{}");123 return bw.writeAll("&.{}");
135 }124 }
136 try print(.fromInterned(slice.ptr), writer, level - 1, pt, opt_sema);125 try print(.fromInterned(slice.ptr), bw, level - 1, pt, opt_sema);
137 } else {126 } else {
138 const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {127 const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {
139 .field, .arr_elem, .eu_payload, .opt_payload => unreachable,128 .field, .arr_elem, .eu_payload, .opt_payload => unreachable,
...@@ -144,15 +133,15 @@ pub fn print(...@@ -144,15 +133,15 @@ pub fn print(
144 // TODO: eventually we want to load the slice as an array with `sema`, but that's133 // TODO: eventually we want to load the slice as an array with `sema`, but that's
145 // currently not possible without e.g. triggering compile errors.134 // currently not possible without e.g. triggering compile errors.
146 }135 }
147 try printPtr(Value.fromInterned(slice.ptr), null, writer, level, pt, opt_sema);136 try printPtr(Value.fromInterned(slice.ptr), null, bw, level, pt, opt_sema);
148 }137 }
149 try writer.writeAll("[0..");138 try bw.writeAll("[0..");
150 if (level == 0) {139 if (level == 0) {
151 try writer.writeAll("(...)");140 try bw.writeAll("(...)");
152 } else {141 } else {
153 try print(Value.fromInterned(slice.len), writer, level - 1, pt, opt_sema);142 try print(Value.fromInterned(slice.len), bw, level - 1, pt, opt_sema);
154 }143 }
155 try writer.writeAll("]");144 try bw.writeAll("]");
156 },145 },
157 .ptr => {146 .ptr => {
158 const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) {147 const print_contents = switch (ip.getBackingAddrTag(val.toIntern()).?) {
...@@ -164,29 +153,29 @@ pub fn print(...@@ -164,29 +153,29 @@ pub fn print(
164 // TODO: eventually we want to load the pointer with `sema`, but that's153 // TODO: eventually we want to load the pointer with `sema`, but that's
165 // currently not possible without e.g. triggering compile errors.154 // currently not possible without e.g. triggering compile errors.
166 }155 }
167 try printPtr(val, .rvalue, writer, level, pt, opt_sema);156 try printPtr(val, .rvalue, bw, level, pt, opt_sema);
168 },157 },
169 .opt => |opt| switch (opt.val) {158 .opt => |opt| switch (opt.val) {
170 .none => try writer.writeAll("null"),159 .none => try bw.writeAll("null"),
171 else => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),160 else => |payload| try print(Value.fromInterned(payload), bw, level, pt, opt_sema),
172 },161 },
173 .aggregate => |aggregate| try printAggregate(val, aggregate, false, writer, level, pt, opt_sema),162 .aggregate => |aggregate| try printAggregate(val, aggregate, false, bw, level, pt, opt_sema),
174 .un => |un| {163 .un => |un| {
175 if (level == 0) {164 if (level == 0) {
176 try writer.writeAll(".{ ... }");165 try bw.writeAll(".{ ... }");
177 return;166 return;
178 }167 }
179 if (un.tag == .none) {168 if (un.tag == .none) {
180 const backing_ty = try val.typeOf(zcu).unionBackingType(pt);169 const backing_ty = try val.typeOf(zcu).unionBackingType(pt);
181 try writer.print("@bitCast(@as({}, ", .{backing_ty.fmt(pt)});170 try bw.print("@bitCast(@as({f}, ", .{backing_ty.fmt(pt)});
182 try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);171 try print(Value.fromInterned(un.val), bw, level - 1, pt, opt_sema);
183 try writer.writeAll("))");172 try bw.writeAll("))");
184 } else {173 } else {
185 try writer.writeAll(".{ ");174 try bw.writeAll(".{ ");
186 try print(Value.fromInterned(un.tag), writer, level - 1, pt, opt_sema);175 try print(Value.fromInterned(un.tag), bw, level - 1, pt, opt_sema);
187 try writer.writeAll(" = ");176 try bw.writeAll(" = ");
188 try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);177 try print(Value.fromInterned(un.val), bw, level - 1, pt, opt_sema);
189 try writer.writeAll(" }");178 try bw.writeAll(" }");
190 }179 }
191 },180 },
192 .memoized_call => unreachable,181 .memoized_call => unreachable,
...@@ -197,33 +186,33 @@ fn printAggregate(...@@ -197,33 +186,33 @@ fn printAggregate(
197 val: Value,186 val: Value,
198 aggregate: InternPool.Key.Aggregate,187 aggregate: InternPool.Key.Aggregate,
199 is_ref: bool,188 is_ref: bool,
200 writer: *std.io.BufferedWriter,189 bw: *std.io.BufferedWriter,
201 level: u8,190 level: u8,
202 pt: Zcu.PerThread,191 pt: Zcu.PerThread,
203 opt_sema: ?*Sema,192 opt_sema: ?*Sema,
204) anyerror!void {193) anyerror!void {
205 if (level == 0) {194 if (level == 0) {
206 if (is_ref) try writer.writeByte('&');195 if (is_ref) try bw.writeByte('&');
207 return writer.writeAll(".{ ... }");196 return bw.writeAll(".{ ... }");
208 }197 }
209 const zcu = pt.zcu;198 const zcu = pt.zcu;
210 const ip = &zcu.intern_pool;199 const ip = &zcu.intern_pool;
211 const ty = Type.fromInterned(aggregate.ty);200 const ty = Type.fromInterned(aggregate.ty);
212 switch (ty.zigTypeTag(zcu)) {201 switch (ty.zigTypeTag(zcu)) {
213 .@"struct" => if (!ty.isTuple(zcu)) {202 .@"struct" => if (!ty.isTuple(zcu)) {
214 if (is_ref) try writer.writeByte('&');203 if (is_ref) try bw.writeByte('&');
215 if (ty.structFieldCount(zcu) == 0) {204 if (ty.structFieldCount(zcu) == 0) {
216 return writer.writeAll(".{}");205 return bw.writeAll(".{}");
217 }206 }
218 try writer.writeAll(".{ ");207 try bw.writeAll(".{ ");
219 const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items);208 const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items);
220 for (0..max_len) |i| {209 for (0..max_len) |i| {
221 if (i != 0) try writer.writeAll(", ");210 if (i != 0) try bw.writeAll(", ");
222 const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;211 const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
223 try writer.print(".{i} = ", .{field_name.fmt(ip)});212 try bw.print(".{fi} = ", .{field_name.fmt(ip)});
224 try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);213 try print(try val.fieldValue(pt, i), bw, level - 1, pt, opt_sema);
225 }214 }
226 try writer.writeAll(" }");215 try bw.writeAll(" }");
227 return;216 return;
228 },217 },
229 .array => {218 .array => {
...@@ -232,16 +221,16 @@ fn printAggregate(...@@ -232,16 +221,16 @@ fn printAggregate(
232 const len = ty.arrayLenIncludingSentinel(zcu);221 const len = ty.arrayLenIncludingSentinel(zcu);
233 if (len == 0) break :string;222 if (len == 0) break :string;
234 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);223 const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip);
235 try writer.print("\"{}\"", .{std.zig.fmtEscapes(slice)});224 try bw.print("\"{f}\"", .{std.zig.fmtEscapes(slice)});
236 if (!is_ref) try writer.writeAll(".*");225 if (!is_ref) try bw.writeAll(".*");
237 return;226 return;
238 },227 },
239 .elems, .repeated_elem => {},228 .elems, .repeated_elem => {},
240 }229 }
241 switch (ty.arrayLen(zcu)) {230 switch (ty.arrayLen(zcu)) {
242 0 => {231 0 => {
243 if (is_ref) try writer.writeByte('&');232 if (is_ref) try bw.writeByte('&');
244 return writer.writeAll(".{}");233 return bw.writeAll(".{}");
245 },234 },
246 1 => one_byte_str: {235 1 => one_byte_str: {
247 // The repr isn't `bytes`, but we might still be able to print this as a string236 // The repr isn't `bytes`, but we might still be able to print this as a string
...@@ -249,47 +238,47 @@ fn printAggregate(...@@ -249,47 +238,47 @@ fn printAggregate(
249 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);238 const elem_val = Value.fromInterned(aggregate.storage.values()[0]);
250 if (elem_val.isUndef(zcu)) break :one_byte_str;239 if (elem_val.isUndef(zcu)) break :one_byte_str;
251 const byte = elem_val.toUnsignedInt(zcu);240 const byte = elem_val.toUnsignedInt(zcu);
252 try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})});241 try bw.print("\"{f}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})});
253 if (!is_ref) try writer.writeAll(".*");242 if (!is_ref) try bw.writeAll(".*");
254 return;243 return;
255 },244 },
256 else => {},245 else => {},
257 }246 }
258 },247 },
259 .vector => if (ty.arrayLen(zcu) == 0) {248 .vector => if (ty.arrayLen(zcu) == 0) {
260 if (is_ref) try writer.writeByte('&');249 if (is_ref) try bw.writeByte('&');
261 return writer.writeAll(".{}");250 return bw.writeAll(".{}");
262 },251 },
263 else => unreachable,252 else => unreachable,
264 }253 }
265254
266 const len = ty.arrayLen(zcu);255 const len = ty.arrayLen(zcu);
267256
268 if (is_ref) try writer.writeByte('&');257 if (is_ref) try bw.writeByte('&');
269 try writer.writeAll(".{ ");258 try bw.writeAll(".{ ");
270259
271 const max_len = @min(len, max_aggregate_items);260 const max_len = @min(len, max_aggregate_items);
272 for (0..max_len) |i| {261 for (0..max_len) |i| {
273 if (i != 0) try writer.writeAll(", ");262 if (i != 0) try bw.writeAll(", ");
274 try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);263 try print(try val.fieldValue(pt, i), bw, level - 1, pt, opt_sema);
275 }264 }
276 if (len > max_aggregate_items) {265 if (len > max_aggregate_items) {
277 try writer.writeAll(", ...");266 try bw.writeAll(", ...");
278 }267 }
279 return writer.writeAll(" }");268 return bw.writeAll(" }");
280}269}
281270
282fn printPtr(271fn printPtr(
283 ptr_val: Value,272 ptr_val: Value,
284 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.273 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
285 want_kind: ?PrintPtrKind,274 want_kind: ?PrintPtrKind,
286 writer: *std.io.BufferedWriter,275 bw: *std.io.BufferedWriter,
287 level: u8,276 level: u8,
288 pt: Zcu.PerThread,277 pt: Zcu.PerThread,
289 opt_sema: ?*Sema,278 opt_sema: ?*Sema,
290) anyerror!void {279) anyerror!void {
291 const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {280 const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {
292 .undef => return writer.writeAll("undefined"),281 .undef => return bw.writeAll("undefined"),
293 .ptr => |ptr| ptr,282 .ptr => |ptr| ptr,
294 else => unreachable,283 else => unreachable,
295 };284 };
...@@ -301,7 +290,7 @@ fn printPtr(...@@ -301,7 +290,7 @@ fn printPtr(
301 Value.fromInterned(ptr.base_addr.uav.val),290 Value.fromInterned(ptr.base_addr.uav.val),
302 agg,291 agg,
303 true,292 true,
304 writer,293 bw,
305 level,294 level,
306 pt,295 pt,
307 opt_sema,296 opt_sema,
...@@ -317,7 +306,7 @@ fn printPtr(...@@ -317,7 +306,7 @@ fn printPtr(
317 else306 else
318 try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, false, null);307 try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, false, null);
319308
320 _ = try printPtrDerivation(derivation, writer, pt, want_kind, .{ .print_val = .{309 _ = try printPtrDerivation(derivation, bw, pt, want_kind, .{ .print_val = .{
321 .level = level,310 .level = level,
322 .opt_sema = opt_sema,311 .opt_sema = opt_sema,
323 } }, 20);312 } }, 20);
...@@ -329,7 +318,7 @@ const PrintPtrKind = enum { lvalue, rvalue };...@@ -329,7 +318,7 @@ const PrintPtrKind = enum { lvalue, rvalue };
329/// Returns the root derivation, which may be ignored.318/// Returns the root derivation, which may be ignored.
330pub fn printPtrDerivation(319pub fn printPtrDerivation(
331 derivation: Value.PointerDeriveStep,320 derivation: Value.PointerDeriveStep,
332 writer: *std.io.BufferedWriter,321 bw: *std.io.BufferedWriter,
333 pt: Zcu.PerThread,322 pt: Zcu.PerThread,
334 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.323 /// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
335 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as324 /// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as
...@@ -361,7 +350,7 @@ pub fn printPtrDerivation(...@@ -361,7 +350,7 @@ pub fn printPtrDerivation(
361 => |step| continue :root step.parent.*,350 => |step| continue :root step.parent.*,
362 else => |step| break :root step,351 else => |step| break :root step,
363 };352 };
364 try writer.writeAll("...");353 try bw.writeAll("...");
365 return root_step;354 return root_step;
366 }355 }
367356
...@@ -384,39 +373,39 @@ pub fn printPtrDerivation(...@@ -384,39 +373,39 @@ pub fn printPtrDerivation(
384 const need_kind = want_kind orelse result_kind;373 const need_kind = want_kind orelse result_kind;
385374
386 if (need_kind == .rvalue and result_kind == .lvalue) {375 if (need_kind == .rvalue and result_kind == .lvalue) {
387 try writer.writeByte('&');376 try bw.writeByte('&');
388 }377 }
389378
390 // null if `derivation` is the root.379 // null if `derivation` is the root.
391 const root_or_null: ?Value.PointerDeriveStep = switch (derivation) {380 const root_or_null: ?Value.PointerDeriveStep = switch (derivation) {
392 .eu_payload_ptr => |info| root: {381 .eu_payload_ptr => |info| root: {
393 try writer.writeByte('(');382 try bw.writeByte('(');
394 const root = try printPtrDerivation(info.parent.*, writer, pt, .lvalue, root_strat, ptr_depth - 1);383 const root = try printPtrDerivation(info.parent.*, bw, pt, .lvalue, root_strat, ptr_depth - 1);
395 try writer.writeAll(" catch unreachable)");384 try bw.writeAll(" catch unreachable)");
396 break :root root;385 break :root root;
397 },386 },
398 .opt_payload_ptr => |info| root: {387 .opt_payload_ptr => |info| root: {
399 const root = try printPtrDerivation(info.parent.*, writer, pt, .lvalue, root_strat, ptr_depth - 1);388 const root = try printPtrDerivation(info.parent.*, bw, pt, .lvalue, root_strat, ptr_depth - 1);
400 try writer.writeAll(".?");389 try bw.writeAll(".?");
401 break :root root;390 break :root root;
402 },391 },
403 .field_ptr => |field| root: {392 .field_ptr => |field| root: {
404 const root = try printPtrDerivation(field.parent.*, writer, pt, null, root_strat, ptr_depth - 1);393 const root = try printPtrDerivation(field.parent.*, bw, pt, null, root_strat, ptr_depth - 1);
405 const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);394 const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);
406 switch (agg_ty.zigTypeTag(zcu)) {395 switch (agg_ty.zigTypeTag(zcu)) {
407 .@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {396 .@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {
408 try writer.print(".{i}", .{field_name.fmt(ip)});397 try bw.print(".{fi}", .{field_name.fmt(ip)});
409 } else {398 } else {
410 try writer.print("[{d}]", .{field.field_idx});399 try bw.print("[{d}]", .{field.field_idx});
411 },400 },
412 .@"union" => {401 .@"union" => {
413 const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);402 const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);
414 const field_name = tag_ty.enumFieldName(field.field_idx, zcu);403 const field_name = tag_ty.enumFieldName(field.field_idx, zcu);
415 try writer.print(".{i}", .{field_name.fmt(ip)});404 try bw.print(".{fi}", .{field_name.fmt(ip)});
416 },405 },
417 .pointer => switch (field.field_idx) {406 .pointer => switch (field.field_idx) {
418 Value.slice_ptr_index => try writer.writeAll(".ptr"),407 Value.slice_ptr_index => try bw.writeAll(".ptr"),
419 Value.slice_len_index => try writer.writeAll(".len"),408 Value.slice_len_index => try bw.writeAll(".len"),
420 else => unreachable,409 else => unreachable,
421 },410 },
422 else => unreachable,411 else => unreachable,
...@@ -424,20 +413,20 @@ pub fn printPtrDerivation(...@@ -424,20 +413,20 @@ pub fn printPtrDerivation(
424 break :root root;413 break :root root;
425 },414 },
426 .elem_ptr => |elem| root: {415 .elem_ptr => |elem| root: {
427 const root = try printPtrDerivation(elem.parent.*, writer, pt, null, root_strat, ptr_depth - 1);416 const root = try printPtrDerivation(elem.parent.*, bw, pt, null, root_strat, ptr_depth - 1);
428 try writer.print("[{d}]", .{elem.elem_idx});417 try bw.print("[{d}]", .{elem.elem_idx});
429 break :root root;418 break :root root;
430 },419 },
431420
432 .offset_and_cast => |oac| if (oac.byte_offset == 0) root: {421 .offset_and_cast => |oac| if (oac.byte_offset == 0) root: {
433 try writer.print("@as({}, @ptrCast(", .{oac.new_ptr_ty.fmt(pt)});422 try bw.print("@as({f}, @ptrCast(", .{oac.new_ptr_ty.fmt(pt)});
434 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);423 const root = try printPtrDerivation(oac.parent.*, bw, pt, .rvalue, root_strat, ptr_depth - 1);
435 try writer.writeAll("))");424 try bw.writeAll("))");
436 break :root root;425 break :root root;
437 } else root: {426 } else root: {
438 try writer.print("@as({}, @ptrFromInt(@intFromPtr(", .{oac.new_ptr_ty.fmt(pt)});427 try bw.print("@as({f}, @ptrFromInt(@intFromPtr(", .{oac.new_ptr_ty.fmt(pt)});
439 const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);428 const root = try printPtrDerivation(oac.parent.*, bw, pt, .rvalue, root_strat, ptr_depth - 1);
440 try writer.print(") + {d}))", .{oac.byte_offset});429 try bw.print(") + {d}))", .{oac.byte_offset});
441 break :root root;430 break :root root;
442 },431 },
443432
...@@ -445,33 +434,33 @@ pub fn printPtrDerivation(...@@ -445,33 +434,33 @@ pub fn printPtrDerivation(
445 };434 };
446435
447 if (root_or_null == null) switch (root_strat) {436 if (root_or_null == null) switch (root_strat) {
448 .str => |x| try writer.writeAll(x),437 .str => |x| try bw.writeAll(x),
449 .print_val => |x| switch (derivation) {438 .print_val => |x| switch (derivation) {
450 .int => |int| try writer.print("@as({}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }),439 .int => |int| try bw.print("@as({f}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }),
451 .nav_ptr => |nav| try writer.print("{}", .{ip.getNav(nav).fqn.fmt(ip)}),440 .nav_ptr => |nav| try bw.print("{f}", .{ip.getNav(nav).fqn.fmt(ip)}),
452 .uav_ptr => |uav| {441 .uav_ptr => |uav| {
453 const ty = Value.fromInterned(uav.val).typeOf(zcu);442 const ty = Value.fromInterned(uav.val).typeOf(zcu);
454 try writer.print("@as({}, ", .{ty.fmt(pt)});443 try bw.print("@as({f}, ", .{ty.fmt(pt)});
455 try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);444 try print(Value.fromInterned(uav.val), bw, x.level - 1, pt, x.opt_sema);
456 try writer.writeByte(')');445 try bw.writeByte(')');
457 },446 },
458 .comptime_alloc_ptr => |info| {447 .comptime_alloc_ptr => |info| {
459 try writer.print("@as({}, ", .{info.val.typeOf(zcu).fmt(pt)});448 try bw.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)});
460 try print(info.val, writer, x.level - 1, pt, x.opt_sema);449 try print(info.val, bw, x.level - 1, pt, x.opt_sema);
461 try writer.writeByte(')');450 try bw.writeByte(')');
462 },451 },
463 .comptime_field_ptr => |val| {452 .comptime_field_ptr => |val| {
464 const ty = val.typeOf(zcu);453 const ty = val.typeOf(zcu);
465 try writer.print("@as({}, ", .{ty.fmt(pt)});454 try bw.print("@as({f}, ", .{ty.fmt(pt)});
466 try print(val, writer, x.level - 1, pt, x.opt_sema);455 try print(val, bw, x.level - 1, pt, x.opt_sema);
467 try writer.writeByte(')');456 try bw.writeByte(')');
468 },457 },
469 else => unreachable,458 else => unreachable,
470 },459 },
471 };460 };
472461
473 if (need_kind == .lvalue and result_kind == .rvalue) {462 if (need_kind == .lvalue and result_kind == .rvalue) {
474 try writer.writeAll(".*");463 try bw.writeAll(".*");
475 }464 }
476465
477 return root_or_null orelse derivation;466 return root_or_null orelse derivation;
src/print_zir.zig+18-18
...@@ -41,7 +41,7 @@ pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.BufferedWr...@@ -41,7 +41,7 @@ pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.BufferedWr
41 extra_index = item.end;41 extra_index = item.end;
4242
43 const import_path = zir.nullTerminatedString(item.data.name);43 const import_path = zir.nullTerminatedString(item.data.name);
44 try bw.print(" @import(\"{}\") ", .{44 try bw.print(" @import(\"{f}\") ", .{
45 std.zig.fmtEscapes(import_path),45 std.zig.fmtEscapes(import_path),
46 });46 });
47 try writer.writeSrcTokAbs(bw, item.data.token);47 try writer.writeSrcTokAbs(bw, item.data.token);
...@@ -783,7 +783,7 @@ const Writer = struct {...@@ -783,7 +783,7 @@ const Writer = struct {
783 ) anyerror!void {783 ) anyerror!void {
784 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;784 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
785 const str = inst_data.get(self.code);785 const str = inst_data.get(self.code);
786 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});786 try stream.print("\"{f}\")", .{std.zig.fmtEscapes(str)});
787 }787 }
788788
789 fn writeSliceStart(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {789 fn writeSliceStart(self: *Writer, stream: *std.io.BufferedWriter, inst: Zir.Inst.Index) !void {
...@@ -939,7 +939,7 @@ const Writer = struct {...@@ -939,7 +939,7 @@ const Writer = struct {
939 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;939 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
940 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);940 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
941 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);941 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
942 try stream.print("\"{}\", ", .{942 try stream.print("\"{f}\", ", .{
943 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),943 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
944 });944 });
945945
...@@ -1210,7 +1210,7 @@ const Writer = struct {...@@ -1210,7 +1210,7 @@ const Writer = struct {
1210 try stream.writeAll(", ");1210 try stream.writeAll(", ");
1211 } else {1211 } else {
1212 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);1212 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
1213 try stream.print("\"{}\", ", .{std.zig.fmtEscapes(asm_source)});1213 try stream.print("\"{f}\", ", .{std.zig.fmtEscapes(asm_source)});
1214 }1214 }
1215 try stream.writeAll(", ");1215 try stream.writeAll(", ");
12161216
...@@ -1227,7 +1227,7 @@ const Writer = struct {...@@ -1227,7 +1227,7 @@ const Writer = struct {
12271227
1228 const name = self.code.nullTerminatedString(output.data.name);1228 const name = self.code.nullTerminatedString(output.data.name);
1229 const constraint = self.code.nullTerminatedString(output.data.constraint);1229 const constraint = self.code.nullTerminatedString(output.data.constraint);
1230 try stream.print("output({p}, \"{}\", ", .{1230 try stream.print("output({fp}, \"{f}\", ", .{
1231 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1231 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
1232 });1232 });
1233 try self.writeFlag(stream, "->", is_type);1233 try self.writeFlag(stream, "->", is_type);
...@@ -1246,7 +1246,7 @@ const Writer = struct {...@@ -1246,7 +1246,7 @@ const Writer = struct {
12461246
1247 const name = self.code.nullTerminatedString(input.data.name);1247 const name = self.code.nullTerminatedString(input.data.name);
1248 const constraint = self.code.nullTerminatedString(input.data.constraint);1248 const constraint = self.code.nullTerminatedString(input.data.constraint);
1249 try stream.print("input({p}, \"{}\", ", .{1249 try stream.print("input({fp}, \"{f}\", ", .{
1250 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),1250 std.zig.fmtId(name), std.zig.fmtEscapes(constraint),
1251 });1251 });
1252 try self.writeInstRef(stream, input.data.operand);1252 try self.writeInstRef(stream, input.data.operand);
...@@ -1262,7 +1262,7 @@ const Writer = struct {...@@ -1262,7 +1262,7 @@ const Writer = struct {
1262 const str_index = self.code.extra[extra_i];1262 const str_index = self.code.extra[extra_i];
1263 extra_i += 1;1263 extra_i += 1;
1264 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));1264 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));
1265 try stream.print("{p}", .{std.zig.fmtId(clobber)});1265 try stream.print("{fp}", .{std.zig.fmtId(clobber)});
1266 if (i + 1 < clobbers_len) {1266 if (i + 1 < clobbers_len) {
1267 try stream.writeAll(", ");1267 try stream.writeAll(", ");
1268 }1268 }
...@@ -1306,7 +1306,7 @@ const Writer = struct {...@@ -1306,7 +1306,7 @@ const Writer = struct {
1306 .field => {1306 .field => {
1307 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);1307 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
1308 try self.writeInstRef(stream, extra.data.obj_ptr);1308 try self.writeInstRef(stream, extra.data.obj_ptr);
1309 try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)});1309 try stream.print(", \"{f}\"", .{std.zig.fmtEscapes(field_name)});
1310 },1310 },
1311 }1311 }
1312 try stream.writeAll(", [");1312 try stream.writeAll(", [");
...@@ -1526,7 +1526,7 @@ const Writer = struct {...@@ -1526,7 +1526,7 @@ const Writer = struct {
1526 try self.writeFlag(stream, "comptime ", field.is_comptime);1526 try self.writeFlag(stream, "comptime ", field.is_comptime);
1527 if (field.name != .empty) {1527 if (field.name != .empty) {
1528 const field_name = self.code.nullTerminatedString(field.name);1528 const field_name = self.code.nullTerminatedString(field.name);
1529 try stream.print("{p}: ", .{std.zig.fmtId(field_name)});1529 try stream.print("{fp}: ", .{std.zig.fmtId(field_name)});
1530 } else {1530 } else {
1531 try stream.print("@\"{d}\": ", .{i});1531 try stream.print("@\"{d}\": ", .{i});
1532 }1532 }
...@@ -1689,7 +1689,7 @@ const Writer = struct {...@@ -1689,7 +1689,7 @@ const Writer = struct {
1689 extra_index += 1;1689 extra_index += 1;
16901690
1691 try stream.splatByteAll(' ', self.indent);1691 try stream.splatByteAll(' ', self.indent);
1692 try stream.print("{p}", .{std.zig.fmtId(field_name)});1692 try stream.print("{fp}", .{std.zig.fmtId(field_name)});
16931693
1694 if (has_type) {1694 if (has_type) {
1695 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1695 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1823,7 +1823,7 @@ const Writer = struct {...@@ -1823,7 +1823,7 @@ const Writer = struct {
1823 extra_index += 1;1823 extra_index += 1;
18241824
1825 try stream.splatByteAll(' ', self.indent);1825 try stream.splatByteAll(' ', self.indent);
1826 try stream.print("{p}", .{std.zig.fmtId(field_name)});1826 try stream.print("{fp}", .{std.zig.fmtId(field_name)});
18271827
1828 if (has_tag_value) {1828 if (has_tag_value) {
1829 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1829 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
...@@ -1928,7 +1928,7 @@ const Writer = struct {...@@ -1928,7 +1928,7 @@ const Writer = struct {
1928 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);1928 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1929 const name = self.code.nullTerminatedString(name_index);1929 const name = self.code.nullTerminatedString(name_index);
1930 try stream.splatByteAll(' ', self.indent);1930 try stream.splatByteAll(' ', self.indent);
1931 try stream.print("{p},\n", .{std.zig.fmtId(name)});1931 try stream.print("{fp},\n", .{std.zig.fmtId(name)});
1932 }1932 }
19331933
1934 self.indent -= 2;1934 self.indent -= 2;
...@@ -2210,7 +2210,7 @@ const Writer = struct {...@@ -2210,7 +2210,7 @@ const Writer = struct {
2210 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;2210 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
2211 const name = self.code.nullTerminatedString(extra.field_name_start);2211 const name = self.code.nullTerminatedString(extra.field_name_start);
2212 try self.writeInstRef(stream, extra.lhs);2212 try self.writeInstRef(stream, extra.lhs);
2213 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)});2213 try stream.print(", \"{f}\") ", .{std.zig.fmtEscapes(name)});
2214 try self.writeSrcNode(stream, inst_data.src_node);2214 try self.writeSrcNode(stream, inst_data.src_node);
2215 }2215 }
22162216
...@@ -2251,7 +2251,7 @@ const Writer = struct {...@@ -2251,7 +2251,7 @@ const Writer = struct {
2251 ) anyerror!void {2251 ) anyerror!void {
2252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;2252 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
2253 const str = inst_data.get(self.code);2253 const str = inst_data.get(self.code);
2254 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});2254 try stream.print("\"{f}\") ", .{std.zig.fmtEscapes(str)});
2255 try self.writeSrcTok(stream, inst_data.src_tok);2255 try self.writeSrcTok(stream, inst_data.src_tok);
2256 }2256 }
22572257
...@@ -2259,7 +2259,7 @@ const Writer = struct {...@@ -2259,7 +2259,7 @@ const Writer = struct {
2259 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;2259 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
2260 const str = inst_data.getStr(self.code);2260 const str = inst_data.getStr(self.code);
2261 try self.writeInstRef(stream, inst_data.operand);2261 try self.writeInstRef(stream, inst_data.operand);
2262 try stream.print(", \"{}\")", .{std.zig.fmtEscapes(str)});2262 try stream.print(", \"{f}\")", .{std.zig.fmtEscapes(str)});
2263 }2263 }
22642264
2265 fn writeFunc(2265 fn writeFunc(
...@@ -2700,10 +2700,10 @@ const Writer = struct {...@@ -2700,10 +2700,10 @@ const Writer = struct {
2700 try stream.writeAll("load ");2700 try stream.writeAll("load ");
2701 try self.writeInstIndex(stream, ptr_inst);2701 try self.writeInstIndex(stream, ptr_inst);
2702 },2702 },
2703 .decl_val => |str| try stream.print("decl_val \"{}\"", .{2703 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2704 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2704 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),
2705 }),2705 }),
2706 .decl_ref => |str| try stream.print("decl_ref \"{}\"", .{2706 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2707 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),2707 std.zig.fmtEscapes(self.code.nullTerminatedString(str)),
2708 }),2708 }),
2709 }2709 }
...@@ -2837,7 +2837,7 @@ const Writer = struct {...@@ -2837,7 +2837,7 @@ const Writer = struct {
2837 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;2837 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2838 try self.writeInstRef(stream, extra.res_ty);2838 try self.writeInstRef(stream, extra.res_ty);
2839 const import_path = self.code.nullTerminatedString(extra.path);2839 const import_path = self.code.nullTerminatedString(extra.path);
2840 try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(import_path)});2840 try stream.print(", \"{f}\") ", .{std.zig.fmtEscapes(import_path)});
2841 try self.writeSrcTok(stream, inst_data.src_tok);2841 try self.writeSrcTok(stream, inst_data.src_tok);
2842 }2842 }
2843};2843};
src/print_zoir.zig+3-3
...@@ -70,8 +70,8 @@ const PrintZon = struct {...@@ -70,8 +70,8 @@ const PrintZon = struct {
70 },70 },
71 .float_literal => |x| try pz.w.print("float({d})", .{x}),71 .float_literal => |x| try pz.w.print("float({d})", .{x}),
72 .char_literal => |x| try pz.w.print("char({d})", .{x}),72 .char_literal => |x| try pz.w.print("char({d})", .{x}),
73 .enum_literal => |x| try pz.w.print("enum_literal({p})", .{std.zig.fmtId(x.get(zoir))}),73 .enum_literal => |x| try pz.w.print("enum_literal({fp})", .{std.zig.fmtId(x.get(zoir))}),
74 .string_literal => |x| try pz.w.print("str(\"{}\")", .{std.zig.fmtEscapes(x)}),74 .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtEscapes(x)}),
75 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),75 .empty_literal => try pz.w.writeAll("empty_literal(.{})"),
76 .array_literal => |vals| {76 .array_literal => |vals| {
77 try pz.w.writeAll("array_literal({");77 try pz.w.writeAll("array_literal({");
...@@ -90,7 +90,7 @@ const PrintZon = struct {...@@ -90,7 +90,7 @@ const PrintZon = struct {
90 pz.indent += 1;90 pz.indent += 1;
91 for (s.names, 0..s.vals.len) |name, idx| {91 for (s.names, 0..s.vals.len) |name, idx| {
92 try pz.newline();92 try pz.newline();
93 try pz.w.print("[{p}] ", .{std.zig.fmtId(name.get(zoir))});93 try pz.w.print("[{fp}] ", .{std.zig.fmtId(name.get(zoir))});
94 try pz.renderNode(s.vals.at(@intCast(idx)));94 try pz.renderNode(s.vals.at(@intCast(idx)));
95 try pz.w.writeByte(',');95 try pz.w.writeByte(',');
96 }96 }
src/register_manager.zig+3-3
...@@ -238,7 +238,7 @@ pub fn RegisterManager(...@@ -238,7 +238,7 @@ pub fn RegisterManager(
238 if (i < count) return null;238 if (i < count) return null;
239239
240 for (regs, insts) |reg, inst| {240 for (regs, insts) |reg, inst| {
241 log.debug("tryAllocReg {} for inst {?}", .{ reg, inst });241 log.debug("tryAllocReg {} for inst {?f}", .{ reg, inst });
242 self.markRegAllocated(reg);242 self.markRegAllocated(reg);
243243
244 if (inst) |tracked_inst| {244 if (inst) |tracked_inst| {
...@@ -317,7 +317,7 @@ pub fn RegisterManager(...@@ -317,7 +317,7 @@ pub fn RegisterManager(
317 tracked_index: TrackedIndex,317 tracked_index: TrackedIndex,
318 inst: ?Air.Inst.Index,318 inst: ?Air.Inst.Index,
319 ) AllocationError!void {319 ) AllocationError!void {
320 log.debug("getReg {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });320 log.debug("getReg {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
321 if (!self.isRegIndexFree(tracked_index)) {321 if (!self.isRegIndexFree(tracked_index)) {
322 // Move the instruction that was previously there to a322 // Move the instruction that was previously there to a
323 // stack allocation.323 // stack allocation.
...@@ -349,7 +349,7 @@ pub fn RegisterManager(...@@ -349,7 +349,7 @@ pub fn RegisterManager(
349 tracked_index: TrackedIndex,349 tracked_index: TrackedIndex,
350 inst: ?Air.Inst.Index,350 inst: ?Air.Inst.Index,
351 ) void {351 ) void {
352 log.debug("getRegAssumeFree {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });352 log.debug("getRegAssumeFree {} for inst {?f}", .{ regAtTrackedIndex(tracked_index), inst });
353 self.markRegIndexAllocated(tracked_index);353 self.markRegIndexAllocated(tracked_index);
354354
355 assert(self.isRegIndexFree(tracked_index));355 assert(self.isRegIndexFree(tracked_index));
src/translate_c.zig+8-8
...@@ -357,7 +357,7 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi...@@ -357,7 +357,7 @@ fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.Fi
357 var len: usize = undefined;357 var len: usize = undefined;
358 const bytes_ptr = asm_string.getString_bytes_begin_size(&len);358 const bytes_ptr = asm_string.getString_bytes_begin_size(&len);
359359
360 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});360 const str = try std.fmt.allocPrint(c.arena, "\"{f}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
361 const str_node = try Tag.string_literal.create(c.arena, str);361 const str_node = try Tag.string_literal.create(c.arena, str);
362362
363 const asm_node = try Tag.asm_simple.create(c.arena, str_node);363 const asm_node = try Tag.asm_simple.create(c.arena, str_node);
...@@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral(...@@ -2276,7 +2276,7 @@ fn transNarrowStringLiteral(
2276 var len: usize = undefined;2276 var len: usize = undefined;
2277 const bytes_ptr = stmt.getString_bytes_begin_size(&len);2277 const bytes_ptr = stmt.getString_bytes_begin_size(&len);
22782278
2279 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});2279 const str = try std.fmt.allocPrint(c.arena, "\"{f}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
2280 const node = try Tag.string_literal.create(c.arena, str);2280 const node = try Tag.string_literal.create(c.arena, str);
2281 return maybeSuppressResult(c, result_used, node);2281 return maybeSuppressResult(c, result_used, node);
2282}2282}
...@@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined...@@ -3338,7 +3338,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
33383338
3339fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {3339fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
3340 return Tag.char_literal.create(c.arena, if (narrow)3340 return Tag.char_literal.create(c.arena, if (narrow)
3341 try std.fmt.allocPrint(c.arena, "'{'}'", .{std.zig.fmtEscapes(&.{@as(u8, @intCast(val))})})3341 try std.fmt.allocPrint(c.arena, "'{f'}'", .{std.zig.fmtEscapes(&.{@as(u8, @intCast(val))})})
3342 else3342 else
3343 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));3343 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
3344}3344}
...@@ -5832,7 +5832,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5832,7 +5832,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5832 num += c - 'A' + 10;5832 num += c - 'A' + 10;
5833 },5833 },
5834 else => {5834 else => {
5835 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });5835 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5836 num = 0;5836 num = 0;
5837 if (c == '\\')5837 if (c == '\\')
5838 state = .escape5838 state = .escape
...@@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5858,7 +5858,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5858 };5858 };
5859 num += c - '0';5859 num += c - '0';
5860 } else {5860 } else {
5861 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });5861 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5862 num = 0;5862 num = 0;
5863 count = 0;5863 count = 0;
5864 if (c == '\\')5864 if (c == '\\')
...@@ -5872,7 +5872,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5872,7 +5872,7 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 {
5872 }5872 }
5873 }5873 }
5874 if (state == .hex or state == .octal)5874 if (state == .hex or state == .octal)
5875 i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });5875 i += std.fmt.printInt(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
5876 return bytes[0..i];5876 return bytes[0..i];
5877}5877}
58785878
...@@ -5884,9 +5884,9 @@ fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 {...@@ -5884,9 +5884,9 @@ fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 {
5884 if (std.unicode.utf8ValidateSlice(zigified)) return zigified;5884 if (std.unicode.utf8ValidateSlice(zigified)) return zigified;
58855885
5886 const formatter = std.fmt.fmtSliceEscapeLower(zigified);5886 const formatter = std.fmt.fmtSliceEscapeLower(zigified);
5887 const encoded_size = @as(usize, @intCast(std.fmt.count("{s}", .{formatter})));5887 const encoded_size = std.fmt.count("{f}", .{formatter});
5888 const output = try ctx.arena.alloc(u8, encoded_size);5888 const output = try ctx.arena.alloc(u8, encoded_size);
5889 return std.fmt.bufPrint(output, "{s}", .{formatter}) catch |err| switch (err) {5889 return std.fmt.bufPrint(output, "{f}", .{formatter}) catch |err| switch (err) {
5890 error.NoSpaceLeft => unreachable,5890 error.NoSpaceLeft => unreachable,
5891 else => |e| return e,5891 else => |e| return e,
5892 };5892 };