| author | |
| committer | |
| log | 4b948e8556b80cbc874415aa7c4bf9ac0027ffed |
| tree | ca48e7208aa23a24db82e8521c37a6c2abcd5dc1 |
| parent | 640c11171bf8d13776629941f3305cf11c62c1f3 |
| parent | 43fbc37a490442ffcecf9817877f542251fee664 |
| signature |
std.Io: delete GenericWriter, AnyWriter, and null_writer106 files changed, 2450 insertions(+), 3606 deletions(-)
lib/compiler/aro/aro/Attribute.zig+1-1| ... | ... | @@ -780,7 +780,7 @@ fn ignoredAttrErr(p: *Parser, tok: TokenIndex, attr: Attribute.Tag, context: []c |
| 780 | 780 | const strings_top = p.strings.items.len; |
| 781 | 781 | defer p.strings.items.len = strings_top; |
| 782 | 782 | |
| 783 | try p.strings.writer().print("attribute '{s}' ignored on {s}", .{ @tagName(attr), context }); | |
| 783 | try p.strings.print("attribute '{s}' ignored on {s}", .{ @tagName(attr), context }); | |
| 784 | 784 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 785 | 785 | try p.errStr(.ignored_attribute, tok, str); |
| 786 | 786 | } |
lib/compiler/aro/aro/Builtins/Builtin.zig+2-3| ... | ... | @@ -119,8 +119,7 @@ pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 { |
| 119 | 119 | |
| 120 | 120 | var node_index: u16 = 0; |
| 121 | 121 | var count: u16 = index; |
| 122 | var fbs = std.io.fixedBufferStream(buf); | |
| 123 | const w = fbs.writer(); | |
| 122 | var w: std.Io.Writer = .fixed(buf); | |
| 124 | 123 | |
| 125 | 124 | while (true) { |
| 126 | 125 | var sibling_index = dafsa[node_index].child_index; |
| ... | ... | @@ -142,7 +141,7 @@ pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 { |
| 142 | 141 | if (count == 0) break; |
| 143 | 142 | } |
| 144 | 143 | |
| 145 | return fbs.getWritten(); | |
| 144 | return w.buffered(); | |
| 146 | 145 | } |
| 147 | 146 | |
| 148 | 147 | /// We're 1 bit shy of being able to fit this in a u32: |
lib/compiler/aro/aro/Compilation.zig+36-28| ... | ... | @@ -16,6 +16,7 @@ const Pragma = @import("Pragma.zig"); |
| 16 | 16 | const StrInt = @import("StringInterner.zig"); |
| 17 | 17 | const record_layout = @import("record_layout.zig"); |
| 18 | 18 | const target_util = @import("target.zig"); |
| 19 | const Writer = std.Io.Writer; | |
| 19 | 20 | |
| 20 | 21 | pub const Error = error{ |
| 21 | 22 | /// A fatal error has ocurred and compilation has stopped. |
| ... | ... | @@ -199,7 +200,7 @@ fn getTimestamp(comp: *Compilation) !u47 { |
| 199 | 200 | return @intCast(std.math.clamp(timestamp, 0, max_timestamp)); |
| 200 | 201 | } |
| 201 | 202 | |
| 202 | fn generateDateAndTime(w: anytype, timestamp: u47) !void { | |
| 203 | fn generateDateAndTime(w: *Writer, timestamp: u47) !void { | |
| 203 | 204 | const epoch_seconds = EpochSeconds{ .secs = timestamp }; |
| 204 | 205 | const epoch_day = epoch_seconds.getEpochDay(); |
| 205 | 206 | const day_seconds = epoch_seconds.getDaySeconds(); |
| ... | ... | @@ -242,7 +243,7 @@ pub const SystemDefinesMode = enum { |
| 242 | 243 | include_system_defines, |
| 243 | 244 | }; |
| 244 | 245 | |
| 245 | fn generateSystemDefines(comp: *Compilation, w: anytype) !void { | |
| 246 | fn generateSystemDefines(comp: *Compilation, w: *Writer) !void { | |
| 246 | 247 | const ptr_width = comp.target.ptrBitWidth(); |
| 247 | 248 | |
| 248 | 249 | if (comp.langopts.gnuc_version > 0) { |
| ... | ... | @@ -533,11 +534,20 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 533 | 534 | pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefinesMode) !Source { |
| 534 | 535 | try comp.generateBuiltinTypes(); |
| 535 | 536 | |
| 536 | var buf = std.array_list.Managed(u8).init(comp.gpa); | |
| 537 | defer buf.deinit(); | |
| 537 | var allocating: std.Io.Writer.Allocating = .init(comp.gpa); | |
| 538 | defer allocating.deinit(); | |
| 539 | ||
| 540 | generateBuiltinMacrosWriter(comp, system_defines_mode, &allocating.writer) catch |err| switch (err) { | |
| 541 | error.WriteFailed => return error.OutOfMemory, | |
| 542 | else => |e| return e, | |
| 543 | }; | |
| 544 | ||
| 545 | return comp.addSourceFromBuffer("<builtin>", allocating.written()); | |
| 546 | } | |
| 538 | 547 | |
| 548 | pub fn generateBuiltinMacrosWriter(comp: *Compilation, system_defines_mode: SystemDefinesMode, buf: *Writer) !void { | |
| 539 | 549 | if (system_defines_mode == .include_system_defines) { |
| 540 | try buf.appendSlice( | |
| 550 | try buf.writeAll( | |
| 541 | 551 | \\#define __VERSION__ "Aro |
| 542 | 552 | ++ " " ++ @import("../backend.zig").version_str ++ "\"\n" ++ |
| 543 | 553 | \\#define __Aro__ |
| ... | ... | @@ -545,11 +555,11 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi |
| 545 | 555 | ); |
| 546 | 556 | } |
| 547 | 557 | |
| 548 | try buf.appendSlice("#define __STDC__ 1\n"); | |
| 549 | try buf.writer().print("#define __STDC_HOSTED__ {d}\n", .{@intFromBool(comp.target.os.tag != .freestanding)}); | |
| 558 | try buf.writeAll("#define __STDC__ 1\n"); | |
| 559 | try buf.print("#define __STDC_HOSTED__ {d}\n", .{@intFromBool(comp.target.os.tag != .freestanding)}); | |
| 550 | 560 | |
| 551 | 561 | // standard macros |
| 552 | try buf.appendSlice( | |
| 562 | try buf.writeAll( | |
| 553 | 563 | \\#define __STDC_NO_COMPLEX__ 1 |
| 554 | 564 | \\#define __STDC_NO_THREADS__ 1 |
| 555 | 565 | \\#define __STDC_NO_VLA__ 1 |
| ... | ... | @@ -561,23 +571,21 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi |
| 561 | 571 | \\ |
| 562 | 572 | ); |
| 563 | 573 | if (comp.langopts.standard.StdCVersionMacro()) |stdc_version| { |
| 564 | try buf.appendSlice("#define __STDC_VERSION__ "); | |
| 565 | try buf.appendSlice(stdc_version); | |
| 566 | try buf.append('\n'); | |
| 574 | try buf.writeAll("#define __STDC_VERSION__ "); | |
| 575 | try buf.writeAll(stdc_version); | |
| 576 | try buf.writeByte('\n'); | |
| 567 | 577 | } |
| 568 | 578 | |
| 569 | 579 | // timestamps |
| 570 | 580 | const timestamp = try comp.getTimestamp(); |
| 571 | try generateDateAndTime(buf.writer(), timestamp); | |
| 581 | try generateDateAndTime(buf, timestamp); | |
| 572 | 582 | |
| 573 | 583 | if (system_defines_mode == .include_system_defines) { |
| 574 | try comp.generateSystemDefines(buf.writer()); | |
| 584 | try comp.generateSystemDefines(buf); | |
| 575 | 585 | } |
| 576 | ||
| 577 | return comp.addSourceFromBuffer("<builtin>", buf.items); | |
| 578 | 586 | } |
| 579 | 587 | |
| 580 | fn generateFloatMacros(w: anytype, prefix: []const u8, semantics: target_util.FPSemantics, ext: []const u8) !void { | |
| 588 | fn generateFloatMacros(w: *Writer, prefix: []const u8, semantics: target_util.FPSemantics, ext: []const u8) !void { | |
| 581 | 589 | const denormMin = semantics.chooseValue( |
| 582 | 590 | []const u8, |
| 583 | 591 | .{ |
| ... | ... | @@ -656,7 +664,7 @@ fn generateFloatMacros(w: anytype, prefix: []const u8, semantics: target_util.FP |
| 656 | 664 | try w.print("#define {s}MIN__ {s}{s}\n", .{ prefix_slice, min, ext }); |
| 657 | 665 | } |
| 658 | 666 | |
| 659 | fn generateTypeMacro(w: anytype, mapper: StrInt.TypeMapper, name: []const u8, ty: Type, langopts: LangOpts) !void { | |
| 667 | fn generateTypeMacro(w: *Writer, mapper: StrInt.TypeMapper, name: []const u8, ty: Type, langopts: LangOpts) !void { | |
| 660 | 668 | try w.print("#define {s} ", .{name}); |
| 661 | 669 | try ty.print(mapper, langopts, w); |
| 662 | 670 | try w.writeByte('\n'); |
| ... | ... | @@ -762,7 +770,7 @@ fn generateFastOrLeastType( |
| 762 | 770 | bits: usize, |
| 763 | 771 | kind: enum { least, fast }, |
| 764 | 772 | signedness: std.builtin.Signedness, |
| 765 | w: anytype, | |
| 773 | w: *Writer, | |
| 766 | 774 | mapper: StrInt.TypeMapper, |
| 767 | 775 | ) !void { |
| 768 | 776 | const ty = comp.intLeastN(bits, signedness); // defining the fast types as the least types is permitted |
| ... | ... | @@ -793,7 +801,7 @@ fn generateFastOrLeastType( |
| 793 | 801 | try comp.generateFmt(prefix, w, ty); |
| 794 | 802 | } |
| 795 | 803 | |
| 796 | fn generateFastAndLeastWidthTypes(comp: *Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { | |
| 804 | fn generateFastAndLeastWidthTypes(comp: *Compilation, w: *Writer, mapper: StrInt.TypeMapper) !void { | |
| 797 | 805 | const sizes = [_]usize{ 8, 16, 32, 64 }; |
| 798 | 806 | for (sizes) |size| { |
| 799 | 807 | try comp.generateFastOrLeastType(size, .least, .signed, w, mapper); |
| ... | ... | @@ -803,7 +811,7 @@ fn generateFastAndLeastWidthTypes(comp: *Compilation, w: anytype, mapper: StrInt |
| 803 | 811 | } |
| 804 | 812 | } |
| 805 | 813 | |
| 806 | fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { | |
| 814 | fn generateExactWidthTypes(comp: *const Compilation, w: *Writer, mapper: StrInt.TypeMapper) !void { | |
| 807 | 815 | try comp.generateExactWidthType(w, mapper, .schar); |
| 808 | 816 | |
| 809 | 817 | if (comp.intSize(.short) > comp.intSize(.char)) { |
| ... | ... | @@ -851,7 +859,7 @@ fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt. |
| 851 | 859 | } |
| 852 | 860 | } |
| 853 | 861 | |
| 854 | fn generateFmt(comp: *const Compilation, prefix: []const u8, w: anytype, ty: Type) !void { | |
| 862 | fn generateFmt(comp: *const Compilation, prefix: []const u8, w: *Writer, ty: Type) !void { | |
| 855 | 863 | const unsigned = ty.isUnsignedInt(comp); |
| 856 | 864 | const modifier = ty.formatModifier(); |
| 857 | 865 | const formats = if (unsigned) "ouxX" else "di"; |
| ... | ... | @@ -860,7 +868,7 @@ fn generateFmt(comp: *const Compilation, prefix: []const u8, w: anytype, ty: Typ |
| 860 | 868 | } |
| 861 | 869 | } |
| 862 | 870 | |
| 863 | fn generateSuffixMacro(comp: *const Compilation, prefix: []const u8, w: anytype, ty: Type) !void { | |
| 871 | fn generateSuffixMacro(comp: *const Compilation, prefix: []const u8, w: *Writer, ty: Type) !void { | |
| 864 | 872 | return w.print("#define {s}_C_SUFFIX__ {s}\n", .{ prefix, ty.intValueSuffix(comp) }); |
| 865 | 873 | } |
| 866 | 874 | |
| ... | ... | @@ -868,7 +876,7 @@ fn generateSuffixMacro(comp: *const Compilation, prefix: []const u8, w: anytype, |
| 868 | 876 | /// Name macro (e.g. #define __UINT32_TYPE__ unsigned int) |
| 869 | 877 | /// Format strings (e.g. #define __UINT32_FMTu__ "u") |
| 870 | 878 | /// Suffix macro (e.g. #define __UINT32_C_SUFFIX__ U) |
| 871 | fn generateExactWidthType(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper, specifier: Type.Specifier) !void { | |
| 879 | fn generateExactWidthType(comp: *const Compilation, w: *Writer, mapper: StrInt.TypeMapper, specifier: Type.Specifier) !void { | |
| 872 | 880 | var ty = Type{ .specifier = specifier }; |
| 873 | 881 | const width = 8 * ty.sizeof(comp).?; |
| 874 | 882 | const unsigned = ty.isUnsignedInt(comp); |
| ... | ... | @@ -998,7 +1006,7 @@ fn generateVaListType(comp: *Compilation) !Type { |
| 998 | 1006 | return ty; |
| 999 | 1007 | } |
| 1000 | 1008 | |
| 1001 | fn generateIntMax(comp: *const Compilation, w: anytype, name: []const u8, ty: Type) !void { | |
| 1009 | fn generateIntMax(comp: *const Compilation, w: *Writer, name: []const u8, ty: Type) !void { | |
| 1002 | 1010 | const bit_count: u8 = @intCast(ty.sizeof(comp).? * 8); |
| 1003 | 1011 | const unsigned = ty.isUnsignedInt(comp); |
| 1004 | 1012 | const max: u128 = switch (bit_count) { |
| ... | ... | @@ -1023,7 +1031,7 @@ pub fn wcharMax(comp: *const Compilation) u32 { |
| 1023 | 1031 | }; |
| 1024 | 1032 | } |
| 1025 | 1033 | |
| 1026 | fn generateExactWidthIntMax(comp: *const Compilation, w: anytype, specifier: Type.Specifier) !void { | |
| 1034 | fn generateExactWidthIntMax(comp: *const Compilation, w: *Writer, specifier: Type.Specifier) !void { | |
| 1027 | 1035 | var ty = Type{ .specifier = specifier }; |
| 1028 | 1036 | const bit_count: u8 = @intCast(ty.sizeof(comp).? * 8); |
| 1029 | 1037 | const unsigned = ty.isUnsignedInt(comp); |
| ... | ... | @@ -1040,16 +1048,16 @@ fn generateExactWidthIntMax(comp: *const Compilation, w: anytype, specifier: Typ |
| 1040 | 1048 | return comp.generateIntMax(w, name, ty); |
| 1041 | 1049 | } |
| 1042 | 1050 | |
| 1043 | fn generateIntWidth(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { | |
| 1051 | fn generateIntWidth(comp: *Compilation, w: *Writer, name: []const u8, ty: Type) !void { | |
| 1044 | 1052 | try w.print("#define __{s}_WIDTH__ {d}\n", .{ name, 8 * ty.sizeof(comp).? }); |
| 1045 | 1053 | } |
| 1046 | 1054 | |
| 1047 | fn generateIntMaxAndWidth(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { | |
| 1055 | fn generateIntMaxAndWidth(comp: *Compilation, w: *Writer, name: []const u8, ty: Type) !void { | |
| 1048 | 1056 | try comp.generateIntMax(w, name, ty); |
| 1049 | 1057 | try comp.generateIntWidth(w, name, ty); |
| 1050 | 1058 | } |
| 1051 | 1059 | |
| 1052 | fn generateSizeofType(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { | |
| 1060 | fn generateSizeofType(comp: *Compilation, w: *Writer, name: []const u8, ty: Type) !void { | |
| 1053 | 1061 | try w.print("#define {s} {d}\n", .{ name, ty.sizeof(comp).? }); |
| 1054 | 1062 | } |
| 1055 | 1063 |
lib/compiler/aro/aro/Parser.zig+121-45| ... | ... | @@ -101,7 +101,7 @@ value_map: Tree.ValueMap, |
| 101 | 101 | |
| 102 | 102 | // buffers used during compilation |
| 103 | 103 | syms: SymbolStack = .{}, |
| 104 | strings: std.array_list.AlignedManaged(u8, .@"4"), | |
| 104 | strings: std.array_list.Managed(u8), | |
| 105 | 105 | labels: std.array_list.Managed(Label), |
| 106 | 106 | list_buf: NodeList, |
| 107 | 107 | decl_buf: NodeList, |
| ... | ... | @@ -447,7 +447,17 @@ pub fn typeStr(p: *Parser, ty: Type) ![]const u8 { |
| 447 | 447 | defer p.strings.items.len = strings_top; |
| 448 | 448 | |
| 449 | 449 | const mapper = p.comp.string_interner.getSlowTypeMapper(); |
| 450 | try ty.print(mapper, p.comp.langopts, p.strings.writer()); | |
| 450 | { | |
| 451 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 452 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 453 | defer { | |
| 454 | unmanaged = allocating.toArrayList(); | |
| 455 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 456 | } | |
| 457 | ty.print(mapper, p.comp.langopts, &allocating.writer) catch |e| switch (e) { | |
| 458 | error.WriteFailed => return error.OutOfMemory, | |
| 459 | }; | |
| 460 | } | |
| 451 | 461 | return try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 452 | 462 | } |
| 453 | 463 | |
| ... | ... | @@ -455,7 +465,7 @@ pub fn typePairStr(p: *Parser, a: Type, b: Type) ![]const u8 { |
| 455 | 465 | return p.typePairStrExtra(a, " and ", b); |
| 456 | 466 | } |
| 457 | 467 | |
| 458 | pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) ![]const u8 { | |
| 468 | pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) Error![]const u8 { | |
| 459 | 469 | if (@import("builtin").mode != .Debug) { |
| 460 | 470 | if (a.is(.invalid) or b.is(.invalid)) { |
| 461 | 471 | return "Tried to render invalid type - this is an aro bug."; |
| ... | ... | @@ -466,29 +476,60 @@ pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) ![]const |
| 466 | 476 | |
| 467 | 477 | try p.strings.append('\''); |
| 468 | 478 | const mapper = p.comp.string_interner.getSlowTypeMapper(); |
| 469 | try a.print(mapper, p.comp.langopts, p.strings.writer()); | |
| 479 | { | |
| 480 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 481 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 482 | defer { | |
| 483 | unmanaged = allocating.toArrayList(); | |
| 484 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 485 | } | |
| 486 | a.print(mapper, p.comp.langopts, &allocating.writer) catch |e| switch (e) { | |
| 487 | error.WriteFailed => return error.OutOfMemory, | |
| 488 | }; | |
| 489 | } | |
| 470 | 490 | try p.strings.append('\''); |
| 471 | 491 | try p.strings.appendSlice(msg); |
| 472 | 492 | try p.strings.append('\''); |
| 473 | try b.print(mapper, p.comp.langopts, p.strings.writer()); | |
| 493 | { | |
| 494 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 495 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 496 | defer { | |
| 497 | unmanaged = allocating.toArrayList(); | |
| 498 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 499 | } | |
| 500 | b.print(mapper, p.comp.langopts, &allocating.writer) catch |e| switch (e) { | |
| 501 | error.WriteFailed => return error.OutOfMemory, | |
| 502 | }; | |
| 503 | } | |
| 474 | 504 | try p.strings.append('\''); |
| 475 | 505 | return try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 476 | 506 | } |
| 477 | 507 | |
| 478 | pub fn valueChangedStr(p: *Parser, res: *Result, old_value: Value, int_ty: Type) ![]const u8 { | |
| 508 | pub fn valueChangedStr(p: *Parser, res: *Result, old_value: Value, int_ty: Type) Error![]const u8 { | |
| 479 | 509 | const strings_top = p.strings.items.len; |
| 480 | 510 | defer p.strings.items.len = strings_top; |
| 481 | 511 | |
| 482 | var w = p.strings.writer(); | |
| 483 | 512 | const type_pair_str = try p.typePairStrExtra(res.ty, " to ", int_ty); |
| 484 | try w.writeAll(type_pair_str); | |
| 513 | { | |
| 514 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 515 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 516 | defer { | |
| 517 | unmanaged = allocating.toArrayList(); | |
| 518 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 519 | } | |
| 520 | allocating.writer.writeAll(type_pair_str) catch return error.OutOfMemory; | |
| 485 | 521 | |
| 486 | try w.writeAll(" changes "); | |
| 487 | if (res.val.isZero(p.comp)) try w.writeAll("non-zero "); | |
| 488 | try w.writeAll("value from "); | |
| 489 | try old_value.print(res.ty, p.comp, w); | |
| 490 | try w.writeAll(" to "); | |
| 491 | try res.val.print(int_ty, p.comp, w); | |
| 522 | allocating.writer.writeAll(" changes ") catch return error.OutOfMemory; | |
| 523 | if (res.val.isZero(p.comp)) allocating.writer.writeAll("non-zero ") catch return error.OutOfMemory; | |
| 524 | allocating.writer.writeAll("value from ") catch return error.OutOfMemory; | |
| 525 | old_value.print(res.ty, p.comp, &allocating.writer) catch |e| switch (e) { | |
| 526 | error.WriteFailed => return error.OutOfMemory, | |
| 527 | }; | |
| 528 | allocating.writer.writeAll(" to ") catch return error.OutOfMemory; | |
| 529 | res.val.print(int_ty, p.comp, &allocating.writer) catch |e| switch (e) { | |
| 530 | error.WriteFailed => return error.OutOfMemory, | |
| 531 | }; | |
| 532 | } | |
| 492 | 533 | |
| 493 | 534 | return try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 494 | 535 | } |
| ... | ... | @@ -498,9 +539,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_ |
| 498 | 539 | const strings_top = p.strings.items.len; |
| 499 | 540 | defer p.strings.items.len = strings_top; |
| 500 | 541 | |
| 501 | const w = p.strings.writer(); | |
| 502 | 542 | const msg_str = p.comp.interner.get(@"error".msg.ref()).bytes; |
| 503 | try w.print("call to '{s}' declared with attribute error: {f}", .{ | |
| 543 | try p.strings.print("call to '{s}' declared with attribute error: {f}", .{ | |
| 504 | 544 | p.tokSlice(@"error".__name_tok), std.zig.fmtString(msg_str), |
| 505 | 545 | }); |
| 506 | 546 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| ... | ... | @@ -510,9 +550,8 @@ fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_ |
| 510 | 550 | const strings_top = p.strings.items.len; |
| 511 | 551 | defer p.strings.items.len = strings_top; |
| 512 | 552 | |
| 513 | const w = p.strings.writer(); | |
| 514 | 553 | const msg_str = p.comp.interner.get(warning.msg.ref()).bytes; |
| 515 | try w.print("call to '{s}' declared with attribute warning: {f}", .{ | |
| 554 | try p.strings.print("call to '{s}' declared with attribute warning: {f}", .{ | |
| 516 | 555 | p.tokSlice(warning.__name_tok), std.zig.fmtString(msg_str), |
| 517 | 556 | }); |
| 518 | 557 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| ... | ... | @@ -532,17 +571,16 @@ fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Valu |
| 532 | 571 | const strings_top = p.strings.items.len; |
| 533 | 572 | defer p.strings.items.len = strings_top; |
| 534 | 573 | |
| 535 | const w = p.strings.writer(); | |
| 536 | try w.print("'{s}' is ", .{p.tokSlice(tok_i)}); | |
| 574 | try p.strings.print("'{s}' is ", .{p.tokSlice(tok_i)}); | |
| 537 | 575 | const reason: []const u8 = switch (tag) { |
| 538 | 576 | .unavailable => "unavailable", |
| 539 | 577 | .deprecated_declarations => "deprecated", |
| 540 | 578 | else => unreachable, |
| 541 | 579 | }; |
| 542 | try w.writeAll(reason); | |
| 580 | try p.strings.appendSlice(reason); | |
| 543 | 581 | if (msg) |m| { |
| 544 | 582 | const str = p.comp.interner.get(m.ref()).bytes; |
| 545 | try w.print(": {f}", .{std.zig.fmtString(str)}); | |
| 583 | try p.strings.print(": {f}", .{std.zig.fmtString(str)}); | |
| 546 | 584 | } |
| 547 | 585 | const str = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 548 | 586 | return p.errStr(tag, tok_i, str); |
| ... | ... | @@ -681,7 +719,7 @@ fn diagnoseIncompleteDefinitions(p: *Parser) !void { |
| 681 | 719 | } |
| 682 | 720 | |
| 683 | 721 | /// root : (decl | assembly ';' | staticAssert)* |
| 684 | pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { | |
| 722 | pub fn parse(pp: *Preprocessor) Error!Tree { | |
| 685 | 723 | assert(pp.linemarkers == .none); |
| 686 | 724 | pp.comp.pragmaEvent(.before_parse); |
| 687 | 725 | |
| ... | ... | @@ -693,7 +731,7 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { |
| 693 | 731 | .gpa = pp.comp.gpa, |
| 694 | 732 | .arena = arena.allocator(), |
| 695 | 733 | .tok_ids = pp.tokens.items(.id), |
| 696 | .strings = std.array_list.AlignedManaged(u8, .@"4").init(pp.comp.gpa), | |
| 734 | .strings = std.array_list.Managed(u8).init(pp.comp.gpa), | |
| 697 | 735 | .value_map = Tree.ValueMap.init(pp.comp.gpa), |
| 698 | 736 | .data = NodeList.init(pp.comp.gpa), |
| 699 | 737 | .labels = std.array_list.Managed(Label).init(pp.comp.gpa), |
| ... | ... | @@ -1218,38 +1256,46 @@ fn decl(p: *Parser) Error!bool { |
| 1218 | 1256 | return true; |
| 1219 | 1257 | } |
| 1220 | 1258 | |
| 1221 | fn staticAssertMessage(p: *Parser, cond_node: NodeIndex, message: Result) !?[]const u8 { | |
| 1259 | fn staticAssertMessage(p: *Parser, cond_node: NodeIndex, message: Result) Error!?[]const u8 { | |
| 1222 | 1260 | const cond_tag = p.nodes.items(.tag)[@intFromEnum(cond_node)]; |
| 1223 | 1261 | if (cond_tag != .builtin_types_compatible_p and message.node == .none) return null; |
| 1224 | 1262 | |
| 1225 | var buf = std.array_list.Managed(u8).init(p.gpa); | |
| 1226 | defer buf.deinit(); | |
| 1263 | var allocating: std.Io.Writer.Allocating = .init(p.gpa); | |
| 1264 | defer allocating.deinit(); | |
| 1265 | ||
| 1266 | const buf = &allocating.writer; | |
| 1227 | 1267 | |
| 1228 | 1268 | if (cond_tag == .builtin_types_compatible_p) { |
| 1229 | 1269 | const mapper = p.comp.string_interner.getSlowTypeMapper(); |
| 1230 | 1270 | const data = p.nodes.items(.data)[@intFromEnum(cond_node)].bin; |
| 1231 | 1271 | |
| 1232 | try buf.appendSlice("'__builtin_types_compatible_p("); | |
| 1272 | buf.writeAll("'__builtin_types_compatible_p(") catch return error.OutOfMemory; | |
| 1233 | 1273 | |
| 1234 | 1274 | const lhs_ty = p.nodes.items(.ty)[@intFromEnum(data.lhs)]; |
| 1235 | try lhs_ty.print(mapper, p.comp.langopts, buf.writer()); | |
| 1236 | try buf.appendSlice(", "); | |
| 1275 | lhs_ty.print(mapper, p.comp.langopts, buf) catch |e| switch (e) { | |
| 1276 | error.WriteFailed => return error.OutOfMemory, | |
| 1277 | }; | |
| 1278 | buf.writeAll(", ") catch return error.OutOfMemory; | |
| 1237 | 1279 | |
| 1238 | 1280 | const rhs_ty = p.nodes.items(.ty)[@intFromEnum(data.rhs)]; |
| 1239 | try rhs_ty.print(mapper, p.comp.langopts, buf.writer()); | |
| 1281 | rhs_ty.print(mapper, p.comp.langopts, buf) catch |e| switch (e) { | |
| 1282 | error.WriteFailed => return error.OutOfMemory, | |
| 1283 | }; | |
| 1240 | 1284 | |
| 1241 | try buf.appendSlice(")'"); | |
| 1285 | buf.writeAll(")'") catch return error.OutOfMemory; | |
| 1242 | 1286 | } |
| 1243 | 1287 | if (message.node != .none) { |
| 1244 | 1288 | assert(p.nodes.items(.tag)[@intFromEnum(message.node)] == .string_literal_expr); |
| 1245 | if (buf.items.len > 0) { | |
| 1246 | try buf.append(' '); | |
| 1289 | if (buf.buffered().len > 0) { | |
| 1290 | buf.writeByte(' ') catch return error.OutOfMemory; | |
| 1247 | 1291 | } |
| 1248 | 1292 | const bytes = p.comp.interner.get(message.val.ref()).bytes; |
| 1249 | try buf.ensureUnusedCapacity(bytes.len); | |
| 1250 | try Value.printString(bytes, message.ty, p.comp, buf.writer()); | |
| 1293 | try allocating.ensureUnusedCapacity(bytes.len); | |
| 1294 | Value.printString(bytes, message.ty, p.comp, buf) catch |e| switch (e) { | |
| 1295 | error.WriteFailed => return error.OutOfMemory, | |
| 1296 | }; | |
| 1251 | 1297 | } |
| 1252 | return try p.comp.diagnostics.arena.allocator().dupe(u8, buf.items); | |
| 1298 | return try p.comp.diagnostics.arena.allocator().dupe(u8, allocating.written()); | |
| 1253 | 1299 | } |
| 1254 | 1300 | |
| 1255 | 1301 | /// staticAssert |
| ... | ... | @@ -4981,7 +5027,7 @@ const CallExpr = union(enum) { |
| 4981 | 5027 | return true; |
| 4982 | 5028 | } |
| 4983 | 5029 | |
| 4984 | fn checkVarArg(self: CallExpr, p: *Parser, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32) !void { | |
| 5030 | fn checkVarArg(self: CallExpr, p: *Parser, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32) Error!void { | |
| 4985 | 5031 | if (self == .standard) return; |
| 4986 | 5032 | |
| 4987 | 5033 | const builtin_tok = p.nodes.items(.data)[@intFromEnum(self.builtin.node)].decl.name; |
| ... | ... | @@ -5183,7 +5229,17 @@ pub const Result = struct { |
| 5183 | 5229 | const strings_top = p.strings.items.len; |
| 5184 | 5230 | defer p.strings.items.len = strings_top; |
| 5185 | 5231 | |
| 5186 | try res.val.print(res.ty, p.comp, p.strings.writer()); | |
| 5232 | { | |
| 5233 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 5234 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 5235 | defer { | |
| 5236 | unmanaged = allocating.toArrayList(); | |
| 5237 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 5238 | } | |
| 5239 | res.val.print(res.ty, p.comp, &allocating.writer) catch |e| switch (e) { | |
| 5240 | error.WriteFailed => return error.OutOfMemory, | |
| 5241 | }; | |
| 5242 | } | |
| 5187 | 5243 | return try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items[strings_top..]); |
| 5188 | 5244 | } |
| 5189 | 5245 | |
| ... | ... | @@ -5347,7 +5403,7 @@ pub const Result = struct { |
| 5347 | 5403 | conditional, |
| 5348 | 5404 | add, |
| 5349 | 5405 | sub, |
| 5350 | }) !bool { | |
| 5406 | }) Error!bool { | |
| 5351 | 5407 | if (b.ty.specifier == .invalid) { |
| 5352 | 5408 | try a.saveValue(p); |
| 5353 | 5409 | a.ty = Type.invalid; |
| ... | ... | @@ -5643,7 +5699,7 @@ pub const Result = struct { |
| 5643 | 5699 | } |
| 5644 | 5700 | } |
| 5645 | 5701 | |
| 5646 | fn floatToIntWarning(res: *Result, p: *Parser, int_ty: Type, old_value: Value, change_kind: Value.FloatToIntChangeKind, tok: TokenIndex) !void { | |
| 5702 | fn floatToIntWarning(res: *Result, p: *Parser, int_ty: Type, old_value: Value, change_kind: Value.FloatToIntChangeKind, tok: TokenIndex) Error!void { | |
| 5647 | 5703 | switch (change_kind) { |
| 5648 | 5704 | .none => return p.errStr(.float_to_int, tok, try p.typePairStrExtra(res.ty, " to ", int_ty)), |
| 5649 | 5705 | .out_of_range => return p.errStr(.float_out_of_range, tok, try p.typePairStrExtra(res.ty, " to ", int_ty)), |
| ... | ... | @@ -5866,7 +5922,7 @@ pub const Result = struct { |
| 5866 | 5922 | res.val = .{}; |
| 5867 | 5923 | } |
| 5868 | 5924 | |
| 5869 | fn castType(res: *Result, p: *Parser, to: Type, operand_tok: TokenIndex, l_paren: TokenIndex) !void { | |
| 5925 | fn castType(res: *Result, p: *Parser, to: Type, operand_tok: TokenIndex, l_paren: TokenIndex) Error!void { | |
| 5870 | 5926 | var cast_kind: Tree.CastKind = undefined; |
| 5871 | 5927 | |
| 5872 | 5928 | if (to.is(.void)) { |
| ... | ... | @@ -7595,9 +7651,19 @@ fn validateFieldAccess(p: *Parser, record_ty: *const Type.Record, expr_ty: Type, |
| 7595 | 7651 | |
| 7596 | 7652 | p.strings.items.len = 0; |
| 7597 | 7653 | |
| 7598 | try p.strings.writer().print("'{s}' in '", .{p.tokSlice(field_name_tok)}); | |
| 7654 | try p.strings.print("'{s}' in '", .{p.tokSlice(field_name_tok)}); | |
| 7599 | 7655 | const mapper = p.comp.string_interner.getSlowTypeMapper(); |
| 7600 | try expr_ty.print(mapper, p.comp.langopts, p.strings.writer()); | |
| 7656 | { | |
| 7657 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 7658 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 7659 | defer { | |
| 7660 | unmanaged = allocating.toArrayList(); | |
| 7661 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 7662 | } | |
| 7663 | expr_ty.print(mapper, p.comp.langopts, &allocating.writer) catch |e| switch (e) { | |
| 7664 | error.WriteFailed => return error.OutOfMemory, | |
| 7665 | }; | |
| 7666 | } | |
| 7601 | 7667 | try p.strings.append('\''); |
| 7602 | 7668 | |
| 7603 | 7669 | const duped = try p.comp.diagnostics.arena.allocator().dupe(u8, p.strings.items); |
| ... | ... | @@ -8016,7 +8082,17 @@ fn primaryExpr(p: *Parser) Error!Result { |
| 8016 | 8082 | defer p.strings.items.len = strings_top; |
| 8017 | 8083 | |
| 8018 | 8084 | const mapper = p.comp.string_interner.getSlowTypeMapper(); |
| 8019 | try Type.printNamed(func_ty, p.tokSlice(p.func.name), mapper, p.comp.langopts, p.strings.writer()); | |
| 8085 | { | |
| 8086 | var unmanaged = p.strings.moveToUnmanaged(); | |
| 8087 | var allocating: std.Io.Writer.Allocating = .fromArrayList(p.comp.gpa, &unmanaged); | |
| 8088 | defer { | |
| 8089 | unmanaged = allocating.toArrayList(); | |
| 8090 | p.strings = unmanaged.toManaged(p.comp.gpa); | |
| 8091 | } | |
| 8092 | Type.printNamed(func_ty, p.tokSlice(p.func.name), mapper, p.comp.langopts, &allocating.writer) catch |e| switch (e) { | |
| 8093 | error.WriteFailed => return error.OutOfMemory, | |
| 8094 | }; | |
| 8095 | } | |
| 8020 | 8096 | try p.strings.append(0); |
| 8021 | 8097 | const predef = try p.makePredefinedIdentifier(strings_top); |
| 8022 | 8098 | ty = predef.ty; |
lib/compiler/aro/aro/Preprocessor.zig+12-17| ... | ... | @@ -15,6 +15,7 @@ const TokenWithExpansionLocs = Tree.TokenWithExpansionLocs; |
| 15 | 15 | const Attribute = @import("Attribute.zig"); |
| 16 | 16 | const features = @import("features.zig"); |
| 17 | 17 | const Hideset = @import("Hideset.zig"); |
| 18 | const Writer = std.Io.Writer; | |
| 18 | 19 | |
| 19 | 20 | const DefineMap = std.StringHashMapUnmanaged(Macro); |
| 20 | 21 | const RawTokenList = std.array_list.Managed(RawToken); |
| ... | ... | @@ -982,7 +983,7 @@ fn expr(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!bool { |
| 982 | 983 | .tok_i = @intCast(token_state.tokens_len), |
| 983 | 984 | .arena = pp.arena.allocator(), |
| 984 | 985 | .in_macro = true, |
| 985 | .strings = std.array_list.AlignedManaged(u8, .@"4").init(pp.comp.gpa), | |
| 986 | .strings = std.array_list.Managed(u8).init(pp.comp.gpa), | |
| 986 | 987 | |
| 987 | 988 | .data = undefined, |
| 988 | 989 | .value_map = undefined, |
| ... | ... | @@ -1193,24 +1194,21 @@ fn expandObjMacro(pp: *Preprocessor, simple_macro: *const Macro) Error!ExpandBuf |
| 1193 | 1194 | .macro_file => { |
| 1194 | 1195 | const start = pp.comp.generated_buf.items.len; |
| 1195 | 1196 | const source = pp.comp.getSource(pp.expansion_source_loc.id); |
| 1196 | const w = pp.comp.generated_buf.writer(pp.gpa); | |
| 1197 | try w.print("\"{s}\"\n", .{source.path}); | |
| 1197 | try pp.comp.generated_buf.print(pp.gpa, "\"{s}\"\n", .{source.path}); | |
| 1198 | 1198 | |
| 1199 | 1199 | buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .string_literal, tok)); |
| 1200 | 1200 | }, |
| 1201 | 1201 | .macro_line => { |
| 1202 | 1202 | const start = pp.comp.generated_buf.items.len; |
| 1203 | 1203 | const source = pp.comp.getSource(pp.expansion_source_loc.id); |
| 1204 | const w = pp.comp.generated_buf.writer(pp.gpa); | |
| 1205 | try w.print("{d}\n", .{source.physicalLine(pp.expansion_source_loc)}); | |
| 1204 | try pp.comp.generated_buf.print(pp.gpa, "{d}\n", .{source.physicalLine(pp.expansion_source_loc)}); | |
| 1206 | 1205 | |
| 1207 | 1206 | buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .pp_num, tok)); |
| 1208 | 1207 | }, |
| 1209 | 1208 | .macro_counter => { |
| 1210 | 1209 | defer pp.counter += 1; |
| 1211 | 1210 | const start = pp.comp.generated_buf.items.len; |
| 1212 | const w = pp.comp.generated_buf.writer(pp.gpa); | |
| 1213 | try w.print("{d}\n", .{pp.counter}); | |
| 1211 | try pp.comp.generated_buf.print(pp.gpa, "{d}\n", .{pp.counter}); | |
| 1214 | 1212 | |
| 1215 | 1213 | buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .pp_num, tok)); |
| 1216 | 1214 | }, |
| ... | ... | @@ -1682,8 +1680,7 @@ fn expandFuncMacro( |
| 1682 | 1680 | break :blk false; |
| 1683 | 1681 | } else try pp.handleBuiltinMacro(raw.id, arg, macro_tok.loc); |
| 1684 | 1682 | const start = pp.comp.generated_buf.items.len; |
| 1685 | const w = pp.comp.generated_buf.writer(pp.gpa); | |
| 1686 | try w.print("{}\n", .{@intFromBool(result)}); | |
| 1683 | try pp.comp.generated_buf.print(pp.gpa, "{}\n", .{@intFromBool(result)}); | |
| 1687 | 1684 | try buf.append(try pp.makeGeneratedToken(start, .pp_num, tokFromRaw(raw))); |
| 1688 | 1685 | }, |
| 1689 | 1686 | .macro_param_has_c_attribute => { |
| ... | ... | @@ -2988,18 +2985,16 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { |
| 2988 | 2985 | // TODO: We currently only support systems with CHAR_BIT == 8 |
| 2989 | 2986 | // If the target's CHAR_BIT is not 8, we need to write out correctly-sized embed_bytes |
| 2990 | 2987 | // and correctly account for the target's endianness |
| 2991 | const writer = pp.comp.generated_buf.writer(pp.gpa); | |
| 2992 | ||
| 2993 | 2988 | { |
| 2994 | 2989 | const byte = embed_bytes[0]; |
| 2995 | 2990 | const start = pp.comp.generated_buf.items.len; |
| 2996 | try writer.print("{d}", .{byte}); | |
| 2991 | try pp.comp.generated_buf.print(pp.gpa, "{d}", .{byte}); | |
| 2997 | 2992 | pp.addTokenAssumeCapacity(try pp.makeGeneratedToken(start, .embed_byte, filename_tok)); |
| 2998 | 2993 | } |
| 2999 | 2994 | |
| 3000 | 2995 | for (embed_bytes[1..]) |byte| { |
| 3001 | 2996 | const start = pp.comp.generated_buf.items.len; |
| 3002 | try writer.print(",{d}", .{byte}); | |
| 2997 | try pp.comp.generated_buf.print(pp.gpa, ",{d}", .{byte}); | |
| 3003 | 2998 | pp.addTokenAssumeCapacity(.{ .id = .comma, .loc = .{ .id = .generated, .byte_offset = @intCast(start) } }); |
| 3004 | 2999 | pp.addTokenAssumeCapacity(try pp.makeGeneratedToken(start + 1, .embed_byte, filename_tok)); |
| 3005 | 3000 | } |
| ... | ... | @@ -3241,7 +3236,7 @@ fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, |
| 3241 | 3236 | |
| 3242 | 3237 | fn printLinemarker( |
| 3243 | 3238 | pp: *Preprocessor, |
| 3244 | w: anytype, | |
| 3239 | w: *Writer, | |
| 3245 | 3240 | line_no: u32, |
| 3246 | 3241 | source: Source, |
| 3247 | 3242 | start_resume: enum(u8) { start, @"resume", none }, |
| ... | ... | @@ -3301,7 +3296,7 @@ pub const DumpMode = enum { |
| 3301 | 3296 | /// Pretty-print the macro define or undef at location `loc`. |
| 3302 | 3297 | /// We re-tokenize the directive because we are printing a macro that may have the same name as one in |
| 3303 | 3298 | /// `pp.defines` but a different definition (due to being #undef'ed and then redefined) |
| 3304 | fn prettyPrintMacro(pp: *Preprocessor, w: anytype, loc: Source.Location, parts: enum { name_only, name_and_body }) !void { | |
| 3299 | fn prettyPrintMacro(pp: *Preprocessor, w: *Writer, loc: Source.Location, parts: enum { name_only, name_and_body }) !void { | |
| 3305 | 3300 | const source = pp.comp.getSource(loc.id); |
| 3306 | 3301 | var tokenizer: Tokenizer = .{ |
| 3307 | 3302 | .buf = source.buf, |
| ... | ... | @@ -3339,7 +3334,7 @@ fn prettyPrintMacro(pp: *Preprocessor, w: anytype, loc: Source.Location, parts: |
| 3339 | 3334 | } |
| 3340 | 3335 | } |
| 3341 | 3336 | |
| 3342 | fn prettyPrintMacrosOnly(pp: *Preprocessor, w: anytype) !void { | |
| 3337 | fn prettyPrintMacrosOnly(pp: *Preprocessor, w: *Writer) !void { | |
| 3343 | 3338 | var it = pp.defines.valueIterator(); |
| 3344 | 3339 | while (it.next()) |macro| { |
| 3345 | 3340 | if (macro.is_builtin) continue; |
| ... | ... | @@ -3351,7 +3346,7 @@ fn prettyPrintMacrosOnly(pp: *Preprocessor, w: anytype) !void { |
| 3351 | 3346 | } |
| 3352 | 3347 | |
| 3353 | 3348 | /// Pretty print tokens and try to preserve whitespace. |
| 3354 | pub fn prettyPrintTokens(pp: *Preprocessor, w: anytype, macro_dump_mode: DumpMode) !void { | |
| 3349 | pub fn prettyPrintTokens(pp: *Preprocessor, w: *Writer, macro_dump_mode: DumpMode) !void { | |
| 3355 | 3350 | if (macro_dump_mode == .macros_only) { |
| 3356 | 3351 | return pp.prettyPrintMacrosOnly(w); |
| 3357 | 3352 | } |
lib/compiler/aro/aro/Type.zig+9-8| ... | ... | @@ -9,6 +9,7 @@ const StringInterner = @import("StringInterner.zig"); |
| 9 | 9 | const StringId = StringInterner.StringId; |
| 10 | 10 | const target_util = @import("target.zig"); |
| 11 | 11 | const LangOpts = @import("LangOpts.zig"); |
| 12 | const Writer = std.Io.Writer; | |
| 12 | 13 | |
| 13 | 14 | pub const Qualifiers = packed struct { |
| 14 | 15 | @"const": bool = false, |
| ... | ... | @@ -23,7 +24,7 @@ pub const Qualifiers = packed struct { |
| 23 | 24 | return quals.@"const" or quals.restrict or quals.@"volatile" or quals.atomic; |
| 24 | 25 | } |
| 25 | 26 | |
| 26 | pub fn dump(quals: Qualifiers, w: anytype) !void { | |
| 27 | pub fn dump(quals: Qualifiers, w: *Writer) !void { | |
| 27 | 28 | if (quals.@"const") try w.writeAll("const "); |
| 28 | 29 | if (quals.atomic) try w.writeAll("_Atomic "); |
| 29 | 30 | if (quals.@"volatile") try w.writeAll("volatile "); |
| ... | ... | @@ -2411,12 +2412,12 @@ pub fn intValueSuffix(ty: Type, comp: *const Compilation) []const u8 { |
| 2411 | 2412 | } |
| 2412 | 2413 | |
| 2413 | 2414 | /// Print type in C style |
| 2414 | pub fn print(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | |
| 2415 | pub fn print(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!void { | |
| 2415 | 2416 | _ = try ty.printPrologue(mapper, langopts, w); |
| 2416 | 2417 | try ty.printEpilogue(mapper, langopts, w); |
| 2417 | 2418 | } |
| 2418 | 2419 | |
| 2419 | pub fn printNamed(ty: Type, name: []const u8, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | |
| 2420 | pub fn printNamed(ty: Type, name: []const u8, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!void { | |
| 2420 | 2421 | const simple = try ty.printPrologue(mapper, langopts, w); |
| 2421 | 2422 | if (simple) try w.writeByte(' '); |
| 2422 | 2423 | try w.writeAll(name); |
| ... | ... | @@ -2426,7 +2427,7 @@ pub fn printNamed(ty: Type, name: []const u8, mapper: StringInterner.TypeMapper, |
| 2426 | 2427 | const StringGetter = fn (TokenIndex) []const u8; |
| 2427 | 2428 | |
| 2428 | 2429 | /// return true if `ty` is simple |
| 2429 | fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!bool { | |
| 2430 | fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!bool { | |
| 2430 | 2431 | if (ty.qual.atomic) { |
| 2431 | 2432 | var non_atomic_ty = ty; |
| 2432 | 2433 | non_atomic_ty.qual.atomic = false; |
| ... | ... | @@ -2497,7 +2498,7 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2497 | 2498 | return true; |
| 2498 | 2499 | } |
| 2499 | 2500 | |
| 2500 | fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | |
| 2501 | fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!void { | |
| 2501 | 2502 | if (ty.qual.atomic) return; |
| 2502 | 2503 | if (ty.isPtr()) { |
| 2503 | 2504 | const elem_ty = ty.elemType(); |
| ... | ... | @@ -2564,7 +2565,7 @@ fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2564 | 2565 | const dump_detailed_containers = false; |
| 2565 | 2566 | |
| 2566 | 2567 | // Print as Zig types since those are actually readable |
| 2567 | pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | |
| 2568 | pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!void { | |
| 2568 | 2569 | try ty.qual.dump(w); |
| 2569 | 2570 | switch (ty.specifier) { |
| 2570 | 2571 | .invalid => try w.writeAll("invalid"), |
| ... | ... | @@ -2656,7 +2657,7 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: |
| 2656 | 2657 | } |
| 2657 | 2658 | } |
| 2658 | 2659 | |
| 2659 | fn dumpEnum(@"enum": *Enum, mapper: StringInterner.TypeMapper, w: anytype) @TypeOf(w).Error!void { | |
| 2660 | fn dumpEnum(@"enum": *Enum, mapper: StringInterner.TypeMapper, w: *Writer) Writer.Error!void { | |
| 2660 | 2661 | try w.writeAll(" {"); |
| 2661 | 2662 | for (@"enum".fields) |field| { |
| 2662 | 2663 | try w.print(" {s} = {d},", .{ mapper.lookup(field.name), field.value }); |
| ... | ... | @@ -2664,7 +2665,7 @@ fn dumpEnum(@"enum": *Enum, mapper: StringInterner.TypeMapper, w: anytype) @Type |
| 2664 | 2665 | try w.writeAll(" }"); |
| 2665 | 2666 | } |
| 2666 | 2667 | |
| 2667 | fn dumpRecord(record: *Record, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | |
| 2668 | fn dumpRecord(record: *Record, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: *Writer) Writer.Error!void { | |
| 2668 | 2669 | try w.writeAll(" {"); |
| 2669 | 2670 | for (record.fields) |field| { |
| 2670 | 2671 | try w.writeByte(' '); |
lib/compiler/aro/aro/Value.zig+3-2| ... | ... | @@ -9,6 +9,7 @@ const Compilation = @import("Compilation.zig"); |
| 9 | 9 | const Type = @import("Type.zig"); |
| 10 | 10 | const target_util = @import("target.zig"); |
| 11 | 11 | const annex_g = @import("annex_g.zig"); |
| 12 | const Writer = std.Io.Writer; | |
| 12 | 13 | |
| 13 | 14 | const Value = @This(); |
| 14 | 15 | |
| ... | ... | @@ -953,7 +954,7 @@ pub fn maxInt(ty: Type, comp: *Compilation) !Value { |
| 953 | 954 | return twosCompIntLimit(.max, ty, comp); |
| 954 | 955 | } |
| 955 | 956 | |
| 956 | pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void { | |
| 957 | pub fn print(v: Value, ty: Type, comp: *const Compilation, w: *Writer) Writer.Error!void { | |
| 957 | 958 | if (ty.is(.bool)) { |
| 958 | 959 | return w.writeAll(if (v.isZero(comp)) "false" else "true"); |
| 959 | 960 | } |
| ... | ... | @@ -977,7 +978,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w |
| 977 | 978 | } |
| 978 | 979 | } |
| 979 | 980 | |
| 980 | pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void { | |
| 981 | pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: *Writer) Writer.Error!void { | |
| 981 | 982 | const size: Compilation.CharUnitSize = @enumFromInt(ty.elemType().sizeof(comp).?); |
| 982 | 983 | const without_null = bytes[0 .. bytes.len - @intFromEnum(size)]; |
| 983 | 984 | try w.writeByte('"'); |
lib/compiler/aro_translate_c.zig+10-8| ... | ... | @@ -116,15 +116,17 @@ pub fn translate( |
| 116 | 116 | var driver: aro.Driver = .{ .comp = comp }; |
| 117 | 117 | defer driver.deinit(); |
| 118 | 118 | |
| 119 | var macro_buf = std.array_list.Managed(u8).init(gpa); | |
| 119 | var macro_buf: std.Io.Writer.Allocating = .init(gpa); | |
| 120 | 120 | defer macro_buf.deinit(); |
| 121 | 121 | |
| 122 | assert(!try driver.parseArgs(std.io.null_writer, macro_buf.writer(), args)); | |
| 122 | var trash: [64]u8 = undefined; | |
| 123 | var discarding: std.Io.Writer.Discarding = .init(&trash); | |
| 124 | assert(!try driver.parseArgs(&discarding.writer, &macro_buf.writer, args)); | |
| 123 | 125 | assert(driver.inputs.items.len == 1); |
| 124 | 126 | const source = driver.inputs.items[0]; |
| 125 | 127 | |
| 126 | 128 | const builtin_macros = try comp.generateBuiltinMacros(.include_system_defines); |
| 127 | const user_macros = try comp.addSourceFromBuffer("<command line>", macro_buf.items); | |
| 129 | const user_macros = try comp.addSourceFromBuffer("<command line>", macro_buf.written()); | |
| 128 | 130 | |
| 129 | 131 | var pp = try aro.Preprocessor.initDefault(comp); |
| 130 | 132 | defer pp.deinit(); |
| ... | ... | @@ -698,11 +700,10 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const Type.Enum, field_ |
| 698 | 700 | } |
| 699 | 701 | |
| 700 | 702 | fn getTypeStr(c: *Context, ty: Type) ![]const u8 { |
| 701 | var buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 702 | defer buf.deinit(c.gpa); | |
| 703 | const w = buf.writer(c.gpa); | |
| 704 | try ty.print(c.mapper, c.comp.langopts, w); | |
| 705 | return c.arena.dupe(u8, buf.items); | |
| 703 | var allocating: std.Io.Writer.Allocating = .init(c.gpa); | |
| 704 | defer allocating.deinit(); | |
| 705 | ty.print(c.mapper, c.comp.langopts, &allocating.writer) catch return error.OutOfMemory; | |
| 706 | return c.arena.dupe(u8, allocating.written()); | |
| 706 | 707 | } |
| 707 | 708 | |
| 708 | 709 | fn transType(c: *Context, scope: *Scope, raw_ty: Type, qual_handling: Type.QualHandling, source_loc: TokenIndex) TypeError!ZigNode { |
| ... | ... | @@ -1820,6 +1821,7 @@ pub fn main() !void { |
| 1820 | 1821 | var tree = translate(gpa, &aro_comp, args) catch |err| switch (err) { |
| 1821 | 1822 | error.ParsingFailed, error.FatalError => renderErrorsAndExit(&aro_comp), |
| 1822 | 1823 | error.OutOfMemory => return error.OutOfMemory, |
| 1824 | error.WriteFailed => return error.WriteFailed, | |
| 1823 | 1825 | error.StreamTooLong => std.process.fatal("An input file was larger than 4GiB", .{}), |
| 1824 | 1826 | }; |
| 1825 | 1827 | defer tree.deinit(gpa); |
lib/compiler/aro_translate_c/ast.zig+1-1| ... | ... | @@ -832,7 +832,7 @@ const Context = struct { |
| 832 | 832 | |
| 833 | 833 | fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex { |
| 834 | 834 | const start_index = c.buf.items.len; |
| 835 | try c.buf.writer().print(format ++ " ", args); | |
| 835 | try c.buf.print(format ++ " ", args); | |
| 836 | 836 | |
| 837 | 837 | try c.tokens.append(c.gpa, .{ |
| 838 | 838 | .tag = tag, |
lib/compiler/resinator/ani.zig+13-13| ... | ... | @@ -16,31 +16,31 @@ const std = @import("std"); |
| 16 | 16 | |
| 17 | 17 | const AF_ICON: u32 = 1; |
| 18 | 18 | |
| 19 | pub fn isAnimatedIcon(reader: anytype) bool { | |
| 19 | pub fn isAnimatedIcon(reader: *std.Io.Reader) bool { | |
| 20 | 20 | const flags = getAniheaderFlags(reader) catch return false; |
| 21 | 21 | return flags & AF_ICON == AF_ICON; |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | fn getAniheaderFlags(reader: anytype) !u32 { | |
| 25 | const riff_header = try reader.readBytesNoEof(4); | |
| 26 | if (!std.mem.eql(u8, &riff_header, "RIFF")) return error.InvalidFormat; | |
| 24 | fn getAniheaderFlags(reader: *std.Io.Reader) !u32 { | |
| 25 | const riff_header = try reader.takeArray(4); | |
| 26 | if (!std.mem.eql(u8, riff_header, "RIFF")) return error.InvalidFormat; | |
| 27 | 27 | |
| 28 | _ = try reader.readInt(u32, .little); // size of RIFF chunk | |
| 28 | _ = try reader.takeInt(u32, .little); // size of RIFF chunk | |
| 29 | 29 | |
| 30 | const form_type = try reader.readBytesNoEof(4); | |
| 31 | if (!std.mem.eql(u8, &form_type, "ACON")) return error.InvalidFormat; | |
| 30 | const form_type = try reader.takeArray(4); | |
| 31 | if (!std.mem.eql(u8, form_type, "ACON")) return error.InvalidFormat; | |
| 32 | 32 | |
| 33 | 33 | while (true) { |
| 34 | const chunk_id = try reader.readBytesNoEof(4); | |
| 35 | const chunk_len = try reader.readInt(u32, .little); | |
| 36 | if (!std.mem.eql(u8, &chunk_id, "anih")) { | |
| 34 | const chunk_id = try reader.takeArray(4); | |
| 35 | const chunk_len = try reader.takeInt(u32, .little); | |
| 36 | if (!std.mem.eql(u8, chunk_id, "anih")) { | |
| 37 | 37 | // TODO: Move file cursor instead of skipBytes |
| 38 | try reader.skipBytes(chunk_len, .{}); | |
| 38 | try reader.discardAll(chunk_len); | |
| 39 | 39 | continue; |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | const aniheader = try reader.readStruct(ANIHEADER); | |
| 43 | return std.mem.nativeToLittle(u32, aniheader.flags); | |
| 42 | const aniheader = try reader.takeStruct(ANIHEADER, .little); | |
| 43 | return aniheader.flags; | |
| 44 | 44 | } |
| 45 | 45 | } |
| 46 | 46 |
lib/compiler/resinator/ast.zig+40-40| ... | ... | @@ -22,13 +22,13 @@ pub const Tree = struct { |
| 22 | 22 | return @alignCast(@fieldParentPtr("base", self.node)); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | pub fn dump(self: *Tree, writer: anytype) @TypeOf(writer).Error!void { | |
| 25 | pub fn dump(self: *Tree, writer: *std.io.Writer) !void { | |
| 26 | 26 | try self.node.dump(self, writer, 0); |
| 27 | 27 | } |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | 30 | pub const CodePageLookup = struct { |
| 31 | lookup: std.ArrayListUnmanaged(SupportedCodePage) = .empty, | |
| 31 | lookup: std.ArrayList(SupportedCodePage) = .empty, | |
| 32 | 32 | allocator: Allocator, |
| 33 | 33 | default_code_page: SupportedCodePage, |
| 34 | 34 | |
| ... | ... | @@ -726,10 +726,10 @@ pub const Node = struct { |
| 726 | 726 | pub fn dump( |
| 727 | 727 | node: *const Node, |
| 728 | 728 | tree: *const Tree, |
| 729 | writer: anytype, | |
| 729 | writer: *std.io.Writer, | |
| 730 | 730 | indent: usize, |
| 731 | ) @TypeOf(writer).Error!void { | |
| 732 | try writer.writeByteNTimes(' ', indent); | |
| 731 | ) std.io.Writer.Error!void { | |
| 732 | try writer.splatByteAll(' ', indent); | |
| 733 | 733 | try writer.writeAll(@tagName(node.id)); |
| 734 | 734 | switch (node.id) { |
| 735 | 735 | .root => { |
| ... | ... | @@ -768,11 +768,11 @@ pub const Node = struct { |
| 768 | 768 | .grouped_expression => { |
| 769 | 769 | const grouped: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); |
| 770 | 770 | try writer.writeAll("\n"); |
| 771 | try writer.writeByteNTimes(' ', indent); | |
| 771 | try writer.splatByteAll(' ', indent); | |
| 772 | 772 | try writer.writeAll(grouped.open_token.slice(tree.source)); |
| 773 | 773 | try writer.writeAll("\n"); |
| 774 | 774 | try grouped.expression.dump(tree, writer, indent + 1); |
| 775 | try writer.writeByteNTimes(' ', indent); | |
| 775 | try writer.splatByteAll(' ', indent); | |
| 776 | 776 | try writer.writeAll(grouped.close_token.slice(tree.source)); |
| 777 | 777 | try writer.writeAll("\n"); |
| 778 | 778 | }, |
| ... | ... | @@ -790,13 +790,13 @@ pub const Node = struct { |
| 790 | 790 | for (accelerators.optional_statements) |statement| { |
| 791 | 791 | try statement.dump(tree, writer, indent + 1); |
| 792 | 792 | } |
| 793 | try writer.writeByteNTimes(' ', indent); | |
| 793 | try writer.splatByteAll(' ', indent); | |
| 794 | 794 | try writer.writeAll(accelerators.begin_token.slice(tree.source)); |
| 795 | 795 | try writer.writeAll("\n"); |
| 796 | 796 | for (accelerators.accelerators) |accelerator| { |
| 797 | 797 | try accelerator.dump(tree, writer, indent + 1); |
| 798 | 798 | } |
| 799 | try writer.writeByteNTimes(' ', indent); | |
| 799 | try writer.splatByteAll(' ', indent); | |
| 800 | 800 | try writer.writeAll(accelerators.end_token.slice(tree.source)); |
| 801 | 801 | try writer.writeAll("\n"); |
| 802 | 802 | }, |
| ... | ... | @@ -815,25 +815,25 @@ pub const Node = struct { |
| 815 | 815 | const dialog: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node)); |
| 816 | 816 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ dialog.id.slice(tree.source), dialog.type.slice(tree.source), dialog.common_resource_attributes.len }); |
| 817 | 817 | inline for (.{ "x", "y", "width", "height" }) |arg| { |
| 818 | try writer.writeByteNTimes(' ', indent + 1); | |
| 818 | try writer.splatByteAll(' ', indent + 1); | |
| 819 | 819 | try writer.writeAll(arg ++ ":\n"); |
| 820 | 820 | try @field(dialog, arg).dump(tree, writer, indent + 2); |
| 821 | 821 | } |
| 822 | 822 | if (dialog.help_id) |help_id| { |
| 823 | try writer.writeByteNTimes(' ', indent + 1); | |
| 823 | try writer.splatByteAll(' ', indent + 1); | |
| 824 | 824 | try writer.writeAll("help_id:\n"); |
| 825 | 825 | try help_id.dump(tree, writer, indent + 2); |
| 826 | 826 | } |
| 827 | 827 | for (dialog.optional_statements) |statement| { |
| 828 | 828 | try statement.dump(tree, writer, indent + 1); |
| 829 | 829 | } |
| 830 | try writer.writeByteNTimes(' ', indent); | |
| 830 | try writer.splatByteAll(' ', indent); | |
| 831 | 831 | try writer.writeAll(dialog.begin_token.slice(tree.source)); |
| 832 | 832 | try writer.writeAll("\n"); |
| 833 | 833 | for (dialog.controls) |control| { |
| 834 | 834 | try control.dump(tree, writer, indent + 1); |
| 835 | 835 | } |
| 836 | try writer.writeByteNTimes(' ', indent); | |
| 836 | try writer.splatByteAll(' ', indent); | |
| 837 | 837 | try writer.writeAll(dialog.end_token.slice(tree.source)); |
| 838 | 838 | try writer.writeAll("\n"); |
| 839 | 839 | }, |
| ... | ... | @@ -845,30 +845,30 @@ pub const Node = struct { |
| 845 | 845 | } |
| 846 | 846 | try writer.writeByte('\n'); |
| 847 | 847 | if (control.class) |class| { |
| 848 | try writer.writeByteNTimes(' ', indent + 1); | |
| 848 | try writer.splatByteAll(' ', indent + 1); | |
| 849 | 849 | try writer.writeAll("class:\n"); |
| 850 | 850 | try class.dump(tree, writer, indent + 2); |
| 851 | 851 | } |
| 852 | 852 | inline for (.{ "id", "x", "y", "width", "height" }) |arg| { |
| 853 | try writer.writeByteNTimes(' ', indent + 1); | |
| 853 | try writer.splatByteAll(' ', indent + 1); | |
| 854 | 854 | try writer.writeAll(arg ++ ":\n"); |
| 855 | 855 | try @field(control, arg).dump(tree, writer, indent + 2); |
| 856 | 856 | } |
| 857 | 857 | inline for (.{ "style", "exstyle", "help_id" }) |arg| { |
| 858 | 858 | if (@field(control, arg)) |val_node| { |
| 859 | try writer.writeByteNTimes(' ', indent + 1); | |
| 859 | try writer.splatByteAll(' ', indent + 1); | |
| 860 | 860 | try writer.writeAll(arg ++ ":\n"); |
| 861 | 861 | try val_node.dump(tree, writer, indent + 2); |
| 862 | 862 | } |
| 863 | 863 | } |
| 864 | 864 | if (control.extra_data_begin != null) { |
| 865 | try writer.writeByteNTimes(' ', indent); | |
| 865 | try writer.splatByteAll(' ', indent); | |
| 866 | 866 | try writer.writeAll(control.extra_data_begin.?.slice(tree.source)); |
| 867 | 867 | try writer.writeAll("\n"); |
| 868 | 868 | for (control.extra_data) |data_node| { |
| 869 | 869 | try data_node.dump(tree, writer, indent + 1); |
| 870 | 870 | } |
| 871 | try writer.writeByteNTimes(' ', indent); | |
| 871 | try writer.splatByteAll(' ', indent); | |
| 872 | 872 | try writer.writeAll(control.extra_data_end.?.slice(tree.source)); |
| 873 | 873 | try writer.writeAll("\n"); |
| 874 | 874 | } |
| ... | ... | @@ -877,17 +877,17 @@ pub const Node = struct { |
| 877 | 877 | const toolbar: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); |
| 878 | 878 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ toolbar.id.slice(tree.source), toolbar.type.slice(tree.source), toolbar.common_resource_attributes.len }); |
| 879 | 879 | inline for (.{ "button_width", "button_height" }) |arg| { |
| 880 | try writer.writeByteNTimes(' ', indent + 1); | |
| 880 | try writer.splatByteAll(' ', indent + 1); | |
| 881 | 881 | try writer.writeAll(arg ++ ":\n"); |
| 882 | 882 | try @field(toolbar, arg).dump(tree, writer, indent + 2); |
| 883 | 883 | } |
| 884 | try writer.writeByteNTimes(' ', indent); | |
| 884 | try writer.splatByteAll(' ', indent); | |
| 885 | 885 | try writer.writeAll(toolbar.begin_token.slice(tree.source)); |
| 886 | 886 | try writer.writeAll("\n"); |
| 887 | 887 | for (toolbar.buttons) |button_or_sep| { |
| 888 | 888 | try button_or_sep.dump(tree, writer, indent + 1); |
| 889 | 889 | } |
| 890 | try writer.writeByteNTimes(' ', indent); | |
| 890 | try writer.splatByteAll(' ', indent); | |
| 891 | 891 | try writer.writeAll(toolbar.end_token.slice(tree.source)); |
| 892 | 892 | try writer.writeAll("\n"); |
| 893 | 893 | }, |
| ... | ... | @@ -898,17 +898,17 @@ pub const Node = struct { |
| 898 | 898 | try statement.dump(tree, writer, indent + 1); |
| 899 | 899 | } |
| 900 | 900 | if (menu.help_id) |help_id| { |
| 901 | try writer.writeByteNTimes(' ', indent + 1); | |
| 901 | try writer.splatByteAll(' ', indent + 1); | |
| 902 | 902 | try writer.writeAll("help_id:\n"); |
| 903 | 903 | try help_id.dump(tree, writer, indent + 2); |
| 904 | 904 | } |
| 905 | try writer.writeByteNTimes(' ', indent); | |
| 905 | try writer.splatByteAll(' ', indent); | |
| 906 | 906 | try writer.writeAll(menu.begin_token.slice(tree.source)); |
| 907 | 907 | try writer.writeAll("\n"); |
| 908 | 908 | for (menu.items) |item| { |
| 909 | 909 | try item.dump(tree, writer, indent + 1); |
| 910 | 910 | } |
| 911 | try writer.writeByteNTimes(' ', indent); | |
| 911 | try writer.splatByteAll(' ', indent); | |
| 912 | 912 | try writer.writeAll(menu.end_token.slice(tree.source)); |
| 913 | 913 | try writer.writeAll("\n"); |
| 914 | 914 | }, |
| ... | ... | @@ -926,7 +926,7 @@ pub const Node = struct { |
| 926 | 926 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) }); |
| 927 | 927 | inline for (.{ "id", "type", "state" }) |arg| { |
| 928 | 928 | if (@field(menu_item, arg)) |val_node| { |
| 929 | try writer.writeByteNTimes(' ', indent + 1); | |
| 929 | try writer.splatByteAll(' ', indent + 1); | |
| 930 | 930 | try writer.writeAll(arg ++ ":\n"); |
| 931 | 931 | try val_node.dump(tree, writer, indent + 2); |
| 932 | 932 | } |
| ... | ... | @@ -935,13 +935,13 @@ pub const Node = struct { |
| 935 | 935 | .popup => { |
| 936 | 936 | const popup: *const Node.Popup = @alignCast(@fieldParentPtr("base", node)); |
| 937 | 937 | try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len }); |
| 938 | try writer.writeByteNTimes(' ', indent); | |
| 938 | try writer.splatByteAll(' ', indent); | |
| 939 | 939 | try writer.writeAll(popup.begin_token.slice(tree.source)); |
| 940 | 940 | try writer.writeAll("\n"); |
| 941 | 941 | for (popup.items) |item| { |
| 942 | 942 | try item.dump(tree, writer, indent + 1); |
| 943 | 943 | } |
| 944 | try writer.writeByteNTimes(' ', indent); | |
| 944 | try writer.splatByteAll(' ', indent); | |
| 945 | 945 | try writer.writeAll(popup.end_token.slice(tree.source)); |
| 946 | 946 | try writer.writeAll("\n"); |
| 947 | 947 | }, |
| ... | ... | @@ -950,18 +950,18 @@ pub const Node = struct { |
| 950 | 950 | try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) }); |
| 951 | 951 | inline for (.{ "id", "type", "state", "help_id" }) |arg| { |
| 952 | 952 | if (@field(popup, arg)) |val_node| { |
| 953 | try writer.writeByteNTimes(' ', indent + 1); | |
| 953 | try writer.splatByteAll(' ', indent + 1); | |
| 954 | 954 | try writer.writeAll(arg ++ ":\n"); |
| 955 | 955 | try val_node.dump(tree, writer, indent + 2); |
| 956 | 956 | } |
| 957 | 957 | } |
| 958 | try writer.writeByteNTimes(' ', indent); | |
| 958 | try writer.splatByteAll(' ', indent); | |
| 959 | 959 | try writer.writeAll(popup.begin_token.slice(tree.source)); |
| 960 | 960 | try writer.writeAll("\n"); |
| 961 | 961 | for (popup.items) |item| { |
| 962 | 962 | try item.dump(tree, writer, indent + 1); |
| 963 | 963 | } |
| 964 | try writer.writeByteNTimes(' ', indent); | |
| 964 | try writer.splatByteAll(' ', indent); | |
| 965 | 965 | try writer.writeAll(popup.end_token.slice(tree.source)); |
| 966 | 966 | try writer.writeAll("\n"); |
| 967 | 967 | }, |
| ... | ... | @@ -971,13 +971,13 @@ pub const Node = struct { |
| 971 | 971 | for (version_info.fixed_info) |fixed_info| { |
| 972 | 972 | try fixed_info.dump(tree, writer, indent + 1); |
| 973 | 973 | } |
| 974 | try writer.writeByteNTimes(' ', indent); | |
| 974 | try writer.splatByteAll(' ', indent); | |
| 975 | 975 | try writer.writeAll(version_info.begin_token.slice(tree.source)); |
| 976 | 976 | try writer.writeAll("\n"); |
| 977 | 977 | for (version_info.block_statements) |block| { |
| 978 | 978 | try block.dump(tree, writer, indent + 1); |
| 979 | 979 | } |
| 980 | try writer.writeByteNTimes(' ', indent); | |
| 980 | try writer.splatByteAll(' ', indent); | |
| 981 | 981 | try writer.writeAll(version_info.end_token.slice(tree.source)); |
| 982 | 982 | try writer.writeAll("\n"); |
| 983 | 983 | }, |
| ... | ... | @@ -994,13 +994,13 @@ pub const Node = struct { |
| 994 | 994 | for (block.values) |value| { |
| 995 | 995 | try value.dump(tree, writer, indent + 1); |
| 996 | 996 | } |
| 997 | try writer.writeByteNTimes(' ', indent); | |
| 997 | try writer.splatByteAll(' ', indent); | |
| 998 | 998 | try writer.writeAll(block.begin_token.slice(tree.source)); |
| 999 | 999 | try writer.writeAll("\n"); |
| 1000 | 1000 | for (block.children) |child| { |
| 1001 | 1001 | try child.dump(tree, writer, indent + 1); |
| 1002 | 1002 | } |
| 1003 | try writer.writeByteNTimes(' ', indent); | |
| 1003 | try writer.splatByteAll(' ', indent); | |
| 1004 | 1004 | try writer.writeAll(block.end_token.slice(tree.source)); |
| 1005 | 1005 | try writer.writeAll("\n"); |
| 1006 | 1006 | }, |
| ... | ... | @@ -1025,13 +1025,13 @@ pub const Node = struct { |
| 1025 | 1025 | for (string_table.optional_statements) |statement| { |
| 1026 | 1026 | try statement.dump(tree, writer, indent + 1); |
| 1027 | 1027 | } |
| 1028 | try writer.writeByteNTimes(' ', indent); | |
| 1028 | try writer.splatByteAll(' ', indent); | |
| 1029 | 1029 | try writer.writeAll(string_table.begin_token.slice(tree.source)); |
| 1030 | 1030 | try writer.writeAll("\n"); |
| 1031 | 1031 | for (string_table.strings) |string| { |
| 1032 | 1032 | try string.dump(tree, writer, indent + 1); |
| 1033 | 1033 | } |
| 1034 | try writer.writeByteNTimes(' ', indent); | |
| 1034 | try writer.splatByteAll(' ', indent); | |
| 1035 | 1035 | try writer.writeAll(string_table.end_token.slice(tree.source)); |
| 1036 | 1036 | try writer.writeAll("\n"); |
| 1037 | 1037 | }, |
| ... | ... | @@ -1039,7 +1039,7 @@ pub const Node = struct { |
| 1039 | 1039 | try writer.writeAll("\n"); |
| 1040 | 1040 | const string: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); |
| 1041 | 1041 | try string.id.dump(tree, writer, indent + 1); |
| 1042 | try writer.writeByteNTimes(' ', indent + 1); | |
| 1042 | try writer.splatByteAll(' ', indent + 1); | |
| 1043 | 1043 | try writer.print("{s}\n", .{string.string.slice(tree.source)}); |
| 1044 | 1044 | }, |
| 1045 | 1045 | .language_statement => { |
| ... | ... | @@ -1051,12 +1051,12 @@ pub const Node = struct { |
| 1051 | 1051 | .font_statement => { |
| 1052 | 1052 | const font: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); |
| 1053 | 1053 | try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) }); |
| 1054 | try writer.writeByteNTimes(' ', indent + 1); | |
| 1054 | try writer.splatByteAll(' ', indent + 1); | |
| 1055 | 1055 | try writer.writeAll("point_size:\n"); |
| 1056 | 1056 | try font.point_size.dump(tree, writer, indent + 2); |
| 1057 | 1057 | inline for (.{ "weight", "italic", "char_set" }) |arg| { |
| 1058 | 1058 | if (@field(font, arg)) |arg_node| { |
| 1059 | try writer.writeByteNTimes(' ', indent + 1); | |
| 1059 | try writer.splatByteAll(' ', indent + 1); | |
| 1060 | 1060 | try writer.writeAll(arg ++ ":\n"); |
| 1061 | 1061 | try arg_node.dump(tree, writer, indent + 2); |
| 1062 | 1062 | } |
| ... | ... | @@ -1071,7 +1071,7 @@ pub const Node = struct { |
| 1071 | 1071 | const invalid: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node)); |
| 1072 | 1072 | try writer.print(" context.len: {}\n", .{invalid.context.len}); |
| 1073 | 1073 | for (invalid.context) |context_token| { |
| 1074 | try writer.writeByteNTimes(' ', indent + 1); | |
| 1074 | try writer.splatByteAll(' ', indent + 1); | |
| 1075 | 1075 | try writer.print("{s}:{s}", .{ @tagName(context_token.id), context_token.slice(tree.source) }); |
| 1076 | 1076 | try writer.writeByte('\n'); |
| 1077 | 1077 | } |
lib/compiler/resinator/bmp.zig+25-15| ... | ... | @@ -27,6 +27,7 @@ pub const windows_format_id = std.mem.readInt(u16, "BM", native_endian); |
| 27 | 27 | pub const file_header_len = 14; |
| 28 | 28 | |
| 29 | 29 | pub const ReadError = error{ |
| 30 | ReadFailed, | |
| 30 | 31 | UnexpectedEOF, |
| 31 | 32 | InvalidFileHeader, |
| 32 | 33 | ImpossiblePixelDataOffset, |
| ... | ... | @@ -94,9 +95,12 @@ pub const BitmapInfo = struct { |
| 94 | 95 | } |
| 95 | 96 | }; |
| 96 | 97 | |
| 97 | pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { | |
| 98 | pub fn read(reader: *std.Io.Reader, max_size: u64) ReadError!BitmapInfo { | |
| 98 | 99 | var bitmap_info: BitmapInfo = undefined; |
| 99 | const file_header = reader.readBytesNoEof(file_header_len) catch return error.UnexpectedEOF; | |
| 100 | const file_header = reader.takeArray(file_header_len) catch |err| switch (err) { | |
| 101 | error.EndOfStream => return error.UnexpectedEOF, | |
| 102 | else => |e| return e, | |
| 103 | }; | |
| 100 | 104 | |
| 101 | 105 | const id = std.mem.readInt(u16, file_header[0..2], native_endian); |
| 102 | 106 | if (id != windows_format_id) return error.InvalidFileHeader; |
| ... | ... | @@ -104,14 +108,17 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { |
| 104 | 108 | bitmap_info.pixel_data_offset = std.mem.readInt(u32, file_header[10..14], .little); |
| 105 | 109 | if (bitmap_info.pixel_data_offset > max_size) return error.ImpossiblePixelDataOffset; |
| 106 | 110 | |
| 107 | bitmap_info.dib_header_size = reader.readInt(u32, .little) catch return error.UnexpectedEOF; | |
| 111 | bitmap_info.dib_header_size = reader.takeInt(u32, .little) catch return error.UnexpectedEOF; | |
| 108 | 112 | if (bitmap_info.pixel_data_offset < file_header_len + bitmap_info.dib_header_size) return error.ImpossiblePixelDataOffset; |
| 109 | 113 | const dib_version = BitmapHeader.Version.get(bitmap_info.dib_header_size); |
| 110 | 114 | switch (dib_version) { |
| 111 | 115 | .@"nt3.1", .@"nt4.0", .@"nt5.0" => { |
| 112 | 116 | var dib_header_buf: [@sizeOf(BITMAPINFOHEADER)]u8 align(@alignOf(BITMAPINFOHEADER)) = undefined; |
| 113 | 117 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); |
| 114 | reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; | |
| 118 | reader.readSliceAll(dib_header_buf[4..]) catch |err| switch (err) { | |
| 119 | error.EndOfStream => return error.UnexpectedEOF, | |
| 120 | error.ReadFailed => |e| return e, | |
| 121 | }; | |
| 115 | 122 | var dib_header: *BITMAPINFOHEADER = @ptrCast(&dib_header_buf); |
| 116 | 123 | structFieldsLittleToNative(BITMAPINFOHEADER, dib_header); |
| 117 | 124 | |
| ... | ... | @@ -126,7 +133,10 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { |
| 126 | 133 | .@"win2.0" => { |
| 127 | 134 | var dib_header_buf: [@sizeOf(BITMAPCOREHEADER)]u8 align(@alignOf(BITMAPCOREHEADER)) = undefined; |
| 128 | 135 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); |
| 129 | reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; | |
| 136 | reader.readSliceAll(dib_header_buf[4..]) catch |err| switch (err) { | |
| 137 | error.EndOfStream => return error.UnexpectedEOF, | |
| 138 | error.ReadFailed => |e| return e, | |
| 139 | }; | |
| 130 | 140 | const dib_header: *BITMAPCOREHEADER = @ptrCast(&dib_header_buf); |
| 131 | 141 | structFieldsLittleToNative(BITMAPCOREHEADER, dib_header); |
| 132 | 142 | |
| ... | ... | @@ -238,26 +248,26 @@ fn structFieldsLittleToNative(comptime T: type, x: *T) void { |
| 238 | 248 | |
| 239 | 249 | test "read" { |
| 240 | 250 | var bmp_data = "BM<\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x06\x00\x00\x00\x12\x0b\x00\x00\x12\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x7f\x00\x00\x00\x00".*; |
| 241 | var fbs = std.io.fixedBufferStream(&bmp_data); | |
| 251 | var fbs: std.Io.Reader = .fixed(&bmp_data); | |
| 242 | 252 | |
| 243 | 253 | { |
| 244 | const bitmap = try read(fbs.reader(), bmp_data.len); | |
| 254 | const bitmap = try read(&fbs, bmp_data.len); | |
| 245 | 255 | try std.testing.expectEqual(@as(u32, BitmapHeader.Version.@"nt3.1".len()), bitmap.dib_header_size); |
| 246 | 256 | } |
| 247 | 257 | |
| 248 | 258 | { |
| 249 | fbs.reset(); | |
| 259 | fbs.seek = 0; | |
| 250 | 260 | bmp_data[file_header_len] = 11; |
| 251 | try std.testing.expectError(error.UnknownBitmapVersion, read(fbs.reader(), bmp_data.len)); | |
| 261 | try std.testing.expectError(error.UnknownBitmapVersion, read(&fbs, bmp_data.len)); | |
| 252 | 262 | |
| 253 | 263 | // restore |
| 254 | 264 | bmp_data[file_header_len] = BitmapHeader.Version.@"nt3.1".len(); |
| 255 | 265 | } |
| 256 | 266 | |
| 257 | 267 | { |
| 258 | fbs.reset(); | |
| 268 | fbs.seek = 0; | |
| 259 | 269 | bmp_data[0] = 'b'; |
| 260 | try std.testing.expectError(error.InvalidFileHeader, read(fbs.reader(), bmp_data.len)); | |
| 270 | try std.testing.expectError(error.InvalidFileHeader, read(&fbs, bmp_data.len)); | |
| 261 | 271 | |
| 262 | 272 | // restore |
| 263 | 273 | bmp_data[0] = 'B'; |
| ... | ... | @@ -265,13 +275,13 @@ test "read" { |
| 265 | 275 | |
| 266 | 276 | { |
| 267 | 277 | const cutoff_len = file_header_len + BitmapHeader.Version.@"nt3.1".len() - 1; |
| 268 | var dib_cutoff_fbs = std.io.fixedBufferStream(bmp_data[0..cutoff_len]); | |
| 269 | try std.testing.expectError(error.UnexpectedEOF, read(dib_cutoff_fbs.reader(), bmp_data.len)); | |
| 278 | var dib_cutoff_fbs: std.Io.Reader = .fixed(bmp_data[0..cutoff_len]); | |
| 279 | try std.testing.expectError(error.UnexpectedEOF, read(&dib_cutoff_fbs, bmp_data.len)); | |
| 270 | 280 | } |
| 271 | 281 | |
| 272 | 282 | { |
| 273 | 283 | const cutoff_len = file_header_len - 1; |
| 274 | var bmp_cutoff_fbs = std.io.fixedBufferStream(bmp_data[0..cutoff_len]); | |
| 275 | try std.testing.expectError(error.UnexpectedEOF, read(bmp_cutoff_fbs.reader(), bmp_data.len)); | |
| 284 | var bmp_cutoff_fbs: std.Io.Reader = .fixed(bmp_data[0..cutoff_len]); | |
| 285 | try std.testing.expectError(error.UnexpectedEOF, read(&bmp_cutoff_fbs, bmp_data.len)); | |
| 276 | 286 | } |
| 277 | 287 | } |
lib/compiler/resinator/cli.zig+77-138| ... | ... | @@ -80,20 +80,20 @@ pub const usage_string_after_command_name = |
| 80 | 80 | \\ |
| 81 | 81 | ; |
| 82 | 82 | |
| 83 | pub fn writeUsage(writer: anytype, command_name: []const u8) !void { | |
| 83 | pub fn writeUsage(writer: *std.Io.Writer, command_name: []const u8) !void { | |
| 84 | 84 | try writer.writeAll("Usage: "); |
| 85 | 85 | try writer.writeAll(command_name); |
| 86 | 86 | try writer.writeAll(usage_string_after_command_name); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | pub const Diagnostics = struct { |
| 90 | errors: std.ArrayListUnmanaged(ErrorDetails) = .empty, | |
| 90 | errors: std.ArrayList(ErrorDetails) = .empty, | |
| 91 | 91 | allocator: Allocator, |
| 92 | 92 | |
| 93 | 93 | pub const ErrorDetails = struct { |
| 94 | 94 | arg_index: usize, |
| 95 | 95 | arg_span: ArgSpan = .{}, |
| 96 | msg: std.ArrayListUnmanaged(u8) = .empty, | |
| 96 | msg: std.ArrayList(u8) = .empty, | |
| 97 | 97 | type: Type = .err, |
| 98 | 98 | print_args: bool = true, |
| 99 | 99 | |
| ... | ... | @@ -148,7 +148,7 @@ pub const Options = struct { |
| 148 | 148 | allocator: Allocator, |
| 149 | 149 | input_source: IoSource = .{ .filename = &[_]u8{} }, |
| 150 | 150 | output_source: IoSource = .{ .filename = &[_]u8{} }, |
| 151 | extra_include_paths: std.ArrayListUnmanaged([]const u8) = .empty, | |
| 151 | extra_include_paths: std.ArrayList([]const u8) = .empty, | |
| 152 | 152 | ignore_include_env_var: bool = false, |
| 153 | 153 | preprocess: Preprocess = .yes, |
| 154 | 154 | default_language_id: ?u16 = null, |
| ... | ... | @@ -295,7 +295,7 @@ pub const Options = struct { |
| 295 | 295 | } |
| 296 | 296 | } |
| 297 | 297 | |
| 298 | pub fn dumpVerbose(self: *const Options, writer: anytype) !void { | |
| 298 | pub fn dumpVerbose(self: *const Options, writer: *std.Io.Writer) !void { | |
| 299 | 299 | const input_source_name = switch (self.input_source) { |
| 300 | 300 | .stdio => "<stdin>", |
| 301 | 301 | .filename => |filename| filename, |
| ... | ... | @@ -520,8 +520,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 520 | 520 | // - or / on its own is an error |
| 521 | 521 | else => { |
| 522 | 522 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 523 | var msg_writer = err_details.msg.writer(allocator); | |
| 524 | try msg_writer.print("invalid option: {s}", .{arg.prefixSlice()}); | |
| 523 | try err_details.msg.print(allocator, "invalid option: {s}", .{arg.prefixSlice()}); | |
| 525 | 524 | try diagnostics.append(err_details); |
| 526 | 525 | arg_i += 1; |
| 527 | 526 | continue :next_arg; |
| ... | ... | @@ -532,8 +531,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 532 | 531 | const args_remaining = args.len - arg_i; |
| 533 | 532 | if (args_remaining <= 2 and arg.looksLikeFilepath()) { |
| 534 | 533 | var err_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i }; |
| 535 | var msg_writer = err_details.msg.writer(allocator); | |
| 536 | try msg_writer.writeAll("this argument was inferred to be a filepath, so argument parsing was terminated"); | |
| 534 | try err_details.msg.appendSlice(allocator, "this argument was inferred to be a filepath, so argument parsing was terminated"); | |
| 537 | 535 | try diagnostics.append(err_details); |
| 538 | 536 | |
| 539 | 537 | break; |
| ... | ... | @@ -550,16 +548,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 550 | 548 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":output-format")) { |
| 551 | 549 | const value = arg.value(":output-format".len, arg_i, args) catch { |
| 552 | 550 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 553 | var msg_writer = err_details.msg.writer(allocator); | |
| 554 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":output-format".len) }); | |
| 551 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":output-format".len) }); | |
| 555 | 552 | try diagnostics.append(err_details); |
| 556 | 553 | arg_i += 1; |
| 557 | 554 | break :next_arg; |
| 558 | 555 | }; |
| 559 | 556 | output_format = std.meta.stringToEnum(Options.OutputFormat, value.slice) orelse blk: { |
| 560 | 557 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 561 | var msg_writer = err_details.msg.writer(allocator); | |
| 562 | try msg_writer.print("invalid output format setting: {s} ", .{value.slice}); | |
| 558 | try err_details.msg.print(allocator, "invalid output format setting: {s} ", .{value.slice}); | |
| 563 | 559 | try diagnostics.append(err_details); |
| 564 | 560 | break :blk output_format; |
| 565 | 561 | }; |
| ... | ... | @@ -569,16 +565,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 569 | 565 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":auto-includes")) { |
| 570 | 566 | const value = arg.value(":auto-includes".len, arg_i, args) catch { |
| 571 | 567 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 572 | var msg_writer = err_details.msg.writer(allocator); | |
| 573 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":auto-includes".len) }); | |
| 568 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":auto-includes".len) }); | |
| 574 | 569 | try diagnostics.append(err_details); |
| 575 | 570 | arg_i += 1; |
| 576 | 571 | break :next_arg; |
| 577 | 572 | }; |
| 578 | 573 | options.auto_includes = std.meta.stringToEnum(Options.AutoIncludes, value.slice) orelse blk: { |
| 579 | 574 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 580 | var msg_writer = err_details.msg.writer(allocator); | |
| 581 | try msg_writer.print("invalid auto includes setting: {s} ", .{value.slice}); | |
| 575 | try err_details.msg.print(allocator, "invalid auto includes setting: {s} ", .{value.slice}); | |
| 582 | 576 | try diagnostics.append(err_details); |
| 583 | 577 | break :blk options.auto_includes; |
| 584 | 578 | }; |
| ... | ... | @@ -587,16 +581,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 587 | 581 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":input-format")) { |
| 588 | 582 | const value = arg.value(":input-format".len, arg_i, args) catch { |
| 589 | 583 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 590 | var msg_writer = err_details.msg.writer(allocator); | |
| 591 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":input-format".len) }); | |
| 584 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":input-format".len) }); | |
| 592 | 585 | try diagnostics.append(err_details); |
| 593 | 586 | arg_i += 1; |
| 594 | 587 | break :next_arg; |
| 595 | 588 | }; |
| 596 | 589 | input_format = std.meta.stringToEnum(Options.InputFormat, value.slice) orelse blk: { |
| 597 | 590 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 598 | var msg_writer = err_details.msg.writer(allocator); | |
| 599 | try msg_writer.print("invalid input format setting: {s} ", .{value.slice}); | |
| 591 | try err_details.msg.print(allocator, "invalid input format setting: {s} ", .{value.slice}); | |
| 600 | 592 | try diagnostics.append(err_details); |
| 601 | 593 | break :blk input_format; |
| 602 | 594 | }; |
| ... | ... | @@ -606,16 +598,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 606 | 598 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile-fmt")) { |
| 607 | 599 | const value = arg.value(":depfile-fmt".len, arg_i, args) catch { |
| 608 | 600 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 609 | var msg_writer = err_details.msg.writer(allocator); | |
| 610 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); | |
| 601 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); | |
| 611 | 602 | try diagnostics.append(err_details); |
| 612 | 603 | arg_i += 1; |
| 613 | 604 | break :next_arg; |
| 614 | 605 | }; |
| 615 | 606 | options.depfile_fmt = std.meta.stringToEnum(Options.DepfileFormat, value.slice) orelse blk: { |
| 616 | 607 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 617 | var msg_writer = err_details.msg.writer(allocator); | |
| 618 | try msg_writer.print("invalid depfile format setting: {s} ", .{value.slice}); | |
| 608 | try err_details.msg.print(allocator, "invalid depfile format setting: {s} ", .{value.slice}); | |
| 619 | 609 | try diagnostics.append(err_details); |
| 620 | 610 | break :blk options.depfile_fmt; |
| 621 | 611 | }; |
| ... | ... | @@ -624,8 +614,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 624 | 614 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile")) { |
| 625 | 615 | const value = arg.value(":depfile".len, arg_i, args) catch { |
| 626 | 616 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 627 | var msg_writer = err_details.msg.writer(allocator); | |
| 628 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile".len) }); | |
| 617 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile".len) }); | |
| 629 | 618 | try diagnostics.append(err_details); |
| 630 | 619 | arg_i += 1; |
| 631 | 620 | break :next_arg; |
| ... | ... | @@ -643,8 +632,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 643 | 632 | } else if (std.ascii.startsWithIgnoreCase(arg_name, ":target")) { |
| 644 | 633 | const value = arg.value(":target".len, arg_i, args) catch { |
| 645 | 634 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 646 | var msg_writer = err_details.msg.writer(allocator); | |
| 647 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":target".len) }); | |
| 635 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":target".len) }); | |
| 648 | 636 | try diagnostics.append(err_details); |
| 649 | 637 | arg_i += 1; |
| 650 | 638 | break :next_arg; |
| ... | ... | @@ -655,8 +643,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 655 | 643 | const arch_str = target_it.first(); |
| 656 | 644 | const arch = cvtres.supported_targets.Arch.fromStringIgnoreCase(arch_str) orelse { |
| 657 | 645 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 658 | var msg_writer = err_details.msg.writer(allocator); | |
| 659 | try msg_writer.print("invalid or unsupported target architecture: {s}", .{arch_str}); | |
| 646 | try err_details.msg.print(allocator, "invalid or unsupported target architecture: {s}", .{arch_str}); | |
| 660 | 647 | try diagnostics.append(err_details); |
| 661 | 648 | arg_i += value.index_increment; |
| 662 | 649 | continue :next_arg; |
| ... | ... | @@ -680,13 +667,11 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 680 | 667 | .prefix_len = arg.prefixSlice().len, |
| 681 | 668 | .value_offset = arg.name_offset + 3, |
| 682 | 669 | } }; |
| 683 | var msg_writer = err_details.msg.writer(allocator); | |
| 684 | try msg_writer.print("missing value for {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); | |
| 670 | try err_details.msg.print(allocator, "missing value for {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); | |
| 685 | 671 | try diagnostics.append(err_details); |
| 686 | 672 | } |
| 687 | 673 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 688 | var msg_writer = err_details.msg.writer(allocator); | |
| 689 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); | |
| 674 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); | |
| 690 | 675 | try diagnostics.append(err_details); |
| 691 | 676 | arg_i += 1; |
| 692 | 677 | continue :next_arg; |
| ... | ... | @@ -695,16 +680,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 695 | 680 | else if (std.ascii.startsWithIgnoreCase(arg_name, "tn")) { |
| 696 | 681 | const value = arg.value(2, arg_i, args) catch no_value: { |
| 697 | 682 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 698 | var msg_writer = err_details.msg.writer(allocator); | |
| 699 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 683 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 700 | 684 | try diagnostics.append(err_details); |
| 701 | 685 | // dummy zero-length slice starting where the value would have been |
| 702 | 686 | const value_start = arg.name_offset + 2; |
| 703 | 687 | break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; |
| 704 | 688 | }; |
| 705 | 689 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 706 | var msg_writer = err_details.msg.writer(allocator); | |
| 707 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 690 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 708 | 691 | try diagnostics.append(err_details); |
| 709 | 692 | arg_i += value.index_increment; |
| 710 | 693 | continue :next_arg; |
| ... | ... | @@ -716,16 +699,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 716 | 699 | { |
| 717 | 700 | const value = arg.value(2, arg_i, args) catch no_value: { |
| 718 | 701 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 719 | var msg_writer = err_details.msg.writer(allocator); | |
| 720 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 702 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 721 | 703 | try diagnostics.append(err_details); |
| 722 | 704 | // dummy zero-length slice starting where the value would have been |
| 723 | 705 | const value_start = arg.name_offset + 2; |
| 724 | 706 | break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; |
| 725 | 707 | }; |
| 726 | 708 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 727 | var msg_writer = err_details.msg.writer(allocator); | |
| 728 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 709 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 729 | 710 | try diagnostics.append(err_details); |
| 730 | 711 | arg_i += value.index_increment; |
| 731 | 712 | continue :next_arg; |
| ... | ... | @@ -733,8 +714,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 733 | 714 | // Unsupported MUI options that do not need a value |
| 734 | 715 | else if (std.ascii.startsWithIgnoreCase(arg_name, "g1")) { |
| 735 | 716 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(2) }; |
| 736 | var msg_writer = err_details.msg.writer(allocator); | |
| 737 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 717 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 738 | 718 | try diagnostics.append(err_details); |
| 739 | 719 | arg.name_offset += 2; |
| 740 | 720 | } |
| ... | ... | @@ -747,15 +727,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 747 | 727 | std.ascii.startsWithIgnoreCase(arg_name, "ta")) |
| 748 | 728 | { |
| 749 | 729 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(2) }; |
| 750 | var msg_writer = err_details.msg.writer(allocator); | |
| 751 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 730 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 752 | 731 | try diagnostics.append(err_details); |
| 753 | 732 | arg.name_offset += 2; |
| 754 | 733 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "fo")) { |
| 755 | 734 | const value = arg.value(2, arg_i, args) catch { |
| 756 | 735 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 757 | var msg_writer = err_details.msg.writer(allocator); | |
| 758 | try msg_writer.print("missing output path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 736 | try err_details.msg.print(allocator, "missing output path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 759 | 737 | try diagnostics.append(err_details); |
| 760 | 738 | arg_i += 1; |
| 761 | 739 | break :next_arg; |
| ... | ... | @@ -767,8 +745,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 767 | 745 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "sl")) { |
| 768 | 746 | const value = arg.value(2, arg_i, args) catch { |
| 769 | 747 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 770 | var msg_writer = err_details.msg.writer(allocator); | |
| 771 | try msg_writer.print("missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 748 | try err_details.msg.print(allocator, "missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 772 | 749 | try diagnostics.append(err_details); |
| 773 | 750 | arg_i += 1; |
| 774 | 751 | break :next_arg; |
| ... | ... | @@ -776,24 +753,20 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 776 | 753 | const percent_str = value.slice; |
| 777 | 754 | const percent: u32 = parsePercent(percent_str) catch { |
| 778 | 755 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 779 | var msg_writer = err_details.msg.writer(allocator); | |
| 780 | try msg_writer.print("invalid percent format '{s}'", .{percent_str}); | |
| 756 | try err_details.msg.print(allocator, "invalid percent format '{s}'", .{percent_str}); | |
| 781 | 757 | try diagnostics.append(err_details); |
| 782 | 758 | var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = false, .arg_index = arg_i }; |
| 783 | var note_writer = note_details.msg.writer(allocator); | |
| 784 | try note_writer.writeAll("string length percent must be an integer between 1 and 100 (inclusive)"); | |
| 759 | try note_details.msg.appendSlice(allocator, "string length percent must be an integer between 1 and 100 (inclusive)"); | |
| 785 | 760 | try diagnostics.append(note_details); |
| 786 | 761 | arg_i += value.index_increment; |
| 787 | 762 | continue :next_arg; |
| 788 | 763 | }; |
| 789 | 764 | if (percent == 0 or percent > 100) { |
| 790 | 765 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 791 | var msg_writer = err_details.msg.writer(allocator); | |
| 792 | try msg_writer.print("percent out of range: {} (parsed from '{s}')", .{ percent, percent_str }); | |
| 766 | try err_details.msg.print(allocator, "percent out of range: {} (parsed from '{s}')", .{ percent, percent_str }); | |
| 793 | 767 | try diagnostics.append(err_details); |
| 794 | 768 | var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = false, .arg_index = arg_i }; |
| 795 | var note_writer = note_details.msg.writer(allocator); | |
| 796 | try note_writer.writeAll("string length percent must be an integer between 1 and 100 (inclusive)"); | |
| 769 | try note_details.msg.appendSlice(allocator, "string length percent must be an integer between 1 and 100 (inclusive)"); | |
| 797 | 770 | try diagnostics.append(note_details); |
| 798 | 771 | arg_i += value.index_increment; |
| 799 | 772 | continue :next_arg; |
| ... | ... | @@ -805,8 +778,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 805 | 778 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "ln")) { |
| 806 | 779 | const value = arg.value(2, arg_i, args) catch { |
| 807 | 780 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 808 | var msg_writer = err_details.msg.writer(allocator); | |
| 809 | try msg_writer.print("missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 781 | try err_details.msg.print(allocator, "missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); | |
| 810 | 782 | try diagnostics.append(err_details); |
| 811 | 783 | arg_i += 1; |
| 812 | 784 | break :next_arg; |
| ... | ... | @@ -814,16 +786,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 814 | 786 | const tag = value.slice; |
| 815 | 787 | options.default_language_id = lang.tagToInt(tag) catch { |
| 816 | 788 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 817 | var msg_writer = err_details.msg.writer(allocator); | |
| 818 | try msg_writer.print("invalid language tag: {s}", .{tag}); | |
| 789 | try err_details.msg.print(allocator, "invalid language tag: {s}", .{tag}); | |
| 819 | 790 | try diagnostics.append(err_details); |
| 820 | 791 | arg_i += value.index_increment; |
| 821 | 792 | continue :next_arg; |
| 822 | 793 | }; |
| 823 | 794 | if (options.default_language_id.? == lang.LOCALE_CUSTOM_UNSPECIFIED) { |
| 824 | 795 | var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 825 | var msg_writer = err_details.msg.writer(allocator); | |
| 826 | try msg_writer.print("language tag '{s}' does not have an assigned ID so it will be resolved to LOCALE_CUSTOM_UNSPECIFIED (id=0x{x})", .{ tag, lang.LOCALE_CUSTOM_UNSPECIFIED }); | |
| 796 | try err_details.msg.print(allocator, "language tag '{s}' does not have an assigned ID so it will be resolved to LOCALE_CUSTOM_UNSPECIFIED (id=0x{x})", .{ tag, lang.LOCALE_CUSTOM_UNSPECIFIED }); | |
| 827 | 797 | try diagnostics.append(err_details); |
| 828 | 798 | } |
| 829 | 799 | arg_i += value.index_increment; |
| ... | ... | @@ -831,8 +801,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 831 | 801 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "l")) { |
| 832 | 802 | const value = arg.value(1, arg_i, args) catch { |
| 833 | 803 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 834 | var msg_writer = err_details.msg.writer(allocator); | |
| 835 | try msg_writer.print("missing language ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 804 | try err_details.msg.print(allocator, "missing language ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 836 | 805 | try diagnostics.append(err_details); |
| 837 | 806 | arg_i += 1; |
| 838 | 807 | break :next_arg; |
| ... | ... | @@ -840,8 +809,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 840 | 809 | const num_str = value.slice; |
| 841 | 810 | options.default_language_id = lang.parseInt(num_str) catch { |
| 842 | 811 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 843 | var msg_writer = err_details.msg.writer(allocator); | |
| 844 | try msg_writer.print("invalid language ID: {s}", .{num_str}); | |
| 812 | try err_details.msg.print(allocator, "invalid language ID: {s}", .{num_str}); | |
| 845 | 813 | try diagnostics.append(err_details); |
| 846 | 814 | arg_i += value.index_increment; |
| 847 | 815 | continue :next_arg; |
| ... | ... | @@ -860,16 +828,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 860 | 828 | { |
| 861 | 829 | const value = arg.value(1, arg_i, args) catch no_value: { |
| 862 | 830 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 863 | var msg_writer = err_details.msg.writer(allocator); | |
| 864 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 831 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 865 | 832 | try diagnostics.append(err_details); |
| 866 | 833 | // dummy zero-length slice starting where the value would have been |
| 867 | 834 | const value_start = arg.name_offset + 1; |
| 868 | 835 | break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; |
| 869 | 836 | }; |
| 870 | 837 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 871 | var msg_writer = err_details.msg.writer(allocator); | |
| 872 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 838 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 873 | 839 | try diagnostics.append(err_details); |
| 874 | 840 | arg_i += value.index_increment; |
| 875 | 841 | continue :next_arg; |
| ... | ... | @@ -882,16 +848,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 882 | 848 | { |
| 883 | 849 | const value = arg.value(1, arg_i, args) catch no_value: { |
| 884 | 850 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 885 | var msg_writer = err_details.msg.writer(allocator); | |
| 886 | try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 851 | try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 887 | 852 | try diagnostics.append(err_details); |
| 888 | 853 | // dummy zero-length slice starting where the value would have been |
| 889 | 854 | const value_start = arg.name_offset + 1; |
| 890 | 855 | break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; |
| 891 | 856 | }; |
| 892 | 857 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 893 | var msg_writer = err_details.msg.writer(allocator); | |
| 894 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 858 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 895 | 859 | try diagnostics.append(err_details); |
| 896 | 860 | arg_i += value.index_increment; |
| 897 | 861 | continue :next_arg; |
| ... | ... | @@ -899,15 +863,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 899 | 863 | // 1 char unsupported LCX/LCE options that do not need a value |
| 900 | 864 | else if (std.ascii.startsWithIgnoreCase(arg_name, "t")) { |
| 901 | 865 | var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(1) }; |
| 902 | var msg_writer = err_details.msg.writer(allocator); | |
| 903 | try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 866 | try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 904 | 867 | try diagnostics.append(err_details); |
| 905 | 868 | arg.name_offset += 1; |
| 906 | 869 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "c")) { |
| 907 | 870 | const value = arg.value(1, arg_i, args) catch { |
| 908 | 871 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 909 | var msg_writer = err_details.msg.writer(allocator); | |
| 910 | try msg_writer.print("missing code page ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 872 | try err_details.msg.print(allocator, "missing code page ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 911 | 873 | try diagnostics.append(err_details); |
| 912 | 874 | arg_i += 1; |
| 913 | 875 | break :next_arg; |
| ... | ... | @@ -915,8 +877,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 915 | 877 | const num_str = value.slice; |
| 916 | 878 | const code_page_id = std.fmt.parseUnsigned(u16, num_str, 10) catch { |
| 917 | 879 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 918 | var msg_writer = err_details.msg.writer(allocator); | |
| 919 | try msg_writer.print("invalid code page ID: {s}", .{num_str}); | |
| 880 | try err_details.msg.print(allocator, "invalid code page ID: {s}", .{num_str}); | |
| 920 | 881 | try diagnostics.append(err_details); |
| 921 | 882 | arg_i += value.index_increment; |
| 922 | 883 | continue :next_arg; |
| ... | ... | @@ -924,16 +885,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 924 | 885 | options.default_code_page = code_pages.getByIdentifierEnsureSupported(code_page_id) catch |err| switch (err) { |
| 925 | 886 | error.InvalidCodePage => { |
| 926 | 887 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 927 | var msg_writer = err_details.msg.writer(allocator); | |
| 928 | try msg_writer.print("invalid or unknown code page ID: {}", .{code_page_id}); | |
| 888 | try err_details.msg.print(allocator, "invalid or unknown code page ID: {}", .{code_page_id}); | |
| 929 | 889 | try diagnostics.append(err_details); |
| 930 | 890 | arg_i += value.index_increment; |
| 931 | 891 | continue :next_arg; |
| 932 | 892 | }, |
| 933 | 893 | error.UnsupportedCodePage => { |
| 934 | 894 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 935 | var msg_writer = err_details.msg.writer(allocator); | |
| 936 | try msg_writer.print("unsupported code page: {s} (id={})", .{ | |
| 895 | try err_details.msg.print(allocator, "unsupported code page: {s} (id={})", .{ | |
| 937 | 896 | @tagName(code_pages.getByIdentifier(code_page_id) catch unreachable), |
| 938 | 897 | code_page_id, |
| 939 | 898 | }); |
| ... | ... | @@ -957,8 +916,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 957 | 916 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "i")) { |
| 958 | 917 | const value = arg.value(1, arg_i, args) catch { |
| 959 | 918 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 960 | var msg_writer = err_details.msg.writer(allocator); | |
| 961 | try msg_writer.print("missing include path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 919 | try err_details.msg.print(allocator, "missing include path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 962 | 920 | try diagnostics.append(err_details); |
| 963 | 921 | arg_i += 1; |
| 964 | 922 | break :next_arg; |
| ... | ... | @@ -986,15 +944,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 986 | 944 | // Undocumented option with unknown function |
| 987 | 945 | // TODO: More investigation to figure out what it does (if anything) |
| 988 | 946 | var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = arg.optionSpan(1) }; |
| 989 | var msg_writer = err_details.msg.writer(allocator); | |
| 990 | try msg_writer.print("option {s}{s} has no effect (it is undocumented and its function is unknown in the Win32 RC compiler)", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 947 | try err_details.msg.print(allocator, "option {s}{s} has no effect (it is undocumented and its function is unknown in the Win32 RC compiler)", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 991 | 948 | try diagnostics.append(err_details); |
| 992 | 949 | arg.name_offset += 1; |
| 993 | 950 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "d")) { |
| 994 | 951 | const value = arg.value(1, arg_i, args) catch { |
| 995 | 952 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 996 | var msg_writer = err_details.msg.writer(allocator); | |
| 997 | try msg_writer.print("missing symbol to define after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 953 | try err_details.msg.print(allocator, "missing symbol to define after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 998 | 954 | try diagnostics.append(err_details); |
| 999 | 955 | arg_i += 1; |
| 1000 | 956 | break :next_arg; |
| ... | ... | @@ -1009,8 +965,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1009 | 965 | try options.define(symbol, symbol_value); |
| 1010 | 966 | } else { |
| 1011 | 967 | var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 1012 | var msg_writer = err_details.msg.writer(allocator); | |
| 1013 | try msg_writer.print("symbol \"{s}\" is not a valid identifier and therefore cannot be defined", .{symbol}); | |
| 968 | try err_details.msg.print(allocator, "symbol \"{s}\" is not a valid identifier and therefore cannot be defined", .{symbol}); | |
| 1014 | 969 | try diagnostics.append(err_details); |
| 1015 | 970 | } |
| 1016 | 971 | arg_i += value.index_increment; |
| ... | ... | @@ -1018,8 +973,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1018 | 973 | } else if (std.ascii.startsWithIgnoreCase(arg_name, "u")) { |
| 1019 | 974 | const value = arg.value(1, arg_i, args) catch { |
| 1020 | 975 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; |
| 1021 | var msg_writer = err_details.msg.writer(allocator); | |
| 1022 | try msg_writer.print("missing symbol to undefine after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 976 | try err_details.msg.print(allocator, "missing symbol to undefine after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); | |
| 1023 | 977 | try diagnostics.append(err_details); |
| 1024 | 978 | arg_i += 1; |
| 1025 | 979 | break :next_arg; |
| ... | ... | @@ -1029,16 +983,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1029 | 983 | try options.undefine(symbol); |
| 1030 | 984 | } else { |
| 1031 | 985 | var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; |
| 1032 | var msg_writer = err_details.msg.writer(allocator); | |
| 1033 | try msg_writer.print("symbol \"{s}\" is not a valid identifier and therefore cannot be undefined", .{symbol}); | |
| 986 | try err_details.msg.print(allocator, "symbol \"{s}\" is not a valid identifier and therefore cannot be undefined", .{symbol}); | |
| 1034 | 987 | try diagnostics.append(err_details); |
| 1035 | 988 | } |
| 1036 | 989 | arg_i += value.index_increment; |
| 1037 | 990 | continue :next_arg; |
| 1038 | 991 | } else { |
| 1039 | 992 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; |
| 1040 | var msg_writer = err_details.msg.writer(allocator); | |
| 1041 | try msg_writer.print("invalid option: {s}{s}", .{ arg.prefixSlice(), arg.name() }); | |
| 993 | try err_details.msg.print(allocator, "invalid option: {s}{s}", .{ arg.prefixSlice(), arg.name() }); | |
| 1042 | 994 | try diagnostics.append(err_details); |
| 1043 | 995 | arg_i += 1; |
| 1044 | 996 | continue :next_arg; |
| ... | ... | @@ -1055,16 +1007,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1055 | 1007 | |
| 1056 | 1008 | if (positionals.len == 0) { |
| 1057 | 1009 | var err_details = Diagnostics.ErrorDetails{ .print_args = false, .arg_index = arg_i }; |
| 1058 | var msg_writer = err_details.msg.writer(allocator); | |
| 1059 | try msg_writer.writeAll("missing input filename"); | |
| 1010 | try err_details.msg.appendSlice(allocator, "missing input filename"); | |
| 1060 | 1011 | try diagnostics.append(err_details); |
| 1061 | 1012 | |
| 1062 | 1013 | if (args.len > 0) { |
| 1063 | 1014 | const last_arg = args[args.len - 1]; |
| 1064 | 1015 | if (arg_i > 0 and last_arg.len > 0 and last_arg[0] == '/' and isSupportedInputExtension(std.fs.path.extension(last_arg))) { |
| 1065 | 1016 | var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i - 1 }; |
| 1066 | var note_writer = note_details.msg.writer(allocator); | |
| 1067 | try note_writer.writeAll("if this argument was intended to be the input filename, adding -- in front of it will exclude it from option parsing"); | |
| 1017 | try note_details.msg.appendSlice(allocator, "if this argument was intended to be the input filename, adding -- in front of it will exclude it from option parsing"); | |
| 1068 | 1018 | try diagnostics.append(note_details); |
| 1069 | 1019 | } |
| 1070 | 1020 | } |
| ... | ... | @@ -1099,16 +1049,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1099 | 1049 | if (positionals.len > 1) { |
| 1100 | 1050 | if (output_filename != null) { |
| 1101 | 1051 | var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i + 1 }; |
| 1102 | var msg_writer = err_details.msg.writer(allocator); | |
| 1103 | try msg_writer.writeAll("output filename already specified"); | |
| 1052 | try err_details.msg.appendSlice(allocator, "output filename already specified"); | |
| 1104 | 1053 | try diagnostics.append(err_details); |
| 1105 | 1054 | var note_details = Diagnostics.ErrorDetails{ |
| 1106 | 1055 | .type = .note, |
| 1107 | 1056 | .arg_index = output_filename_context.arg.index, |
| 1108 | 1057 | .arg_span = output_filename_context.arg.value.argSpan(output_filename_context.arg.arg), |
| 1109 | 1058 | }; |
| 1110 | var note_writer = note_details.msg.writer(allocator); | |
| 1111 | try note_writer.writeAll("output filename previously specified here"); | |
| 1059 | try note_details.msg.appendSlice(allocator, "output filename previously specified here"); | |
| 1112 | 1060 | try diagnostics.append(note_details); |
| 1113 | 1061 | } else { |
| 1114 | 1062 | output_filename = positionals[1]; |
| ... | ... | @@ -1173,16 +1121,15 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1173 | 1121 | var print_output_format_source_note: bool = false; |
| 1174 | 1122 | if (options.depfile_path != null and (options.input_format == .res or options.output_format == .rcpp)) { |
| 1175 | 1123 | var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = depfile_context.index, .arg_span = depfile_context.value.argSpan(depfile_context.arg) }; |
| 1176 | var msg_writer = err_details.msg.writer(allocator); | |
| 1177 | 1124 | if (options.input_format == .res) { |
| 1178 | try msg_writer.print("the {s}{s} option was ignored because the input format is '{s}'", .{ | |
| 1125 | try err_details.msg.print(allocator, "the {s}{s} option was ignored because the input format is '{s}'", .{ | |
| 1179 | 1126 | depfile_context.arg.prefixSlice(), |
| 1180 | 1127 | depfile_context.arg.optionWithoutPrefix(depfile_context.option_len), |
| 1181 | 1128 | @tagName(options.input_format), |
| 1182 | 1129 | }); |
| 1183 | 1130 | print_input_format_source_note = true; |
| 1184 | 1131 | } else if (options.output_format == .rcpp) { |
| 1185 | try msg_writer.print("the {s}{s} option was ignored because the output format is '{s}'", .{ | |
| 1132 | try err_details.msg.print(allocator, "the {s}{s} option was ignored because the output format is '{s}'", .{ | |
| 1186 | 1133 | depfile_context.arg.prefixSlice(), |
| 1187 | 1134 | depfile_context.arg.optionWithoutPrefix(depfile_context.option_len), |
| 1188 | 1135 | @tagName(options.output_format), |
| ... | ... | @@ -1193,16 +1140,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1193 | 1140 | } |
| 1194 | 1141 | if (!isSupportedTransformation(options.input_format, options.output_format)) { |
| 1195 | 1142 | var err_details = Diagnostics.ErrorDetails{ .arg_index = input_filename_arg_i, .print_args = false }; |
| 1196 | var msg_writer = err_details.msg.writer(allocator); | |
| 1197 | try msg_writer.print("input format '{s}' cannot be converted to output format '{s}'", .{ @tagName(options.input_format), @tagName(options.output_format) }); | |
| 1143 | try err_details.msg.print(allocator, "input format '{s}' cannot be converted to output format '{s}'", .{ @tagName(options.input_format), @tagName(options.output_format) }); | |
| 1198 | 1144 | try diagnostics.append(err_details); |
| 1199 | 1145 | print_input_format_source_note = true; |
| 1200 | 1146 | print_output_format_source_note = true; |
| 1201 | 1147 | } |
| 1202 | 1148 | if (options.preprocess == .only and options.output_format != .rcpp) { |
| 1203 | 1149 | var err_details = Diagnostics.ErrorDetails{ .arg_index = preprocess_only_context.index }; |
| 1204 | var msg_writer = err_details.msg.writer(allocator); | |
| 1205 | try msg_writer.print("the {s}{s} option cannot be used with output format '{s}'", .{ | |
| 1150 | try err_details.msg.print(allocator, "the {s}{s} option cannot be used with output format '{s}'", .{ | |
| 1206 | 1151 | preprocess_only_context.arg.prefixSlice(), |
| 1207 | 1152 | preprocess_only_context.arg.optionWithoutPrefix(preprocess_only_context.option_len), |
| 1208 | 1153 | @tagName(options.output_format), |
| ... | ... | @@ -1214,8 +1159,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1214 | 1159 | switch (input_format_source) { |
| 1215 | 1160 | .inferred_from_input_filename => { |
| 1216 | 1161 | var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = input_filename_arg_i }; |
| 1217 | var msg_writer = err_details.msg.writer(allocator); | |
| 1218 | try msg_writer.writeAll("the input format was inferred from the input filename"); | |
| 1162 | try err_details.msg.appendSlice(allocator, "the input format was inferred from the input filename"); | |
| 1219 | 1163 | try diagnostics.append(err_details); |
| 1220 | 1164 | }, |
| 1221 | 1165 | .input_format_arg => { |
| ... | ... | @@ -1224,8 +1168,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1224 | 1168 | .arg_index = input_format_context.index, |
| 1225 | 1169 | .arg_span = input_format_context.value.argSpan(input_format_context.arg), |
| 1226 | 1170 | }; |
| 1227 | var msg_writer = err_details.msg.writer(allocator); | |
| 1228 | try msg_writer.writeAll("the input format was specified here"); | |
| 1171 | try err_details.msg.appendSlice(allocator, "the input format was specified here"); | |
| 1229 | 1172 | try diagnostics.append(err_details); |
| 1230 | 1173 | }, |
| 1231 | 1174 | } |
| ... | ... | @@ -1234,11 +1177,10 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1234 | 1177 | switch (output_format_source) { |
| 1235 | 1178 | .inferred_from_input_filename, .unable_to_infer_from_input_filename => { |
| 1236 | 1179 | var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = input_filename_arg_i }; |
| 1237 | var msg_writer = err_details.msg.writer(allocator); | |
| 1238 | 1180 | if (output_format_source == .inferred_from_input_filename) { |
| 1239 | try msg_writer.writeAll("the output format was inferred from the input filename"); | |
| 1181 | try err_details.msg.appendSlice(allocator, "the output format was inferred from the input filename"); | |
| 1240 | 1182 | } else { |
| 1241 | try msg_writer.writeAll("the output format was unable to be inferred from the input filename, so the default was used"); | |
| 1183 | try err_details.msg.appendSlice(allocator, "the output format was unable to be inferred from the input filename, so the default was used"); | |
| 1242 | 1184 | } |
| 1243 | 1185 | try diagnostics.append(err_details); |
| 1244 | 1186 | }, |
| ... | ... | @@ -1248,11 +1190,10 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1248 | 1190 | .arg => |ctx| .{ .type = .note, .arg_index = ctx.index, .arg_span = ctx.value.argSpan(ctx.arg) }, |
| 1249 | 1191 | .unspecified => unreachable, |
| 1250 | 1192 | }; |
| 1251 | var msg_writer = err_details.msg.writer(allocator); | |
| 1252 | 1193 | if (output_format_source == .inferred_from_output_filename) { |
| 1253 | try msg_writer.writeAll("the output format was inferred from the output filename"); | |
| 1194 | try err_details.msg.appendSlice(allocator, "the output format was inferred from the output filename"); | |
| 1254 | 1195 | } else { |
| 1255 | try msg_writer.writeAll("the output format was unable to be inferred from the output filename, so the default was used"); | |
| 1196 | try err_details.msg.appendSlice(allocator, "the output format was unable to be inferred from the output filename, so the default was used"); | |
| 1256 | 1197 | } |
| 1257 | 1198 | try diagnostics.append(err_details); |
| 1258 | 1199 | }, |
| ... | ... | @@ -1262,14 +1203,12 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1262 | 1203 | .arg_index = output_format_context.index, |
| 1263 | 1204 | .arg_span = output_format_context.value.argSpan(output_format_context.arg), |
| 1264 | 1205 | }; |
| 1265 | var msg_writer = err_details.msg.writer(allocator); | |
| 1266 | try msg_writer.writeAll("the output format was specified here"); | |
| 1206 | try err_details.msg.appendSlice(allocator, "the output format was specified here"); | |
| 1267 | 1207 | try diagnostics.append(err_details); |
| 1268 | 1208 | }, |
| 1269 | 1209 | .inferred_from_preprocess_only => { |
| 1270 | 1210 | var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = preprocess_only_context.index }; |
| 1271 | var msg_writer = err_details.msg.writer(allocator); | |
| 1272 | try msg_writer.print("the output format was inferred from the usage of the {s}{s} option", .{ | |
| 1211 | try err_details.msg.print(allocator, "the output format was inferred from the usage of the {s}{s} option", .{ | |
| 1273 | 1212 | preprocess_only_context.arg.prefixSlice(), |
| 1274 | 1213 | preprocess_only_context.arg.optionWithoutPrefix(preprocess_only_context.option_len), |
| 1275 | 1214 | }); |
| ... | ... | @@ -1291,19 +1230,19 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1291 | 1230 | } |
| 1292 | 1231 | |
| 1293 | 1232 | pub fn filepathWithExtension(allocator: Allocator, path: []const u8, ext: []const u8) ![]const u8 { |
| 1294 | var buf = std.array_list.Managed(u8).init(allocator); | |
| 1295 | errdefer buf.deinit(); | |
| 1233 | var buf: std.ArrayList(u8) = .empty; | |
| 1234 | errdefer buf.deinit(allocator); | |
| 1296 | 1235 | if (std.fs.path.dirname(path)) |dirname| { |
| 1297 | 1236 | var end_pos = dirname.len; |
| 1298 | 1237 | // We want to ensure that we write a path separator at the end, so if the dirname |
| 1299 | 1238 | // doesn't end with a path sep then include the char after the dirname |
| 1300 | 1239 | // which must be a path sep. |
| 1301 | 1240 | if (!std.fs.path.isSep(dirname[dirname.len - 1])) end_pos += 1; |
| 1302 | try buf.appendSlice(path[0..end_pos]); | |
| 1241 | try buf.appendSlice(allocator, path[0..end_pos]); | |
| 1303 | 1242 | } |
| 1304 | try buf.appendSlice(std.fs.path.stem(path)); | |
| 1305 | try buf.appendSlice(ext); | |
| 1306 | return try buf.toOwnedSlice(); | |
| 1243 | try buf.appendSlice(allocator, std.fs.path.stem(path)); | |
| 1244 | try buf.appendSlice(allocator, ext); | |
| 1245 | return try buf.toOwnedSlice(allocator); | |
| 1307 | 1246 | } |
| 1308 | 1247 | |
| 1309 | 1248 | pub fn isSupportedInputExtension(ext: []const u8) bool { |
| ... | ... | @@ -1537,7 +1476,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti |
| 1537 | 1476 | var options = parse(std.testing.allocator, args, &diagnostics) catch |err| switch (err) { |
| 1538 | 1477 | error.ParseError => { |
| 1539 | 1478 | try diagnostics.renderToWriter(args, &output.writer, .no_color); |
| 1540 | try std.testing.expectEqualStrings(expected_output, output.getWritten()); | |
| 1479 | try std.testing.expectEqualStrings(expected_output, output.written()); | |
| 1541 | 1480 | return null; |
| 1542 | 1481 | }, |
| 1543 | 1482 | else => |e| return e, |
| ... | ... | @@ -1545,7 +1484,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti |
| 1545 | 1484 | errdefer options.deinit(); |
| 1546 | 1485 | |
| 1547 | 1486 | try diagnostics.renderToWriter(args, &output.writer, .no_color); |
| 1548 | try std.testing.expectEqualStrings(expected_output, output.getWritten()); | |
| 1487 | try std.testing.expectEqualStrings(expected_output, output.written()); | |
| 1549 | 1488 | return options; |
| 1550 | 1489 | } |
| 1551 | 1490 |
lib/compiler/resinator/compile.zig+219-309| ... | ... | @@ -35,10 +35,7 @@ pub const CompileOptions = struct { |
| 35 | 35 | diagnostics: *Diagnostics, |
| 36 | 36 | source_mappings: ?*SourceMappings = null, |
| 37 | 37 | /// List of paths (absolute or relative to `cwd`) for every file that the resources within the .rc file depend on. |
| 38 | /// Items within the list will be allocated using the allocator of the ArrayList and must be | |
| 39 | /// freed by the caller. | |
| 40 | /// TODO: Maybe a dedicated struct for this purpose so that it's a bit nicer to work with. | |
| 41 | dependencies_list: ?*std.array_list.Managed([]const u8) = null, | |
| 38 | dependencies: ?*Dependencies = null, | |
| 42 | 39 | default_code_page: SupportedCodePage = .windows1252, |
| 43 | 40 | /// If true, the first #pragma code_page directive only sets the input code page, but not the output code page. |
| 44 | 41 | /// This check must be done before comments are removed from the file. |
| ... | ... | @@ -61,7 +58,26 @@ pub const CompileOptions = struct { |
| 61 | 58 | warn_instead_of_error_on_invalid_code_page: bool = false, |
| 62 | 59 | }; |
| 63 | 60 | |
| 64 | pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, options: CompileOptions) !void { | |
| 61 | pub const Dependencies = struct { | |
| 62 | list: std.ArrayList([]const u8), | |
| 63 | allocator: Allocator, | |
| 64 | ||
| 65 | pub fn init(allocator: Allocator) Dependencies { | |
| 66 | return .{ | |
| 67 | .list = .empty, | |
| 68 | .allocator = allocator, | |
| 69 | }; | |
| 70 | } | |
| 71 | ||
| 72 | pub fn deinit(self: *Dependencies) void { | |
| 73 | for (self.list.items) |item| { | |
| 74 | self.allocator.free(item); | |
| 75 | } | |
| 76 | self.list.deinit(self.allocator); | |
| 77 | } | |
| 78 | }; | |
| 79 | ||
| 80 | pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void { | |
| 65 | 81 | var lexer = lex.Lexer.init(source, .{ |
| 66 | 82 | .default_code_page = options.default_code_page, |
| 67 | 83 | .source_mappings = options.source_mappings, |
| ... | ... | @@ -74,12 +90,12 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 74 | 90 | var tree = try parser.parse(allocator, options.diagnostics); |
| 75 | 91 | defer tree.deinit(); |
| 76 | 92 | |
| 77 | var search_dirs = std.array_list.Managed(SearchDir).init(allocator); | |
| 93 | var search_dirs: std.ArrayList(SearchDir) = .empty; | |
| 78 | 94 | defer { |
| 79 | 95 | for (search_dirs.items) |*search_dir| { |
| 80 | 96 | search_dir.deinit(allocator); |
| 81 | 97 | } |
| 82 | search_dirs.deinit(); | |
| 98 | search_dirs.deinit(allocator); | |
| 83 | 99 | } |
| 84 | 100 | |
| 85 | 101 | if (options.source_mappings) |source_mappings| { |
| ... | ... | @@ -89,7 +105,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 89 | 105 | if (std.fs.path.dirname(root_path)) |root_dir_path| { |
| 90 | 106 | var root_dir = try options.cwd.openDir(root_dir_path, .{}); |
| 91 | 107 | errdefer root_dir.close(); |
| 92 | try search_dirs.append(.{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); | |
| 108 | try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); | |
| 93 | 109 | } |
| 94 | 110 | } |
| 95 | 111 | // Re-open the passed in cwd since we want to be able to close it (std.fs.cwd() shouldn't be closed) |
| ... | ... | @@ -111,14 +127,14 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 111 | 127 | }); |
| 112 | 128 | return error.CompileError; |
| 113 | 129 | }; |
| 114 | try search_dirs.append(.{ .dir = cwd_dir, .path = null }); | |
| 130 | try search_dirs.append(allocator, .{ .dir = cwd_dir, .path = null }); | |
| 115 | 131 | for (options.extra_include_paths) |extra_include_path| { |
| 116 | 132 | var dir = openSearchPathDir(options.cwd, extra_include_path) catch { |
| 117 | 133 | // TODO: maybe a warning that the search path is skipped? |
| 118 | 134 | continue; |
| 119 | 135 | }; |
| 120 | 136 | errdefer dir.close(); |
| 121 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); | |
| 137 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); | |
| 122 | 138 | } |
| 123 | 139 | for (options.system_include_paths) |system_include_path| { |
| 124 | 140 | var dir = openSearchPathDir(options.cwd, system_include_path) catch { |
| ... | ... | @@ -126,7 +142,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 126 | 142 | continue; |
| 127 | 143 | }; |
| 128 | 144 | errdefer dir.close(); |
| 129 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); | |
| 145 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); | |
| 130 | 146 | } |
| 131 | 147 | if (!options.ignore_include_env_var) { |
| 132 | 148 | const INCLUDE = std.process.getEnvVarOwned(allocator, "INCLUDE") catch ""; |
| ... | ... | @@ -142,7 +158,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 142 | 158 | while (it.next()) |search_path| { |
| 143 | 159 | var dir = openSearchPathDir(options.cwd, search_path) catch continue; |
| 144 | 160 | errdefer dir.close(); |
| 145 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); | |
| 161 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); | |
| 146 | 162 | } |
| 147 | 163 | } |
| 148 | 164 | |
| ... | ... | @@ -156,7 +172,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, option |
| 156 | 172 | .allocator = allocator, |
| 157 | 173 | .cwd = options.cwd, |
| 158 | 174 | .diagnostics = options.diagnostics, |
| 159 | .dependencies_list = options.dependencies_list, | |
| 175 | .dependencies = options.dependencies, | |
| 160 | 176 | .input_code_pages = &tree.input_code_pages, |
| 161 | 177 | .output_code_pages = &tree.output_code_pages, |
| 162 | 178 | // This is only safe because we know search_dirs won't be modified past this point |
| ... | ... | @@ -178,7 +194,7 @@ pub const Compiler = struct { |
| 178 | 194 | cwd: std.fs.Dir, |
| 179 | 195 | state: State = .{}, |
| 180 | 196 | diagnostics: *Diagnostics, |
| 181 | dependencies_list: ?*std.array_list.Managed([]const u8), | |
| 197 | dependencies: ?*Dependencies, | |
| 182 | 198 | input_code_pages: *const CodePageLookup, |
| 183 | 199 | output_code_pages: *const CodePageLookup, |
| 184 | 200 | search_dirs: []SearchDir, |
| ... | ... | @@ -194,7 +210,7 @@ pub const Compiler = struct { |
| 194 | 210 | characteristics: u32 = 0, |
| 195 | 211 | }; |
| 196 | 212 | |
| 197 | pub fn writeRoot(self: *Compiler, root: *Node.Root, writer: anytype) !void { | |
| 213 | pub fn writeRoot(self: *Compiler, root: *Node.Root, writer: *std.Io.Writer) !void { | |
| 198 | 214 | try writeEmptyResource(writer); |
| 199 | 215 | for (root.body) |node| { |
| 200 | 216 | try self.writeNode(node, writer); |
| ... | ... | @@ -236,7 +252,7 @@ pub const Compiler = struct { |
| 236 | 252 | } |
| 237 | 253 | } |
| 238 | 254 | |
| 239 | pub fn writeNode(self: *Compiler, node: *Node, writer: anytype) !void { | |
| 255 | pub fn writeNode(self: *Compiler, node: *Node, writer: *std.Io.Writer) !void { | |
| 240 | 256 | switch (node.id) { |
| 241 | 257 | .root => unreachable, // writeRoot should be called directly instead |
| 242 | 258 | .resource_external => try self.writeResourceExternal(@alignCast(@fieldParentPtr("base", node)), writer), |
| ... | ... | @@ -279,32 +295,32 @@ pub const Compiler = struct { |
| 279 | 295 | .literal, .number => { |
| 280 | 296 | const slice = literal_node.token.slice(self.source); |
| 281 | 297 | const code_page = self.input_code_pages.getForToken(literal_node.token); |
| 282 | var buf = try std.array_list.Managed(u8).initCapacity(self.allocator, slice.len); | |
| 283 | errdefer buf.deinit(); | |
| 298 | var buf = try std.ArrayList(u8).initCapacity(self.allocator, slice.len); | |
| 299 | errdefer buf.deinit(self.allocator); | |
| 284 | 300 | |
| 285 | 301 | var index: usize = 0; |
| 286 | 302 | while (code_page.codepointAt(index, slice)) |codepoint| : (index += codepoint.byte_len) { |
| 287 | 303 | const c = codepoint.value; |
| 288 | 304 | if (c == code_pages.Codepoint.invalid) { |
| 289 | try buf.appendSlice("�"); | |
| 305 | try buf.appendSlice(self.allocator, "�"); | |
| 290 | 306 | } else { |
| 291 | 307 | // Anything that is not returned as an invalid codepoint must be encodable as UTF-8. |
| 292 | 308 | const utf8_len = std.unicode.utf8CodepointSequenceLength(c) catch unreachable; |
| 293 | try buf.ensureUnusedCapacity(utf8_len); | |
| 309 | try buf.ensureUnusedCapacity(self.allocator, utf8_len); | |
| 294 | 310 | _ = std.unicode.utf8Encode(c, buf.unusedCapacitySlice()) catch unreachable; |
| 295 | 311 | buf.items.len += utf8_len; |
| 296 | 312 | } |
| 297 | 313 | } |
| 298 | 314 | |
| 299 | return buf.toOwnedSlice(); | |
| 315 | return buf.toOwnedSlice(self.allocator); | |
| 300 | 316 | }, |
| 301 | 317 | .quoted_ascii_string, .quoted_wide_string => { |
| 302 | 318 | const slice = literal_node.token.slice(self.source); |
| 303 | 319 | const column = literal_node.token.calculateColumn(self.source, 8, null); |
| 304 | 320 | const bytes = SourceBytes{ .slice = slice, .code_page = self.input_code_pages.getForToken(literal_node.token) }; |
| 305 | 321 | |
| 306 | var buf = std.array_list.Managed(u8).init(self.allocator); | |
| 307 | errdefer buf.deinit(); | |
| 322 | var buf: std.ArrayList(u8) = .empty; | |
| 323 | errdefer buf.deinit(self.allocator); | |
| 308 | 324 | |
| 309 | 325 | // Filenames are sort-of parsed as if they were wide strings, but the max escape width of |
| 310 | 326 | // hex/octal escapes is still determined by the L prefix. Since we want to end up with |
| ... | ... | @@ -320,19 +336,19 @@ pub const Compiler = struct { |
| 320 | 336 | while (try parser.nextUnchecked()) |parsed| { |
| 321 | 337 | const c = parsed.codepoint; |
| 322 | 338 | if (c == code_pages.Codepoint.invalid) { |
| 323 | try buf.appendSlice("�"); | |
| 339 | try buf.appendSlice(self.allocator, "�"); | |
| 324 | 340 | } else { |
| 325 | 341 | var codepoint_buf: [4]u8 = undefined; |
| 326 | 342 | // If the codepoint cannot be encoded, we fall back to � |
| 327 | 343 | if (std.unicode.utf8Encode(c, &codepoint_buf)) |len| { |
| 328 | try buf.appendSlice(codepoint_buf[0..len]); | |
| 344 | try buf.appendSlice(self.allocator, codepoint_buf[0..len]); | |
| 329 | 345 | } else |_| { |
| 330 | try buf.appendSlice("�"); | |
| 346 | try buf.appendSlice(self.allocator, "�"); | |
| 331 | 347 | } |
| 332 | 348 | } |
| 333 | 349 | } |
| 334 | 350 | |
| 335 | return buf.toOwnedSlice(); | |
| 351 | return buf.toOwnedSlice(self.allocator); | |
| 336 | 352 | }, |
| 337 | 353 | else => unreachable, // no other token types should be in a filename literal node |
| 338 | 354 | } |
| ... | ... | @@ -386,10 +402,10 @@ pub const Compiler = struct { |
| 386 | 402 | const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); |
| 387 | 403 | errdefer file.close(); |
| 388 | 404 | |
| 389 | if (self.dependencies_list) |dependencies_list| { | |
| 390 | const duped_path = try dependencies_list.allocator.dupe(u8, path); | |
| 391 | errdefer dependencies_list.allocator.free(duped_path); | |
| 392 | try dependencies_list.append(duped_path); | |
| 405 | if (self.dependencies) |dependencies| { | |
| 406 | const duped_path = try dependencies.allocator.dupe(u8, path); | |
| 407 | errdefer dependencies.allocator.free(duped_path); | |
| 408 | try dependencies.list.append(dependencies.allocator, duped_path); | |
| 393 | 409 | } |
| 394 | 410 | } |
| 395 | 411 | |
| ... | ... | @@ -398,12 +414,12 @@ pub const Compiler = struct { |
| 398 | 414 | if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| { |
| 399 | 415 | errdefer file.close(); |
| 400 | 416 | |
| 401 | if (self.dependencies_list) |dependencies_list| { | |
| 402 | const searched_file_path = try std.fs.path.join(dependencies_list.allocator, &.{ | |
| 417 | if (self.dependencies) |dependencies| { | |
| 418 | const searched_file_path = try std.fs.path.join(dependencies.allocator, &.{ | |
| 403 | 419 | search_dir.path orelse "", path, |
| 404 | 420 | }); |
| 405 | errdefer dependencies_list.allocator.free(searched_file_path); | |
| 406 | try dependencies_list.append(searched_file_path); | |
| 421 | errdefer dependencies.allocator.free(searched_file_path); | |
| 422 | try dependencies.list.append(dependencies.allocator, searched_file_path); | |
| 407 | 423 | } |
| 408 | 424 | |
| 409 | 425 | return file; |
| ... | ... | @@ -421,8 +437,8 @@ pub const Compiler = struct { |
| 421 | 437 | const bytes = self.sourceBytesForToken(token); |
| 422 | 438 | const output_code_page = self.output_code_pages.getForToken(token); |
| 423 | 439 | |
| 424 | var buf = try std.array_list.Managed(u8).initCapacity(self.allocator, bytes.slice.len); | |
| 425 | errdefer buf.deinit(); | |
| 440 | var buf = try std.ArrayList(u8).initCapacity(self.allocator, bytes.slice.len); | |
| 441 | errdefer buf.deinit(self.allocator); | |
| 426 | 442 | |
| 427 | 443 | var iterative_parser = literals.IterativeStringParser.init(bytes, .{ |
| 428 | 444 | .start_column = token.calculateColumn(self.source, 8, null), |
| ... | ... | @@ -444,11 +460,11 @@ pub const Compiler = struct { |
| 444 | 460 | switch (iterative_parser.declared_string_type) { |
| 445 | 461 | .wide => { |
| 446 | 462 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 447 | try buf.append(best_fit); | |
| 463 | try buf.append(self.allocator, best_fit); | |
| 448 | 464 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid or parsed.escaped_surrogate_pair) { |
| 449 | try buf.append('?'); | |
| 465 | try buf.append(self.allocator, '?'); | |
| 450 | 466 | } else { |
| 451 | try buf.appendSlice("??"); | |
| 467 | try buf.appendSlice(self.allocator, "??"); | |
| 452 | 468 | } |
| 453 | 469 | }, |
| 454 | 470 | .ascii => { |
| ... | ... | @@ -456,30 +472,30 @@ pub const Compiler = struct { |
| 456 | 472 | const truncated: u8 = @truncate(c); |
| 457 | 473 | switch (output_code_page) { |
| 458 | 474 | .utf8 => switch (truncated) { |
| 459 | 0...0x7F => try buf.append(truncated), | |
| 460 | else => try buf.append('?'), | |
| 475 | 0...0x7F => try buf.append(self.allocator, truncated), | |
| 476 | else => try buf.append(self.allocator, '?'), | |
| 461 | 477 | }, |
| 462 | 478 | .windows1252 => { |
| 463 | try buf.append(truncated); | |
| 479 | try buf.append(self.allocator, truncated); | |
| 464 | 480 | }, |
| 465 | 481 | } |
| 466 | 482 | } else { |
| 467 | 483 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 468 | try buf.append(best_fit); | |
| 484 | try buf.append(self.allocator, best_fit); | |
| 469 | 485 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { |
| 470 | try buf.append('?'); | |
| 486 | try buf.append(self.allocator, '?'); | |
| 471 | 487 | } else { |
| 472 | try buf.appendSlice("??"); | |
| 488 | try buf.appendSlice(self.allocator, "??"); | |
| 473 | 489 | } |
| 474 | 490 | } |
| 475 | 491 | }, |
| 476 | 492 | } |
| 477 | 493 | } |
| 478 | 494 | |
| 479 | return buf.toOwnedSlice(); | |
| 495 | return buf.toOwnedSlice(self.allocator); | |
| 480 | 496 | } |
| 481 | 497 | |
| 482 | pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: anytype) !void { | |
| 498 | pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void { | |
| 483 | 499 | // Init header with data size zero for now, will need to fill it in later |
| 484 | 500 | var header = try self.resourceHeader(node.id, node.type, .{}); |
| 485 | 501 | defer header.deinit(self.allocator); |
| ... | ... | @@ -572,7 +588,7 @@ pub const Compiler = struct { |
| 572 | 588 | switch (predefined_type) { |
| 573 | 589 | .GROUP_ICON, .GROUP_CURSOR => { |
| 574 | 590 | // Check for animated icon first |
| 575 | if (ani.isAnimatedIcon(file_reader.interface.adaptToOldInterface())) { | |
| 591 | if (ani.isAnimatedIcon(&file_reader.interface)) { | |
| 576 | 592 | // Animated icons are just put into the resource unmodified, |
| 577 | 593 | // and the resource type changes to ANIICON/ANICURSOR |
| 578 | 594 | |
| ... | ... | @@ -584,7 +600,12 @@ pub const Compiler = struct { |
| 584 | 600 | header.type_value.ordinal = @intFromEnum(new_predefined_type); |
| 585 | 601 | header.memory_flags = MemoryFlags.defaults(new_predefined_type); |
| 586 | 602 | header.applyMemoryFlags(node.common_resource_attributes, self.source); |
| 587 | header.data_size = @intCast(try file_reader.getSize()); | |
| 603 | header.data_size = std.math.cast(u32, try file_reader.getSize()) orelse { | |
| 604 | return self.addErrorDetailsAndFail(.{ | |
| 605 | .err = .resource_data_size_exceeds_max, | |
| 606 | .token = node.id, | |
| 607 | }); | |
| 608 | }; | |
| 588 | 609 | |
| 589 | 610 | try header.write(writer, self.errContext(node.id)); |
| 590 | 611 | try file_reader.seekTo(0); |
| ... | ... | @@ -595,7 +616,7 @@ pub const Compiler = struct { |
| 595 | 616 | // isAnimatedIcon moved the file cursor so reset to the start |
| 596 | 617 | try file_reader.seekTo(0); |
| 597 | 618 | |
| 598 | const icon_dir = ico.read(self.allocator, file_reader.interface.adaptToOldInterface(), try file_reader.getSize()) catch |err| switch (err) { | |
| 619 | const icon_dir = ico.read(self.allocator, &file_reader.interface, try file_reader.getSize()) catch |err| switch (err) { | |
| 599 | 620 | error.OutOfMemory => |e| return e, |
| 600 | 621 | else => |e| { |
| 601 | 622 | return self.iconReadError( |
| ... | ... | @@ -861,7 +882,7 @@ pub const Compiler = struct { |
| 861 | 882 | header.applyMemoryFlags(node.common_resource_attributes, self.source); |
| 862 | 883 | const file_size = try file_reader.getSize(); |
| 863 | 884 | |
| 864 | const bitmap_info = bmp.read(file_reader.interface.adaptToOldInterface(), file_size) catch |err| { | |
| 885 | const bitmap_info = bmp.read(&file_reader.interface, file_size) catch |err| { | |
| 865 | 886 | const filename_string_index = try self.diagnostics.putString(filename_utf8); |
| 866 | 887 | return self.addErrorDetailsAndFail(.{ |
| 867 | 888 | .err = .bmp_read_error, |
| ... | ... | @@ -969,13 +990,19 @@ pub const Compiler = struct { |
| 969 | 990 | header.data_size = @intCast(file_size); |
| 970 | 991 | try header.write(writer, self.errContext(node.id)); |
| 971 | 992 | |
| 972 | var header_slurping_reader = headerSlurpingReader(148, file_reader.interface.adaptToOldInterface()); | |
| 973 | var adapter = header_slurping_reader.reader().adaptToNewApi(&.{}); | |
| 974 | try writeResourceData(writer, &adapter.new_interface, header.data_size); | |
| 993 | // Slurp the first 148 bytes separately so we can store them in the FontDir | |
| 994 | var font_dir_header_buf: [148]u8 = @splat(0); | |
| 995 | const populated_len: u32 = @intCast(try file_reader.interface.readSliceShort(&font_dir_header_buf)); | |
| 996 | ||
| 997 | // Write only the populated bytes slurped from the header | |
| 998 | try writer.writeAll(font_dir_header_buf[0..populated_len]); | |
| 999 | // Then write the rest of the bytes and the padding | |
| 1000 | try writeResourceDataNoPadding(writer, &file_reader.interface, header.data_size - populated_len); | |
| 1001 | try writeDataPadding(writer, header.data_size); | |
| 975 | 1002 | |
| 976 | 1003 | try self.state.font_dir.add(self.arena, FontDir.Font{ |
| 977 | 1004 | .id = header.name_value.ordinal, |
| 978 | .header_bytes = header_slurping_reader.slurped_header, | |
| 1005 | .header_bytes = font_dir_header_buf, | |
| 979 | 1006 | }, node.id); |
| 980 | 1007 | return; |
| 981 | 1008 | }, |
| ... | ... | @@ -1053,7 +1080,7 @@ pub const Compiler = struct { |
| 1053 | 1080 | } |
| 1054 | 1081 | } |
| 1055 | 1082 | |
| 1056 | pub fn write(self: Data, writer: anytype) !void { | |
| 1083 | pub fn write(self: Data, writer: *std.Io.Writer) !void { | |
| 1057 | 1084 | switch (self) { |
| 1058 | 1085 | .number => |number| switch (number.is_long) { |
| 1059 | 1086 | false => try writer.writeInt(WORD, number.asWord(), .little), |
| ... | ... | @@ -1225,38 +1252,30 @@ pub const Compiler = struct { |
| 1225 | 1252 | } |
| 1226 | 1253 | } |
| 1227 | 1254 | |
| 1228 | pub fn writeResourceRawData(self: *Compiler, node: *Node.ResourceRawData, writer: anytype) !void { | |
| 1229 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 1255 | pub fn writeResourceRawData(self: *Compiler, node: *Node.ResourceRawData, writer: *std.Io.Writer) !void { | |
| 1256 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 1230 | 1257 | defer data_buffer.deinit(); |
| 1231 | // The header's data length field is a u32 so limit the resource's data size so that | |
| 1232 | // we know we can always specify the real size. | |
| 1233 | var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); | |
| 1234 | const data_writer = limited_writer.writer(); | |
| 1235 | 1258 | |
| 1236 | 1259 | for (node.raw_data) |expression| { |
| 1237 | 1260 | const data = try self.evaluateDataExpression(expression); |
| 1238 | 1261 | defer data.deinit(self.allocator); |
| 1239 | data.write(data_writer) catch |err| switch (err) { | |
| 1240 | error.NoSpaceLeft => { | |
| 1241 | return self.addErrorDetailsAndFail(.{ | |
| 1242 | .err = .resource_data_size_exceeds_max, | |
| 1243 | .token = node.id, | |
| 1244 | }); | |
| 1245 | }, | |
| 1246 | else => |e| return e, | |
| 1247 | }; | |
| 1262 | try data.write(&data_buffer.writer); | |
| 1248 | 1263 | } |
| 1249 | 1264 | |
| 1250 | // This intCast can't fail because the limitedWriter above guarantees that | |
| 1251 | // we will never write more than maxInt(u32) bytes. | |
| 1252 | const data_len: u32 = @intCast(data_buffer.items.len); | |
| 1265 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes | |
| 1266 | const data_len: u32 = std.math.cast(u32, data_buffer.written().len) orelse { | |
| 1267 | return self.addErrorDetailsAndFail(.{ | |
| 1268 | .err = .resource_data_size_exceeds_max, | |
| 1269 | .token = node.id, | |
| 1270 | }); | |
| 1271 | }; | |
| 1253 | 1272 | try self.writeResourceHeader(writer, node.id, node.type, data_len, node.common_resource_attributes, self.state.language); |
| 1254 | 1273 | |
| 1255 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 1274 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 1256 | 1275 | try writeResourceData(writer, &data_fbs, data_len); |
| 1257 | 1276 | } |
| 1258 | 1277 | |
| 1259 | pub fn writeResourceHeader(self: *Compiler, writer: anytype, id_token: Token, type_token: Token, data_size: u32, common_resource_attributes: []Token, language: res.Language) !void { | |
| 1278 | pub fn writeResourceHeader(self: *Compiler, writer: *std.Io.Writer, id_token: Token, type_token: Token, data_size: u32, common_resource_attributes: []Token, language: res.Language) !void { | |
| 1260 | 1279 | var header = try self.resourceHeader(id_token, type_token, .{ |
| 1261 | 1280 | .language = language, |
| 1262 | 1281 | .data_size = data_size, |
| ... | ... | @@ -1272,7 +1291,7 @@ pub const Compiler = struct { |
| 1272 | 1291 | try data_reader.streamExact(writer, data_size); |
| 1273 | 1292 | } |
| 1274 | 1293 | |
| 1275 | pub fn writeResourceData(writer: anytype, data_reader: *std.Io.Reader, data_size: u32) !void { | |
| 1294 | pub fn writeResourceData(writer: *std.Io.Writer, data_reader: *std.Io.Reader, data_size: u32) !void { | |
| 1276 | 1295 | try writeResourceDataNoPadding(writer, data_reader, data_size); |
| 1277 | 1296 | try writeDataPadding(writer, data_size); |
| 1278 | 1297 | } |
| ... | ... | @@ -1305,28 +1324,19 @@ pub const Compiler = struct { |
| 1305 | 1324 | } |
| 1306 | 1325 | } |
| 1307 | 1326 | |
| 1308 | pub fn writeAccelerators(self: *Compiler, node: *Node.Accelerators, writer: anytype) !void { | |
| 1309 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 1327 | pub fn writeAccelerators(self: *Compiler, node: *Node.Accelerators, writer: *std.Io.Writer) !void { | |
| 1328 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 1310 | 1329 | defer data_buffer.deinit(); |
| 1311 | 1330 | |
| 1312 | // The header's data length field is a u32 so limit the resource's data size so that | |
| 1313 | // we know we can always specify the real size. | |
| 1314 | var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); | |
| 1315 | const data_writer = limited_writer.writer(); | |
| 1331 | try self.writeAcceleratorsData(node, &data_buffer.writer); | |
| 1316 | 1332 | |
| 1317 | self.writeAcceleratorsData(node, data_writer) catch |err| switch (err) { | |
| 1318 | error.NoSpaceLeft => { | |
| 1319 | return self.addErrorDetailsAndFail(.{ | |
| 1320 | .err = .resource_data_size_exceeds_max, | |
| 1321 | .token = node.id, | |
| 1322 | }); | |
| 1323 | }, | |
| 1324 | else => |e| return e, | |
| 1333 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes | |
| 1334 | const data_size: u32 = std.math.cast(u32, data_buffer.written().len) orelse { | |
| 1335 | return self.addErrorDetailsAndFail(.{ | |
| 1336 | .err = .resource_data_size_exceeds_max, | |
| 1337 | .token = node.id, | |
| 1338 | }); | |
| 1325 | 1339 | }; |
| 1326 | ||
| 1327 | // This intCast can't fail because the limitedWriter above guarantees that | |
| 1328 | // we will never write more than maxInt(u32) bytes. | |
| 1329 | const data_size: u32 = @intCast(data_buffer.items.len); | |
| 1330 | 1340 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 1331 | 1341 | .data_size = data_size, |
| 1332 | 1342 | }); |
| ... | ... | @@ -1337,13 +1347,13 @@ pub const Compiler = struct { |
| 1337 | 1347 | |
| 1338 | 1348 | try header.write(writer, self.errContext(node.id)); |
| 1339 | 1349 | |
| 1340 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 1350 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 1341 | 1351 | try writeResourceData(writer, &data_fbs, data_size); |
| 1342 | 1352 | } |
| 1343 | 1353 | |
| 1344 | 1354 | /// Expects `data_writer` to be a LimitedWriter limited to u32, meaning all writes to |
| 1345 | 1355 | /// the writer within this function could return error.NoSpaceLeft |
| 1346 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: anytype) !void { | |
| 1356 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: *std.Io.Writer) !void { | |
| 1347 | 1357 | for (node.accelerators, 0..) |accel_node, i| { |
| 1348 | 1358 | const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", accel_node)); |
| 1349 | 1359 | var modifiers = res.AcceleratorModifiers{}; |
| ... | ... | @@ -1404,13 +1414,9 @@ pub const Compiler = struct { |
| 1404 | 1414 | caption: ?Token = null, |
| 1405 | 1415 | }; |
| 1406 | 1416 | |
| 1407 | pub fn writeDialog(self: *Compiler, node: *Node.Dialog, writer: anytype) !void { | |
| 1408 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 1417 | pub fn writeDialog(self: *Compiler, node: *Node.Dialog, writer: *std.Io.Writer) !void { | |
| 1418 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 1409 | 1419 | defer data_buffer.deinit(); |
| 1410 | // The header's data length field is a u32 so limit the resource's data size so that | |
| 1411 | // we know we can always specify the real size. | |
| 1412 | var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); | |
| 1413 | const data_writer = limited_writer.writer(); | |
| 1414 | 1420 | |
| 1415 | 1421 | const resource = ResourceType.fromString(.{ |
| 1416 | 1422 | .slice = node.type.slice(self.source), |
| ... | ... | @@ -1671,21 +1677,18 @@ pub const Compiler = struct { |
| 1671 | 1677 | optional_statement_values.style |= res.WS.CAPTION; |
| 1672 | 1678 | } |
| 1673 | 1679 | |
| 1674 | self.writeDialogHeaderAndStrings( | |
| 1680 | // NOTE: Dialog header and menu/class/title strings can never exceed u32 bytes | |
| 1681 | // on their own. | |
| 1682 | try self.writeDialogHeaderAndStrings( | |
| 1675 | 1683 | node, |
| 1676 | data_writer, | |
| 1684 | &data_buffer.writer, | |
| 1677 | 1685 | resource, |
| 1678 | 1686 | &optional_statement_values, |
| 1679 | 1687 | x, |
| 1680 | 1688 | y, |
| 1681 | 1689 | width, |
| 1682 | 1690 | height, |
| 1683 | ) catch |err| switch (err) { | |
| 1684 | // Dialog header and menu/class/title strings can never exceed u32 bytes | |
| 1685 | // on their own, so this error is unreachable. | |
| 1686 | error.NoSpaceLeft => unreachable, | |
| 1687 | else => |e| return e, | |
| 1688 | }; | |
| 1691 | ); | |
| 1689 | 1692 | |
| 1690 | 1693 | var controls_by_id = std.AutoHashMap(u32, *const Node.ControlStatement).init(self.allocator); |
| 1691 | 1694 | // Number of controls are guaranteed by the parser to be within maxInt(u16). |
| ... | ... | @@ -1695,31 +1698,30 @@ pub const Compiler = struct { |
| 1695 | 1698 | for (node.controls) |control_node| { |
| 1696 | 1699 | const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", control_node)); |
| 1697 | 1700 | |
| 1698 | self.writeDialogControl( | |
| 1701 | try self.writeDialogControl( | |
| 1699 | 1702 | control, |
| 1700 | data_writer, | |
| 1703 | &data_buffer.writer, | |
| 1701 | 1704 | resource, |
| 1702 | 1705 | // We know the data_buffer len is limited to u32 max. |
| 1703 | @intCast(data_buffer.items.len), | |
| 1706 | @intCast(data_buffer.written().len), | |
| 1704 | 1707 | &controls_by_id, |
| 1705 | ) catch |err| switch (err) { | |
| 1706 | error.NoSpaceLeft => { | |
| 1707 | try self.addErrorDetails(.{ | |
| 1708 | .err = .resource_data_size_exceeds_max, | |
| 1709 | .token = node.id, | |
| 1710 | }); | |
| 1711 | return self.addErrorDetailsAndFail(.{ | |
| 1712 | .err = .resource_data_size_exceeds_max, | |
| 1713 | .type = .note, | |
| 1714 | .token = control.type, | |
| 1715 | }); | |
| 1716 | }, | |
| 1717 | else => |e| return e, | |
| 1718 | }; | |
| 1708 | ); | |
| 1709 | ||
| 1710 | if (data_buffer.written().len > std.math.maxInt(u32)) { | |
| 1711 | try self.addErrorDetails(.{ | |
| 1712 | .err = .resource_data_size_exceeds_max, | |
| 1713 | .token = node.id, | |
| 1714 | }); | |
| 1715 | return self.addErrorDetailsAndFail(.{ | |
| 1716 | .err = .resource_data_size_exceeds_max, | |
| 1717 | .type = .note, | |
| 1718 | .token = control.type, | |
| 1719 | }); | |
| 1720 | } | |
| 1719 | 1721 | } |
| 1720 | 1722 | |
| 1721 | 1723 | // We know the data_buffer len is limited to u32 max. |
| 1722 | const data_size: u32 = @intCast(data_buffer.items.len); | |
| 1724 | const data_size: u32 = @intCast(data_buffer.written().len); | |
| 1723 | 1725 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 1724 | 1726 | .data_size = data_size, |
| 1725 | 1727 | }); |
| ... | ... | @@ -1730,14 +1732,14 @@ pub const Compiler = struct { |
| 1730 | 1732 | |
| 1731 | 1733 | try header.write(writer, self.errContext(node.id)); |
| 1732 | 1734 | |
| 1733 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 1735 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 1734 | 1736 | try writeResourceData(writer, &data_fbs, data_size); |
| 1735 | 1737 | } |
| 1736 | 1738 | |
| 1737 | 1739 | fn writeDialogHeaderAndStrings( |
| 1738 | 1740 | self: *Compiler, |
| 1739 | 1741 | node: *Node.Dialog, |
| 1740 | data_writer: anytype, | |
| 1742 | data_writer: *std.Io.Writer, | |
| 1741 | 1743 | resource: ResourceType, |
| 1742 | 1744 | optional_statement_values: *const DialogOptionalStatementValues, |
| 1743 | 1745 | x: Number, |
| ... | ... | @@ -1797,7 +1799,7 @@ pub const Compiler = struct { |
| 1797 | 1799 | fn writeDialogControl( |
| 1798 | 1800 | self: *Compiler, |
| 1799 | 1801 | control: *Node.ControlStatement, |
| 1800 | data_writer: anytype, | |
| 1802 | data_writer: *std.Io.Writer, | |
| 1801 | 1803 | resource: ResourceType, |
| 1802 | 1804 | bytes_written_so_far: u32, |
| 1803 | 1805 | controls_by_id: *std.AutoHashMap(u32, *const Node.ControlStatement), |
| ... | ... | @@ -1821,7 +1823,7 @@ pub const Compiler = struct { |
| 1821 | 1823 | .token = control.type, |
| 1822 | 1824 | }); |
| 1823 | 1825 | } |
| 1824 | try data_writer.writeByteNTimes(0, num_padding); | |
| 1826 | try data_writer.splatByteAll(0, num_padding); | |
| 1825 | 1827 | |
| 1826 | 1828 | const style = if (control.style) |style_expression| |
| 1827 | 1829 | // Certain styles are implied by the control type |
| ... | ... | @@ -1973,40 +1975,37 @@ pub const Compiler = struct { |
| 1973 | 1975 | try NameOrOrdinal.writeEmpty(data_writer); |
| 1974 | 1976 | } |
| 1975 | 1977 | |
| 1976 | var extra_data_buf = std.array_list.Managed(u8).init(self.allocator); | |
| 1977 | defer extra_data_buf.deinit(); | |
| 1978 | 1978 | // The extra data byte length must be able to fit within a u16. |
| 1979 | var limited_extra_data_writer = limitedWriter(extra_data_buf.writer(), std.math.maxInt(u16)); | |
| 1980 | const extra_data_writer = limited_extra_data_writer.writer(); | |
| 1979 | var extra_data_buf: std.Io.Writer.Allocating = .init(self.allocator); | |
| 1980 | defer extra_data_buf.deinit(); | |
| 1981 | 1981 | for (control.extra_data) |data_expression| { |
| 1982 | 1982 | const data = try self.evaluateDataExpression(data_expression); |
| 1983 | 1983 | defer data.deinit(self.allocator); |
| 1984 | data.write(extra_data_writer) catch |err| switch (err) { | |
| 1985 | error.NoSpaceLeft => { | |
| 1986 | try self.addErrorDetails(.{ | |
| 1987 | .err = .control_extra_data_size_exceeds_max, | |
| 1988 | .token = control.type, | |
| 1989 | }); | |
| 1990 | return self.addErrorDetailsAndFail(.{ | |
| 1991 | .err = .control_extra_data_size_exceeds_max, | |
| 1992 | .type = .note, | |
| 1993 | .token = data_expression.getFirstToken(), | |
| 1994 | .token_span_end = data_expression.getLastToken(), | |
| 1995 | }); | |
| 1996 | }, | |
| 1997 | else => |e| return e, | |
| 1998 | }; | |
| 1984 | try data.write(&extra_data_buf.writer); | |
| 1985 | ||
| 1986 | if (extra_data_buf.written().len > std.math.maxInt(u16)) { | |
| 1987 | try self.addErrorDetails(.{ | |
| 1988 | .err = .control_extra_data_size_exceeds_max, | |
| 1989 | .token = control.type, | |
| 1990 | }); | |
| 1991 | return self.addErrorDetailsAndFail(.{ | |
| 1992 | .err = .control_extra_data_size_exceeds_max, | |
| 1993 | .type = .note, | |
| 1994 | .token = data_expression.getFirstToken(), | |
| 1995 | .token_span_end = data_expression.getLastToken(), | |
| 1996 | }); | |
| 1997 | } | |
| 1999 | 1998 | } |
| 2000 | 1999 | // We know the extra_data_buf size fits within a u16. |
| 2001 | const extra_data_size: u16 = @intCast(extra_data_buf.items.len); | |
| 2000 | const extra_data_size: u16 = @intCast(extra_data_buf.written().len); | |
| 2002 | 2001 | try data_writer.writeInt(u16, extra_data_size, .little); |
| 2003 | try data_writer.writeAll(extra_data_buf.items); | |
| 2002 | try data_writer.writeAll(extra_data_buf.written()); | |
| 2004 | 2003 | } |
| 2005 | 2004 | |
| 2006 | pub fn writeToolbar(self: *Compiler, node: *Node.Toolbar, writer: anytype) !void { | |
| 2007 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 2005 | pub fn writeToolbar(self: *Compiler, node: *Node.Toolbar, writer: *std.Io.Writer) !void { | |
| 2006 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 2008 | 2007 | defer data_buffer.deinit(); |
| 2009 | const data_writer = data_buffer.writer(); | |
| 2008 | const data_writer = &data_buffer.writer; | |
| 2010 | 2009 | |
| 2011 | 2010 | const button_width = evaluateNumberExpression(node.button_width, self.source, self.input_code_pages); |
| 2012 | 2011 | const button_height = evaluateNumberExpression(node.button_height, self.source, self.input_code_pages); |
| ... | ... | @@ -2034,7 +2033,7 @@ pub const Compiler = struct { |
| 2034 | 2033 | } |
| 2035 | 2034 | } |
| 2036 | 2035 | |
| 2037 | const data_size: u32 = @intCast(data_buffer.items.len); | |
| 2036 | const data_size: u32 = @intCast(data_buffer.written().len); | |
| 2038 | 2037 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 2039 | 2038 | .data_size = data_size, |
| 2040 | 2039 | }); |
| ... | ... | @@ -2044,7 +2043,7 @@ pub const Compiler = struct { |
| 2044 | 2043 | |
| 2045 | 2044 | try header.write(writer, self.errContext(node.id)); |
| 2046 | 2045 | |
| 2047 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 2046 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 2048 | 2047 | try writeResourceData(writer, &data_fbs, data_size); |
| 2049 | 2048 | } |
| 2050 | 2049 | |
| ... | ... | @@ -2056,7 +2055,7 @@ pub const Compiler = struct { |
| 2056 | 2055 | node: *Node.FontStatement, |
| 2057 | 2056 | }; |
| 2058 | 2057 | |
| 2059 | pub fn writeDialogFont(self: *Compiler, resource: ResourceType, values: FontStatementValues, writer: anytype) !void { | |
| 2058 | pub fn writeDialogFont(self: *Compiler, resource: ResourceType, values: FontStatementValues, writer: *std.Io.Writer) !void { | |
| 2060 | 2059 | const node = values.node; |
| 2061 | 2060 | const point_size = evaluateNumberExpression(node.point_size, self.source, self.input_code_pages); |
| 2062 | 2061 | try writer.writeInt(u16, point_size.asWord(), .little); |
| ... | ... | @@ -2081,13 +2080,9 @@ pub const Compiler = struct { |
| 2081 | 2080 | try writer.writeAll(std.mem.sliceAsBytes(typeface[0 .. typeface.len + 1])); |
| 2082 | 2081 | } |
| 2083 | 2082 | |
| 2084 | pub fn writeMenu(self: *Compiler, node: *Node.Menu, writer: anytype) !void { | |
| 2085 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 2083 | pub fn writeMenu(self: *Compiler, node: *Node.Menu, writer: *std.Io.Writer) !void { | |
| 2084 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 2086 | 2085 | defer data_buffer.deinit(); |
| 2087 | // The header's data length field is a u32 so limit the resource's data size so that | |
| 2088 | // we know we can always specify the real size. | |
| 2089 | var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); | |
| 2090 | const data_writer = limited_writer.writer(); | |
| 2091 | 2086 | |
| 2092 | 2087 | const type_bytes = SourceBytes{ |
| 2093 | 2088 | .slice = node.type.slice(self.source), |
| ... | ... | @@ -2096,21 +2091,15 @@ pub const Compiler = struct { |
| 2096 | 2091 | const resource = ResourceType.fromString(type_bytes); |
| 2097 | 2092 | std.debug.assert(resource == .menu or resource == .menuex); |
| 2098 | 2093 | |
| 2099 | var adapted = data_writer.adaptToNewApi(&.{}); | |
| 2094 | try self.writeMenuData(node, &data_buffer.writer, resource); | |
| 2100 | 2095 | |
| 2101 | self.writeMenuData(node, &adapted.new_interface, resource) catch |err| switch (err) { | |
| 2102 | error.WriteFailed => { | |
| 2103 | return self.addErrorDetailsAndFail(.{ | |
| 2104 | .err = .resource_data_size_exceeds_max, | |
| 2105 | .token = node.id, | |
| 2106 | }); | |
| 2107 | }, | |
| 2108 | else => |e| return e, | |
| 2096 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes | |
| 2097 | const data_size: u32 = std.math.cast(u32, data_buffer.written().len) orelse { | |
| 2098 | return self.addErrorDetailsAndFail(.{ | |
| 2099 | .err = .resource_data_size_exceeds_max, | |
| 2100 | .token = node.id, | |
| 2101 | }); | |
| 2109 | 2102 | }; |
| 2110 | ||
| 2111 | // This intCast can't fail because the limitedWriter above guarantees that | |
| 2112 | // we will never write more than maxInt(u32) bytes. | |
| 2113 | const data_size: u32 = @intCast(data_buffer.items.len); | |
| 2114 | 2103 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 2115 | 2104 | .data_size = data_size, |
| 2116 | 2105 | }); |
| ... | ... | @@ -2121,7 +2110,7 @@ pub const Compiler = struct { |
| 2121 | 2110 | |
| 2122 | 2111 | try header.write(writer, self.errContext(node.id)); |
| 2123 | 2112 | |
| 2124 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 2113 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 2125 | 2114 | try writeResourceData(writer, &data_fbs, data_size); |
| 2126 | 2115 | } |
| 2127 | 2116 | |
| ... | ... | @@ -2264,13 +2253,11 @@ pub const Compiler = struct { |
| 2264 | 2253 | } |
| 2265 | 2254 | } |
| 2266 | 2255 | |
| 2267 | pub fn writeVersionInfo(self: *Compiler, node: *Node.VersionInfo, writer: anytype) !void { | |
| 2268 | var data_buffer = std.array_list.Managed(u8).init(self.allocator); | |
| 2256 | pub fn writeVersionInfo(self: *Compiler, node: *Node.VersionInfo, writer: *std.Io.Writer) !void { | |
| 2257 | // NOTE: The node's length field (which is inclusive of the length of all of its children) is a u16 | |
| 2258 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | |
| 2269 | 2259 | defer data_buffer.deinit(); |
| 2270 | // The node's length field (which is inclusive of the length of all of its children) is a u16 | |
| 2271 | // so limit the node's data size so that we know we can always specify the real size. | |
| 2272 | var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u16)); | |
| 2273 | const data_writer = limited_writer.writer(); | |
| 2260 | const data_writer = &data_buffer.writer; | |
| 2274 | 2261 | |
| 2275 | 2262 | try data_writer.writeInt(u16, 0, .little); // placeholder size |
| 2276 | 2263 | try data_writer.writeInt(u16, res.FixedFileInfo.byte_len, .little); |
| ... | ... | @@ -2354,29 +2341,32 @@ pub const Compiler = struct { |
| 2354 | 2341 | try fixed_file_info.write(data_writer); |
| 2355 | 2342 | |
| 2356 | 2343 | for (node.block_statements) |statement| { |
| 2357 | var adapted = data_writer.adaptToNewApi(&.{}); | |
| 2358 | self.writeVersionNode(statement, &adapted.new_interface, &data_buffer) catch |err| switch (err) { | |
| 2359 | error.WriteFailed => { | |
| 2360 | try self.addErrorDetails(.{ | |
| 2361 | .err = .version_node_size_exceeds_max, | |
| 2362 | .token = node.id, | |
| 2363 | }); | |
| 2364 | return self.addErrorDetailsAndFail(.{ | |
| 2365 | .err = .version_node_size_exceeds_max, | |
| 2366 | .type = .note, | |
| 2367 | .token = statement.getFirstToken(), | |
| 2368 | .token_span_end = statement.getLastToken(), | |
| 2369 | }); | |
| 2344 | var overflow = false; | |
| 2345 | self.writeVersionNode(statement, data_writer) catch |err| switch (err) { | |
| 2346 | error.NoSpaceLeft => { | |
| 2347 | overflow = true; | |
| 2370 | 2348 | }, |
| 2371 | 2349 | else => |e| return e, |
| 2372 | 2350 | }; |
| 2351 | if (overflow or data_buffer.written().len > std.math.maxInt(u16)) { | |
| 2352 | try self.addErrorDetails(.{ | |
| 2353 | .err = .version_node_size_exceeds_max, | |
| 2354 | .token = node.id, | |
| 2355 | }); | |
| 2356 | return self.addErrorDetailsAndFail(.{ | |
| 2357 | .err = .version_node_size_exceeds_max, | |
| 2358 | .type = .note, | |
| 2359 | .token = statement.getFirstToken(), | |
| 2360 | .token_span_end = statement.getLastToken(), | |
| 2361 | }); | |
| 2362 | } | |
| 2373 | 2363 | } |
| 2374 | 2364 | |
| 2375 | // We know that data_buffer.items.len is within the limits of a u16, since we | |
| 2376 | // limited the writer to maxInt(u16) | |
| 2377 | const data_size: u16 = @intCast(data_buffer.items.len); | |
| 2365 | // We know that data_buffer len is within the limits of a u16, since we check in the block | |
| 2366 | // statements loop above which is the only place it can overflow. | |
| 2367 | const data_size: u16 = @intCast(data_buffer.written().len); | |
| 2378 | 2368 | // And now that we know the full size of this node (including its children), set its size |
| 2379 | std.mem.writeInt(u16, data_buffer.items[0..2], data_size, .little); | |
| 2369 | std.mem.writeInt(u16, data_buffer.written()[0..2], data_size, .little); | |
| 2380 | 2370 | |
| 2381 | 2371 | var header = try self.resourceHeader(node.id, node.versioninfo, .{ |
| 2382 | 2372 | .data_size = data_size, |
| ... | ... | @@ -2387,22 +2377,21 @@ pub const Compiler = struct { |
| 2387 | 2377 | |
| 2388 | 2378 | try header.write(writer, self.errContext(node.id)); |
| 2389 | 2379 | |
| 2390 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 2380 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 2391 | 2381 | try writeResourceData(writer, &data_fbs, data_size); |
| 2392 | 2382 | } |
| 2393 | 2383 | |
| 2394 | /// Expects writer to be a LimitedWriter limited to u16, meaning all writes to | |
| 2395 | /// the writer within this function could return error.NoSpaceLeft, and that buf.items.len | |
| 2396 | /// will never be able to exceed maxInt(u16). | |
| 2397 | pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer, buf: *std.array_list.Managed(u8)) !void { | |
| 2384 | /// Assumes that writer is Writer.Allocating (specifically, that buffered() gets the entire data) | |
| 2385 | /// TODO: This function could be nicer if writer was guaranteed to fail if it wrote more than u16 max bytes | |
| 2386 | pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer) !void { | |
| 2398 | 2387 | // We can assume that buf.items.len will never be able to exceed the limits of a u16 |
| 2399 | try writeDataPadding(writer, @as(u16, @intCast(buf.items.len))); | |
| 2388 | try writeDataPadding(writer, std.math.cast(u16, writer.buffered().len) orelse return error.NoSpaceLeft); | |
| 2400 | 2389 | |
| 2401 | const node_and_children_size_offset = buf.items.len; | |
| 2390 | const node_and_children_size_offset = writer.buffered().len; | |
| 2402 | 2391 | try writer.writeInt(u16, 0, .little); // placeholder for size |
| 2403 | const data_size_offset = buf.items.len; | |
| 2392 | const data_size_offset = writer.buffered().len; | |
| 2404 | 2393 | try writer.writeInt(u16, 0, .little); // placeholder for data size |
| 2405 | const data_type_offset = buf.items.len; | |
| 2394 | const data_type_offset = writer.buffered().len; | |
| 2406 | 2395 | // Data type is string unless the node contains values that are numbers. |
| 2407 | 2396 | try writer.writeInt(u16, res.VersionNode.type_string, .little); |
| 2408 | 2397 | |
| ... | ... | @@ -2432,7 +2421,7 @@ pub const Compiler = struct { |
| 2432 | 2421 | // during parsing, so we can just do the correct thing here. |
| 2433 | 2422 | var values_size: usize = 0; |
| 2434 | 2423 | |
| 2435 | try writeDataPadding(writer, @intCast(buf.items.len)); | |
| 2424 | try writeDataPadding(writer, std.math.cast(u16, writer.buffered().len) orelse return error.NoSpaceLeft); | |
| 2436 | 2425 | |
| 2437 | 2426 | for (block_or_value.values, 0..) |value_value_node_uncasted, i| { |
| 2438 | 2427 | const value_value_node = value_value_node_uncasted.cast(.block_value_value).?; |
| ... | ... | @@ -2471,26 +2460,26 @@ pub const Compiler = struct { |
| 2471 | 2460 | } |
| 2472 | 2461 | } |
| 2473 | 2462 | } |
| 2474 | var data_size_slice = buf.items[data_size_offset..]; | |
| 2463 | var data_size_slice = writer.buffered()[data_size_offset..]; | |
| 2475 | 2464 | std.mem.writeInt(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size)), .little); |
| 2476 | 2465 | |
| 2477 | 2466 | if (has_number_value) { |
| 2478 | const data_type_slice = buf.items[data_type_offset..]; | |
| 2467 | const data_type_slice = writer.buffered()[data_type_offset..]; | |
| 2479 | 2468 | std.mem.writeInt(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary, .little); |
| 2480 | 2469 | } |
| 2481 | 2470 | |
| 2482 | 2471 | if (node_type == .block) { |
| 2483 | 2472 | const block = block_or_value; |
| 2484 | 2473 | for (block.children) |child| { |
| 2485 | try self.writeVersionNode(child, writer, buf); | |
| 2474 | try self.writeVersionNode(child, writer); | |
| 2486 | 2475 | } |
| 2487 | 2476 | } |
| 2488 | 2477 | }, |
| 2489 | 2478 | else => unreachable, |
| 2490 | 2479 | } |
| 2491 | 2480 | |
| 2492 | const node_and_children_size = buf.items.len - node_and_children_size_offset; | |
| 2493 | const node_and_children_size_slice = buf.items[node_and_children_size_offset..]; | |
| 2481 | const node_and_children_size = writer.buffered().len - node_and_children_size_offset; | |
| 2482 | const node_and_children_size_slice = writer.buffered()[node_and_children_size_offset..]; | |
| 2494 | 2483 | std.mem.writeInt(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size)), .little); |
| 2495 | 2484 | } |
| 2496 | 2485 | |
| ... | ... | @@ -2683,11 +2672,11 @@ pub const Compiler = struct { |
| 2683 | 2672 | return .{ .bytes = header_size, .padding_after_name = padding_after_name }; |
| 2684 | 2673 | } |
| 2685 | 2674 | |
| 2686 | pub fn writeAssertNoOverflow(self: ResourceHeader, writer: anytype) !void { | |
| 2675 | pub fn writeAssertNoOverflow(self: ResourceHeader, writer: *std.Io.Writer) !void { | |
| 2687 | 2676 | return self.writeSizeInfo(writer, self.calcSize() catch unreachable); |
| 2688 | 2677 | } |
| 2689 | 2678 | |
| 2690 | pub fn write(self: ResourceHeader, writer: anytype, err_ctx: errors.DiagnosticsContext) !void { | |
| 2679 | pub fn write(self: ResourceHeader, writer: *std.Io.Writer, err_ctx: errors.DiagnosticsContext) !void { | |
| 2691 | 2680 | const size_info = self.calcSize() catch { |
| 2692 | 2681 | try err_ctx.diagnostics.append(.{ |
| 2693 | 2682 | .err = .resource_data_size_exceeds_max, |
| ... | ... | @@ -2825,7 +2814,7 @@ pub const Compiler = struct { |
| 2825 | 2814 | return null; |
| 2826 | 2815 | } |
| 2827 | 2816 | |
| 2828 | pub fn writeEmptyResource(writer: anytype) !void { | |
| 2817 | pub fn writeEmptyResource(writer: *std.Io.Writer) !void { | |
| 2829 | 2818 | const header = ResourceHeader{ |
| 2830 | 2819 | .name_value = .{ .ordinal = 0 }, |
| 2831 | 2820 | .type_value = .{ .ordinal = 0 }, |
| ... | ... | @@ -2942,87 +2931,8 @@ pub const SearchDir = struct { |
| 2942 | 2931 | } |
| 2943 | 2932 | }; |
| 2944 | 2933 | |
| 2945 | /// Slurps the first `size` bytes read into `slurped_header` | |
| 2946 | pub fn HeaderSlurpingReader(comptime size: usize, comptime ReaderType: anytype) type { | |
| 2947 | return struct { | |
| 2948 | child_reader: ReaderType, | |
| 2949 | bytes_read: usize = 0, | |
| 2950 | slurped_header: [size]u8 = [_]u8{0x00} ** size, | |
| 2951 | ||
| 2952 | pub const Error = ReaderType.Error; | |
| 2953 | pub const Reader = std.io.GenericReader(*@This(), Error, read); | |
| 2954 | ||
| 2955 | pub fn read(self: *@This(), buf: []u8) Error!usize { | |
| 2956 | const amt = try self.child_reader.read(buf); | |
| 2957 | if (self.bytes_read < size) { | |
| 2958 | const bytes_to_add = @min(amt, size - self.bytes_read); | |
| 2959 | const end_index = self.bytes_read + bytes_to_add; | |
| 2960 | @memcpy(self.slurped_header[self.bytes_read..end_index], buf[0..bytes_to_add]); | |
| 2961 | } | |
| 2962 | self.bytes_read +|= amt; | |
| 2963 | return amt; | |
| 2964 | } | |
| 2965 | ||
| 2966 | pub fn reader(self: *@This()) Reader { | |
| 2967 | return .{ .context = self }; | |
| 2968 | } | |
| 2969 | }; | |
| 2970 | } | |
| 2971 | ||
| 2972 | pub fn headerSlurpingReader(comptime size: usize, reader: anytype) HeaderSlurpingReader(size, @TypeOf(reader)) { | |
| 2973 | return .{ .child_reader = reader }; | |
| 2974 | } | |
| 2975 | ||
| 2976 | /// Sort of like std.io.LimitedReader, but a Writer. | |
| 2977 | /// Returns an error if writing the requested number of bytes | |
| 2978 | /// would ever exceed bytes_left, i.e. it does not always | |
| 2979 | /// write up to the limit and instead will error if the | |
| 2980 | /// limit would be breached if the entire slice was written. | |
| 2981 | pub fn LimitedWriter(comptime WriterType: type) type { | |
| 2982 | return struct { | |
| 2983 | inner_writer: WriterType, | |
| 2984 | bytes_left: u64, | |
| 2985 | ||
| 2986 | pub const Error = error{NoSpaceLeft} || WriterType.Error; | |
| 2987 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 2988 | ||
| 2989 | const Self = @This(); | |
| 2990 | ||
| 2991 | pub fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 2992 | if (bytes.len > self.bytes_left) return error.NoSpaceLeft; | |
| 2993 | const amt = try self.inner_writer.write(bytes); | |
| 2994 | self.bytes_left -= amt; | |
| 2995 | return amt; | |
| 2996 | } | |
| 2997 | ||
| 2998 | pub fn writer(self: *Self) Writer { | |
| 2999 | return .{ .context = self }; | |
| 3000 | } | |
| 3001 | }; | |
| 3002 | } | |
| 3003 | ||
| 3004 | /// Returns an initialised `LimitedWriter` | |
| 3005 | /// `bytes_left` is a `u64` to be able to take 64 bit file offsets | |
| 3006 | pub fn limitedWriter(inner_writer: anytype, bytes_left: u64) LimitedWriter(@TypeOf(inner_writer)) { | |
| 3007 | return .{ .inner_writer = inner_writer, .bytes_left = bytes_left }; | |
| 3008 | } | |
| 3009 | ||
| 3010 | test "limitedWriter basic usage" { | |
| 3011 | var buf: [4]u8 = undefined; | |
| 3012 | var fbs = std.io.fixedBufferStream(&buf); | |
| 3013 | var limited_stream = limitedWriter(fbs.writer(), 4); | |
| 3014 | var writer = limited_stream.writer(); | |
| 3015 | ||
| 3016 | try std.testing.expectEqual(@as(usize, 3), try writer.write("123")); | |
| 3017 | try std.testing.expectEqualSlices(u8, "123", buf[0..3]); | |
| 3018 | try std.testing.expectError(error.NoSpaceLeft, writer.write("45")); | |
| 3019 | try std.testing.expectEqual(@as(usize, 1), try writer.write("4")); | |
| 3020 | try std.testing.expectEqualSlices(u8, "1234", buf[0..4]); | |
| 3021 | try std.testing.expectError(error.NoSpaceLeft, writer.write("5")); | |
| 3022 | } | |
| 3023 | ||
| 3024 | 2934 | pub const FontDir = struct { |
| 3025 | fonts: std.ArrayListUnmanaged(Font) = .empty, | |
| 2935 | fonts: std.ArrayList(Font) = .empty, | |
| 3026 | 2936 | /// To keep track of which ids are set and where they were set from |
| 3027 | 2937 | ids: std.AutoHashMapUnmanaged(u16, Token) = .empty, |
| 3028 | 2938 | |
| ... | ... | @@ -3040,7 +2950,7 @@ pub const FontDir = struct { |
| 3040 | 2950 | try self.fonts.append(allocator, font); |
| 3041 | 2951 | } |
| 3042 | 2952 | |
| 3043 | pub fn writeResData(self: *FontDir, compiler: *Compiler, writer: anytype) !void { | |
| 2953 | pub fn writeResData(self: *FontDir, compiler: *Compiler, writer: *std.Io.Writer) !void { | |
| 3044 | 2954 | if (self.fonts.items.len == 0) return; |
| 3045 | 2955 | |
| 3046 | 2956 | // We know the number of fonts is limited to maxInt(u16) because fonts |
| ... | ... | @@ -3164,7 +3074,7 @@ pub const StringTable = struct { |
| 3164 | 3074 | blocks: std.AutoArrayHashMapUnmanaged(u16, Block) = .empty, |
| 3165 | 3075 | |
| 3166 | 3076 | pub const Block = struct { |
| 3167 | strings: std.ArrayListUnmanaged(Token) = .empty, | |
| 3077 | strings: std.ArrayList(Token) = .empty, | |
| 3168 | 3078 | set_indexes: std.bit_set.IntegerBitSet(16) = .{ .mask = 0 }, |
| 3169 | 3079 | memory_flags: MemoryFlags = MemoryFlags.defaults(res.RT.STRING), |
| 3170 | 3080 | characteristics: u32, |
| ... | ... | @@ -3245,10 +3155,10 @@ pub const StringTable = struct { |
| 3245 | 3155 | try std.testing.expectEqualStrings("a", trimToDoubleNUL(u8, "a\x00\x00b")); |
| 3246 | 3156 | } |
| 3247 | 3157 | |
| 3248 | pub fn writeResData(self: *Block, compiler: *Compiler, language: res.Language, block_id: u16, writer: anytype) !void { | |
| 3249 | var data_buffer = std.array_list.Managed(u8).init(compiler.allocator); | |
| 3158 | pub fn writeResData(self: *Block, compiler: *Compiler, language: res.Language, block_id: u16, writer: *std.Io.Writer) !void { | |
| 3159 | var data_buffer: std.Io.Writer.Allocating = .init(compiler.allocator); | |
| 3250 | 3160 | defer data_buffer.deinit(); |
| 3251 | const data_writer = data_buffer.writer(); | |
| 3161 | const data_writer = &data_buffer.writer; | |
| 3252 | 3162 | |
| 3253 | 3163 | var i: u8 = 0; |
| 3254 | 3164 | var string_i: u8 = 0; |
| ... | ... | @@ -3307,7 +3217,7 @@ pub const StringTable = struct { |
| 3307 | 3217 | // 16 * (131,070 + 2) = 2,097,152 which is well within the u32 max. |
| 3308 | 3218 | // |
| 3309 | 3219 | // Note: The string literal maximum length is enforced by the lexer. |
| 3310 | const data_size: u32 = @intCast(data_buffer.items.len); | |
| 3220 | const data_size: u32 = @intCast(data_buffer.written().len); | |
| 3311 | 3221 | |
| 3312 | 3222 | const header = Compiler.ResourceHeader{ |
| 3313 | 3223 | .name_value = .{ .ordinal = block_id }, |
| ... | ... | @@ -3322,7 +3232,7 @@ pub const StringTable = struct { |
| 3322 | 3232 | // we fully control and know are numbers, so they have a fixed size. |
| 3323 | 3233 | try header.writeAssertNoOverflow(writer); |
| 3324 | 3234 | |
| 3325 | var data_fbs: std.Io.Reader = .fixed(data_buffer.items); | |
| 3235 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | |
| 3326 | 3236 | try Compiler.writeResourceData(writer, &data_fbs, data_size); |
| 3327 | 3237 | } |
| 3328 | 3238 | }; |
lib/compiler/resinator/cvtres.zig+12-12| ... | ... | @@ -43,7 +43,7 @@ pub const Resource = struct { |
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | 45 | pub const ParsedResources = struct { |
| 46 | list: std.ArrayListUnmanaged(Resource) = .empty, | |
| 46 | list: std.ArrayList(Resource) = .empty, | |
| 47 | 47 | allocator: Allocator, |
| 48 | 48 | |
| 49 | 49 | pub fn init(allocator: Allocator) ParsedResources { |
| ... | ... | @@ -157,7 +157,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO |
| 157 | 157 | const ordinal_value = try reader.takeInt(u16, .little); |
| 158 | 158 | return .{ .ordinal = ordinal_value }; |
| 159 | 159 | } |
| 160 | var name_buf = try std.ArrayListUnmanaged(u16).initCapacity(allocator, 16); | |
| 160 | var name_buf = try std.ArrayList(u16).initCapacity(allocator, 16); | |
| 161 | 161 | errdefer name_buf.deinit(allocator); |
| 162 | 162 | var code_unit = first_code_unit; |
| 163 | 163 | while (code_unit != 0) { |
| ... | ... | @@ -373,7 +373,7 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons |
| 373 | 373 | try writer.writeAll(string_table.bytes.items); |
| 374 | 374 | } |
| 375 | 375 | |
| 376 | fn writeSymbol(writer: anytype, symbol: std.coff.Symbol) !void { | |
| 376 | fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void { | |
| 377 | 377 | try writer.writeAll(&symbol.name); |
| 378 | 378 | try writer.writeInt(u32, symbol.value, .little); |
| 379 | 379 | try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little); |
| ... | ... | @@ -383,7 +383,7 @@ fn writeSymbol(writer: anytype, symbol: std.coff.Symbol) !void { |
| 383 | 383 | try writer.writeInt(u8, symbol.number_of_aux_symbols, .little); |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | fn writeSectionDefinition(writer: anytype, def: std.coff.SectionDefinition) !void { | |
| 386 | fn writeSectionDefinition(writer: *std.Io.Writer, def: std.coff.SectionDefinition) !void { | |
| 387 | 387 | try writer.writeInt(u32, def.length, .little); |
| 388 | 388 | try writer.writeInt(u16, def.number_of_relocations, .little); |
| 389 | 389 | try writer.writeInt(u16, def.number_of_linenumbers, .little); |
| ... | ... | @@ -417,7 +417,7 @@ pub const ResourceDirectoryEntry = extern struct { |
| 417 | 417 | to_subdirectory: bool, |
| 418 | 418 | }, |
| 419 | 419 | |
| 420 | pub fn writeCoff(self: ResourceDirectoryEntry, writer: anytype) !void { | |
| 420 | pub fn writeCoff(self: ResourceDirectoryEntry, writer: *std.Io.Writer) !void { | |
| 421 | 421 | try writer.writeInt(u32, @bitCast(self.entry), .little); |
| 422 | 422 | try writer.writeInt(u32, @bitCast(self.offset), .little); |
| 423 | 423 | } |
| ... | ... | @@ -435,7 +435,7 @@ const ResourceTree = struct { |
| 435 | 435 | type_to_name_map: std.ArrayHashMapUnmanaged(NameOrOrdinal, NameToLanguageMap, NameOrOrdinalHashContext, true), |
| 436 | 436 | rsrc_string_table: std.ArrayHashMapUnmanaged(NameOrOrdinal, void, NameOrOrdinalHashContext, true), |
| 437 | 437 | deduplicated_data: std.StringArrayHashMapUnmanaged(u32), |
| 438 | data_offsets: std.ArrayListUnmanaged(u32), | |
| 438 | data_offsets: std.ArrayList(u32), | |
| 439 | 439 | rsrc02_len: u32, |
| 440 | 440 | coff_options: CoffOptions, |
| 441 | 441 | allocator: Allocator, |
| ... | ... | @@ -675,13 +675,13 @@ const ResourceTree = struct { |
| 675 | 675 | return &.{}; |
| 676 | 676 | } |
| 677 | 677 | |
| 678 | var level2_list: std.ArrayListUnmanaged(*const NameToLanguageMap) = .empty; | |
| 678 | var level2_list: std.ArrayList(*const NameToLanguageMap) = .empty; | |
| 679 | 679 | defer level2_list.deinit(allocator); |
| 680 | 680 | |
| 681 | var level3_list: std.ArrayListUnmanaged(*const LanguageToResourceMap) = .empty; | |
| 681 | var level3_list: std.ArrayList(*const LanguageToResourceMap) = .empty; | |
| 682 | 682 | defer level3_list.deinit(allocator); |
| 683 | 683 | |
| 684 | var resources_list: std.ArrayListUnmanaged(*const RelocatableResource) = .empty; | |
| 684 | var resources_list: std.ArrayList(*const RelocatableResource) = .empty; | |
| 685 | 685 | defer resources_list.deinit(allocator); |
| 686 | 686 | |
| 687 | 687 | var relocations = Relocations.init(allocator); |
| ... | ... | @@ -896,7 +896,7 @@ const ResourceTree = struct { |
| 896 | 896 | return symbols; |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | fn writeRelocation(writer: anytype, relocation: std.coff.Relocation) !void { | |
| 899 | fn writeRelocation(writer: *std.Io.Writer, relocation: std.coff.Relocation) !void { | |
| 900 | 900 | try writer.writeInt(u32, relocation.virtual_address, .little); |
| 901 | 901 | try writer.writeInt(u32, relocation.symbol_table_index, .little); |
| 902 | 902 | try writer.writeInt(u16, relocation.type, .little); |
| ... | ... | @@ -928,7 +928,7 @@ const Relocation = struct { |
| 928 | 928 | |
| 929 | 929 | const Relocations = struct { |
| 930 | 930 | allocator: Allocator, |
| 931 | list: std.ArrayListUnmanaged(Relocation) = .empty, | |
| 931 | list: std.ArrayList(Relocation) = .empty, | |
| 932 | 932 | cur_symbol_index: u32 = 5, |
| 933 | 933 | |
| 934 | 934 | pub fn init(allocator: Allocator) Relocations { |
| ... | ... | @@ -952,7 +952,7 @@ const Relocations = struct { |
| 952 | 952 | /// Does not do deduplication (only because there's no chance of duplicate strings in this |
| 953 | 953 | /// instance). |
| 954 | 954 | const StringTable = struct { |
| 955 | bytes: std.ArrayListUnmanaged(u8) = .empty, | |
| 955 | bytes: std.ArrayList(u8) = .empty, | |
| 956 | 956 | |
| 957 | 957 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
| 958 | 958 | self.bytes.deinit(allocator); |
lib/compiler/resinator/errors.zig+25-28| ... | ... | @@ -15,10 +15,10 @@ const builtin = @import("builtin"); |
| 15 | 15 | const native_endian = builtin.cpu.arch.endian(); |
| 16 | 16 | |
| 17 | 17 | pub const Diagnostics = struct { |
| 18 | errors: std.ArrayListUnmanaged(ErrorDetails) = .empty, | |
| 18 | errors: std.ArrayList(ErrorDetails) = .empty, | |
| 19 | 19 | /// Append-only, cannot handle removing strings. |
| 20 | 20 | /// Expects to own all strings within the list. |
| 21 | strings: std.ArrayListUnmanaged([]const u8) = .empty, | |
| 21 | strings: std.ArrayList([]const u8) = .empty, | |
| 22 | 22 | allocator: std.mem.Allocator, |
| 23 | 23 | |
| 24 | 24 | pub fn init(allocator: std.mem.Allocator) Diagnostics { |
| ... | ... | @@ -256,7 +256,7 @@ pub const ErrorDetails = struct { |
| 256 | 256 | .{ "literal", "unquoted literal" }, |
| 257 | 257 | }); |
| 258 | 258 | |
| 259 | pub fn writeCommaSeparated(self: ExpectedTypes, writer: anytype) !void { | |
| 259 | pub fn writeCommaSeparated(self: ExpectedTypes, writer: *std.Io.Writer) !void { | |
| 260 | 260 | const struct_info = @typeInfo(ExpectedTypes).@"struct"; |
| 261 | 261 | const num_real_fields = struct_info.fields.len - 1; |
| 262 | 262 | const num_padding_bits = @bitSizeOf(ExpectedTypes) - num_real_fields; |
| ... | ... | @@ -441,7 +441,7 @@ pub const ErrorDetails = struct { |
| 441 | 441 | } }; |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | pub fn render(self: ErrorDetails, writer: anytype, source: []const u8, strings: []const []const u8) !void { | |
| 444 | pub fn render(self: ErrorDetails, writer: *std.Io.Writer, source: []const u8, strings: []const []const u8) !void { | |
| 445 | 445 | switch (self.err) { |
| 446 | 446 | .unfinished_string_literal => { |
| 447 | 447 | return writer.print("unfinished string literal at '{f}', expected closing '\"'", .{self.fmtToken(source)}); |
| ... | ... | @@ -987,12 +987,14 @@ pub fn renderErrorMessage(writer: *std.io.Writer, tty_config: std.io.tty.Config, |
| 987 | 987 | if (corresponding_span != null and corresponding_file != null) { |
| 988 | 988 | var worth_printing_lines: bool = true; |
| 989 | 989 | var initial_lines_err: ?anyerror = null; |
| 990 | var file_reader_buf: [max_source_line_bytes * 2]u8 = undefined; | |
| 990 | 991 | var corresponding_lines: ?CorrespondingLines = CorrespondingLines.init( |
| 991 | 992 | cwd, |
| 992 | 993 | err_details, |
| 993 | 994 | source_line_for_display.line, |
| 994 | 995 | corresponding_span.?, |
| 995 | 996 | corresponding_file.?, |
| 997 | &file_reader_buf, | |
| 996 | 998 | ) catch |err| switch (err) { |
| 997 | 999 | error.NotWorthPrintingLines => blk: { |
| 998 | 1000 | worth_printing_lines = false; |
| ... | ... | @@ -1078,10 +1080,17 @@ const CorrespondingLines = struct { |
| 1078 | 1080 | at_eof: bool = false, |
| 1079 | 1081 | span: SourceMappings.CorrespondingSpan, |
| 1080 | 1082 | file: std.fs.File, |
| 1081 | buffered_reader: std.fs.File.Reader, | |
| 1083 | file_reader: std.fs.File.Reader, | |
| 1082 | 1084 | code_page: SupportedCodePage, |
| 1083 | 1085 | |
| 1084 | pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines { | |
| 1086 | pub fn init( | |
| 1087 | cwd: std.fs.Dir, | |
| 1088 | err_details: ErrorDetails, | |
| 1089 | line_for_comparison: []const u8, | |
| 1090 | corresponding_span: SourceMappings.CorrespondingSpan, | |
| 1091 | corresponding_file: []const u8, | |
| 1092 | file_reader_buf: []u8, | |
| 1093 | ) !CorrespondingLines { | |
| 1085 | 1094 | // We don't do line comparison for this error, so don't print the note if the line |
| 1086 | 1095 | // number is different |
| 1087 | 1096 | if (err_details.err == .string_literal_too_long and err_details.token.line_number != corresponding_span.start_line) { |
| ... | ... | @@ -1096,18 +1105,14 @@ const CorrespondingLines = struct { |
| 1096 | 1105 | var corresponding_lines = CorrespondingLines{ |
| 1097 | 1106 | .span = corresponding_span, |
| 1098 | 1107 | .file = try utils.openFileNotDir(cwd, corresponding_file, .{}), |
| 1099 | .buffered_reader = undefined, | |
| 1100 | 1108 | .code_page = err_details.code_page, |
| 1109 | .file_reader = undefined, | |
| 1101 | 1110 | }; |
| 1102 | corresponding_lines.buffered_reader = corresponding_lines.file.reader(&.{}); | |
| 1111 | corresponding_lines.file_reader = corresponding_lines.file.reader(file_reader_buf); | |
| 1103 | 1112 | errdefer corresponding_lines.deinit(); |
| 1104 | 1113 | |
| 1105 | var fbs = std.io.fixedBufferStream(&corresponding_lines.line_buf); | |
| 1106 | const writer = fbs.writer(); | |
| 1107 | ||
| 1108 | 1114 | try corresponding_lines.writeLineFromStreamVerbatim( |
| 1109 | writer, | |
| 1110 | corresponding_lines.buffered_reader.interface.adaptToOldInterface(), | |
| 1115 | &corresponding_lines.file_reader.interface, | |
| 1111 | 1116 | corresponding_span.start_line, |
| 1112 | 1117 | ); |
| 1113 | 1118 | |
| ... | ... | @@ -1145,12 +1150,8 @@ const CorrespondingLines = struct { |
| 1145 | 1150 | self.line_len = 0; |
| 1146 | 1151 | self.visual_line_len = 0; |
| 1147 | 1152 | |
| 1148 | var fbs = std.io.fixedBufferStream(&self.line_buf); | |
| 1149 | const writer = fbs.writer(); | |
| 1150 | ||
| 1151 | 1153 | try self.writeLineFromStreamVerbatim( |
| 1152 | writer, | |
| 1153 | self.buffered_reader.interface.adaptToOldInterface(), | |
| 1154 | &self.file_reader.interface, | |
| 1154 | 1155 | self.line_num, |
| 1155 | 1156 | ); |
| 1156 | 1157 | |
| ... | ... | @@ -1164,7 +1165,7 @@ const CorrespondingLines = struct { |
| 1164 | 1165 | return visual_line; |
| 1165 | 1166 | } |
| 1166 | 1167 | |
| 1167 | fn writeLineFromStreamVerbatim(self: *CorrespondingLines, writer: anytype, input: anytype, line_num: usize) !void { | |
| 1168 | fn writeLineFromStreamVerbatim(self: *CorrespondingLines, input: *std.Io.Reader, line_num: usize) !void { | |
| 1168 | 1169 | while (try readByteOrEof(input)) |byte| { |
| 1169 | 1170 | switch (byte) { |
| 1170 | 1171 | '\n', '\r' => { |
| ... | ... | @@ -1184,13 +1185,9 @@ const CorrespondingLines = struct { |
| 1184 | 1185 | } |
| 1185 | 1186 | }, |
| 1186 | 1187 | else => { |
| 1187 | if (self.line_num == line_num) { | |
| 1188 | if (writer.writeByte(byte)) { | |
| 1189 | self.line_len += 1; | |
| 1190 | } else |err| switch (err) { | |
| 1191 | error.NoSpaceLeft => {}, | |
| 1192 | else => |e| return e, | |
| 1193 | } | |
| 1188 | if (self.line_num == line_num and self.line_len < self.line_buf.len) { | |
| 1189 | self.line_buf[self.line_len] = byte; | |
| 1190 | self.line_len += 1; | |
| 1194 | 1191 | } |
| 1195 | 1192 | }, |
| 1196 | 1193 | } |
| ... | ... | @@ -1201,8 +1198,8 @@ const CorrespondingLines = struct { |
| 1201 | 1198 | self.line_num += 1; |
| 1202 | 1199 | } |
| 1203 | 1200 | |
| 1204 | fn readByteOrEof(reader: anytype) !?u8 { | |
| 1205 | return reader.readByte() catch |err| switch (err) { | |
| 1201 | fn readByteOrEof(reader: *std.Io.Reader) !?u8 { | |
| 1202 | return reader.takeByte() catch |err| switch (err) { | |
| 1206 | 1203 | error.EndOfStream => return null, |
| 1207 | 1204 | else => |e| return e, |
| 1208 | 1205 | }; |
lib/compiler/resinator/ico.zig+43-57| ... | ... | @@ -8,80 +8,66 @@ const std = @import("std"); |
| 8 | 8 | const builtin = @import("builtin"); |
| 9 | 9 | const native_endian = builtin.cpu.arch.endian(); |
| 10 | 10 | |
| 11 | pub const ReadError = std.mem.Allocator.Error || error{ InvalidHeader, InvalidImageType, ImpossibleDataSize, UnexpectedEOF, ReadError }; | |
| 12 | ||
| 13 | pub fn read(allocator: std.mem.Allocator, reader: anytype, max_size: u64) ReadError!IconDir { | |
| 14 | // Some Reader implementations have an empty ReadError error set which would | |
| 15 | // cause 'unreachable else' if we tried to use an else in the switch, so we | |
| 16 | // need to detect this case and not try to translate to ReadError | |
| 17 | const anyerror_reader_errorset = @TypeOf(reader).Error == anyerror; | |
| 18 | const empty_reader_errorset = @typeInfo(@TypeOf(reader).Error).error_set == null or @typeInfo(@TypeOf(reader).Error).error_set.?.len == 0; | |
| 19 | if (empty_reader_errorset and !anyerror_reader_errorset) { | |
| 20 | return readAnyError(allocator, reader, max_size) catch |err| switch (err) { | |
| 21 | error.EndOfStream => error.UnexpectedEOF, | |
| 22 | else => |e| return e, | |
| 23 | }; | |
| 24 | } else { | |
| 25 | return readAnyError(allocator, reader, max_size) catch |err| switch (err) { | |
| 26 | error.OutOfMemory, | |
| 27 | error.InvalidHeader, | |
| 28 | error.InvalidImageType, | |
| 29 | error.ImpossibleDataSize, | |
| 30 | => |e| return e, | |
| 31 | error.EndOfStream => error.UnexpectedEOF, | |
| 32 | // The remaining errors are dependent on the `reader`, so | |
| 33 | // we just translate them all to generic ReadError | |
| 34 | else => error.ReadError, | |
| 35 | }; | |
| 36 | } | |
| 11 | pub const ReadError = std.mem.Allocator.Error || error{ InvalidHeader, InvalidImageType, ImpossibleDataSize, UnexpectedEOF, ReadFailed }; | |
| 12 | ||
| 13 | pub fn read(allocator: std.mem.Allocator, reader: *std.Io.Reader, max_size: u64) ReadError!IconDir { | |
| 14 | return readInner(allocator, reader, max_size) catch |err| switch (err) { | |
| 15 | error.OutOfMemory, | |
| 16 | error.InvalidHeader, | |
| 17 | error.InvalidImageType, | |
| 18 | error.ImpossibleDataSize, | |
| 19 | error.ReadFailed, | |
| 20 | => |e| return e, | |
| 21 | error.EndOfStream => error.UnexpectedEOF, | |
| 22 | }; | |
| 37 | 23 | } |
| 38 | 24 | |
| 39 | 25 | // TODO: This seems like a somewhat strange pattern, could be a better way |
| 40 | 26 | // to do this. Maybe it makes more sense to handle the translation |
| 41 | 27 | // at the call site instead of having a helper function here. |
| 42 | pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64) !IconDir { | |
| 43 | const reserved = try reader.readInt(u16, .little); | |
| 28 | fn readInner(allocator: std.mem.Allocator, reader: *std.Io.Reader, max_size: u64) !IconDir { | |
| 29 | const reserved = try reader.takeInt(u16, .little); | |
| 44 | 30 | if (reserved != 0) { |
| 45 | 31 | return error.InvalidHeader; |
| 46 | 32 | } |
| 47 | 33 | |
| 48 | const image_type = reader.readEnum(ImageType, .little) catch |err| switch (err) { | |
| 49 | error.InvalidValue => return error.InvalidImageType, | |
| 34 | const image_type = reader.takeEnum(ImageType, .little) catch |err| switch (err) { | |
| 35 | error.InvalidEnumTag => return error.InvalidImageType, | |
| 50 | 36 | else => |e| return e, |
| 51 | 37 | }; |
| 52 | 38 | |
| 53 | const num_images = try reader.readInt(u16, .little); | |
| 39 | const num_images = try reader.takeInt(u16, .little); | |
| 54 | 40 | |
| 55 | 41 | // To avoid over-allocation in the case of a file that says it has way more |
| 56 | 42 | // entries than it actually does, we use an ArrayList with a conservatively |
| 57 | 43 | // limited initial capacity instead of allocating the entire slice at once. |
| 58 | 44 | const initial_capacity = @min(num_images, 8); |
| 59 | var entries = try std.array_list.Managed(Entry).initCapacity(allocator, initial_capacity); | |
| 60 | errdefer entries.deinit(); | |
| 45 | var entries = try std.ArrayList(Entry).initCapacity(allocator, initial_capacity); | |
| 46 | errdefer entries.deinit(allocator); | |
| 61 | 47 | |
| 62 | 48 | var i: usize = 0; |
| 63 | 49 | while (i < num_images) : (i += 1) { |
| 64 | 50 | var entry: Entry = undefined; |
| 65 | entry.width = try reader.readByte(); | |
| 66 | entry.height = try reader.readByte(); | |
| 67 | entry.num_colors = try reader.readByte(); | |
| 68 | entry.reserved = try reader.readByte(); | |
| 51 | entry.width = try reader.takeByte(); | |
| 52 | entry.height = try reader.takeByte(); | |
| 53 | entry.num_colors = try reader.takeByte(); | |
| 54 | entry.reserved = try reader.takeByte(); | |
| 69 | 55 | switch (image_type) { |
| 70 | 56 | .icon => { |
| 71 | 57 | entry.type_specific_data = .{ .icon = .{ |
| 72 | .color_planes = try reader.readInt(u16, .little), | |
| 73 | .bits_per_pixel = try reader.readInt(u16, .little), | |
| 58 | .color_planes = try reader.takeInt(u16, .little), | |
| 59 | .bits_per_pixel = try reader.takeInt(u16, .little), | |
| 74 | 60 | } }; |
| 75 | 61 | }, |
| 76 | 62 | .cursor => { |
| 77 | 63 | entry.type_specific_data = .{ .cursor = .{ |
| 78 | .hotspot_x = try reader.readInt(u16, .little), | |
| 79 | .hotspot_y = try reader.readInt(u16, .little), | |
| 64 | .hotspot_x = try reader.takeInt(u16, .little), | |
| 65 | .hotspot_y = try reader.takeInt(u16, .little), | |
| 80 | 66 | } }; |
| 81 | 67 | }, |
| 82 | 68 | } |
| 83 | entry.data_size_in_bytes = try reader.readInt(u32, .little); | |
| 84 | entry.data_offset_from_start_of_file = try reader.readInt(u32, .little); | |
| 69 | entry.data_size_in_bytes = try reader.takeInt(u32, .little); | |
| 70 | entry.data_offset_from_start_of_file = try reader.takeInt(u32, .little); | |
| 85 | 71 | // Validate that the offset/data size is feasible |
| 86 | 72 | if (@as(u64, entry.data_offset_from_start_of_file) + entry.data_size_in_bytes > max_size) { |
| 87 | 73 | return error.ImpossibleDataSize; |
| ... | ... | @@ -101,12 +87,12 @@ pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64 |
| 101 | 87 | if (entry.data_size_in_bytes < 16) { |
| 102 | 88 | return error.ImpossibleDataSize; |
| 103 | 89 | } |
| 104 | try entries.append(entry); | |
| 90 | try entries.append(allocator, entry); | |
| 105 | 91 | } |
| 106 | 92 | |
| 107 | 93 | return .{ |
| 108 | 94 | .image_type = image_type, |
| 109 | .entries = try entries.toOwnedSlice(), | |
| 95 | .entries = try entries.toOwnedSlice(allocator), | |
| 110 | 96 | .allocator = allocator, |
| 111 | 97 | }; |
| 112 | 98 | } |
| ... | ... | @@ -135,7 +121,7 @@ pub const IconDir = struct { |
| 135 | 121 | return @intCast(IconDir.res_header_byte_len + self.entries.len * Entry.res_byte_len); |
| 136 | 122 | } |
| 137 | 123 | |
| 138 | pub fn writeResData(self: IconDir, writer: anytype, first_image_id: u16) !void { | |
| 124 | pub fn writeResData(self: IconDir, writer: *std.Io.Writer, first_image_id: u16) !void { | |
| 139 | 125 | try writer.writeInt(u16, 0, .little); |
| 140 | 126 | try writer.writeInt(u16, @intFromEnum(self.image_type), .little); |
| 141 | 127 | // We know that entries.len must fit into a u16 |
| ... | ... | @@ -173,7 +159,7 @@ pub const Entry = struct { |
| 173 | 159 | |
| 174 | 160 | pub const res_byte_len = 14; |
| 175 | 161 | |
| 176 | pub fn writeResData(self: Entry, writer: anytype, id: u16) !void { | |
| 162 | pub fn writeResData(self: Entry, writer: *std.Io.Writer, id: u16) !void { | |
| 177 | 163 | switch (self.type_specific_data) { |
| 178 | 164 | .icon => |icon_data| { |
| 179 | 165 | try writer.writeInt(u8, @as(u8, @truncate(self.width)), .little); |
| ... | ... | @@ -198,8 +184,8 @@ pub const Entry = struct { |
| 198 | 184 | |
| 199 | 185 | test "icon" { |
| 200 | 186 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 201 | var fbs = std.io.fixedBufferStream(data); | |
| 202 | const icon = try read(std.testing.allocator, fbs.reader(), data.len); | |
| 187 | var fbs: std.Io.Reader = .fixed(data); | |
| 188 | const icon = try read(std.testing.allocator, &fbs, data.len); | |
| 203 | 189 | defer icon.deinit(); |
| 204 | 190 | |
| 205 | 191 | try std.testing.expectEqual(ImageType.icon, icon.image_type); |
| ... | ... | @@ -211,26 +197,26 @@ test "icon too many images" { |
| 211 | 197 | // it's not possible to hit EOF when looking for more RESDIR structures, since they are |
| 212 | 198 | // themselves 16 bytes long, so we'll always hit ImpossibleDataSize instead. |
| 213 | 199 | const data = "\x00\x00\x01\x00\x02\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 214 | var fbs = std.io.fixedBufferStream(data); | |
| 215 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | |
| 200 | var fbs: std.Io.Reader = .fixed(data); | |
| 201 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); | |
| 216 | 202 | } |
| 217 | 203 | |
| 218 | 204 | test "icon data size past EOF" { |
| 219 | 205 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x01\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 220 | var fbs = std.io.fixedBufferStream(data); | |
| 221 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | |
| 206 | var fbs: std.Io.Reader = .fixed(data); | |
| 207 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); | |
| 222 | 208 | } |
| 223 | 209 | |
| 224 | 210 | test "icon data offset past EOF" { |
| 225 | 211 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x17\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 226 | var fbs = std.io.fixedBufferStream(data); | |
| 227 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | |
| 212 | var fbs: std.Io.Reader = .fixed(data); | |
| 213 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); | |
| 228 | 214 | } |
| 229 | 215 | |
| 230 | 216 | test "icon data size too small" { |
| 231 | 217 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x0F\x00\x00\x00\x16\x00\x00\x00"; |
| 232 | var fbs = std.io.fixedBufferStream(data); | |
| 233 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | |
| 218 | var fbs: std.Io.Reader = .fixed(data); | |
| 219 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); | |
| 234 | 220 | } |
| 235 | 221 | |
| 236 | 222 | pub const ImageFormat = enum(u2) { |
lib/compiler/resinator/lang.zig+6-5| ... | ... | @@ -119,6 +119,7 @@ test tagToId { |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | test "exhaustive tagToId" { |
| 122 | @setEvalBranchQuota(2000); | |
| 122 | 123 | inline for (@typeInfo(LanguageId).@"enum".fields) |field| { |
| 123 | 124 | const id = tagToId(field.name) catch |err| { |
| 124 | 125 | std.debug.print("tag: {s}\n", .{field.name}); |
| ... | ... | @@ -131,8 +132,8 @@ test "exhaustive tagToId" { |
| 131 | 132 | } |
| 132 | 133 | var buf: [32]u8 = undefined; |
| 133 | 134 | inline for (valid_alternate_sorts) |parsed_sort| { |
| 134 | var fbs = std.io.fixedBufferStream(&buf); | |
| 135 | const writer = fbs.writer(); | |
| 135 | var fbs: std.Io.Writer = .fixed(&buf); | |
| 136 | const writer = &fbs; | |
| 136 | 137 | writer.writeAll(parsed_sort.language_code) catch unreachable; |
| 137 | 138 | writer.writeAll("-") catch unreachable; |
| 138 | 139 | writer.writeAll(parsed_sort.country_code.?) catch unreachable; |
| ... | ... | @@ -146,12 +147,12 @@ test "exhaustive tagToId" { |
| 146 | 147 | break :field name_buf; |
| 147 | 148 | }; |
| 148 | 149 | const expected = @field(LanguageId, &expected_field_name); |
| 149 | const id = tagToId(fbs.getWritten()) catch |err| { | |
| 150 | std.debug.print("tag: {s}\n", .{fbs.getWritten()}); | |
| 150 | const id = tagToId(fbs.buffered()) catch |err| { | |
| 151 | std.debug.print("tag: {s}\n", .{fbs.buffered()}); | |
| 151 | 152 | return err; |
| 152 | 153 | }; |
| 153 | 154 | try std.testing.expectEqual(expected, id orelse { |
| 154 | std.debug.print("tag: {s}, expected: {}, got null\n", .{ fbs.getWritten(), expected }); | |
| 155 | std.debug.print("tag: {s}, expected: {}, got null\n", .{ fbs.buffered(), expected }); | |
| 155 | 156 | return error.TestExpectedEqual; |
| 156 | 157 | }); |
| 157 | 158 | } |
lib/compiler/resinator/literals.zig+22-22| ... | ... | @@ -469,8 +469,8 @@ pub fn parseQuotedString( |
| 469 | 469 | const T = if (literal_type == .ascii) u8 else u16; |
| 470 | 470 | std.debug.assert(bytes.slice.len >= 2); // must at least have 2 double quote chars |
| 471 | 471 | |
| 472 | var buf = try std.array_list.Managed(T).initCapacity(allocator, bytes.slice.len); | |
| 473 | errdefer buf.deinit(); | |
| 472 | var buf = try std.ArrayList(T).initCapacity(allocator, bytes.slice.len); | |
| 473 | errdefer buf.deinit(allocator); | |
| 474 | 474 | |
| 475 | 475 | var iterative_parser = IterativeStringParser.init(bytes, options); |
| 476 | 476 | |
| ... | ... | @@ -480,13 +480,13 @@ pub fn parseQuotedString( |
| 480 | 480 | .ascii => switch (options.output_code_page) { |
| 481 | 481 | .windows1252 => { |
| 482 | 482 | if (parsed.from_escaped_integer) { |
| 483 | try buf.append(@truncate(c)); | |
| 483 | try buf.append(allocator, @truncate(c)); | |
| 484 | 484 | } else if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 485 | try buf.append(best_fit); | |
| 485 | try buf.append(allocator, best_fit); | |
| 486 | 486 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { |
| 487 | try buf.append('?'); | |
| 487 | try buf.append(allocator, '?'); | |
| 488 | 488 | } else { |
| 489 | try buf.appendSlice("??"); | |
| 489 | try buf.appendSlice(allocator, "??"); | |
| 490 | 490 | } |
| 491 | 491 | }, |
| 492 | 492 | .utf8 => { |
| ... | ... | @@ -500,35 +500,35 @@ pub fn parseQuotedString( |
| 500 | 500 | } |
| 501 | 501 | var utf8_buf: [4]u8 = undefined; |
| 502 | 502 | const utf8_len = std.unicode.utf8Encode(codepoint_to_encode, &utf8_buf) catch unreachable; |
| 503 | try buf.appendSlice(utf8_buf[0..utf8_len]); | |
| 503 | try buf.appendSlice(allocator, utf8_buf[0..utf8_len]); | |
| 504 | 504 | }, |
| 505 | 505 | }, |
| 506 | 506 | .wide => { |
| 507 | 507 | // Parsing any string type as a wide string is handled separately, see parseQuotedStringAsWideString |
| 508 | 508 | std.debug.assert(iterative_parser.declared_string_type == .wide); |
| 509 | 509 | if (parsed.from_escaped_integer) { |
| 510 | try buf.append(std.mem.nativeToLittle(u16, @truncate(c))); | |
| 510 | try buf.append(allocator, std.mem.nativeToLittle(u16, @truncate(c))); | |
| 511 | 511 | } else if (c == code_pages.Codepoint.invalid) { |
| 512 | try buf.append(std.mem.nativeToLittle(u16, '�')); | |
| 512 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); | |
| 513 | 513 | } else if (c < 0x10000) { |
| 514 | 514 | const short: u16 = @intCast(c); |
| 515 | try buf.append(std.mem.nativeToLittle(u16, short)); | |
| 515 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); | |
| 516 | 516 | } else { |
| 517 | 517 | if (!parsed.escaped_surrogate_pair) { |
| 518 | 518 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 519 | try buf.append(std.mem.nativeToLittle(u16, high)); | |
| 519 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); | |
| 520 | 520 | } |
| 521 | 521 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 522 | try buf.append(std.mem.nativeToLittle(u16, low)); | |
| 522 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); | |
| 523 | 523 | } |
| 524 | 524 | }, |
| 525 | 525 | } |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | 528 | if (literal_type == .wide) { |
| 529 | return buf.toOwnedSliceSentinel(0); | |
| 529 | return buf.toOwnedSliceSentinel(allocator, 0); | |
| 530 | 530 | } else { |
| 531 | return buf.toOwnedSlice(); | |
| 531 | return buf.toOwnedSlice(allocator); | |
| 532 | 532 | } |
| 533 | 533 | } |
| 534 | 534 | |
| ... | ... | @@ -564,8 +564,8 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source |
| 564 | 564 | // Note: We're only handling the case of parsing an ASCII string into a wide string from here on out. |
| 565 | 565 | // TODO: The logic below is similar to that in AcceleratorKeyCodepointTranslator, might be worth merging the two |
| 566 | 566 | |
| 567 | var buf = try std.array_list.Managed(u16).initCapacity(allocator, bytes.slice.len); | |
| 568 | errdefer buf.deinit(); | |
| 567 | var buf = try std.ArrayList(u16).initCapacity(allocator, bytes.slice.len); | |
| 568 | errdefer buf.deinit(allocator); | |
| 569 | 569 | |
| 570 | 570 | var iterative_parser = IterativeStringParser.init(bytes, options); |
| 571 | 571 | |
| ... | ... | @@ -578,23 +578,23 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source |
| 578 | 578 | .windows1252 => windows1252.toCodepoint(byte_to_interpret), |
| 579 | 579 | .utf8 => if (byte_to_interpret > 0x7F) '�' else byte_to_interpret, |
| 580 | 580 | }; |
| 581 | try buf.append(std.mem.nativeToLittle(u16, code_unit_to_encode)); | |
| 581 | try buf.append(allocator, std.mem.nativeToLittle(u16, code_unit_to_encode)); | |
| 582 | 582 | } else if (c == code_pages.Codepoint.invalid) { |
| 583 | try buf.append(std.mem.nativeToLittle(u16, '�')); | |
| 583 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); | |
| 584 | 584 | } else if (c < 0x10000) { |
| 585 | 585 | const short: u16 = @intCast(c); |
| 586 | try buf.append(std.mem.nativeToLittle(u16, short)); | |
| 586 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); | |
| 587 | 587 | } else { |
| 588 | 588 | if (!parsed.escaped_surrogate_pair) { |
| 589 | 589 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 590 | try buf.append(std.mem.nativeToLittle(u16, high)); | |
| 590 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); | |
| 591 | 591 | } |
| 592 | 592 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 593 | try buf.append(std.mem.nativeToLittle(u16, low)); | |
| 593 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); | |
| 594 | 594 | } |
| 595 | 595 | } |
| 596 | 596 | |
| 597 | return buf.toOwnedSliceSentinel(0); | |
| 597 | return buf.toOwnedSliceSentinel(allocator, 0); | |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | test "parse quoted ascii string" { |
lib/compiler/resinator/main.zig+68-62| ... | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | 3 | const removeComments = @import("comments.zig").removeComments; |
| 4 | 4 | const parseAndRemoveLineCommands = @import("source_mapping.zig").parseAndRemoveLineCommands; |
| 5 | 5 | const compile = @import("compile.zig").compile; |
| 6 | const Dependencies = @import("compile.zig").Dependencies; | |
| 6 | 7 | const Diagnostics = @import("errors.zig").Diagnostics; |
| 7 | 8 | const cli = @import("cli.zig"); |
| 8 | 9 | const preprocess = @import("preprocess.zig"); |
| ... | ... | @@ -13,8 +14,6 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag |
| 13 | 14 | const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; |
| 14 | 15 | const aro = @import("aro"); |
| 15 | 16 | |
| 16 | var stdout_buffer: [1024]u8 = undefined; | |
| 17 | ||
| 18 | 17 | pub fn main() !void { |
| 19 | 18 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; |
| 20 | 19 | defer std.debug.assert(gpa.deinit() == .ok); |
| ... | ... | @@ -43,11 +42,13 @@ pub fn main() !void { |
| 43 | 42 | cli_args = args[3..]; |
| 44 | 43 | } |
| 45 | 44 | |
| 46 | var stdout_writer2 = std.fs.File.stdout().writer(&stdout_buffer); | |
| 45 | var stdout_buffer: [1024]u8 = undefined; | |
| 46 | var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); | |
| 47 | const stdout = &stdout_writer.interface; | |
| 47 | 48 | var error_handler: ErrorHandler = switch (zig_integration) { |
| 48 | 49 | true => .{ |
| 49 | 50 | .server = .{ |
| 50 | .out = &stdout_writer2.interface, | |
| 51 | .out = stdout, | |
| 51 | 52 | .in = undefined, // won't be receiving messages |
| 52 | 53 | }, |
| 53 | 54 | }, |
| ... | ... | @@ -83,28 +84,23 @@ pub fn main() !void { |
| 83 | 84 | defer options.deinit(); |
| 84 | 85 | |
| 85 | 86 | if (options.print_help_and_exit) { |
| 86 | const stdout = std.fs.File.stdout(); | |
| 87 | try cli.writeUsage(stdout.deprecatedWriter(), "zig rc"); | |
| 87 | try cli.writeUsage(stdout, "zig rc"); | |
| 88 | try stdout.flush(); | |
| 88 | 89 | return; |
| 89 | 90 | } |
| 90 | 91 | |
| 91 | 92 | // Don't allow verbose when integrating with Zig via stdout |
| 92 | 93 | options.verbose = false; |
| 93 | 94 | |
| 94 | const stdout_writer = std.fs.File.stdout().deprecatedWriter(); | |
| 95 | 95 | if (options.verbose) { |
| 96 | try options.dumpVerbose(stdout_writer); | |
| 97 | try stdout_writer.writeByte('\n'); | |
| 96 | try options.dumpVerbose(stdout); | |
| 97 | try stdout.writeByte('\n'); | |
| 98 | try stdout.flush(); | |
| 98 | 99 | } |
| 99 | 100 | |
| 100 | var dependencies_list = std.array_list.Managed([]const u8).init(allocator); | |
| 101 | defer { | |
| 102 | for (dependencies_list.items) |item| { | |
| 103 | allocator.free(item); | |
| 104 | } | |
| 105 | dependencies_list.deinit(); | |
| 106 | } | |
| 107 | const maybe_dependencies_list: ?*std.array_list.Managed([]const u8) = if (options.depfile_path != null) &dependencies_list else null; | |
| 101 | var dependencies = Dependencies.init(allocator); | |
| 102 | defer dependencies.deinit(); | |
| 103 | const maybe_dependencies: ?*Dependencies = if (options.depfile_path != null) &dependencies else null; | |
| 108 | 104 | |
| 109 | 105 | var include_paths = LazyIncludePaths{ |
| 110 | 106 | .arena = arena, |
| ... | ... | @@ -115,7 +111,7 @@ pub fn main() !void { |
| 115 | 111 | |
| 116 | 112 | const full_input = full_input: { |
| 117 | 113 | if (options.input_format == .rc and options.preprocess != .no) { |
| 118 | var preprocessed_buf = std.array_list.Managed(u8).init(allocator); | |
| 114 | var preprocessed_buf: std.Io.Writer.Allocating = .init(allocator); | |
| 119 | 115 | errdefer preprocessed_buf.deinit(); |
| 120 | 116 | |
| 121 | 117 | // We're going to throw away everything except the final preprocessed output anyway, |
| ... | ... | @@ -127,26 +123,27 @@ pub fn main() !void { |
| 127 | 123 | var comp = aro.Compilation.init(aro_arena, std.fs.cwd()); |
| 128 | 124 | defer comp.deinit(); |
| 129 | 125 | |
| 130 | var argv = std.array_list.Managed([]const u8).init(comp.gpa); | |
| 131 | defer argv.deinit(); | |
| 126 | var argv: std.ArrayList([]const u8) = .empty; | |
| 127 | defer argv.deinit(aro_arena); | |
| 132 | 128 | |
| 133 | try argv.append("arocc"); // dummy command name | |
| 129 | try argv.append(aro_arena, "arocc"); // dummy command name | |
| 134 | 130 | const resolved_include_paths = try include_paths.get(&error_handler); |
| 135 | 131 | try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); |
| 136 | try argv.append(switch (options.input_source) { | |
| 132 | try argv.append(aro_arena, switch (options.input_source) { | |
| 137 | 133 | .stdio => "-", |
| 138 | 134 | .filename => |filename| filename, |
| 139 | 135 | }); |
| 140 | 136 | |
| 141 | 137 | if (options.verbose) { |
| 142 | try stdout_writer.writeAll("Preprocessor: arocc (built-in)\n"); | |
| 138 | try stdout.writeAll("Preprocessor: arocc (built-in)\n"); | |
| 143 | 139 | for (argv.items[0 .. argv.items.len - 1]) |arg| { |
| 144 | try stdout_writer.print("{s} ", .{arg}); | |
| 140 | try stdout.print("{s} ", .{arg}); | |
| 145 | 141 | } |
| 146 | try stdout_writer.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); | |
| 142 | try stdout.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); | |
| 143 | try stdout.flush(); | |
| 147 | 144 | } |
| 148 | 145 | |
| 149 | preprocess.preprocess(&comp, preprocessed_buf.writer(), argv.items, maybe_dependencies_list) catch |err| switch (err) { | |
| 146 | preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies) catch |err| switch (err) { | |
| 150 | 147 | error.GeneratedSourceError => { |
| 151 | 148 | try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug):", &comp); |
| 152 | 149 | std.process.exit(1); |
| ... | ... | @@ -249,14 +246,15 @@ pub fn main() !void { |
| 249 | 246 | defer diagnostics.deinit(); |
| 250 | 247 | |
| 251 | 248 | var output_buffer: [4096]u8 = undefined; |
| 252 | var res_stream_writer = res_stream.source.writer(allocator).adaptToNewApi(&output_buffer); | |
| 253 | const output_buffered_stream = &res_stream_writer.new_interface; | |
| 249 | var res_stream_writer = res_stream.source.writer(allocator, &output_buffer); | |
| 250 | defer res_stream_writer.deinit(&res_stream.source); | |
| 251 | const output_buffered_stream = res_stream_writer.interface(); | |
| 254 | 252 | |
| 255 | 253 | compile(allocator, final_input, output_buffered_stream, .{ |
| 256 | 254 | .cwd = std.fs.cwd(), |
| 257 | 255 | .diagnostics = &diagnostics, |
| 258 | 256 | .source_mappings = &mapping_results.mappings, |
| 259 | .dependencies_list = maybe_dependencies_list, | |
| 257 | .dependencies = maybe_dependencies, | |
| 260 | 258 | .ignore_include_env_var = options.ignore_include_env_var, |
| 261 | 259 | .extra_include_paths = options.extra_include_paths.items, |
| 262 | 260 | .system_include_paths = try include_paths.get(&error_handler), |
| ... | ... | @@ -303,7 +301,7 @@ pub fn main() !void { |
| 303 | 301 | }; |
| 304 | 302 | |
| 305 | 303 | try write_stream.beginArray(); |
| 306 | for (dependencies_list.items) |dep_path| { | |
| 304 | for (dependencies.list.items) |dep_path| { | |
| 307 | 305 | try write_stream.write(dep_path); |
| 308 | 306 | } |
| 309 | 307 | try write_stream.endArray(); |
| ... | ... | @@ -342,10 +340,10 @@ pub fn main() !void { |
| 342 | 340 | defer coff_stream.deinit(allocator); |
| 343 | 341 | |
| 344 | 342 | var coff_output_buffer: [4096]u8 = undefined; |
| 345 | var coff_output_buffered_stream = coff_stream.source.writer(allocator).adaptToNewApi(&coff_output_buffer); | |
| 343 | var coff_output_buffered_stream = coff_stream.source.writer(allocator, &coff_output_buffer); | |
| 346 | 344 | |
| 347 | 345 | var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} }; |
| 348 | cvtres.writeCoff(allocator, &coff_output_buffered_stream.new_interface, resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| { | |
| 346 | cvtres.writeCoff(allocator, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| { | |
| 349 | 347 | switch (err) { |
| 350 | 348 | error.DuplicateResource => { |
| 351 | 349 | const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; |
| ... | ... | @@ -382,7 +380,7 @@ pub fn main() !void { |
| 382 | 380 | std.process.exit(1); |
| 383 | 381 | }; |
| 384 | 382 | |
| 385 | try coff_output_buffered_stream.new_interface.flush(); | |
| 383 | try coff_output_buffered_stream.interface().flush(); | |
| 386 | 384 | } |
| 387 | 385 | |
| 388 | 386 | const IoStream = struct { |
| ... | ... | @@ -425,7 +423,7 @@ const IoStream = struct { |
| 425 | 423 | pub const Source = union(enum) { |
| 426 | 424 | file: std.fs.File, |
| 427 | 425 | stdio: std.fs.File, |
| 428 | memory: std.ArrayListUnmanaged(u8), | |
| 426 | memory: std.ArrayList(u8), | |
| 429 | 427 | /// The source has been closed and any usage of the Source in this state is illegal (except deinit). |
| 430 | 428 | closed: void, |
| 431 | 429 | |
| ... | ... | @@ -472,26 +470,34 @@ const IoStream = struct { |
| 472 | 470 | }; |
| 473 | 471 | } |
| 474 | 472 | |
| 475 | pub const WriterContext = struct { | |
| 476 | self: *Source, | |
| 477 | allocator: std.mem.Allocator, | |
| 478 | }; | |
| 479 | pub const WriteError = std.mem.Allocator.Error || std.fs.File.WriteError; | |
| 480 | pub const Writer = std.io.GenericWriter(WriterContext, WriteError, write); | |
| 481 | ||
| 482 | pub fn write(ctx: WriterContext, bytes: []const u8) WriteError!usize { | |
| 483 | switch (ctx.self.*) { | |
| 484 | inline .file, .stdio => |file| return file.write(bytes), | |
| 485 | .memory => |*list| { | |
| 486 | try list.appendSlice(ctx.allocator, bytes); | |
| 487 | return bytes.len; | |
| 488 | }, | |
| 489 | .closed => unreachable, | |
| 473 | pub const Writer = union(enum) { | |
| 474 | file: std.fs.File.Writer, | |
| 475 | allocating: std.Io.Writer.Allocating, | |
| 476 | ||
| 477 | pub const Error = std.mem.Allocator.Error || std.fs.File.WriteError; | |
| 478 | ||
| 479 | pub fn interface(this: *@This()) *std.Io.Writer { | |
| 480 | return switch (this.*) { | |
| 481 | .file => |*fw| &fw.interface, | |
| 482 | .allocating => |*a| &a.writer, | |
| 483 | }; | |
| 490 | 484 | } |
| 491 | } | |
| 492 | 485 | |
| 493 | pub fn writer(self: *Source, allocator: std.mem.Allocator) Writer { | |
| 494 | return .{ .context = .{ .self = self, .allocator = allocator } }; | |
| 486 | pub fn deinit(this: *@This(), source: *Source) void { | |
| 487 | switch (this.*) { | |
| 488 | .file => {}, | |
| 489 | .allocating => |*a| source.memory = a.toArrayList(), | |
| 490 | } | |
| 491 | this.* = undefined; | |
| 492 | } | |
| 493 | }; | |
| 494 | ||
| 495 | pub fn writer(source: *Source, allocator: std.mem.Allocator, buffer: []u8) Writer { | |
| 496 | return switch (source.*) { | |
| 497 | .file, .stdio => |file| .{ .file = file.writer(buffer) }, | |
| 498 | .memory => |*list| .{ .allocating = .fromArrayList(allocator, list) }, | |
| 499 | .closed => unreachable, | |
| 500 | }; | |
| 495 | 501 | } |
| 496 | 502 | }; |
| 497 | 503 | }; |
| ... | ... | @@ -721,7 +727,7 @@ fn cliDiagnosticsToErrorBundle( |
| 721 | 727 | }); |
| 722 | 728 | |
| 723 | 729 | var cur_err: ?ErrorBundle.ErrorMessage = null; |
| 724 | var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; | |
| 730 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | |
| 725 | 731 | defer cur_notes.deinit(gpa); |
| 726 | 732 | for (diagnostics.errors.items) |err_details| { |
| 727 | 733 | switch (err_details.type) { |
| ... | ... | @@ -763,10 +769,10 @@ fn diagnosticsToErrorBundle( |
| 763 | 769 | try bundle.init(gpa); |
| 764 | 770 | errdefer bundle.deinit(); |
| 765 | 771 | |
| 766 | var msg_buf: std.ArrayListUnmanaged(u8) = .empty; | |
| 767 | defer msg_buf.deinit(gpa); | |
| 772 | var msg_buf: std.Io.Writer.Allocating = .init(gpa); | |
| 773 | defer msg_buf.deinit(); | |
| 768 | 774 | var cur_err: ?ErrorBundle.ErrorMessage = null; |
| 769 | var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; | |
| 775 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | |
| 770 | 776 | defer cur_notes.deinit(gpa); |
| 771 | 777 | for (diagnostics.errors.items) |err_details| { |
| 772 | 778 | switch (err_details.type) { |
| ... | ... | @@ -789,7 +795,7 @@ fn diagnosticsToErrorBundle( |
| 789 | 795 | const column = err_details.token.calculateColumn(source, 1, source_line_start) + 1; |
| 790 | 796 | |
| 791 | 797 | msg_buf.clearRetainingCapacity(); |
| 792 | try err_details.render(msg_buf.writer(gpa), source, diagnostics.strings.items); | |
| 798 | try err_details.render(&msg_buf.writer, source, diagnostics.strings.items); | |
| 793 | 799 | |
| 794 | 800 | const src_loc = src_loc: { |
| 795 | 801 | var src_loc: ErrorBundle.SourceLocation = .{ |
| ... | ... | @@ -817,7 +823,7 @@ fn diagnosticsToErrorBundle( |
| 817 | 823 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); |
| 818 | 824 | } |
| 819 | 825 | cur_err = .{ |
| 820 | .msg = try bundle.addString(msg_buf.items), | |
| 826 | .msg = try bundle.addString(msg_buf.written()), | |
| 821 | 827 | .src_loc = src_loc, |
| 822 | 828 | }; |
| 823 | 829 | cur_notes.clearRetainingCapacity(); |
| ... | ... | @@ -825,7 +831,7 @@ fn diagnosticsToErrorBundle( |
| 825 | 831 | .note => { |
| 826 | 832 | cur_err.?.notes_len += 1; |
| 827 | 833 | try cur_notes.append(gpa, .{ |
| 828 | .msg = try bundle.addString(msg_buf.items), | |
| 834 | .msg = try bundle.addString(msg_buf.written()), | |
| 829 | 835 | .src_loc = src_loc, |
| 830 | 836 | }); |
| 831 | 837 | }, |
| ... | ... | @@ -876,7 +882,7 @@ fn aroDiagnosticsToErrorBundle( |
| 876 | 882 | var msg_writer = MsgWriter.init(gpa); |
| 877 | 883 | defer msg_writer.deinit(); |
| 878 | 884 | var cur_err: ?ErrorBundle.ErrorMessage = null; |
| 879 | var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; | |
| 885 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | |
| 880 | 886 | defer cur_notes.deinit(gpa); |
| 881 | 887 | for (comp.diagnostics.list.items) |msg| { |
| 882 | 888 | switch (msg.kind) { |
| ... | ... | @@ -971,11 +977,11 @@ const MsgWriter = struct { |
| 971 | 977 | } |
| 972 | 978 | |
| 973 | 979 | pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void { |
| 974 | m.buf.writer().print(fmt, args) catch {}; | |
| 980 | m.buf.print(fmt, args) catch {}; | |
| 975 | 981 | } |
| 976 | 982 | |
| 977 | 983 | pub fn write(m: *MsgWriter, msg: []const u8) void { |
| 978 | m.buf.writer().writeAll(msg) catch {}; | |
| 984 | m.buf.appendSlice(msg) catch {}; | |
| 979 | 985 | } |
| 980 | 986 | |
| 981 | 987 | pub fn setColor(m: *MsgWriter, color: std.io.tty.Color) void { |
lib/compiler/resinator/parse.zig+26-26| ... | ... | @@ -82,8 +82,8 @@ pub const Parser = struct { |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | fn parseRoot(self: *Self) Error!*Node { |
| 85 | var statements = std.array_list.Managed(*Node).init(self.state.allocator); | |
| 86 | defer statements.deinit(); | |
| 85 | var statements: std.ArrayList(*Node) = .empty; | |
| 86 | defer statements.deinit(self.state.allocator); | |
| 87 | 87 | |
| 88 | 88 | try self.parseStatements(&statements); |
| 89 | 89 | try self.check(.eof); |
| ... | ... | @@ -95,7 +95,7 @@ pub const Parser = struct { |
| 95 | 95 | return &node.base; |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | fn parseStatements(self: *Self, statements: *std.array_list.Managed(*Node)) Error!void { | |
| 98 | fn parseStatements(self: *Self, statements: *std.ArrayList(*Node)) Error!void { | |
| 99 | 99 | while (true) { |
| 100 | 100 | try self.nextToken(.whitespace_delimiter_only); |
| 101 | 101 | if (self.state.token.id == .eof) break; |
| ... | ... | @@ -105,7 +105,7 @@ pub const Parser = struct { |
| 105 | 105 | // (usually it will end up with bogus things like 'file |
| 106 | 106 | // not found: {') |
| 107 | 107 | const statement = try self.parseStatement(); |
| 108 | try statements.append(statement); | |
| 108 | try statements.append(self.state.allocator, statement); | |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | |
| ... | ... | @@ -115,7 +115,7 @@ pub const Parser = struct { |
| 115 | 115 | /// current token is unchanged. |
| 116 | 116 | /// The returned slice is allocated by the parser's arena |
| 117 | 117 | fn parseCommonResourceAttributes(self: *Self) ![]Token { |
| 118 | var common_resource_attributes: std.ArrayListUnmanaged(Token) = .empty; | |
| 118 | var common_resource_attributes: std.ArrayList(Token) = .empty; | |
| 119 | 119 | while (true) { |
| 120 | 120 | const maybe_common_resource_attribute = try self.lookaheadToken(.normal); |
| 121 | 121 | if (maybe_common_resource_attribute.id == .literal and rc.CommonResourceAttributes.map.has(maybe_common_resource_attribute.slice(self.lexer.buffer))) { |
| ... | ... | @@ -135,7 +135,7 @@ pub const Parser = struct { |
| 135 | 135 | /// current token is unchanged. |
| 136 | 136 | /// The returned slice is allocated by the parser's arena |
| 137 | 137 | fn parseOptionalStatements(self: *Self, resource: ResourceType) ![]*Node { |
| 138 | var optional_statements: std.ArrayListUnmanaged(*Node) = .empty; | |
| 138 | var optional_statements: std.ArrayList(*Node) = .empty; | |
| 139 | 139 | |
| 140 | 140 | const num_statement_types = @typeInfo(rc.OptionalStatements).@"enum".fields.len; |
| 141 | 141 | var statement_type_has_duplicates = [_]bool{false} ** num_statement_types; |
| ... | ... | @@ -355,8 +355,8 @@ pub const Parser = struct { |
| 355 | 355 | const begin_token = self.state.token; |
| 356 | 356 | try self.check(.begin); |
| 357 | 357 | |
| 358 | var strings = std.array_list.Managed(*Node).init(self.state.allocator); | |
| 359 | defer strings.deinit(); | |
| 358 | var strings: std.ArrayList(*Node) = .empty; | |
| 359 | defer strings.deinit(self.state.allocator); | |
| 360 | 360 | while (true) { |
| 361 | 361 | const maybe_end_token = try self.lookaheadToken(.normal); |
| 362 | 362 | switch (maybe_end_token.id) { |
| ... | ... | @@ -392,7 +392,7 @@ pub const Parser = struct { |
| 392 | 392 | .maybe_comma = comma_token, |
| 393 | 393 | .string = self.state.token, |
| 394 | 394 | }; |
| 395 | try strings.append(&string_node.base); | |
| 395 | try strings.append(self.state.allocator, &string_node.base); | |
| 396 | 396 | } |
| 397 | 397 | |
| 398 | 398 | if (strings.items.len == 0) { |
| ... | ... | @@ -501,7 +501,7 @@ pub const Parser = struct { |
| 501 | 501 | const begin_token = self.state.token; |
| 502 | 502 | try self.check(.begin); |
| 503 | 503 | |
| 504 | var accelerators: std.ArrayListUnmanaged(*Node) = .empty; | |
| 504 | var accelerators: std.ArrayList(*Node) = .empty; | |
| 505 | 505 | |
| 506 | 506 | while (true) { |
| 507 | 507 | const lookahead = try self.lookaheadToken(.normal); |
| ... | ... | @@ -519,7 +519,7 @@ pub const Parser = struct { |
| 519 | 519 | |
| 520 | 520 | const idvalue = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); |
| 521 | 521 | |
| 522 | var type_and_options: std.ArrayListUnmanaged(Token) = .empty; | |
| 522 | var type_and_options: std.ArrayList(Token) = .empty; | |
| 523 | 523 | while (true) { |
| 524 | 524 | if (!(try self.parseOptionalToken(.comma))) break; |
| 525 | 525 | |
| ... | ... | @@ -584,7 +584,7 @@ pub const Parser = struct { |
| 584 | 584 | const begin_token = self.state.token; |
| 585 | 585 | try self.check(.begin); |
| 586 | 586 | |
| 587 | var controls: std.ArrayListUnmanaged(*Node) = .empty; | |
| 587 | var controls: std.ArrayList(*Node) = .empty; | |
| 588 | 588 | defer controls.deinit(self.state.allocator); |
| 589 | 589 | while (try self.parseControlStatement(resource)) |control_node| { |
| 590 | 590 | // The number of controls must fit in a u16 in order for it to |
| ... | ... | @@ -643,7 +643,7 @@ pub const Parser = struct { |
| 643 | 643 | const begin_token = self.state.token; |
| 644 | 644 | try self.check(.begin); |
| 645 | 645 | |
| 646 | var buttons: std.ArrayListUnmanaged(*Node) = .empty; | |
| 646 | var buttons: std.ArrayList(*Node) = .empty; | |
| 647 | 647 | defer buttons.deinit(self.state.allocator); |
| 648 | 648 | while (try self.parseToolbarButtonStatement()) |button_node| { |
| 649 | 649 | // The number of buttons must fit in a u16 in order for it to |
| ... | ... | @@ -701,7 +701,7 @@ pub const Parser = struct { |
| 701 | 701 | const begin_token = self.state.token; |
| 702 | 702 | try self.check(.begin); |
| 703 | 703 | |
| 704 | var items: std.ArrayListUnmanaged(*Node) = .empty; | |
| 704 | var items: std.ArrayList(*Node) = .empty; | |
| 705 | 705 | defer items.deinit(self.state.allocator); |
| 706 | 706 | while (try self.parseMenuItemStatement(resource, id_token, 1)) |item_node| { |
| 707 | 707 | try items.append(self.state.allocator, item_node); |
| ... | ... | @@ -735,7 +735,7 @@ pub const Parser = struct { |
| 735 | 735 | // common resource attributes must all be contiguous and come before optional-statements |
| 736 | 736 | const common_resource_attributes = try self.parseCommonResourceAttributes(); |
| 737 | 737 | |
| 738 | var fixed_info: std.ArrayListUnmanaged(*Node) = .empty; | |
| 738 | var fixed_info: std.ArrayList(*Node) = .empty; | |
| 739 | 739 | while (try self.parseVersionStatement()) |version_statement| { |
| 740 | 740 | try fixed_info.append(self.state.arena, version_statement); |
| 741 | 741 | } |
| ... | ... | @@ -744,7 +744,7 @@ pub const Parser = struct { |
| 744 | 744 | const begin_token = self.state.token; |
| 745 | 745 | try self.check(.begin); |
| 746 | 746 | |
| 747 | var block_statements: std.ArrayListUnmanaged(*Node) = .empty; | |
| 747 | var block_statements: std.ArrayList(*Node) = .empty; | |
| 748 | 748 | while (try self.parseVersionBlockOrValue(id_token, 1)) |block_node| { |
| 749 | 749 | try block_statements.append(self.state.arena, block_node); |
| 750 | 750 | } |
| ... | ... | @@ -852,8 +852,8 @@ pub const Parser = struct { |
| 852 | 852 | /// Expects the current token to be a begin token. |
| 853 | 853 | /// After return, the current token will be the end token. |
| 854 | 854 | fn parseRawDataBlock(self: *Self) Error![]*Node { |
| 855 | var raw_data = std.array_list.Managed(*Node).init(self.state.allocator); | |
| 856 | defer raw_data.deinit(); | |
| 855 | var raw_data: std.ArrayList(*Node) = .empty; | |
| 856 | defer raw_data.deinit(self.state.allocator); | |
| 857 | 857 | while (true) { |
| 858 | 858 | const maybe_end_token = try self.lookaheadToken(.normal); |
| 859 | 859 | switch (maybe_end_token.id) { |
| ... | ... | @@ -888,7 +888,7 @@ pub const Parser = struct { |
| 888 | 888 | else => {}, |
| 889 | 889 | } |
| 890 | 890 | const expression = try self.parseExpression(.{ .allowed_types = .{ .number = true, .string = true } }); |
| 891 | try raw_data.append(expression); | |
| 891 | try raw_data.append(self.state.allocator, expression); | |
| 892 | 892 | |
| 893 | 893 | if (expression.isNumberExpression()) { |
| 894 | 894 | const maybe_close_paren = try self.lookaheadToken(.normal); |
| ... | ... | @@ -1125,7 +1125,7 @@ pub const Parser = struct { |
| 1125 | 1125 | |
| 1126 | 1126 | _ = try self.parseOptionalToken(.comma); |
| 1127 | 1127 | |
| 1128 | var options: std.ArrayListUnmanaged(Token) = .empty; | |
| 1128 | var options: std.ArrayList(Token) = .empty; | |
| 1129 | 1129 | while (true) { |
| 1130 | 1130 | const option_token = try self.lookaheadToken(.normal); |
| 1131 | 1131 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { |
| ... | ... | @@ -1160,7 +1160,7 @@ pub const Parser = struct { |
| 1160 | 1160 | } |
| 1161 | 1161 | try self.skipAnyCommas(); |
| 1162 | 1162 | |
| 1163 | var options: std.ArrayListUnmanaged(Token) = .empty; | |
| 1163 | var options: std.ArrayList(Token) = .empty; | |
| 1164 | 1164 | while (true) { |
| 1165 | 1165 | const option_token = try self.lookaheadToken(.normal); |
| 1166 | 1166 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { |
| ... | ... | @@ -1175,7 +1175,7 @@ pub const Parser = struct { |
| 1175 | 1175 | const begin_token = self.state.token; |
| 1176 | 1176 | try self.check(.begin); |
| 1177 | 1177 | |
| 1178 | var items: std.ArrayListUnmanaged(*Node) = .empty; | |
| 1178 | var items: std.ArrayList(*Node) = .empty; | |
| 1179 | 1179 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { |
| 1180 | 1180 | try items.append(self.state.arena, item_node); |
| 1181 | 1181 | } |
| ... | ... | @@ -1245,7 +1245,7 @@ pub const Parser = struct { |
| 1245 | 1245 | const begin_token = self.state.token; |
| 1246 | 1246 | try self.check(.begin); |
| 1247 | 1247 | |
| 1248 | var items: std.ArrayListUnmanaged(*Node) = .empty; | |
| 1248 | var items: std.ArrayList(*Node) = .empty; | |
| 1249 | 1249 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { |
| 1250 | 1250 | try items.append(self.state.arena, item_node); |
| 1251 | 1251 | } |
| ... | ... | @@ -1322,7 +1322,7 @@ pub const Parser = struct { |
| 1322 | 1322 | switch (statement_type) { |
| 1323 | 1323 | .file_version, .product_version => { |
| 1324 | 1324 | var parts_buffer: [4]*Node = undefined; |
| 1325 | var parts = std.ArrayListUnmanaged(*Node).initBuffer(&parts_buffer); | |
| 1325 | var parts = std.ArrayList(*Node).initBuffer(&parts_buffer); | |
| 1326 | 1326 | |
| 1327 | 1327 | while (true) { |
| 1328 | 1328 | const value = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); |
| ... | ... | @@ -1402,7 +1402,7 @@ pub const Parser = struct { |
| 1402 | 1402 | const begin_token = self.state.token; |
| 1403 | 1403 | try self.check(.begin); |
| 1404 | 1404 | |
| 1405 | var children: std.ArrayListUnmanaged(*Node) = .empty; | |
| 1405 | var children: std.ArrayList(*Node) = .empty; | |
| 1406 | 1406 | while (try self.parseVersionBlockOrValue(top_level_version_id_token, nesting_level + 1)) |value_node| { |
| 1407 | 1407 | try children.append(self.state.arena, value_node); |
| 1408 | 1408 | } |
| ... | ... | @@ -1435,7 +1435,7 @@ pub const Parser = struct { |
| 1435 | 1435 | } |
| 1436 | 1436 | |
| 1437 | 1437 | fn parseBlockValuesList(self: *Self, had_comma_before_first_value: bool) Error![]*Node { |
| 1438 | var values: std.ArrayListUnmanaged(*Node) = .empty; | |
| 1438 | var values: std.ArrayList(*Node) = .empty; | |
| 1439 | 1439 | var seen_number: bool = false; |
| 1440 | 1440 | var first_string_value: ?*Node = null; |
| 1441 | 1441 | while (true) { |
lib/compiler/resinator/preprocess.zig+28-22| ... | ... | @@ -2,28 +2,32 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const Allocator = std.mem.Allocator; |
| 4 | 4 | const cli = @import("cli.zig"); |
| 5 | const Dependencies = @import("compile.zig").Dependencies; | |
| 5 | 6 | const aro = @import("aro"); |
| 6 | 7 | |
| 7 | 8 | const PreprocessError = error{ ArgError, GeneratedSourceError, PreprocessError, StreamTooLong, OutOfMemory }; |
| 8 | 9 | |
| 9 | 10 | pub fn preprocess( |
| 10 | 11 | comp: *aro.Compilation, |
| 11 | writer: anytype, | |
| 12 | writer: *std.Io.Writer, | |
| 12 | 13 | /// Expects argv[0] to be the command name |
| 13 | 14 | argv: []const []const u8, |
| 14 | maybe_dependencies_list: ?*std.array_list.Managed([]const u8), | |
| 15 | maybe_dependencies: ?*Dependencies, | |
| 15 | 16 | ) PreprocessError!void { |
| 16 | 17 | try comp.addDefaultPragmaHandlers(); |
| 17 | 18 | |
| 18 | 19 | var driver: aro.Driver = .{ .comp = comp, .aro_name = "arocc" }; |
| 19 | 20 | defer driver.deinit(); |
| 20 | 21 | |
| 21 | var macro_buf = std.array_list.Managed(u8).init(comp.gpa); | |
| 22 | var macro_buf: std.Io.Writer.Allocating = .init(comp.gpa); | |
| 22 | 23 | defer macro_buf.deinit(); |
| 23 | 24 | |
| 24 | _ = driver.parseArgs(std.io.null_writer, macro_buf.writer(), argv) catch |err| switch (err) { | |
| 25 | var trash: [64]u8 = undefined; | |
| 26 | var discarding: std.Io.Writer.Discarding = .init(&trash); | |
| 27 | _ = driver.parseArgs(&discarding.writer, &macro_buf.writer, argv) catch |err| switch (err) { | |
| 25 | 28 | error.FatalError => return error.ArgError, |
| 26 | 29 | error.OutOfMemory => |e| return e, |
| 30 | error.WriteFailed => return error.OutOfMemory, | |
| 27 | 31 | }; |
| 28 | 32 | |
| 29 | 33 | if (hasAnyErrors(comp)) return error.ArgError; |
| ... | ... | @@ -33,7 +37,7 @@ pub fn preprocess( |
| 33 | 37 | error.FatalError => return error.GeneratedSourceError, |
| 34 | 38 | else => |e| return e, |
| 35 | 39 | }; |
| 36 | const user_macros = comp.addSourceFromBuffer("<command line>", macro_buf.items) catch |err| switch (err) { | |
| 40 | const user_macros = comp.addSourceFromBuffer("<command line>", macro_buf.written()) catch |err| switch (err) { | |
| 37 | 41 | error.FatalError => return error.GeneratedSourceError, |
| 38 | 42 | else => |e| return e, |
| 39 | 43 | }; |
| ... | ... | @@ -59,15 +63,17 @@ pub fn preprocess( |
| 59 | 63 | |
| 60 | 64 | if (hasAnyErrors(comp)) return error.PreprocessError; |
| 61 | 65 | |
| 62 | try pp.prettyPrintTokens(writer, .result_only); | |
| 66 | pp.prettyPrintTokens(writer, .result_only) catch |err| switch (err) { | |
| 67 | error.WriteFailed => return error.OutOfMemory, | |
| 68 | }; | |
| 63 | 69 | |
| 64 | if (maybe_dependencies_list) |dependencies_list| { | |
| 70 | if (maybe_dependencies) |dependencies| { | |
| 65 | 71 | for (comp.sources.values()) |comp_source| { |
| 66 | 72 | if (comp_source.id == builtin_macros.id or comp_source.id == user_macros.id) continue; |
| 67 | 73 | if (comp_source.id == .unused or comp_source.id == .generated) continue; |
| 68 | const duped_path = try dependencies_list.allocator.dupe(u8, comp_source.path); | |
| 69 | errdefer dependencies_list.allocator.free(duped_path); | |
| 70 | try dependencies_list.append(duped_path); | |
| 74 | const duped_path = try dependencies.allocator.dupe(u8, comp_source.path); | |
| 75 | errdefer dependencies.allocator.free(duped_path); | |
| 76 | try dependencies.list.append(dependencies.allocator, duped_path); | |
| 71 | 77 | } |
| 72 | 78 | } |
| 73 | 79 | } |
| ... | ... | @@ -87,8 +93,8 @@ fn hasAnyErrors(comp: *aro.Compilation) bool { |
| 87 | 93 | |
| 88 | 94 | /// `arena` is used for temporary -D argument strings and the INCLUDE environment variable. |
| 89 | 95 | /// The arena should be kept alive at least as long as `argv`. |
| 90 | pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8), options: cli.Options, system_include_paths: []const []const u8) !void { | |
| 91 | try argv.appendSlice(&.{ | |
| 96 | pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8) !void { | |
| 97 | try argv.appendSlice(arena, &.{ | |
| 92 | 98 | "-E", |
| 93 | 99 | "--comments", |
| 94 | 100 | "-fuse-line-directives", |
| ... | ... | @@ -99,13 +105,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 99 | 105 | "-D_WIN32", // undocumented, but defined by default |
| 100 | 106 | }); |
| 101 | 107 | for (options.extra_include_paths.items) |extra_include_path| { |
| 102 | try argv.append("-I"); | |
| 103 | try argv.append(extra_include_path); | |
| 108 | try argv.append(arena, "-I"); | |
| 109 | try argv.append(arena, extra_include_path); | |
| 104 | 110 | } |
| 105 | 111 | |
| 106 | 112 | for (system_include_paths) |include_path| { |
| 107 | try argv.append("-isystem"); | |
| 108 | try argv.append(include_path); | |
| 113 | try argv.append(arena, "-isystem"); | |
| 114 | try argv.append(arena, include_path); | |
| 109 | 115 | } |
| 110 | 116 | |
| 111 | 117 | if (!options.ignore_include_env_var) { |
| ... | ... | @@ -119,8 +125,8 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 119 | 125 | }; |
| 120 | 126 | var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter); |
| 121 | 127 | while (it.next()) |include_path| { |
| 122 | try argv.append("-isystem"); | |
| 123 | try argv.append(include_path); | |
| 128 | try argv.append(arena, "-isystem"); | |
| 129 | try argv.append(arena, include_path); | |
| 124 | 130 | } |
| 125 | 131 | } |
| 126 | 132 | |
| ... | ... | @@ -128,13 +134,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 128 | 134 | while (symbol_it.next()) |entry| { |
| 129 | 135 | switch (entry.value_ptr.*) { |
| 130 | 136 | .define => |value| { |
| 131 | try argv.append("-D"); | |
| 137 | try argv.append(arena, "-D"); | |
| 132 | 138 | const define_arg = try std.fmt.allocPrint(arena, "{s}={s}", .{ entry.key_ptr.*, value }); |
| 133 | try argv.append(define_arg); | |
| 139 | try argv.append(arena, define_arg); | |
| 134 | 140 | }, |
| 135 | 141 | .undefine => { |
| 136 | try argv.append("-U"); | |
| 137 | try argv.append(entry.key_ptr.*); | |
| 142 | try argv.append(arena, "-U"); | |
| 143 | try argv.append(arena, entry.key_ptr.*); | |
| 138 | 144 | }, |
| 139 | 145 | } |
| 140 | 146 | } |
lib/compiler/resinator/res.zig+11-11| ... | ... | @@ -258,7 +258,7 @@ pub const NameOrOrdinal = union(enum) { |
| 258 | 258 | } |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | pub fn write(self: NameOrOrdinal, writer: anytype) !void { | |
| 261 | pub fn write(self: NameOrOrdinal, writer: *std.Io.Writer) !void { | |
| 262 | 262 | switch (self) { |
| 263 | 263 | .name => |name| { |
| 264 | 264 | try writer.writeAll(std.mem.sliceAsBytes(name[0 .. name.len + 1])); |
| ... | ... | @@ -270,7 +270,7 @@ pub const NameOrOrdinal = union(enum) { |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | pub fn writeEmpty(writer: anytype) !void { | |
| 273 | pub fn writeEmpty(writer: *std.Io.Writer) !void { | |
| 274 | 274 | try writer.writeInt(u16, 0, .little); |
| 275 | 275 | } |
| 276 | 276 | |
| ... | ... | @@ -283,8 +283,8 @@ pub const NameOrOrdinal = union(enum) { |
| 283 | 283 | |
| 284 | 284 | pub fn nameFromString(allocator: Allocator, bytes: SourceBytes) !NameOrOrdinal { |
| 285 | 285 | // Names have a limit of 256 UTF-16 code units + null terminator |
| 286 | var buf = try std.array_list.Managed(u16).initCapacity(allocator, @min(257, bytes.slice.len)); | |
| 287 | errdefer buf.deinit(); | |
| 286 | var buf = try std.ArrayList(u16).initCapacity(allocator, @min(257, bytes.slice.len)); | |
| 287 | errdefer buf.deinit(allocator); | |
| 288 | 288 | |
| 289 | 289 | var i: usize = 0; |
| 290 | 290 | while (bytes.code_page.codepointAt(i, bytes.slice)) |codepoint| : (i += codepoint.byte_len) { |
| ... | ... | @@ -292,27 +292,27 @@ pub const NameOrOrdinal = union(enum) { |
| 292 | 292 | |
| 293 | 293 | const c = codepoint.value; |
| 294 | 294 | if (c == Codepoint.invalid) { |
| 295 | try buf.append(std.mem.nativeToLittle(u16, '�')); | |
| 295 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); | |
| 296 | 296 | } else if (c < 0x7F) { |
| 297 | 297 | // ASCII chars in names are always converted to uppercase |
| 298 | try buf.append(std.mem.nativeToLittle(u16, std.ascii.toUpper(@intCast(c)))); | |
| 298 | try buf.append(allocator, std.mem.nativeToLittle(u16, std.ascii.toUpper(@intCast(c)))); | |
| 299 | 299 | } else if (c < 0x10000) { |
| 300 | 300 | const short: u16 = @intCast(c); |
| 301 | try buf.append(std.mem.nativeToLittle(u16, short)); | |
| 301 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); | |
| 302 | 302 | } else { |
| 303 | 303 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 304 | try buf.append(std.mem.nativeToLittle(u16, high)); | |
| 304 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); | |
| 305 | 305 | |
| 306 | 306 | // Note: This can cut-off in the middle of a UTF-16 surrogate pair, |
| 307 | 307 | // i.e. it can make the string end with an unpaired high surrogate |
| 308 | 308 | if (buf.items.len == 256) break; |
| 309 | 309 | |
| 310 | 310 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 311 | try buf.append(std.mem.nativeToLittle(u16, low)); | |
| 311 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); | |
| 312 | 312 | } |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | return NameOrOrdinal{ .name = try buf.toOwnedSliceSentinel(0) }; | |
| 315 | return NameOrOrdinal{ .name = try buf.toOwnedSliceSentinel(allocator, 0) }; | |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | 318 | /// Returns `null` if the bytes do not form a valid number. |
| ... | ... | @@ -1079,7 +1079,7 @@ pub const FixedFileInfo = struct { |
| 1079 | 1079 | } |
| 1080 | 1080 | }; |
| 1081 | 1081 | |
| 1082 | pub fn write(self: FixedFileInfo, writer: anytype) !void { | |
| 1082 | pub fn write(self: FixedFileInfo, writer: *std.Io.Writer) !void { | |
| 1083 | 1083 | try writer.writeInt(u32, signature, .little); |
| 1084 | 1084 | try writer.writeInt(u32, version, .little); |
| 1085 | 1085 | try writer.writeInt(u32, self.file_version.mostSignificantCombinedParts(), .little); |
lib/compiler/resinator/source_mapping.zig+5-5| ... | ... | @@ -10,7 +10,7 @@ pub const ParseLineCommandsResult = struct { |
| 10 | 10 | |
| 11 | 11 | const CurrentMapping = struct { |
| 12 | 12 | line_num: usize = 1, |
| 13 | filename: std.ArrayListUnmanaged(u8) = .empty, | |
| 13 | filename: std.ArrayList(u8) = .empty, | |
| 14 | 14 | pending: bool = true, |
| 15 | 15 | ignore_contents: bool = false, |
| 16 | 16 | }; |
| ... | ... | @@ -574,8 +574,8 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva |
| 574 | 574 | escape_u, |
| 575 | 575 | }; |
| 576 | 576 | |
| 577 | var filename = try std.array_list.Managed(u8).initCapacity(allocator, str.len); | |
| 578 | errdefer filename.deinit(); | |
| 577 | var filename = try std.ArrayList(u8).initCapacity(allocator, str.len); | |
| 578 | errdefer filename.deinit(allocator); | |
| 579 | 579 | var state: State = .string; |
| 580 | 580 | var index: usize = 0; |
| 581 | 581 | var escape_len: usize = undefined; |
| ... | ... | @@ -693,7 +693,7 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva |
| 693 | 693 | } |
| 694 | 694 | } |
| 695 | 695 | |
| 696 | return filename.toOwnedSlice(); | |
| 696 | return filename.toOwnedSlice(allocator); | |
| 697 | 697 | } |
| 698 | 698 | |
| 699 | 699 | fn testParseFilename(expected: []const u8, input: []const u8) !void { |
| ... | ... | @@ -927,7 +927,7 @@ test "SourceMappings collapse" { |
| 927 | 927 | |
| 928 | 928 | /// Same thing as StringTable in Zig's src/Wasm.zig |
| 929 | 929 | pub const StringTable = struct { |
| 930 | data: std.ArrayListUnmanaged(u8) = .empty, | |
| 930 | data: std.ArrayList(u8) = .empty, | |
| 931 | 931 | map: std.HashMapUnmanaged(u32, void, std.hash_map.StringIndexContext, std.hash_map.default_max_load_percentage) = .empty, |
| 932 | 932 | |
| 933 | 933 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
lib/compiler/resinator/windows1252.zig-45| ... | ... | @@ -1,36 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | pub fn windows1252ToUtf8Stream(writer: anytype, reader: anytype) !usize { | |
| 4 | var bytes_written: usize = 0; | |
| 5 | var utf8_buf: [3]u8 = undefined; | |
| 6 | while (true) { | |
| 7 | const c = reader.readByte() catch |err| switch (err) { | |
| 8 | error.EndOfStream => return bytes_written, | |
| 9 | else => |e| return e, | |
| 10 | }; | |
| 11 | const codepoint = toCodepoint(c); | |
| 12 | if (codepoint <= 0x7F) { | |
| 13 | try writer.writeByte(c); | |
| 14 | bytes_written += 1; | |
| 15 | } else { | |
| 16 | const utf8_len = std.unicode.utf8Encode(codepoint, &utf8_buf) catch unreachable; | |
| 17 | try writer.writeAll(utf8_buf[0..utf8_len]); | |
| 18 | bytes_written += utf8_len; | |
| 19 | } | |
| 20 | } | |
| 21 | } | |
| 22 | ||
| 23 | /// Returns the number of code units written to the writer | |
| 24 | pub fn windows1252ToUtf16AllocZ(allocator: std.mem.Allocator, win1252_str: []const u8) ![:0]u16 { | |
| 25 | // Guaranteed to need exactly the same number of code units as Windows-1252 bytes | |
| 26 | var utf16_slice = try allocator.allocSentinel(u16, win1252_str.len, 0); | |
| 27 | errdefer allocator.free(utf16_slice); | |
| 28 | for (win1252_str, 0..) |c, i| { | |
| 29 | utf16_slice[i] = toCodepoint(c); | |
| 30 | } | |
| 31 | return utf16_slice; | |
| 32 | } | |
| 33 | ||
| 34 | 3 | /// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1252.txt |
| 35 | 4 | pub fn toCodepoint(c: u8) u16 { |
| 36 | 5 | return switch (c) { |
| ... | ... | @@ -572,17 +541,3 @@ pub fn bestFitFromCodepoint(codepoint: u21) ?u8 { |
| 572 | 541 | else => null, |
| 573 | 542 | }; |
| 574 | 543 | } |
| 575 | ||
| 576 | test "windows-1252 to utf8" { | |
| 577 | var buf = std.array_list.Managed(u8).init(std.testing.allocator); | |
| 578 | defer buf.deinit(); | |
| 579 | ||
| 580 | const input_windows1252 = "\x81pqrstuvwxyz{|}~\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8e\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9e\x9f\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; | |
| 581 | const expected_utf8 = "\xc2\x81pqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; | |
| 582 | ||
| 583 | var fbs = std.io.fixedBufferStream(input_windows1252); | |
| 584 | const bytes_written = try windows1252ToUtf8Stream(buf.writer(), fbs.reader()); | |
| 585 | ||
| 586 | try std.testing.expectEqualStrings(expected_utf8, buf.items); | |
| 587 | try std.testing.expectEqual(expected_utf8.len, bytes_written); | |
| 588 | } |
lib/docs/wasm/Decl.zig+5-4| ... | ... | @@ -6,6 +6,7 @@ const gpa = std.heap.wasm_allocator; |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const log = std.log; |
| 8 | 8 | const Oom = error{OutOfMemory}; |
| 9 | const ArrayList = std.ArrayList; | |
| 9 | 10 | |
| 10 | 11 | ast_node: Ast.Node.Index, |
| 11 | 12 | file: Walk.File.Index, |
| ... | ... | @@ -189,7 +190,7 @@ pub fn lookup(decl: *const Decl, name: []const u8) ?Decl.Index { |
| 189 | 190 | } |
| 190 | 191 | |
| 191 | 192 | /// Appends the fully qualified name to `out`. |
| 192 | pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { | |
| 193 | pub fn fqn(decl: *const Decl, out: *ArrayList(u8)) Oom!void { | |
| 193 | 194 | try decl.append_path(out); |
| 194 | 195 | if (decl.parent != .none) { |
| 195 | 196 | try append_parent_ns(out, decl.parent); |
| ... | ... | @@ -199,12 +200,12 @@ pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { |
| 199 | 200 | } |
| 200 | 201 | } |
| 201 | 202 | |
| 202 | pub fn reset_with_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void { | |
| 203 | pub fn reset_with_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void { | |
| 203 | 204 | list.clearRetainingCapacity(); |
| 204 | 205 | try append_path(decl, list); |
| 205 | 206 | } |
| 206 | 207 | |
| 207 | pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void { | |
| 208 | pub fn append_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void { | |
| 208 | 209 | const start = list.items.len; |
| 209 | 210 | // Prefer the module name alias. |
| 210 | 211 | for (Walk.modules.keys(), Walk.modules.values()) |pkg_name, pkg_file| { |
| ... | ... | @@ -230,7 +231,7 @@ pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!voi |
| 230 | 231 | } |
| 231 | 232 | } |
| 232 | 233 | |
| 233 | pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) Oom!void { | |
| 234 | pub fn append_parent_ns(list: *ArrayList(u8), parent: Decl.Index) Oom!void { | |
| 234 | 235 | assert(parent != .none); |
| 235 | 236 | const decl = parent.get(); |
| 236 | 237 | if (decl.parent != .none) { |
lib/docs/wasm/html_render.zig+10-8| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Ast = std.zig.Ast; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | const ArrayList = std.ArrayList; | |
| 5 | const Writer = std.Io.Writer; | |
| 4 | 6 | |
| 5 | 7 | const Walk = @import("Walk"); |
| 6 | 8 | const Decl = Walk.Decl; |
| ... | ... | @@ -30,7 +32,7 @@ pub const Annotation = struct { |
| 30 | 32 | |
| 31 | 33 | pub fn fileSourceHtml( |
| 32 | 34 | file_index: Walk.File.Index, |
| 33 | out: *std.ArrayListUnmanaged(u8), | |
| 35 | out: *ArrayList(u8), | |
| 34 | 36 | root_node: Ast.Node.Index, |
| 35 | 37 | options: RenderSourceOptions, |
| 36 | 38 | ) !void { |
| ... | ... | @@ -38,7 +40,7 @@ pub fn fileSourceHtml( |
| 38 | 40 | const file = file_index.get(); |
| 39 | 41 | |
| 40 | 42 | const g = struct { |
| 41 | var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty; | |
| 43 | var field_access_buffer: ArrayList(u8) = .empty; | |
| 42 | 44 | }; |
| 43 | 45 | |
| 44 | 46 | const start_token = ast.firstToken(root_node); |
| ... | ... | @@ -88,7 +90,7 @@ pub fn fileSourceHtml( |
| 88 | 90 | if (next_annotate_index >= options.source_location_annotations.len) break; |
| 89 | 91 | const next_annotation = options.source_location_annotations[next_annotate_index]; |
| 90 | 92 | if (cursor <= next_annotation.file_byte_offset) break; |
| 91 | try out.writer(gpa).print("<span id=\"{s}{d}\"></span>", .{ | |
| 93 | try out.print(gpa, "<span id=\"{s}{d}\"></span>", .{ | |
| 92 | 94 | options.annotation_prefix, next_annotation.dom_id, |
| 93 | 95 | }); |
| 94 | 96 | next_annotate_index += 1; |
| ... | ... | @@ -318,7 +320,7 @@ pub fn fileSourceHtml( |
| 318 | 320 | } |
| 319 | 321 | } |
| 320 | 322 | |
| 321 | fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usize) !void { | |
| 323 | fn appendUnindented(out: *ArrayList(u8), s: []const u8, indent: usize) !void { | |
| 322 | 324 | var it = std.mem.splitScalar(u8, s, '\n'); |
| 323 | 325 | var is_first_line = true; |
| 324 | 326 | while (it.next()) |line| { |
| ... | ... | @@ -332,7 +334,7 @@ fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usi |
| 332 | 334 | } |
| 333 | 335 | } |
| 334 | 336 | |
| 335 | pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void { | |
| 337 | pub fn appendEscaped(out: *ArrayList(u8), s: []const u8) !void { | |
| 336 | 338 | for (s) |c| { |
| 337 | 339 | try out.ensureUnusedCapacity(gpa, 6); |
| 338 | 340 | switch (c) { |
| ... | ... | @@ -347,7 +349,7 @@ pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void { |
| 347 | 349 | |
| 348 | 350 | fn walkFieldAccesses( |
| 349 | 351 | file_index: Walk.File.Index, |
| 350 | out: *std.ArrayListUnmanaged(u8), | |
| 352 | out: *ArrayList(u8), | |
| 351 | 353 | node: Ast.Node.Index, |
| 352 | 354 | ) Oom!void { |
| 353 | 355 | const ast = file_index.get_ast(); |
| ... | ... | @@ -371,7 +373,7 @@ fn walkFieldAccesses( |
| 371 | 373 | |
| 372 | 374 | fn resolveIdentLink( |
| 373 | 375 | file_index: Walk.File.Index, |
| 374 | out: *std.ArrayListUnmanaged(u8), | |
| 376 | out: *ArrayList(u8), | |
| 375 | 377 | ident_token: Ast.TokenIndex, |
| 376 | 378 | ) Oom!void { |
| 377 | 379 | const decl_index = file_index.get().lookup_token(ident_token); |
| ... | ... | @@ -391,7 +393,7 @@ fn unindent(s: []const u8, indent: usize) []const u8 { |
| 391 | 393 | return s[indent_idx..]; |
| 392 | 394 | } |
| 393 | 395 | |
| 394 | pub fn resolveDeclLink(decl_index: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void { | |
| 396 | pub fn resolveDeclLink(decl_index: Decl.Index, out: *ArrayList(u8)) Oom!void { | |
| 395 | 397 | const decl = decl_index.get(); |
| 396 | 398 | switch (decl.categorize()) { |
| 397 | 399 | .alias => |alias_decl| try alias_decl.get().fqn(out), |
lib/docs/wasm/main.zig+30-24| ... | ... | @@ -5,6 +5,8 @@ const Ast = std.zig.Ast; |
| 5 | 5 | const Walk = @import("Walk"); |
| 6 | 6 | const markdown = @import("markdown.zig"); |
| 7 | 7 | const Decl = Walk.Decl; |
| 8 | const ArrayList = std.ArrayList; | |
| 9 | const Writer = std.Io.Writer; | |
| 8 | 10 | |
| 9 | 11 | const fileSourceHtml = @import("html_render.zig").fileSourceHtml; |
| 10 | 12 | const appendEscaped = @import("html_render.zig").appendEscaped; |
| ... | ... | @@ -66,8 +68,8 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void { |
| 66 | 68 | }; |
| 67 | 69 | } |
| 68 | 70 | |
| 69 | var query_string: std.ArrayListUnmanaged(u8) = .empty; | |
| 70 | var query_results: std.ArrayListUnmanaged(Decl.Index) = .empty; | |
| 71 | var query_string: ArrayList(u8) = .empty; | |
| 72 | var query_results: ArrayList(Decl.Index) = .empty; | |
| 71 | 73 | |
| 72 | 74 | /// Resizes the query string to be the correct length; returns the pointer to |
| 73 | 75 | /// the query string. |
| ... | ... | @@ -99,11 +101,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void { |
| 99 | 101 | segments: u16, |
| 100 | 102 | }; |
| 101 | 103 | const g = struct { |
| 102 | var full_path_search_text: std.ArrayListUnmanaged(u8) = .empty; | |
| 103 | var full_path_search_text_lower: std.ArrayListUnmanaged(u8) = .empty; | |
| 104 | var doc_search_text: std.ArrayListUnmanaged(u8) = .empty; | |
| 104 | var full_path_search_text: ArrayList(u8) = .empty; | |
| 105 | var full_path_search_text_lower: ArrayList(u8) = .empty; | |
| 106 | var doc_search_text: ArrayList(u8) = .empty; | |
| 105 | 107 | /// Each element matches a corresponding query_results element. |
| 106 | var scores: std.ArrayListUnmanaged(Score) = .empty; | |
| 108 | var scores: ArrayList(Score) = .empty; | |
| 107 | 109 | }; |
| 108 | 110 | |
| 109 | 111 | // First element stores the size of the list. |
| ... | ... | @@ -234,7 +236,7 @@ const ErrorIdentifier = packed struct(u64) { |
| 234 | 236 | return ast.tokenTag(token_index - 1) == .doc_comment; |
| 235 | 237 | } |
| 236 | 238 | |
| 237 | fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void { | |
| 239 | fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *ArrayList(u8)) Oom!void { | |
| 238 | 240 | const decl_index = ei.decl_index; |
| 239 | 241 | const ast = decl_index.get().file.get_ast(); |
| 240 | 242 | const name = ast.tokenSlice(ei.token_index); |
| ... | ... | @@ -260,7 +262,7 @@ const ErrorIdentifier = packed struct(u64) { |
| 260 | 262 | } |
| 261 | 263 | }; |
| 262 | 264 | |
| 263 | var string_result: std.ArrayListUnmanaged(u8) = .empty; | |
| 265 | var string_result: ArrayList(u8) = .empty; | |
| 264 | 266 | var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty; |
| 265 | 267 | |
| 266 | 268 | export fn decl_error_set(decl_index: Decl.Index) Slice(ErrorIdentifier) { |
| ... | ... | @@ -411,7 +413,7 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 411 | 413 | |
| 412 | 414 | fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index { |
| 413 | 415 | const g = struct { |
| 414 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; | |
| 416 | var result: ArrayList(Ast.Node.Index) = .empty; | |
| 415 | 417 | }; |
| 416 | 418 | g.result.clearRetainingCapacity(); |
| 417 | 419 | var buf: [2]Ast.Node.Index = undefined; |
| ... | ... | @@ -429,7 +431,7 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In |
| 429 | 431 | |
| 430 | 432 | fn decl_params_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 431 | 433 | const g = struct { |
| 432 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; | |
| 434 | var result: ArrayList(Ast.Node.Index) = .empty; | |
| 433 | 435 | }; |
| 434 | 436 | g.result.clearRetainingCapacity(); |
| 435 | 437 | const decl = decl_index.get(); |
| ... | ... | @@ -460,7 +462,7 @@ export fn decl_param_html(decl_index: Decl.Index, param_node: Ast.Node.Index) St |
| 460 | 462 | } |
| 461 | 463 | |
| 462 | 464 | fn decl_field_html_fallible( |
| 463 | out: *std.ArrayListUnmanaged(u8), | |
| 465 | out: *ArrayList(u8), | |
| 464 | 466 | decl_index: Decl.Index, |
| 465 | 467 | field_node: Ast.Node.Index, |
| 466 | 468 | ) !void { |
| ... | ... | @@ -480,7 +482,7 @@ fn decl_field_html_fallible( |
| 480 | 482 | } |
| 481 | 483 | |
| 482 | 484 | fn decl_param_html_fallible( |
| 483 | out: *std.ArrayListUnmanaged(u8), | |
| 485 | out: *ArrayList(u8), | |
| 484 | 486 | decl_index: Decl.Index, |
| 485 | 487 | param_node: Ast.Node.Index, |
| 486 | 488 | ) !void { |
| ... | ... | @@ -649,7 +651,7 @@ export fn decl_docs_html(decl_index: Decl.Index, short: bool) String { |
| 649 | 651 | } |
| 650 | 652 | |
| 651 | 653 | fn collect_docs( |
| 652 | list: *std.ArrayListUnmanaged(u8), | |
| 654 | list: *ArrayList(u8), | |
| 653 | 655 | ast: *const Ast, |
| 654 | 656 | first_doc_comment: Ast.TokenIndex, |
| 655 | 657 | ) Oom!void { |
| ... | ... | @@ -667,7 +669,7 @@ fn collect_docs( |
| 667 | 669 | } |
| 668 | 670 | |
| 669 | 671 | fn render_docs( |
| 670 | out: *std.ArrayListUnmanaged(u8), | |
| 672 | out: *ArrayList(u8), | |
| 671 | 673 | decl_index: Decl.Index, |
| 672 | 674 | first_doc_comment: Ast.TokenIndex, |
| 673 | 675 | short: bool, |
| ... | ... | @@ -691,11 +693,10 @@ fn render_docs( |
| 691 | 693 | defer parsed_doc.deinit(gpa); |
| 692 | 694 | |
| 693 | 695 | const g = struct { |
| 694 | var link_buffer: std.ArrayListUnmanaged(u8) = .empty; | |
| 696 | var link_buffer: ArrayList(u8) = .empty; | |
| 695 | 697 | }; |
| 696 | 698 | |
| 697 | const Writer = std.ArrayListUnmanaged(u8).Writer; | |
| 698 | const Renderer = markdown.Renderer(Writer, Decl.Index); | |
| 699 | const Renderer = markdown.Renderer(Decl.Index); | |
| 699 | 700 | const renderer: Renderer = .{ |
| 700 | 701 | .context = decl_index, |
| 701 | 702 | .renderFn = struct { |
| ... | ... | @@ -703,8 +704,8 @@ fn render_docs( |
| 703 | 704 | r: Renderer, |
| 704 | 705 | doc: markdown.Document, |
| 705 | 706 | node: markdown.Document.Node.Index, |
| 706 | writer: Writer, | |
| 707 | ) !void { | |
| 707 | writer: *Writer, | |
| 708 | ) Writer.Error!void { | |
| 708 | 709 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 709 | 710 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| 710 | 711 | .code_span => { |
| ... | ... | @@ -712,7 +713,7 @@ fn render_docs( |
| 712 | 713 | const content = doc.string(data.text.content); |
| 713 | 714 | if (resolve_decl_path(r.context, content)) |resolved_decl_index| { |
| 714 | 715 | g.link_buffer.clearRetainingCapacity(); |
| 715 | try resolveDeclLink(resolved_decl_index, &g.link_buffer); | |
| 716 | resolveDeclLink(resolved_decl_index, &g.link_buffer) catch return error.WriteFailed; | |
| 716 | 717 | |
| 717 | 718 | try writer.writeAll("<a href=\"#"); |
| 718 | 719 | _ = missing_feature_url_escape; |
| ... | ... | @@ -730,7 +731,12 @@ fn render_docs( |
| 730 | 731 | } |
| 731 | 732 | }.render, |
| 732 | 733 | }; |
| 733 | try renderer.render(parsed_doc, out.writer(gpa)); | |
| 734 | ||
| 735 | var allocating = Writer.Allocating.fromArrayList(gpa, out); | |
| 736 | defer out.* = allocating.toArrayList(); | |
| 737 | renderer.render(parsed_doc, &allocating.writer) catch |err| switch (err) { | |
| 738 | error.WriteFailed => return error.OutOfMemory, | |
| 739 | }; | |
| 734 | 740 | } |
| 735 | 741 | |
| 736 | 742 | fn resolve_decl_path(decl_index: Decl.Index, path: []const u8) ?Decl.Index { |
| ... | ... | @@ -827,7 +833,7 @@ export fn find_module_root(pkg: Walk.ModuleIndex) Decl.Index { |
| 827 | 833 | } |
| 828 | 834 | |
| 829 | 835 | /// Set by `set_input_string`. |
| 830 | var input_string: std.ArrayListUnmanaged(u8) = .empty; | |
| 836 | var input_string: ArrayList(u8) = .empty; | |
| 831 | 837 | |
| 832 | 838 | export fn set_input_string(len: usize) [*]u8 { |
| 833 | 839 | input_string.resize(gpa, len) catch @panic("OOM"); |
| ... | ... | @@ -849,7 +855,7 @@ export fn find_decl() Decl.Index { |
| 849 | 855 | if (result != .none) return result; |
| 850 | 856 | |
| 851 | 857 | const g = struct { |
| 852 | var match_fqn: std.ArrayListUnmanaged(u8) = .empty; | |
| 858 | var match_fqn: ArrayList(u8) = .empty; | |
| 853 | 859 | }; |
| 854 | 860 | for (Walk.decls.items, 0..) |*decl, decl_index| { |
| 855 | 861 | g.match_fqn.clearRetainingCapacity(); |
| ... | ... | @@ -905,7 +911,7 @@ export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl. |
| 905 | 911 | |
| 906 | 912 | export fn namespace_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { |
| 907 | 913 | const g = struct { |
| 908 | var members: std.ArrayListUnmanaged(Decl.Index) = .empty; | |
| 914 | var members: ArrayList(Decl.Index) = .empty; | |
| 909 | 915 | }; |
| 910 | 916 | |
| 911 | 917 | g.members.clearRetainingCapacity(); |
lib/docs/wasm/markdown/renderer.zig+15-16| ... | ... | @@ -2,25 +2,26 @@ const std = @import("std"); |
| 2 | 2 | const Document = @import("Document.zig"); |
| 3 | 3 | const Node = Document.Node; |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | const Writer = std.Io.Writer; | |
| 5 | 6 | |
| 6 | 7 | /// A Markdown document renderer. |
| 7 | 8 | /// |
| 8 | 9 | /// Each concrete `Renderer` type has a `renderDefault` function, with the |
| 9 | 10 | /// intention that custom `renderFn` implementations can call `renderDefault` |
| 10 | 11 | /// for node types for which they require no special rendering. |
| 11 | pub fn Renderer(comptime Writer: type, comptime Context: type) type { | |
| 12 | pub fn Renderer(comptime Context: type) type { | |
| 12 | 13 | return struct { |
| 13 | 14 | renderFn: *const fn ( |
| 14 | 15 | r: Self, |
| 15 | 16 | doc: Document, |
| 16 | 17 | node: Node.Index, |
| 17 | writer: Writer, | |
| 18 | writer: *Writer, | |
| 18 | 19 | ) Writer.Error!void = renderDefault, |
| 19 | 20 | context: Context, |
| 20 | 21 | |
| 21 | 22 | const Self = @This(); |
| 22 | 23 | |
| 23 | pub fn render(r: Self, doc: Document, writer: Writer) Writer.Error!void { | |
| 24 | pub fn render(r: Self, doc: Document, writer: *Writer) Writer.Error!void { | |
| 24 | 25 | try r.renderFn(r, doc, .root, writer); |
| 25 | 26 | } |
| 26 | 27 | |
| ... | ... | @@ -28,7 +29,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 28 | 29 | r: Self, |
| 29 | 30 | doc: Document, |
| 30 | 31 | node: Node.Index, |
| 31 | writer: Writer, | |
| 32 | writer: *Writer, | |
| 32 | 33 | ) Writer.Error!void { |
| 33 | 34 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 34 | 35 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| ... | ... | @@ -188,8 +189,8 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 188 | 189 | pub fn renderInlineNodeText( |
| 189 | 190 | doc: Document, |
| 190 | 191 | node: Node.Index, |
| 191 | writer: anytype, | |
| 192 | ) @TypeOf(writer).Error!void { | |
| 192 | writer: *Writer, | |
| 193 | ) Writer.Error!void { | |
| 193 | 194 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 194 | 195 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| 195 | 196 | .root, |
| ... | ... | @@ -234,14 +235,12 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) { |
| 234 | 235 | return .{ .data = bytes }; |
| 235 | 236 | } |
| 236 | 237 | |
| 237 | fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 238 | for (bytes) |b| { | |
| 239 | switch (b) { | |
| 240 | '<' => try writer.writeAll("&lt;"), | |
| 241 | '>' => try writer.writeAll("&gt;"), | |
| 242 | '&' => try writer.writeAll("&amp;"), | |
| 243 | '"' => try writer.writeAll("&quot;"), | |
| 244 | else => try writer.writeByte(b), | |
| 245 | } | |
| 246 | } | |
| 238 | fn formatHtml(bytes: []const u8, w: *Writer) Writer.Error!void { | |
| 239 | for (bytes) |b| switch (b) { | |
| 240 | '<' => try w.writeAll("&lt;"), | |
| 241 | '>' => try w.writeAll("&gt;"), | |
| 242 | '&' => try w.writeAll("&amp;"), | |
| 243 | '"' => try w.writeAll("&quot;"), | |
| 244 | else => try w.writeByte(b), | |
| 245 | }; | |
| 247 | 246 | } |
lib/std/Build/Step/CheckObject.zig+25-27| ... | ... | @@ -257,7 +257,7 @@ const Check = struct { |
| 257 | 257 | fn dumpSection(allocator: Allocator, name: [:0]const u8) Check { |
| 258 | 258 | var check = Check.create(allocator, .dump_section); |
| 259 | 259 | const off: u32 = @intCast(check.data.items.len); |
| 260 | check.data.writer().print("{s}\x00", .{name}) catch @panic("OOM"); | |
| 260 | check.data.print("{s}\x00", .{name}) catch @panic("OOM"); | |
| 261 | 261 | check.payload = .{ .dump_section = off }; |
| 262 | 262 | return check; |
| 263 | 263 | } |
| ... | ... | @@ -1320,7 +1320,8 @@ const MachODumper = struct { |
| 1320 | 1320 | } |
| 1321 | 1321 | bindings.deinit(); |
| 1322 | 1322 | } |
| 1323 | try ctx.parseBindInfo(data, &bindings); | |
| 1323 | var data_reader: std.Io.Reader = .fixed(data); | |
| 1324 | try ctx.parseBindInfo(&data_reader, &bindings); | |
| 1324 | 1325 | mem.sort(Binding, bindings.items, {}, Binding.lessThan); |
| 1325 | 1326 | for (bindings.items) |binding| { |
| 1326 | 1327 | try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend }); |
| ... | ... | @@ -1335,11 +1336,7 @@ const MachODumper = struct { |
| 1335 | 1336 | } |
| 1336 | 1337 | } |
| 1337 | 1338 | |
| 1338 | fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.array_list.Managed(Binding)) !void { | |
| 1339 | var stream = std.io.fixedBufferStream(data); | |
| 1340 | var creader = std.io.countingReader(stream.reader()); | |
| 1341 | const reader = creader.reader(); | |
| 1342 | ||
| 1339 | fn parseBindInfo(ctx: ObjectContext, reader: *std.Io.Reader, bindings: *std.array_list.Managed(Binding)) !void { | |
| 1343 | 1340 | var seg_id: ?u8 = null; |
| 1344 | 1341 | var tag: Binding.Tag = .self; |
| 1345 | 1342 | var ordinal: u16 = 0; |
| ... | ... | @@ -1350,7 +1347,7 @@ const MachODumper = struct { |
| 1350 | 1347 | defer name_buf.deinit(); |
| 1351 | 1348 | |
| 1352 | 1349 | while (true) { |
| 1353 | const byte = reader.readByte() catch break; | |
| 1350 | const byte = reader.takeByte() catch break; | |
| 1354 | 1351 | const opc = byte & macho.BIND_OPCODE_MASK; |
| 1355 | 1352 | const imm = byte & macho.BIND_IMMEDIATE_MASK; |
| 1356 | 1353 | switch (opc) { |
| ... | ... | @@ -1371,18 +1368,17 @@ const MachODumper = struct { |
| 1371 | 1368 | }, |
| 1372 | 1369 | macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => { |
| 1373 | 1370 | seg_id = imm; |
| 1374 | offset = try std.leb.readUleb128(u64, reader); | |
| 1371 | offset = try reader.takeLeb128(u64); | |
| 1375 | 1372 | }, |
| 1376 | 1373 | macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => { |
| 1377 | 1374 | name_buf.clearRetainingCapacity(); |
| 1378 | try reader.readUntilDelimiterArrayList(&name_buf, 0, std.math.maxInt(u32)); | |
| 1379 | try name_buf.append(0); | |
| 1375 | try name_buf.appendSlice(try reader.takeDelimiterInclusive(0)); | |
| 1380 | 1376 | }, |
| 1381 | 1377 | macho.BIND_OPCODE_SET_ADDEND_SLEB => { |
| 1382 | addend = try std.leb.readIleb128(i64, reader); | |
| 1378 | addend = try reader.takeLeb128(i64); | |
| 1383 | 1379 | }, |
| 1384 | 1380 | macho.BIND_OPCODE_ADD_ADDR_ULEB => { |
| 1385 | const x = try std.leb.readUleb128(u64, reader); | |
| 1381 | const x = try reader.takeLeb128(u64); | |
| 1386 | 1382 | offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x))); |
| 1387 | 1383 | }, |
| 1388 | 1384 | macho.BIND_OPCODE_DO_BIND, |
| ... | ... | @@ -1397,14 +1393,14 @@ const MachODumper = struct { |
| 1397 | 1393 | switch (opc) { |
| 1398 | 1394 | macho.BIND_OPCODE_DO_BIND => {}, |
| 1399 | 1395 | macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => { |
| 1400 | add_addr = try std.leb.readUleb128(u64, reader); | |
| 1396 | add_addr = try reader.takeLeb128(u64); | |
| 1401 | 1397 | }, |
| 1402 | 1398 | macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => { |
| 1403 | 1399 | add_addr = imm * @sizeOf(u64); |
| 1404 | 1400 | }, |
| 1405 | 1401 | macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => { |
| 1406 | count = try std.leb.readUleb128(u64, reader); | |
| 1407 | skip = try std.leb.readUleb128(u64, reader); | |
| 1402 | count = try reader.takeLeb128(u64); | |
| 1403 | skip = try reader.takeLeb128(u64); | |
| 1408 | 1404 | }, |
| 1409 | 1405 | else => unreachable, |
| 1410 | 1406 | } |
| ... | ... | @@ -1621,8 +1617,9 @@ const MachODumper = struct { |
| 1621 | 1617 | var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr }; |
| 1622 | 1618 | try ctx.parse(); |
| 1623 | 1619 | |
| 1624 | var output = std.array_list.Managed(u8).init(gpa); | |
| 1625 | const writer = output.writer(); | |
| 1620 | var output: std.Io.Writer.Allocating = .init(gpa); | |
| 1621 | defer output.deinit(); | |
| 1622 | const writer = &output.writer; | |
| 1626 | 1623 | |
| 1627 | 1624 | switch (check.kind) { |
| 1628 | 1625 | .headers => { |
| ... | ... | @@ -1787,8 +1784,9 @@ const ElfDumper = struct { |
| 1787 | 1784 | try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size }); |
| 1788 | 1785 | } |
| 1789 | 1786 | |
| 1790 | var output = std.array_list.Managed(u8).init(gpa); | |
| 1791 | const writer = output.writer(); | |
| 1787 | var output: std.Io.Writer.Allocating = .init(gpa); | |
| 1788 | defer output.deinit(); | |
| 1789 | const writer = &output.writer; | |
| 1792 | 1790 | |
| 1793 | 1791 | switch (check.kind) { |
| 1794 | 1792 | .archive_symtab => if (ctx.symtab.items.len > 0) { |
| ... | ... | @@ -1944,8 +1942,9 @@ const ElfDumper = struct { |
| 1944 | 1942 | else => {}, |
| 1945 | 1943 | }; |
| 1946 | 1944 | |
| 1947 | var output = std.array_list.Managed(u8).init(gpa); | |
| 1948 | const writer = output.writer(); | |
| 1945 | var output: std.Io.Writer.Allocating = .init(gpa); | |
| 1946 | defer output.deinit(); | |
| 1947 | const writer = &output.writer; | |
| 1949 | 1948 | |
| 1950 | 1949 | switch (check.kind) { |
| 1951 | 1950 | .headers => { |
| ... | ... | @@ -2398,10 +2397,10 @@ const WasmDumper = struct { |
| 2398 | 2397 | return error.UnsupportedWasmVersion; |
| 2399 | 2398 | } |
| 2400 | 2399 | |
| 2401 | var output = std.array_list.Managed(u8).init(gpa); | |
| 2400 | var output: std.Io.Writer.Allocating = .init(gpa); | |
| 2402 | 2401 | defer output.deinit(); |
| 2403 | parseAndDumpInner(step, check, bytes, &fbs, &output) catch |err| switch (err) { | |
| 2404 | error.EndOfStream => try output.appendSlice("\n<UnexpectedEndOfStream>"), | |
| 2402 | parseAndDumpInner(step, check, bytes, &fbs, &output.writer) catch |err| switch (err) { | |
| 2403 | error.EndOfStream => try output.writer.writeAll("\n<UnexpectedEndOfStream>"), | |
| 2405 | 2404 | else => |e| return e, |
| 2406 | 2405 | }; |
| 2407 | 2406 | return output.toOwnedSlice(); |
| ... | ... | @@ -2412,10 +2411,9 @@ const WasmDumper = struct { |
| 2412 | 2411 | check: Check, |
| 2413 | 2412 | bytes: []const u8, |
| 2414 | 2413 | fbs: *std.io.FixedBufferStream([]const u8), |
| 2415 | output: *std.array_list.Managed(u8), | |
| 2414 | writer: *std.Io.Writer, | |
| 2416 | 2415 | ) !void { |
| 2417 | 2416 | const reader = fbs.reader(); |
| 2418 | const writer = output.writer(); | |
| 2419 | 2417 | |
| 2420 | 2418 | switch (check.kind) { |
| 2421 | 2419 | .headers => { |
lib/std/Io.zig-163| ... | ... | @@ -144,61 +144,6 @@ pub fn GenericReader( |
| 144 | 144 | return @errorCast(self.any().readAllAlloc(allocator, max_size)); |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | pub inline fn readUntilDelimiterArrayList( | |
| 148 | self: Self, | |
| 149 | array_list: *std.array_list.Managed(u8), | |
| 150 | delimiter: u8, | |
| 151 | max_size: usize, | |
| 152 | ) (NoEofError || Allocator.Error || error{StreamTooLong})!void { | |
| 153 | return @errorCast(self.any().readUntilDelimiterArrayList( | |
| 154 | array_list, | |
| 155 | delimiter, | |
| 156 | max_size, | |
| 157 | )); | |
| 158 | } | |
| 159 | ||
| 160 | pub inline fn readUntilDelimiterAlloc( | |
| 161 | self: Self, | |
| 162 | allocator: Allocator, | |
| 163 | delimiter: u8, | |
| 164 | max_size: usize, | |
| 165 | ) (NoEofError || Allocator.Error || error{StreamTooLong})![]u8 { | |
| 166 | return @errorCast(self.any().readUntilDelimiterAlloc( | |
| 167 | allocator, | |
| 168 | delimiter, | |
| 169 | max_size, | |
| 170 | )); | |
| 171 | } | |
| 172 | ||
| 173 | pub inline fn readUntilDelimiter( | |
| 174 | self: Self, | |
| 175 | buf: []u8, | |
| 176 | delimiter: u8, | |
| 177 | ) (NoEofError || error{StreamTooLong})![]u8 { | |
| 178 | return @errorCast(self.any().readUntilDelimiter(buf, delimiter)); | |
| 179 | } | |
| 180 | ||
| 181 | pub inline fn readUntilDelimiterOrEofAlloc( | |
| 182 | self: Self, | |
| 183 | allocator: Allocator, | |
| 184 | delimiter: u8, | |
| 185 | max_size: usize, | |
| 186 | ) (Error || Allocator.Error || error{StreamTooLong})!?[]u8 { | |
| 187 | return @errorCast(self.any().readUntilDelimiterOrEofAlloc( | |
| 188 | allocator, | |
| 189 | delimiter, | |
| 190 | max_size, | |
| 191 | )); | |
| 192 | } | |
| 193 | ||
| 194 | pub inline fn readUntilDelimiterOrEof( | |
| 195 | self: Self, | |
| 196 | buf: []u8, | |
| 197 | delimiter: u8, | |
| 198 | ) (Error || error{StreamTooLong})!?[]u8 { | |
| 199 | return @errorCast(self.any().readUntilDelimiterOrEof(buf, delimiter)); | |
| 200 | } | |
| 201 | ||
| 202 | 147 | pub inline fn streamUntilDelimiter( |
| 203 | 148 | self: Self, |
| 204 | 149 | writer: anytype, |
| ... | ... | @@ -326,103 +271,8 @@ pub fn GenericReader( |
| 326 | 271 | }; |
| 327 | 272 | } |
| 328 | 273 | |
| 329 | /// Deprecated in favor of `Writer`. | |
| 330 | pub fn GenericWriter( | |
| 331 | comptime Context: type, | |
| 332 | comptime WriteError: type, | |
| 333 | comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize, | |
| 334 | ) type { | |
| 335 | return struct { | |
| 336 | context: Context, | |
| 337 | ||
| 338 | const Self = @This(); | |
| 339 | pub const Error = WriteError; | |
| 340 | ||
| 341 | pub inline fn write(self: Self, bytes: []const u8) Error!usize { | |
| 342 | return writeFn(self.context, bytes); | |
| 343 | } | |
| 344 | ||
| 345 | pub inline fn writeAll(self: Self, bytes: []const u8) Error!void { | |
| 346 | return @errorCast(self.any().writeAll(bytes)); | |
| 347 | } | |
| 348 | ||
| 349 | pub inline fn print(self: Self, comptime format: []const u8, args: anytype) Error!void { | |
| 350 | return @errorCast(self.any().print(format, args)); | |
| 351 | } | |
| 352 | ||
| 353 | pub inline fn writeByte(self: Self, byte: u8) Error!void { | |
| 354 | return @errorCast(self.any().writeByte(byte)); | |
| 355 | } | |
| 356 | ||
| 357 | pub inline fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void { | |
| 358 | return @errorCast(self.any().writeByteNTimes(byte, n)); | |
| 359 | } | |
| 360 | ||
| 361 | pub inline fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) Error!void { | |
| 362 | return @errorCast(self.any().writeBytesNTimes(bytes, n)); | |
| 363 | } | |
| 364 | ||
| 365 | pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { | |
| 366 | return @errorCast(self.any().writeInt(T, value, endian)); | |
| 367 | } | |
| 368 | ||
| 369 | pub inline fn writeStruct(self: Self, value: anytype) Error!void { | |
| 370 | return @errorCast(self.any().writeStruct(value)); | |
| 371 | } | |
| 372 | ||
| 373 | pub inline fn writeStructEndian(self: Self, value: anytype, endian: std.builtin.Endian) Error!void { | |
| 374 | return @errorCast(self.any().writeStructEndian(value, endian)); | |
| 375 | } | |
| 376 | ||
| 377 | pub inline fn any(self: *const Self) AnyWriter { | |
| 378 | return .{ | |
| 379 | .context = @ptrCast(&self.context), | |
| 380 | .writeFn = typeErasedWriteFn, | |
| 381 | }; | |
| 382 | } | |
| 383 | ||
| 384 | fn typeErasedWriteFn(context: *const anyopaque, bytes: []const u8) anyerror!usize { | |
| 385 | const ptr: *const Context = @ptrCast(@alignCast(context)); | |
| 386 | return writeFn(ptr.*, bytes); | |
| 387 | } | |
| 388 | ||
| 389 | /// Helper for bridging to the new `Writer` API while upgrading. | |
| 390 | pub fn adaptToNewApi(self: *const Self, buffer: []u8) Adapter { | |
| 391 | return .{ | |
| 392 | .derp_writer = self.*, | |
| 393 | .new_interface = .{ | |
| 394 | .buffer = buffer, | |
| 395 | .vtable = &.{ .drain = Adapter.drain }, | |
| 396 | }, | |
| 397 | }; | |
| 398 | } | |
| 399 | ||
| 400 | pub const Adapter = struct { | |
| 401 | derp_writer: Self, | |
| 402 | new_interface: Writer, | |
| 403 | err: ?Error = null, | |
| 404 | ||
| 405 | fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize { | |
| 406 | _ = splat; | |
| 407 | const a: *@This() = @alignCast(@fieldParentPtr("new_interface", w)); | |
| 408 | const buffered = w.buffered(); | |
| 409 | if (buffered.len != 0) return w.consume(a.derp_writer.write(buffered) catch |err| { | |
| 410 | a.err = err; | |
| 411 | return error.WriteFailed; | |
| 412 | }); | |
| 413 | return a.derp_writer.write(data[0]) catch |err| { | |
| 414 | a.err = err; | |
| 415 | return error.WriteFailed; | |
| 416 | }; | |
| 417 | } | |
| 418 | }; | |
| 419 | }; | |
| 420 | } | |
| 421 | ||
| 422 | 274 | /// Deprecated in favor of `Reader`. |
| 423 | 275 | pub const AnyReader = @import("Io/DeprecatedReader.zig"); |
| 424 | /// Deprecated in favor of `Writer`. | |
| 425 | pub const AnyWriter = @import("Io/DeprecatedWriter.zig"); | |
| 426 | 276 | /// Deprecated in favor of `Reader`. |
| 427 | 277 | pub const FixedBufferStream = @import("Io/fixed_buffer_stream.zig").FixedBufferStream; |
| 428 | 278 | /// Deprecated in favor of `Reader`. |
| ... | ... | @@ -434,19 +284,6 @@ pub const countingReader = @import("Io/counting_reader.zig").countingReader; |
| 434 | 284 | |
| 435 | 285 | pub const tty = @import("Io/tty.zig"); |
| 436 | 286 | |
| 437 | /// Deprecated in favor of `Writer.Discarding`. | |
| 438 | pub const null_writer: NullWriter = .{ .context = {} }; | |
| 439 | /// Deprecated in favor of `Writer.Discarding`. | |
| 440 | pub const NullWriter = GenericWriter(void, error{}, dummyWrite); | |
| 441 | fn dummyWrite(context: void, data: []const u8) error{}!usize { | |
| 442 | _ = context; | |
| 443 | return data.len; | |
| 444 | } | |
| 445 | ||
| 446 | test null_writer { | |
| 447 | null_writer.writeAll("yay" ** 10) catch |err| switch (err) {}; | |
| 448 | } | |
| 449 | ||
| 450 | 287 | pub fn poll( |
| 451 | 288 | gpa: Allocator, |
| 452 | 289 | comptime StreamEnum: type, |
lib/std/Io/DeprecatedReader.zig-98| ... | ... | @@ -93,100 +93,6 @@ pub fn readAllAlloc(self: Self, allocator: mem.Allocator, max_size: usize) anyer |
| 93 | 93 | return try array_list.toOwnedSlice(); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead. | |
| 97 | /// Replaces the `std.array_list.Managed` contents by reading from the stream until `delimiter` is found. | |
| 98 | /// Does not include the delimiter in the result. | |
| 99 | /// If the `std.array_list.Managed` length would exceed `max_size`, `error.StreamTooLong` is returned and the | |
| 100 | /// `std.array_list.Managed` is populated with `max_size` bytes from the stream. | |
| 101 | pub fn readUntilDelimiterArrayList( | |
| 102 | self: Self, | |
| 103 | array_list: *std.array_list.Managed(u8), | |
| 104 | delimiter: u8, | |
| 105 | max_size: usize, | |
| 106 | ) anyerror!void { | |
| 107 | array_list.shrinkRetainingCapacity(0); | |
| 108 | try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); | |
| 109 | } | |
| 110 | ||
| 111 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's writer instead. | |
| 112 | /// Allocates enough memory to read until `delimiter`. If the allocated | |
| 113 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. | |
| 114 | /// Caller owns returned memory. | |
| 115 | /// If this function returns an error, the contents from the stream read so far are lost. | |
| 116 | pub fn readUntilDelimiterAlloc( | |
| 117 | self: Self, | |
| 118 | allocator: mem.Allocator, | |
| 119 | delimiter: u8, | |
| 120 | max_size: usize, | |
| 121 | ) anyerror![]u8 { | |
| 122 | var array_list = std.array_list.Managed(u8).init(allocator); | |
| 123 | defer array_list.deinit(); | |
| 124 | try self.streamUntilDelimiter(array_list.writer(), delimiter, max_size); | |
| 125 | return try array_list.toOwnedSlice(); | |
| 126 | } | |
| 127 | ||
| 128 | /// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead. | |
| 129 | /// Reads from the stream until specified byte is found. If the buffer is not | |
| 130 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. | |
| 131 | /// If end-of-stream is found, `error.EndOfStream` is returned. | |
| 132 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | |
| 133 | /// delimiter byte is written to the output buffer but is not included | |
| 134 | /// in the returned slice. | |
| 135 | pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) anyerror![]u8 { | |
| 136 | var fbs = std.io.fixedBufferStream(buf); | |
| 137 | try self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len); | |
| 138 | const output = fbs.getWritten(); | |
| 139 | buf[output.len] = delimiter; // emulating old behaviour | |
| 140 | return output; | |
| 141 | } | |
| 142 | ||
| 143 | /// Deprecated: use `streamUntilDelimiter` with ArrayList's (or any other's) writer instead. | |
| 144 | /// Allocates enough memory to read until `delimiter` or end-of-stream. | |
| 145 | /// If the allocated memory would be greater than `max_size`, returns | |
| 146 | /// `error.StreamTooLong`. If end-of-stream is found, returns the rest | |
| 147 | /// of the stream. If this function is called again after that, returns | |
| 148 | /// null. | |
| 149 | /// Caller owns returned memory. | |
| 150 | /// If this function returns an error, the contents from the stream read so far are lost. | |
| 151 | pub fn readUntilDelimiterOrEofAlloc( | |
| 152 | self: Self, | |
| 153 | allocator: mem.Allocator, | |
| 154 | delimiter: u8, | |
| 155 | max_size: usize, | |
| 156 | ) anyerror!?[]u8 { | |
| 157 | var array_list = std.array_list.Managed(u8).init(allocator); | |
| 158 | defer array_list.deinit(); | |
| 159 | self.streamUntilDelimiter(array_list.writer(), delimiter, max_size) catch |err| switch (err) { | |
| 160 | error.EndOfStream => if (array_list.items.len == 0) { | |
| 161 | return null; | |
| 162 | }, | |
| 163 | else => |e| return e, | |
| 164 | }; | |
| 165 | return try array_list.toOwnedSlice(); | |
| 166 | } | |
| 167 | ||
| 168 | /// Deprecated: use `streamUntilDelimiter` with FixedBufferStream's writer instead. | |
| 169 | /// Reads from the stream until specified byte is found. If the buffer is not | |
| 170 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. | |
| 171 | /// If end-of-stream is found, returns the rest of the stream. If this | |
| 172 | /// function is called again after that, returns null. | |
| 173 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | |
| 174 | /// delimiter byte is written to the output buffer but is not included | |
| 175 | /// in the returned slice. | |
| 176 | pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) anyerror!?[]u8 { | |
| 177 | var fbs = std.io.fixedBufferStream(buf); | |
| 178 | self.streamUntilDelimiter(fbs.writer(), delimiter, fbs.buffer.len) catch |err| switch (err) { | |
| 179 | error.EndOfStream => if (fbs.getWritten().len == 0) { | |
| 180 | return null; | |
| 181 | }, | |
| 182 | ||
| 183 | else => |e| return e, | |
| 184 | }; | |
| 185 | const output = fbs.getWritten(); | |
| 186 | buf[output.len] = delimiter; // emulating old behaviour | |
| 187 | return output; | |
| 188 | } | |
| 189 | ||
| 190 | 96 | /// Appends to the `writer` contents by reading from the stream until `delimiter` is found. |
| 191 | 97 | /// Does not write the delimiter itself. |
| 192 | 98 | /// If `optional_max_size` is not null and amount of written bytes exceeds `optional_max_size`, |
| ... | ... | @@ -384,7 +290,3 @@ const mem = std.mem; |
| 384 | 290 | const testing = std.testing; |
| 385 | 291 | const native_endian = @import("builtin").target.cpu.arch.endian(); |
| 386 | 292 | const Alignment = std.mem.Alignment; |
| 387 | ||
| 388 | test { | |
| 389 | _ = @import("Reader/test.zig"); | |
| 390 | } |
lib/std/Io/DeprecatedWriter.zig deleted-114| ... | ... | @@ -1,114 +0,0 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 5 | ||
| 6 | context: *const anyopaque, | |
| 7 | writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize, | |
| 8 | ||
| 9 | const Self = @This(); | |
| 10 | pub const Error = anyerror; | |
| 11 | ||
| 12 | pub fn write(self: Self, bytes: []const u8) anyerror!usize { | |
| 13 | return self.writeFn(self.context, bytes); | |
| 14 | } | |
| 15 | ||
| 16 | pub fn writeAll(self: Self, bytes: []const u8) anyerror!void { | |
| 17 | var index: usize = 0; | |
| 18 | while (index != bytes.len) { | |
| 19 | index += try self.write(bytes[index..]); | |
| 20 | } | |
| 21 | } | |
| 22 | ||
| 23 | pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void { | |
| 24 | return std.fmt.format(self, format, args); | |
| 25 | } | |
| 26 | ||
| 27 | pub fn writeByte(self: Self, byte: u8) anyerror!void { | |
| 28 | const array = [1]u8{byte}; | |
| 29 | return self.writeAll(&array); | |
| 30 | } | |
| 31 | ||
| 32 | pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void { | |
| 33 | var bytes: [256]u8 = undefined; | |
| 34 | @memset(bytes[0..], byte); | |
| 35 | ||
| 36 | var remaining: usize = n; | |
| 37 | while (remaining > 0) { | |
| 38 | const to_write = @min(remaining, bytes.len); | |
| 39 | try self.writeAll(bytes[0..to_write]); | |
| 40 | remaining -= to_write; | |
| 41 | } | |
| 42 | } | |
| 43 | ||
| 44 | pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) anyerror!void { | |
| 45 | var i: usize = 0; | |
| 46 | while (i < n) : (i += 1) { | |
| 47 | try self.writeAll(bytes); | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) anyerror!void { | |
| 52 | var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined; | |
| 53 | mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); | |
| 54 | return self.writeAll(&bytes); | |
| 55 | } | |
| 56 | ||
| 57 | pub fn writeStruct(self: Self, value: anytype) anyerror!void { | |
| 58 | // Only extern and packed structs have defined in-memory layout. | |
| 59 | comptime assert(@typeInfo(@TypeOf(value)).@"struct".layout != .auto); | |
| 60 | return self.writeAll(mem.asBytes(&value)); | |
| 61 | } | |
| 62 | ||
| 63 | pub fn writeStructEndian(self: Self, value: anytype, endian: std.builtin.Endian) anyerror!void { | |
| 64 | // TODO: make sure this value is not a reference type | |
| 65 | if (native_endian == endian) { | |
| 66 | return self.writeStruct(value); | |
| 67 | } else { | |
| 68 | var copy = value; | |
| 69 | mem.byteSwapAllFields(@TypeOf(value), &copy); | |
| 70 | return self.writeStruct(copy); | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | pub fn writeFile(self: Self, file: std.fs.File) anyerror!void { | |
| 75 | // TODO: figure out how to adjust std lib abstractions so that this ends up | |
| 76 | // doing sendfile or maybe even copy_file_range under the right conditions. | |
| 77 | var buf: [4000]u8 = undefined; | |
| 78 | while (true) { | |
| 79 | const n = try file.readAll(&buf); | |
| 80 | try self.writeAll(buf[0..n]); | |
| 81 | if (n < buf.len) return; | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | /// Helper for bridging to the new `Writer` API while upgrading. | |
| 86 | pub fn adaptToNewApi(self: *const Self, buffer: []u8) Adapter { | |
| 87 | return .{ | |
| 88 | .derp_writer = self.*, | |
| 89 | .new_interface = .{ | |
| 90 | .buffer = buffer, | |
| 91 | .vtable = &.{ .drain = Adapter.drain }, | |
| 92 | }, | |
| 93 | }; | |
| 94 | } | |
| 95 | ||
| 96 | pub const Adapter = struct { | |
| 97 | derp_writer: Self, | |
| 98 | new_interface: std.io.Writer, | |
| 99 | err: ?Error = null, | |
| 100 | ||
| 101 | fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize { | |
| 102 | _ = splat; | |
| 103 | const a: *@This() = @alignCast(@fieldParentPtr("new_interface", w)); | |
| 104 | const buffered = w.buffered(); | |
| 105 | if (buffered.len != 0) return w.consume(a.derp_writer.write(buffered) catch |err| { | |
| 106 | a.err = err; | |
| 107 | return error.WriteFailed; | |
| 108 | }); | |
| 109 | return a.derp_writer.write(data[0]) catch |err| { | |
| 110 | a.err = err; | |
| 111 | return error.WriteFailed; | |
| 112 | }; | |
| 113 | } | |
| 114 | }; |
lib/std/Io/Reader.zig+48-5| ... | ... | @@ -143,8 +143,8 @@ pub const failing: Reader = .{ |
| 143 | 143 | |
| 144 | 144 | /// This is generally safe to `@constCast` because it has an empty buffer, so |
| 145 | 145 | /// there is not really a way to accidentally attempt mutation of these fields. |
| 146 | const ending_state: Reader = .fixed(&.{}); | |
| 147 | pub const ending: *Reader = @constCast(&ending_state); | |
| 146 | pub const ending_instance: Reader = .fixed(&.{}); | |
| 147 | pub const ending: *Reader = @constCast(&ending_instance); | |
| 148 | 148 | |
| 149 | 149 | pub fn limited(r: *Reader, limit: Limit, buffer: []u8) Limited { |
| 150 | 150 | return .init(r, limit, buffer); |
| ... | ... | @@ -784,7 +784,7 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 784 | 784 | } |
| 785 | 785 | |
| 786 | 786 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 787 | /// `delimiter` is found, advancing the seek position. | |
| 787 | /// `delimiter` is found, advancing the seek position up to the delimiter. | |
| 788 | 788 | /// |
| 789 | 789 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| 790 | 790 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| ... | ... | @@ -814,6 +814,37 @@ pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 814 | 814 | return result[0 .. result.len - 1]; |
| 815 | 815 | } |
| 816 | 816 | |
| 817 | /// Returns a slice of the next bytes of buffered data from the stream until | |
| 818 | /// `delimiter` is found, advancing the seek position past the delimiter. | |
| 819 | /// | |
| 820 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent | |
| 821 | /// to a delimiter, unless it would result in a length 0 return value, in which | |
| 822 | /// case `null` is returned instead. | |
| 823 | /// | |
| 824 | /// If the delimiter is not found within a number of bytes matching the | |
| 825 | /// capacity of this `Reader`, `error.StreamTooLong` is returned. In | |
| 826 | /// such case, the stream state is unmodified as if this function was never | |
| 827 | /// called. | |
| 828 | /// | |
| 829 | /// Invalidates previously returned values from `peek`. | |
| 830 | /// | |
| 831 | /// See also: | |
| 832 | /// * `takeDelimiterInclusive` | |
| 833 | /// * `takeDelimiterExclusive` | |
| 834 | pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong }!?[]u8 { | |
| 835 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { | |
| 836 | error.EndOfStream => { | |
| 837 | const remaining = r.buffer[r.seek..r.end]; | |
| 838 | if (remaining.len == 0) return null; | |
| 839 | r.toss(remaining.len); | |
| 840 | return remaining; | |
| 841 | }, | |
| 842 | else => |e| return e, | |
| 843 | }; | |
| 844 | r.toss(result.len + 1); | |
| 845 | return result[0 .. result.len - 1]; | |
| 846 | } | |
| 847 | ||
| 817 | 848 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 818 | 849 | /// `delimiter` is found, without advancing the seek position. |
| 819 | 850 | /// |
| ... | ... | @@ -846,6 +877,8 @@ pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 846 | 877 | /// Appends to `w` contents by reading from the stream until `delimiter` is |
| 847 | 878 | /// found. Does not write the delimiter itself. |
| 848 | 879 | /// |
| 880 | /// Does not discard the delimiter from the `Reader`. | |
| 881 | /// | |
| 849 | 882 | /// Returns number of bytes streamed, which may be zero, or error.EndOfStream |
| 850 | 883 | /// if the delimiter was not found. |
| 851 | 884 | /// |
| ... | ... | @@ -899,6 +932,8 @@ pub const StreamDelimiterLimitError = error{ |
| 899 | 932 | /// Appends to `w` contents by reading from the stream until `delimiter` is found. |
| 900 | 933 | /// Does not write the delimiter itself. |
| 901 | 934 | /// |
| 935 | /// Does not discard the delimiter from the `Reader`. | |
| 936 | /// | |
| 902 | 937 | /// Returns number of bytes streamed, which may be zero. End of stream can be |
| 903 | 938 | /// detected by checking if the next byte in the stream is the delimiter. |
| 904 | 939 | /// |
| ... | ... | @@ -1128,7 +1163,11 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia |
| 1128 | 1163 | .@"struct" => |info| switch (info.layout) { |
| 1129 | 1164 | .auto => @compileError("ill-defined memory layout"), |
| 1130 | 1165 | .@"extern" => { |
| 1131 | var res = (try r.takeStructPointer(T)).*; | |
| 1166 | // This code works around https://github.com/ziglang/zig/issues/25067 | |
| 1167 | // by avoiding a call to `peekStructPointer`. | |
| 1168 | const struct_bytes = try r.takeArray(@sizeOf(T)); | |
| 1169 | var res: T = undefined; | |
| 1170 | @memcpy(@as([]u8, @ptrCast(&res)), struct_bytes); | |
| 1132 | 1171 | if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); |
| 1133 | 1172 | return res; |
| 1134 | 1173 | }, |
| ... | ... | @@ -1153,7 +1192,11 @@ pub inline fn peekStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia |
| 1153 | 1192 | .@"struct" => |info| switch (info.layout) { |
| 1154 | 1193 | .auto => @compileError("ill-defined memory layout"), |
| 1155 | 1194 | .@"extern" => { |
| 1156 | var res = (try r.peekStructPointer(T)).*; | |
| 1195 | // This code works around https://github.com/ziglang/zig/issues/25067 | |
| 1196 | // by avoiding a call to `peekStructPointer`. | |
| 1197 | const struct_bytes = try r.peekArray(@sizeOf(T)); | |
| 1198 | var res: T = undefined; | |
| 1199 | @memcpy(@as([]u8, @ptrCast(&res)), struct_bytes); | |
| 1157 | 1200 | if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); |
| 1158 | 1201 | return res; |
| 1159 | 1202 | }, |
lib/std/Io/Reader/test.zig deleted-351| ... | ... | @@ -1,351 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("../../std.zig"); | |
| 3 | const testing = std.testing; | |
| 4 | ||
| 5 | test "Reader" { | |
| 6 | var buf = "a\x02".*; | |
| 7 | var fis = std.io.fixedBufferStream(&buf); | |
| 8 | const reader = fis.reader(); | |
| 9 | try testing.expect((try reader.readByte()) == 'a'); | |
| 10 | try testing.expect((try reader.readEnum(enum(u8) { | |
| 11 | a = 0, | |
| 12 | b = 99, | |
| 13 | c = 2, | |
| 14 | d = 3, | |
| 15 | }, builtin.cpu.arch.endian())) == .c); | |
| 16 | try testing.expectError(error.EndOfStream, reader.readByte()); | |
| 17 | } | |
| 18 | ||
| 19 | test "isBytes" { | |
| 20 | var fis = std.io.fixedBufferStream("foobar"); | |
| 21 | const reader = fis.reader(); | |
| 22 | try testing.expectEqual(true, try reader.isBytes("foo")); | |
| 23 | try testing.expectEqual(false, try reader.isBytes("qux")); | |
| 24 | } | |
| 25 | ||
| 26 | test "skipBytes" { | |
| 27 | var fis = std.io.fixedBufferStream("foobar"); | |
| 28 | const reader = fis.reader(); | |
| 29 | try reader.skipBytes(3, .{}); | |
| 30 | try testing.expect(try reader.isBytes("bar")); | |
| 31 | try reader.skipBytes(0, .{}); | |
| 32 | try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{})); | |
| 33 | } | |
| 34 | ||
| 35 | test "readUntilDelimiterArrayList returns ArrayLists with bytes read until the delimiter, then EndOfStream" { | |
| 36 | const a = std.testing.allocator; | |
| 37 | var list = std.array_list.Managed(u8).init(a); | |
| 38 | defer list.deinit(); | |
| 39 | ||
| 40 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 41 | const reader = fis.reader(); | |
| 42 | ||
| 43 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); | |
| 44 | try std.testing.expectEqualStrings("0000", list.items); | |
| 45 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); | |
| 46 | try std.testing.expectEqualStrings("1234", list.items); | |
| 47 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5)); | |
| 48 | } | |
| 49 | ||
| 50 | test "readUntilDelimiterArrayList returns an empty ArrayList" { | |
| 51 | const a = std.testing.allocator; | |
| 52 | var list = std.array_list.Managed(u8).init(a); | |
| 53 | defer list.deinit(); | |
| 54 | ||
| 55 | var fis = std.io.fixedBufferStream("\n"); | |
| 56 | const reader = fis.reader(); | |
| 57 | ||
| 58 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); | |
| 59 | try std.testing.expectEqualStrings("", list.items); | |
| 60 | } | |
| 61 | ||
| 62 | test "readUntilDelimiterArrayList returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { | |
| 63 | const a = std.testing.allocator; | |
| 64 | var list = std.array_list.Managed(u8).init(a); | |
| 65 | defer list.deinit(); | |
| 66 | ||
| 67 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 68 | const reader = fis.reader(); | |
| 69 | ||
| 70 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5)); | |
| 71 | try std.testing.expectEqualStrings("12345", list.items); | |
| 72 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); | |
| 73 | try std.testing.expectEqualStrings("67", list.items); | |
| 74 | } | |
| 75 | ||
| 76 | test "readUntilDelimiterArrayList returns EndOfStream" { | |
| 77 | const a = std.testing.allocator; | |
| 78 | var list = std.array_list.Managed(u8).init(a); | |
| 79 | defer list.deinit(); | |
| 80 | ||
| 81 | var fis = std.io.fixedBufferStream("1234"); | |
| 82 | const reader = fis.reader(); | |
| 83 | ||
| 84 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5)); | |
| 85 | try std.testing.expectEqualStrings("1234", list.items); | |
| 86 | } | |
| 87 | ||
| 88 | test "readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { | |
| 89 | const a = std.testing.allocator; | |
| 90 | ||
| 91 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 92 | const reader = fis.reader(); | |
| 93 | ||
| 94 | { | |
| 95 | const result = try reader.readUntilDelimiterAlloc(a, '\n', 5); | |
| 96 | defer a.free(result); | |
| 97 | try std.testing.expectEqualStrings("0000", result); | |
| 98 | } | |
| 99 | ||
| 100 | { | |
| 101 | const result = try reader.readUntilDelimiterAlloc(a, '\n', 5); | |
| 102 | defer a.free(result); | |
| 103 | try std.testing.expectEqualStrings("1234", result); | |
| 104 | } | |
| 105 | ||
| 106 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5)); | |
| 107 | } | |
| 108 | ||
| 109 | test "readUntilDelimiterAlloc returns an empty ArrayList" { | |
| 110 | const a = std.testing.allocator; | |
| 111 | ||
| 112 | var fis = std.io.fixedBufferStream("\n"); | |
| 113 | const reader = fis.reader(); | |
| 114 | ||
| 115 | { | |
| 116 | const result = try reader.readUntilDelimiterAlloc(a, '\n', 5); | |
| 117 | defer a.free(result); | |
| 118 | try std.testing.expectEqualStrings("", result); | |
| 119 | } | |
| 120 | } | |
| 121 | ||
| 122 | test "readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { | |
| 123 | const a = std.testing.allocator; | |
| 124 | ||
| 125 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 126 | const reader = fis.reader(); | |
| 127 | ||
| 128 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5)); | |
| 129 | ||
| 130 | const result = try reader.readUntilDelimiterAlloc(a, '\n', 5); | |
| 131 | defer a.free(result); | |
| 132 | try std.testing.expectEqualStrings("67", result); | |
| 133 | } | |
| 134 | ||
| 135 | test "readUntilDelimiterAlloc returns EndOfStream" { | |
| 136 | const a = std.testing.allocator; | |
| 137 | ||
| 138 | var fis = std.io.fixedBufferStream("1234"); | |
| 139 | const reader = fis.reader(); | |
| 140 | ||
| 141 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5)); | |
| 142 | } | |
| 143 | ||
| 144 | test "readUntilDelimiter returns bytes read until the delimiter" { | |
| 145 | var buf: [5]u8 = undefined; | |
| 146 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 147 | const reader = fis.reader(); | |
| 148 | try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n')); | |
| 149 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); | |
| 150 | } | |
| 151 | ||
| 152 | test "readUntilDelimiter returns an empty string" { | |
| 153 | var buf: [5]u8 = undefined; | |
| 154 | var fis = std.io.fixedBufferStream("\n"); | |
| 155 | const reader = fis.reader(); | |
| 156 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); | |
| 157 | } | |
| 158 | ||
| 159 | test "readUntilDelimiter returns StreamTooLong, then an empty string" { | |
| 160 | var buf: [5]u8 = undefined; | |
| 161 | var fis = std.io.fixedBufferStream("12345\n"); | |
| 162 | const reader = fis.reader(); | |
| 163 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); | |
| 164 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); | |
| 165 | } | |
| 166 | ||
| 167 | test "readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" { | |
| 168 | var buf: [5]u8 = undefined; | |
| 169 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 170 | const reader = fis.reader(); | |
| 171 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); | |
| 172 | try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n')); | |
| 173 | } | |
| 174 | ||
| 175 | test "readUntilDelimiter returns EndOfStream" { | |
| 176 | { | |
| 177 | var buf: [5]u8 = undefined; | |
| 178 | var fis = std.io.fixedBufferStream(""); | |
| 179 | const reader = fis.reader(); | |
| 180 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); | |
| 181 | } | |
| 182 | { | |
| 183 | var buf: [5]u8 = undefined; | |
| 184 | var fis = std.io.fixedBufferStream("1234"); | |
| 185 | const reader = fis.reader(); | |
| 186 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); | |
| 187 | } | |
| 188 | } | |
| 189 | ||
| 190 | test "readUntilDelimiter returns bytes read until delimiter, then EndOfStream" { | |
| 191 | var buf: [5]u8 = undefined; | |
| 192 | var fis = std.io.fixedBufferStream("1234\n"); | |
| 193 | const reader = fis.reader(); | |
| 194 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); | |
| 195 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); | |
| 196 | } | |
| 197 | ||
| 198 | test "readUntilDelimiter returns StreamTooLong, then EndOfStream" { | |
| 199 | var buf: [5]u8 = undefined; | |
| 200 | var fis = std.io.fixedBufferStream("12345"); | |
| 201 | const reader = fis.reader(); | |
| 202 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); | |
| 203 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); | |
| 204 | } | |
| 205 | ||
| 206 | test "readUntilDelimiter writes all bytes read to the output buffer" { | |
| 207 | var buf: [5]u8 = undefined; | |
| 208 | var fis = std.io.fixedBufferStream("0000\n12345"); | |
| 209 | const reader = fis.reader(); | |
| 210 | _ = try reader.readUntilDelimiter(&buf, '\n'); | |
| 211 | try std.testing.expectEqualStrings("0000\n", &buf); | |
| 212 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); | |
| 213 | try std.testing.expectEqualStrings("12345", &buf); | |
| 214 | } | |
| 215 | ||
| 216 | test "readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { | |
| 217 | const a = std.testing.allocator; | |
| 218 | ||
| 219 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 220 | const reader = fis.reader(); | |
| 221 | ||
| 222 | { | |
| 223 | const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; | |
| 224 | defer a.free(result); | |
| 225 | try std.testing.expectEqualStrings("0000", result); | |
| 226 | } | |
| 227 | ||
| 228 | { | |
| 229 | const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; | |
| 230 | defer a.free(result); | |
| 231 | try std.testing.expectEqualStrings("1234", result); | |
| 232 | } | |
| 233 | ||
| 234 | try std.testing.expect((try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)) == null); | |
| 235 | } | |
| 236 | ||
| 237 | test "readUntilDelimiterOrEofAlloc returns an empty ArrayList" { | |
| 238 | const a = std.testing.allocator; | |
| 239 | ||
| 240 | var fis = std.io.fixedBufferStream("\n"); | |
| 241 | const reader = fis.reader(); | |
| 242 | ||
| 243 | { | |
| 244 | const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; | |
| 245 | defer a.free(result); | |
| 246 | try std.testing.expectEqualStrings("", result); | |
| 247 | } | |
| 248 | } | |
| 249 | ||
| 250 | test "readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { | |
| 251 | const a = std.testing.allocator; | |
| 252 | ||
| 253 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 254 | const reader = fis.reader(); | |
| 255 | ||
| 256 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)); | |
| 257 | ||
| 258 | const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; | |
| 259 | defer a.free(result); | |
| 260 | try std.testing.expectEqualStrings("67", result); | |
| 261 | } | |
| 262 | ||
| 263 | test "readUntilDelimiterOrEof returns bytes read until the delimiter" { | |
| 264 | var buf: [5]u8 = undefined; | |
| 265 | var fis = std.io.fixedBufferStream("0000\n1234\n"); | |
| 266 | const reader = fis.reader(); | |
| 267 | try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 268 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 269 | } | |
| 270 | ||
| 271 | test "readUntilDelimiterOrEof returns an empty string" { | |
| 272 | var buf: [5]u8 = undefined; | |
| 273 | var fis = std.io.fixedBufferStream("\n"); | |
| 274 | const reader = fis.reader(); | |
| 275 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 276 | } | |
| 277 | ||
| 278 | test "readUntilDelimiterOrEof returns StreamTooLong, then an empty string" { | |
| 279 | var buf: [5]u8 = undefined; | |
| 280 | var fis = std.io.fixedBufferStream("12345\n"); | |
| 281 | const reader = fis.reader(); | |
| 282 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); | |
| 283 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 284 | } | |
| 285 | ||
| 286 | test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" { | |
| 287 | var buf: [5]u8 = undefined; | |
| 288 | var fis = std.io.fixedBufferStream("1234567\n"); | |
| 289 | const reader = fis.reader(); | |
| 290 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); | |
| 291 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 292 | } | |
| 293 | ||
| 294 | test "readUntilDelimiterOrEof returns null" { | |
| 295 | var buf: [5]u8 = undefined; | |
| 296 | var fis = std.io.fixedBufferStream(""); | |
| 297 | const reader = fis.reader(); | |
| 298 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); | |
| 299 | } | |
| 300 | ||
| 301 | test "readUntilDelimiterOrEof returns bytes read until delimiter, then null" { | |
| 302 | var buf: [5]u8 = undefined; | |
| 303 | var fis = std.io.fixedBufferStream("1234\n"); | |
| 304 | const reader = fis.reader(); | |
| 305 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 306 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); | |
| 307 | } | |
| 308 | ||
| 309 | test "readUntilDelimiterOrEof returns bytes read until end-of-stream" { | |
| 310 | var buf: [5]u8 = undefined; | |
| 311 | var fis = std.io.fixedBufferStream("1234"); | |
| 312 | const reader = fis.reader(); | |
| 313 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 314 | } | |
| 315 | ||
| 316 | test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" { | |
| 317 | var buf: [5]u8 = undefined; | |
| 318 | var fis = std.io.fixedBufferStream("1234567"); | |
| 319 | const reader = fis.reader(); | |
| 320 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); | |
| 321 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); | |
| 322 | } | |
| 323 | ||
| 324 | test "readUntilDelimiterOrEof writes all bytes read to the output buffer" { | |
| 325 | var buf: [5]u8 = undefined; | |
| 326 | var fis = std.io.fixedBufferStream("0000\n12345"); | |
| 327 | const reader = fis.reader(); | |
| 328 | _ = try reader.readUntilDelimiterOrEof(&buf, '\n'); | |
| 329 | try std.testing.expectEqualStrings("0000\n", &buf); | |
| 330 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); | |
| 331 | try std.testing.expectEqualStrings("12345", &buf); | |
| 332 | } | |
| 333 | ||
| 334 | test "streamUntilDelimiter writes all bytes without delimiter to the output" { | |
| 335 | const input_string = "some_string_with_delimiter!"; | |
| 336 | var input_fbs = std.io.fixedBufferStream(input_string); | |
| 337 | const reader = input_fbs.reader(); | |
| 338 | ||
| 339 | var output: [input_string.len]u8 = undefined; | |
| 340 | var output_fbs = std.io.fixedBufferStream(&output); | |
| 341 | const writer = output_fbs.writer(); | |
| 342 | ||
| 343 | try reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len); | |
| 344 | try std.testing.expectEqualStrings("some_string_with_delimiter", output_fbs.getWritten()); | |
| 345 | try std.testing.expectError(error.EndOfStream, reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len)); | |
| 346 | ||
| 347 | input_fbs.reset(); | |
| 348 | output_fbs.reset(); | |
| 349 | ||
| 350 | try std.testing.expectError(error.StreamTooLong, reader.streamUntilDelimiter(writer, '!', 5)); | |
| 351 | } |
lib/std/Io/Writer.zig+29-5| ... | ... | @@ -8,6 +8,7 @@ const Limit = std.Io.Limit; |
| 8 | 8 | const File = std.fs.File; |
| 9 | 9 | const testing = std.testing; |
| 10 | 10 | const Allocator = std.mem.Allocator; |
| 11 | const ArrayList = std.ArrayList; | |
| 11 | 12 | |
| 12 | 13 | vtable: *const VTable, |
| 13 | 14 | /// If this has length zero, the writer is unbuffered, and `flush` is a no-op. |
| ... | ... | @@ -2374,6 +2375,29 @@ pub fn unreachableRebase(w: *Writer, preserve: usize, capacity: usize) Error!voi |
| 2374 | 2375 | unreachable; |
| 2375 | 2376 | } |
| 2376 | 2377 | |
| 2378 | pub fn fromArrayList(array_list: *ArrayList(u8)) Writer { | |
| 2379 | defer array_list.* = .empty; | |
| 2380 | return .{ | |
| 2381 | .vtable = &.{ | |
| 2382 | .drain = fixedDrain, | |
| 2383 | .flush = noopFlush, | |
| 2384 | .rebase = failingRebase, | |
| 2385 | }, | |
| 2386 | .buffer = array_list.allocatedSlice(), | |
| 2387 | .end = array_list.items.len, | |
| 2388 | }; | |
| 2389 | } | |
| 2390 | ||
| 2391 | pub fn toArrayList(w: *Writer) ArrayList(u8) { | |
| 2392 | const result: ArrayList(u8) = .{ | |
| 2393 | .items = w.buffer[0..w.end], | |
| 2394 | .capacity = w.buffer.len, | |
| 2395 | }; | |
| 2396 | w.buffer = &.{}; | |
| 2397 | w.end = 0; | |
| 2398 | return result; | |
| 2399 | } | |
| 2400 | ||
| 2377 | 2401 | /// Provides a `Writer` implementation based on calling `Hasher.update`, sending |
| 2378 | 2402 | /// all data also to an underlying `Writer`. |
| 2379 | 2403 | /// |
| ... | ... | @@ -2546,7 +2570,7 @@ pub const Allocating = struct { |
| 2546 | 2570 | } |
| 2547 | 2571 | |
| 2548 | 2572 | /// Replaces `array_list` with empty, taking ownership of the memory. |
| 2549 | pub fn fromArrayList(allocator: Allocator, array_list: *std.ArrayListUnmanaged(u8)) Allocating { | |
| 2573 | pub fn fromArrayList(allocator: Allocator, array_list: *ArrayList(u8)) Allocating { | |
| 2550 | 2574 | defer array_list.* = .empty; |
| 2551 | 2575 | return .{ |
| 2552 | 2576 | .allocator = allocator, |
| ... | ... | @@ -2572,9 +2596,9 @@ pub const Allocating = struct { |
| 2572 | 2596 | |
| 2573 | 2597 | /// Returns an array list that takes ownership of the allocated memory. |
| 2574 | 2598 | /// Resets the `Allocating` to an empty state. |
| 2575 | pub fn toArrayList(a: *Allocating) std.ArrayListUnmanaged(u8) { | |
| 2599 | pub fn toArrayList(a: *Allocating) ArrayList(u8) { | |
| 2576 | 2600 | const w = &a.writer; |
| 2577 | const result: std.ArrayListUnmanaged(u8) = .{ | |
| 2601 | const result: ArrayList(u8) = .{ | |
| 2578 | 2602 | .items = w.buffer[0..w.end], |
| 2579 | 2603 | .capacity = w.buffer.len, |
| 2580 | 2604 | }; |
| ... | ... | @@ -2603,7 +2627,7 @@ pub const Allocating = struct { |
| 2603 | 2627 | |
| 2604 | 2628 | pub fn toOwnedSliceSentinel(a: *Allocating, comptime sentinel: u8) error{OutOfMemory}![:sentinel]u8 { |
| 2605 | 2629 | const gpa = a.allocator; |
| 2606 | var list = toArrayList(a); | |
| 2630 | var list = @This().toArrayList(a); | |
| 2607 | 2631 | defer a.setArrayList(list); |
| 2608 | 2632 | return list.toOwnedSliceSentinel(gpa, sentinel); |
| 2609 | 2633 | } |
| ... | ... | @@ -2670,7 +2694,7 @@ pub const Allocating = struct { |
| 2670 | 2694 | list.ensureUnusedCapacity(gpa, minimum_len) catch return error.WriteFailed; |
| 2671 | 2695 | } |
| 2672 | 2696 | |
| 2673 | fn setArrayList(a: *Allocating, list: std.ArrayListUnmanaged(u8)) void { | |
| 2697 | fn setArrayList(a: *Allocating, list: ArrayList(u8)) void { | |
| 2674 | 2698 | a.writer.buffer = list.allocatedSlice(); |
| 2675 | 2699 | a.writer.end = list.items.len; |
| 2676 | 2700 | } |
lib/std/Io/fixed_buffer_stream.zig-69| ... | ... | @@ -17,7 +17,6 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 17 | 17 | pub const GetSeekPosError = error{}; |
| 18 | 18 | |
| 19 | 19 | pub const Reader = io.GenericReader(*Self, ReadError, read); |
| 20 | pub const Writer = io.GenericWriter(*Self, WriteError, write); | |
| 21 | 20 | |
| 22 | 21 | const Self = @This(); |
| 23 | 22 | |
| ... | ... | @@ -25,10 +24,6 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 25 | 24 | return .{ .context = self }; |
| 26 | 25 | } |
| 27 | 26 | |
| 28 | pub fn writer(self: *Self) Writer { | |
| 29 | return .{ .context = self }; | |
| 30 | } | |
| 31 | ||
| 32 | 27 | pub fn read(self: *Self, dest: []u8) ReadError!usize { |
| 33 | 28 | const size = @min(dest.len, self.buffer.len - self.pos); |
| 34 | 29 | const end = self.pos + size; |
| ... | ... | @@ -39,23 +34,6 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 39 | 34 | return size; |
| 40 | 35 | } |
| 41 | 36 | |
| 42 | /// If the returned number of bytes written is less than requested, the | |
| 43 | /// buffer is full. Returns `error.NoSpaceLeft` when no bytes would be written. | |
| 44 | /// Note: `error.NoSpaceLeft` matches the corresponding error from | |
| 45 | /// `std.fs.File.WriteError`. | |
| 46 | pub fn write(self: *Self, bytes: []const u8) WriteError!usize { | |
| 47 | if (bytes.len == 0) return 0; | |
| 48 | if (self.pos >= self.buffer.len) return error.NoSpaceLeft; | |
| 49 | ||
| 50 | const n = @min(self.buffer.len - self.pos, bytes.len); | |
| 51 | @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]); | |
| 52 | self.pos += n; | |
| 53 | ||
| 54 | if (n == 0) return error.NoSpaceLeft; | |
| 55 | ||
| 56 | return n; | |
| 57 | } | |
| 58 | ||
| 59 | 37 | pub fn seekTo(self: *Self, pos: u64) SeekError!void { |
| 60 | 38 | self.pos = @min(std.math.lossyCast(usize, pos), self.buffer.len); |
| 61 | 39 | } |
| ... | ... | @@ -84,10 +62,6 @@ pub fn FixedBufferStream(comptime Buffer: type) type { |
| 84 | 62 | return self.pos; |
| 85 | 63 | } |
| 86 | 64 | |
| 87 | pub fn getWritten(self: Self) Buffer { | |
| 88 | return self.buffer[0..self.pos]; | |
| 89 | } | |
| 90 | ||
| 91 | 65 | pub fn reset(self: *Self) void { |
| 92 | 66 | self.pos = 0; |
| 93 | 67 | } |
| ... | ... | @@ -117,49 +91,6 @@ fn Slice(comptime T: type) type { |
| 117 | 91 | } |
| 118 | 92 | } |
| 119 | 93 | |
| 120 | test "output" { | |
| 121 | var buf: [255]u8 = undefined; | |
| 122 | var fbs = fixedBufferStream(&buf); | |
| 123 | const stream = fbs.writer(); | |
| 124 | ||
| 125 | try stream.print("{s}{s}!", .{ "Hello", "World" }); | |
| 126 | try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten()); | |
| 127 | } | |
| 128 | ||
| 129 | test "output at comptime" { | |
| 130 | comptime { | |
| 131 | var buf: [255]u8 = undefined; | |
| 132 | var fbs = fixedBufferStream(&buf); | |
| 133 | const stream = fbs.writer(); | |
| 134 | ||
| 135 | try stream.print("{s}{s}!", .{ "Hello", "World" }); | |
| 136 | try testing.expectEqualSlices(u8, "HelloWorld!", fbs.getWritten()); | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | test "output 2" { | |
| 141 | var buffer: [10]u8 = undefined; | |
| 142 | var fbs = fixedBufferStream(&buffer); | |
| 143 | ||
| 144 | try fbs.writer().writeAll("Hello"); | |
| 145 | try testing.expect(mem.eql(u8, fbs.getWritten(), "Hello")); | |
| 146 | ||
| 147 | try fbs.writer().writeAll("world"); | |
| 148 | try testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); | |
| 149 | ||
| 150 | try testing.expectError(error.NoSpaceLeft, fbs.writer().writeAll("!")); | |
| 151 | try testing.expect(mem.eql(u8, fbs.getWritten(), "Helloworld")); | |
| 152 | ||
| 153 | fbs.reset(); | |
| 154 | try testing.expect(fbs.getWritten().len == 0); | |
| 155 | ||
| 156 | try testing.expectError(error.NoSpaceLeft, fbs.writer().writeAll("Hello world!")); | |
| 157 | try testing.expect(mem.eql(u8, fbs.getWritten(), "Hello worl")); | |
| 158 | ||
| 159 | try fbs.seekTo((try fbs.getEndPos()) + 1); | |
| 160 | try testing.expectError(error.NoSpaceLeft, fbs.writer().writeAll("H")); | |
| 161 | } | |
| 162 | ||
| 163 | 94 | test "input" { |
| 164 | 95 | const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7 }; |
| 165 | 96 | var fbs = fixedBufferStream(&bytes); |
lib/std/Thread.zig+1-1| ... | ... | @@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { |
| 167 | 167 | const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only }); |
| 168 | 168 | defer file.close(); |
| 169 | 169 | |
| 170 | try file.deprecatedWriter().writeAll(name); | |
| 170 | try file.writeAll(name); | |
| 171 | 171 | return; |
| 172 | 172 | }, |
| 173 | 173 | .windows => { |
lib/std/array_list.zig-129| ... | ... | @@ -336,39 +336,6 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 336 | 336 | try unmanaged.print(gpa, fmt, args); |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | pub const Writer = if (T != u8) void else std.io.GenericWriter(*Self, Allocator.Error, appendWrite); | |
| 340 | ||
| 341 | /// Initializes a Writer which will append to the list. | |
| 342 | pub fn writer(self: *Self) Writer { | |
| 343 | return .{ .context = self }; | |
| 344 | } | |
| 345 | ||
| 346 | /// Same as `append` except it returns the number of bytes written, which is always the same | |
| 347 | /// as `m.len`. The purpose of this function existing is to match `std.io.GenericWriter` API. | |
| 348 | /// Invalidates element pointers if additional memory is needed. | |
| 349 | fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize { | |
| 350 | try self.appendSlice(m); | |
| 351 | return m.len; | |
| 352 | } | |
| 353 | ||
| 354 | pub const FixedWriter = std.io.GenericWriter(*Self, Allocator.Error, appendWriteFixed); | |
| 355 | ||
| 356 | /// Initializes a Writer which will append to the list but will return | |
| 357 | /// `error.OutOfMemory` rather than increasing capacity. | |
| 358 | pub fn fixedWriter(self: *Self) FixedWriter { | |
| 359 | return .{ .context = self }; | |
| 360 | } | |
| 361 | ||
| 362 | /// The purpose of this function existing is to match `std.io.GenericWriter` API. | |
| 363 | fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize { | |
| 364 | const available_capacity = self.capacity - self.items.len; | |
| 365 | if (m.len > available_capacity) | |
| 366 | return error.OutOfMemory; | |
| 367 | ||
| 368 | self.appendSliceAssumeCapacity(m); | |
| 369 | return m.len; | |
| 370 | } | |
| 371 | ||
| 372 | 339 | /// Append a value to the list `n` times. |
| 373 | 340 | /// Allocates more memory as necessary. |
| 374 | 341 | /// Invalidates element pointers if additional memory is needed. |
| ... | ... | @@ -1083,48 +1050,6 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1083 | 1050 | self.items.len += w.end; |
| 1084 | 1051 | } |
| 1085 | 1052 | |
| 1086 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1087 | pub const WriterContext = struct { | |
| 1088 | self: *Self, | |
| 1089 | allocator: Allocator, | |
| 1090 | }; | |
| 1091 | ||
| 1092 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1093 | pub const Writer = if (T != u8) | |
| 1094 | @compileError("The Writer interface is only defined for ArrayList(u8) " ++ | |
| 1095 | "but the given type is ArrayList(" ++ @typeName(T) ++ ")") | |
| 1096 | else | |
| 1097 | std.io.GenericWriter(WriterContext, Allocator.Error, appendWrite); | |
| 1098 | ||
| 1099 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1100 | pub fn writer(self: *Self, gpa: Allocator) Writer { | |
| 1101 | return .{ .context = .{ .self = self, .allocator = gpa } }; | |
| 1102 | } | |
| 1103 | ||
| 1104 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1105 | fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize { | |
| 1106 | try context.self.appendSlice(context.allocator, m); | |
| 1107 | return m.len; | |
| 1108 | } | |
| 1109 | ||
| 1110 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1111 | pub const FixedWriter = std.io.GenericWriter(*Self, Allocator.Error, appendWriteFixed); | |
| 1112 | ||
| 1113 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1114 | pub fn fixedWriter(self: *Self) FixedWriter { | |
| 1115 | return .{ .context = self }; | |
| 1116 | } | |
| 1117 | ||
| 1118 | /// Deprecated in favor of `print` or `std.io.Writer.Allocating`. | |
| 1119 | fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize { | |
| 1120 | const available_capacity = self.capacity - self.items.len; | |
| 1121 | if (m.len > available_capacity) | |
| 1122 | return error.OutOfMemory; | |
| 1123 | ||
| 1124 | self.appendSliceAssumeCapacity(m); | |
| 1125 | return m.len; | |
| 1126 | } | |
| 1127 | ||
| 1128 | 1053 | /// Append a value to the list `n` times. |
| 1129 | 1054 | /// Allocates more memory as necessary. |
| 1130 | 1055 | /// Invalidates element pointers if additional memory is needed. |
| ... | ... | @@ -2116,60 +2041,6 @@ test "Managed(T) of struct T" { |
| 2116 | 2041 | } |
| 2117 | 2042 | } |
| 2118 | 2043 | |
| 2119 | test "Managed(u8) implements writer" { | |
| 2120 | const a = testing.allocator; | |
| 2121 | ||
| 2122 | { | |
| 2123 | var buffer = Managed(u8).init(a); | |
| 2124 | defer buffer.deinit(); | |
| 2125 | ||
| 2126 | const x: i32 = 42; | |
| 2127 | const y: i32 = 1234; | |
| 2128 | try buffer.writer().print("x: {}\ny: {}\n", .{ x, y }); | |
| 2129 | ||
| 2130 | try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); | |
| 2131 | } | |
| 2132 | { | |
| 2133 | var list = AlignedManaged(u8, .@"2").init(a); | |
| 2134 | defer list.deinit(); | |
| 2135 | ||
| 2136 | const writer = list.writer(); | |
| 2137 | try writer.writeAll("a"); | |
| 2138 | try writer.writeAll("bc"); | |
| 2139 | try writer.writeAll("d"); | |
| 2140 | try writer.writeAll("efg"); | |
| 2141 | ||
| 2142 | try testing.expectEqualSlices(u8, list.items, "abcdefg"); | |
| 2143 | } | |
| 2144 | } | |
| 2145 | ||
| 2146 | test "ArrayList(u8) implements writer" { | |
| 2147 | const a = testing.allocator; | |
| 2148 | ||
| 2149 | { | |
| 2150 | var buffer: ArrayList(u8) = .empty; | |
| 2151 | defer buffer.deinit(a); | |
| 2152 | ||
| 2153 | const x: i32 = 42; | |
| 2154 | const y: i32 = 1234; | |
| 2155 | try buffer.writer(a).print("x: {}\ny: {}\n", .{ x, y }); | |
| 2156 | ||
| 2157 | try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); | |
| 2158 | } | |
| 2159 | { | |
| 2160 | var list: Aligned(u8, .@"2") = .empty; | |
| 2161 | defer list.deinit(a); | |
| 2162 | ||
| 2163 | const writer = list.writer(a); | |
| 2164 | try writer.writeAll("a"); | |
| 2165 | try writer.writeAll("bc"); | |
| 2166 | try writer.writeAll("d"); | |
| 2167 | try writer.writeAll("efg"); | |
| 2168 | ||
| 2169 | try testing.expectEqualSlices(u8, list.items, "abcdefg"); | |
| 2170 | } | |
| 2171 | } | |
| 2172 | ||
| 2173 | 2044 | test "shrink still sets length when resizing is disabled" { |
| 2174 | 2045 | var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 }); |
| 2175 | 2046 | const a = failing_allocator.allocator(); |
lib/std/base64.zig+1-2| ... | ... | @@ -108,8 +108,7 @@ pub const Base64Encoder = struct { |
| 108 | 108 | } |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | // dest must be compatible with std.io.GenericWriter's writeAll interface | |
| 112 | pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void { | |
| 111 | pub fn encodeWriter(encoder: *const Base64Encoder, dest: *std.Io.Writer, source: []const u8) !void { | |
| 113 | 112 | var chunker = window(u8, source, 3, 3); |
| 114 | 113 | while (chunker.next()) |chunk| { |
| 115 | 114 | var temp: [5]u8 = undefined; |
lib/std/crypto/aegis.zig-12| ... | ... | @@ -801,18 +801,6 @@ fn AegisMac(comptime T: type) type { |
| 801 | 801 | ctx.update(msg); |
| 802 | 802 | ctx.final(out); |
| 803 | 803 | } |
| 804 | ||
| 805 | pub const Error = error{}; | |
| 806 | pub const Writer = std.io.GenericWriter(*Mac, Error, write); | |
| 807 | ||
| 808 | fn write(self: *Mac, bytes: []const u8) Error!usize { | |
| 809 | self.update(bytes); | |
| 810 | return bytes.len; | |
| 811 | } | |
| 812 | ||
| 813 | pub fn writer(self: *Mac) Writer { | |
| 814 | return .{ .context = self }; | |
| 815 | } | |
| 816 | 804 | }; |
| 817 | 805 | } |
| 818 | 806 |
lib/std/crypto/blake2.zig-12| ... | ... | @@ -185,18 +185,6 @@ pub fn Blake2s(comptime out_bits: usize) type { |
| 185 | 185 | r.* ^= v[i] ^ v[i + 8]; |
| 186 | 186 | } |
| 187 | 187 | } |
| 188 | ||
| 189 | pub const Error = error{}; | |
| 190 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 191 | ||
| 192 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 193 | self.update(bytes); | |
| 194 | return bytes.len; | |
| 195 | } | |
| 196 | ||
| 197 | pub fn writer(self: *Self) Writer { | |
| 198 | return .{ .context = self }; | |
| 199 | } | |
| 200 | 188 | }; |
| 201 | 189 | } |
| 202 | 190 |
lib/std/crypto/blake3.zig-12| ... | ... | @@ -474,18 +474,6 @@ pub const Blake3 = struct { |
| 474 | 474 | } |
| 475 | 475 | output.rootOutputBytes(out_slice); |
| 476 | 476 | } |
| 477 | ||
| 478 | pub const Error = error{}; | |
| 479 | pub const Writer = std.io.GenericWriter(*Blake3, Error, write); | |
| 480 | ||
| 481 | fn write(self: *Blake3, bytes: []const u8) Error!usize { | |
| 482 | self.update(bytes); | |
| 483 | return bytes.len; | |
| 484 | } | |
| 485 | ||
| 486 | pub fn writer(self: *Blake3) Writer { | |
| 487 | return .{ .context = self }; | |
| 488 | } | |
| 489 | 477 | }; |
| 490 | 478 | |
| 491 | 479 | // Use named type declarations to workaround crash with anonymous structs (issue #4373). |
lib/std/crypto/codecs/asn1/der/ArrayListReverse.zig+6-11| ... | ... | @@ -4,6 +4,12 @@ |
| 4 | 4 | //! Laid out in memory like: |
| 5 | 5 | //! capacity |--------------------------| |
| 6 | 6 | //! data |-------------| |
| 7 | ||
| 8 | const std = @import("std"); | |
| 9 | const Allocator = std.mem.Allocator; | |
| 10 | const assert = std.debug.assert; | |
| 11 | const testing = std.testing; | |
| 12 | ||
| 7 | 13 | data: []u8, |
| 8 | 14 | capacity: usize, |
| 9 | 15 | allocator: Allocator, |
| ... | ... | @@ -45,12 +51,6 @@ pub fn prependSlice(self: *ArrayListReverse, data: []const u8) Error!void { |
| 45 | 51 | self.data.ptr = begin; |
| 46 | 52 | } |
| 47 | 53 | |
| 48 | pub const Writer = std.io.GenericWriter(*ArrayListReverse, Error, prependSliceSize); | |
| 49 | /// Warning: This writer writes backwards. `fn print` will NOT work as expected. | |
| 50 | pub fn writer(self: *ArrayListReverse) Writer { | |
| 51 | return .{ .context = self }; | |
| 52 | } | |
| 53 | ||
| 54 | 54 | fn prependSliceSize(self: *ArrayListReverse, data: []const u8) Error!usize { |
| 55 | 55 | try self.prependSlice(data); |
| 56 | 56 | return data.len; |
| ... | ... | @@ -77,11 +77,6 @@ pub fn toOwnedSlice(self: *ArrayListReverse) Error![]u8 { |
| 77 | 77 | return new_memory; |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | const std = @import("std"); | |
| 81 | const Allocator = std.mem.Allocator; | |
| 82 | const assert = std.debug.assert; | |
| 83 | const testing = std.testing; | |
| 84 | ||
| 85 | 80 | test ArrayListReverse { |
| 86 | 81 | var b = ArrayListReverse.init(testing.allocator); |
| 87 | 82 | defer b.deinit(); |
lib/std/crypto/ml_kem.zig+47-45| ... | ... | @@ -1721,53 +1721,55 @@ test "Test happy flow" { |
| 1721 | 1721 | |
| 1722 | 1722 | // Code to test NIST Known Answer Tests (KAT), see PQCgenKAT.c. |
| 1723 | 1723 | |
| 1724 | const sha2 = crypto.hash.sha2; | |
| 1725 | ||
| 1726 | test "NIST KAT test" { | |
| 1727 | inline for (.{ | |
| 1728 | .{ d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547" }, | |
| 1729 | .{ d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5" }, | |
| 1730 | .{ d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2" }, | |
| 1731 | }) |modeHash| { | |
| 1732 | const mode = modeHash[0]; | |
| 1733 | var seed: [48]u8 = undefined; | |
| 1734 | for (&seed, 0..) |*s, i| { | |
| 1735 | s.* = @as(u8, @intCast(i)); | |
| 1736 | } | |
| 1737 | var f = sha2.Sha256.init(.{}); | |
| 1738 | const fw = f.writer(); | |
| 1739 | var g = NistDRBG.init(seed); | |
| 1740 | try std.fmt.format(fw, "# {s}\n\n", .{mode.name}); | |
| 1741 | for (0..100) |i| { | |
| 1742 | g.fill(&seed); | |
| 1743 | try std.fmt.format(fw, "count = {}\n", .{i}); | |
| 1744 | try std.fmt.format(fw, "seed = {X}\n", .{&seed}); | |
| 1745 | var g2 = NistDRBG.init(seed); | |
| 1746 | ||
| 1747 | // This is not equivalent to g2.fill(kseed[:]). As the reference | |
| 1748 | // implementation calls randombytes twice generating the keypair, | |
| 1749 | // we have to do that as well. | |
| 1750 | var kseed: [64]u8 = undefined; | |
| 1751 | var eseed: [32]u8 = undefined; | |
| 1752 | g2.fill(kseed[0..32]); | |
| 1753 | g2.fill(kseed[32..64]); | |
| 1754 | g2.fill(&eseed); | |
| 1755 | const kp = try mode.KeyPair.generateDeterministic(kseed); | |
| 1756 | const e = kp.public_key.encaps(eseed); | |
| 1757 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); | |
| 1758 | try testing.expectEqual(ss2, e.shared_secret); | |
| 1759 | try std.fmt.format(fw, "pk = {X}\n", .{&kp.public_key.toBytes()}); | |
| 1760 | try std.fmt.format(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()}); | |
| 1761 | try std.fmt.format(fw, "ct = {X}\n", .{&e.ciphertext}); | |
| 1762 | try std.fmt.format(fw, "ss = {X}\n\n", .{&e.shared_secret}); | |
| 1763 | } | |
| 1724 | test "NIST KAT test d00.Kyber512" { | |
| 1725 | try testNistKat(d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547"); | |
| 1726 | } | |
| 1764 | 1727 | |
| 1765 | var out: [32]u8 = undefined; | |
| 1766 | f.final(&out); | |
| 1767 | var outHex: [64]u8 = undefined; | |
| 1768 | _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out}); | |
| 1769 | try testing.expectEqual(outHex, modeHash[1].*); | |
| 1728 | test "NIST KAT test d00.Kyber1024" { | |
| 1729 | try testNistKat(d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5"); | |
| 1730 | } | |
| 1731 | ||
| 1732 | test "NIST KAT test d00.Kyber768" { | |
| 1733 | try testNistKat(d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2"); | |
| 1734 | } | |
| 1735 | ||
| 1736 | fn testNistKat(mode: type, hash: []const u8) !void { | |
| 1737 | var seed: [48]u8 = undefined; | |
| 1738 | for (&seed, 0..) |*s, i| { | |
| 1739 | s.* = @as(u8, @intCast(i)); | |
| 1770 | 1740 | } |
| 1741 | var fw: std.Io.Writer.Hashing(crypto.hash.sha2.Sha256) = .init(&.{}); | |
| 1742 | var g = NistDRBG.init(seed); | |
| 1743 | try fw.writer.print("# {s}\n\n", .{mode.name}); | |
| 1744 | for (0..100) |i| { | |
| 1745 | g.fill(&seed); | |
| 1746 | try fw.writer.print("count = {}\n", .{i}); | |
| 1747 | try fw.writer.print("seed = {X}\n", .{&seed}); | |
| 1748 | var g2 = NistDRBG.init(seed); | |
| 1749 | ||
| 1750 | // This is not equivalent to g2.fill(kseed[:]). As the reference | |
| 1751 | // implementation calls randombytes twice generating the keypair, | |
| 1752 | // we have to do that as well. | |
| 1753 | var kseed: [64]u8 = undefined; | |
| 1754 | var eseed: [32]u8 = undefined; | |
| 1755 | g2.fill(kseed[0..32]); | |
| 1756 | g2.fill(kseed[32..64]); | |
| 1757 | g2.fill(&eseed); | |
| 1758 | const kp = try mode.KeyPair.generateDeterministic(kseed); | |
| 1759 | const e = kp.public_key.encaps(eseed); | |
| 1760 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); | |
| 1761 | try testing.expectEqual(ss2, e.shared_secret); | |
| 1762 | try fw.writer.print("pk = {X}\n", .{&kp.public_key.toBytes()}); | |
| 1763 | try fw.writer.print("sk = {X}\n", .{&kp.secret_key.toBytes()}); | |
| 1764 | try fw.writer.print("ct = {X}\n", .{&e.ciphertext}); | |
| 1765 | try fw.writer.print("ss = {X}\n\n", .{&e.shared_secret}); | |
| 1766 | } | |
| 1767 | ||
| 1768 | var out: [32]u8 = undefined; | |
| 1769 | fw.hasher.final(&out); | |
| 1770 | var outHex: [64]u8 = undefined; | |
| 1771 | _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out}); | |
| 1772 | try testing.expectEqualStrings(&outHex, hash); | |
| 1771 | 1773 | } |
| 1772 | 1774 | |
| 1773 | 1775 | const NistDRBG = struct { |
lib/std/crypto/scrypt.zig+12-9| ... | ... | @@ -304,31 +304,34 @@ const crypt_format = struct { |
| 304 | 304 | |
| 305 | 305 | /// Serialize parameters into a string in modular crypt format. |
| 306 | 306 | pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 { |
| 307 | var buf = io.fixedBufferStream(str); | |
| 308 | try serializeTo(params, buf.writer()); | |
| 309 | return buf.getWritten(); | |
| 307 | var w: std.Io.Writer = .fixed(str); | |
| 308 | serializeTo(params, &w) catch |err| switch (err) { | |
| 309 | error.WriteFailed => return error.NoSpaceLeft, | |
| 310 | else => |e| return e, | |
| 311 | }; | |
| 312 | return w.buffered(); | |
| 310 | 313 | } |
| 311 | 314 | |
| 312 | 315 | /// Compute the number of bytes required to serialize `params` |
| 313 | 316 | pub fn calcSize(params: anytype) usize { |
| 314 | 317 | var trash: [128]u8 = undefined; |
| 315 | 318 | var d: std.Io.Writer.Discarding = .init(&trash); |
| 316 | serializeTo(params, &d) catch unreachable; | |
| 319 | serializeTo(params, &d.writer) catch unreachable; | |
| 317 | 320 | return @intCast(d.fullCount()); |
| 318 | 321 | } |
| 319 | 322 | |
| 320 | fn serializeTo(params: anytype, out: anytype) !void { | |
| 323 | fn serializeTo(params: anytype, w: *std.Io.Writer) !void { | |
| 321 | 324 | var header: [14]u8 = undefined; |
| 322 | 325 | header[0..3].* = prefix.*; |
| 323 | 326 | Codec.intEncode(header[3..4], params.ln); |
| 324 | 327 | Codec.intEncode(header[4..9], params.r); |
| 325 | 328 | Codec.intEncode(header[9..14], params.p); |
| 326 | try out.writeAll(&header); | |
| 327 | try out.writeAll(params.salt); | |
| 328 | try out.writeAll("$"); | |
| 329 | try w.writeAll(&header); | |
| 330 | try w.writeAll(params.salt); | |
| 331 | try w.writeAll("$"); | |
| 329 | 332 | var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined; |
| 330 | 333 | const hash_str = try params.hash.toB64(&buf); |
| 331 | try out.writeAll(hash_str); | |
| 334 | try w.writeAll(hash_str); | |
| 332 | 335 | } |
| 333 | 336 | |
| 334 | 337 | /// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet, |
lib/std/crypto/sha2.zig-12| ... | ... | @@ -373,18 +373,6 @@ fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type { |
| 373 | 373 | |
| 374 | 374 | for (&d.s, v) |*dv, vv| dv.* +%= vv; |
| 375 | 375 | } |
| 376 | ||
| 377 | pub const Error = error{}; | |
| 378 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 379 | ||
| 380 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 381 | self.update(bytes); | |
| 382 | return bytes.len; | |
| 383 | } | |
| 384 | ||
| 385 | pub fn writer(self: *Self) Writer { | |
| 386 | return .{ .context = self }; | |
| 387 | } | |
| 388 | 376 | }; |
| 389 | 377 | } |
| 390 | 378 |
lib/std/crypto/sha3.zig-60| ... | ... | @@ -80,18 +80,6 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim |
| 80 | 80 | self.st.pad(); |
| 81 | 81 | self.st.squeeze(out[0..]); |
| 82 | 82 | } |
| 83 | ||
| 84 | pub const Error = error{}; | |
| 85 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 86 | ||
| 87 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 88 | self.update(bytes); | |
| 89 | return bytes.len; | |
| 90 | } | |
| 91 | ||
| 92 | pub fn writer(self: *Self) Writer { | |
| 93 | return .{ .context = self }; | |
| 94 | } | |
| 95 | 83 | }; |
| 96 | 84 | } |
| 97 | 85 | |
| ... | ... | @@ -191,18 +179,6 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime |
| 191 | 179 | pub fn fillBlock(self: *Self) void { |
| 192 | 180 | self.st.fillBlock(); |
| 193 | 181 | } |
| 194 | ||
| 195 | pub const Error = error{}; | |
| 196 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 197 | ||
| 198 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 199 | self.update(bytes); | |
| 200 | return bytes.len; | |
| 201 | } | |
| 202 | ||
| 203 | pub fn writer(self: *Self) Writer { | |
| 204 | return .{ .context = self }; | |
| 205 | } | |
| 206 | 182 | }; |
| 207 | 183 | } |
| 208 | 184 | |
| ... | ... | @@ -284,18 +260,6 @@ fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime |
| 284 | 260 | pub fn fillBlock(self: *Self) void { |
| 285 | 261 | self.shaker.fillBlock(); |
| 286 | 262 | } |
| 287 | ||
| 288 | pub const Error = error{}; | |
| 289 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 290 | ||
| 291 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 292 | self.update(bytes); | |
| 293 | return bytes.len; | |
| 294 | } | |
| 295 | ||
| 296 | pub fn writer(self: *Self) Writer { | |
| 297 | return .{ .context = self }; | |
| 298 | } | |
| 299 | 263 | }; |
| 300 | 264 | } |
| 301 | 265 | |
| ... | ... | @@ -390,18 +354,6 @@ fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime r |
| 390 | 354 | ctx.update(msg); |
| 391 | 355 | ctx.final(out); |
| 392 | 356 | } |
| 393 | ||
| 394 | pub const Error = error{}; | |
| 395 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 396 | ||
| 397 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 398 | self.update(bytes); | |
| 399 | return bytes.len; | |
| 400 | } | |
| 401 | ||
| 402 | pub fn writer(self: *Self) Writer { | |
| 403 | return .{ .context = self }; | |
| 404 | } | |
| 405 | 357 | }; |
| 406 | 358 | } |
| 407 | 359 | |
| ... | ... | @@ -482,18 +434,6 @@ fn TupleHashLike(comptime security_level: u11, comptime default_delim: u8, compt |
| 482 | 434 | } |
| 483 | 435 | self.cshaker.squeeze(out); |
| 484 | 436 | } |
| 485 | ||
| 486 | pub const Error = error{}; | |
| 487 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 488 | ||
| 489 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 490 | self.update(bytes); | |
| 491 | return bytes.len; | |
| 492 | } | |
| 493 | ||
| 494 | pub fn writer(self: *Self) Writer { | |
| 495 | return .{ .context = self }; | |
| 496 | } | |
| 497 | 437 | }; |
| 498 | 438 | } |
| 499 | 439 |
lib/std/crypto/siphash.zig-12| ... | ... | @@ -238,18 +238,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 238 | 238 | pub fn toInt(msg: []const u8, key: *const [key_length]u8) T { |
| 239 | 239 | return State.hash(msg, key); |
| 240 | 240 | } |
| 241 | ||
| 242 | pub const Error = error{}; | |
| 243 | pub const Writer = std.io.GenericWriter(*Self, Error, write); | |
| 244 | ||
| 245 | fn write(self: *Self, bytes: []const u8) Error!usize { | |
| 246 | self.update(bytes); | |
| 247 | return bytes.len; | |
| 248 | } | |
| 249 | ||
| 250 | pub fn writer(self: *Self) Writer { | |
| 251 | return .{ .context = self }; | |
| 252 | } | |
| 253 | 241 | }; |
| 254 | 242 | } |
| 255 | 243 |
lib/std/debug/Dwarf/expression.zig+101-100| ... | ... | @@ -8,6 +8,8 @@ const OP = std.dwarf.OP; |
| 8 | 8 | const abi = std.debug.Dwarf.abi; |
| 9 | 9 | const mem = std.mem; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | const testing = std.testing; | |
| 12 | const Writer = std.Io.Writer; | |
| 11 | 13 | |
| 12 | 14 | /// Expressions can be evaluated in different contexts, each requiring its own set of inputs. |
| 13 | 15 | /// Callers should specify all the fields relevant to their context. If a field is required |
| ... | ... | @@ -782,7 +784,7 @@ pub fn Builder(comptime options: Options) type { |
| 782 | 784 | |
| 783 | 785 | return struct { |
| 784 | 786 | /// Zero-operand instructions |
| 785 | pub fn writeOpcode(writer: anytype, comptime opcode: u8) !void { | |
| 787 | pub fn writeOpcode(writer: *Writer, comptime opcode: u8) !void { | |
| 786 | 788 | if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode; |
| 787 | 789 | switch (opcode) { |
| 788 | 790 | OP.dup, |
| ... | ... | @@ -823,14 +825,14 @@ pub fn Builder(comptime options: Options) type { |
| 823 | 825 | } |
| 824 | 826 | |
| 825 | 827 | // 2.5.1.1: Literal Encodings |
| 826 | pub fn writeLiteral(writer: anytype, literal: u8) !void { | |
| 828 | pub fn writeLiteral(writer: *Writer, literal: u8) !void { | |
| 827 | 829 | switch (literal) { |
| 828 | 830 | 0...31 => |n| try writer.writeByte(n + OP.lit0), |
| 829 | 831 | else => return error.InvalidLiteral, |
| 830 | 832 | } |
| 831 | 833 | } |
| 832 | 834 | |
| 833 | pub fn writeConst(writer: anytype, comptime T: type, value: T) !void { | |
| 835 | pub fn writeConst(writer: *Writer, comptime T: type, value: T) !void { | |
| 834 | 836 | if (@typeInfo(T) != .int) @compileError("Constants must be integers"); |
| 835 | 837 | |
| 836 | 838 | switch (T) { |
| ... | ... | @@ -852,7 +854,7 @@ pub fn Builder(comptime options: Options) type { |
| 852 | 854 | else => switch (@typeInfo(T).int.signedness) { |
| 853 | 855 | .unsigned => { |
| 854 | 856 | try writer.writeByte(OP.constu); |
| 855 | try leb.writeUleb128(writer, value); | |
| 857 | try writer.writeUleb128(value); | |
| 856 | 858 | }, |
| 857 | 859 | .signed => { |
| 858 | 860 | try writer.writeByte(OP.consts); |
| ... | ... | @@ -862,105 +864,105 @@ pub fn Builder(comptime options: Options) type { |
| 862 | 864 | } |
| 863 | 865 | } |
| 864 | 866 | |
| 865 | pub fn writeConstx(writer: anytype, debug_addr_offset: anytype) !void { | |
| 867 | pub fn writeConstx(writer: *Writer, debug_addr_offset: anytype) !void { | |
| 866 | 868 | try writer.writeByte(OP.constx); |
| 867 | try leb.writeUleb128(writer, debug_addr_offset); | |
| 869 | try writer.writeUleb128(debug_addr_offset); | |
| 868 | 870 | } |
| 869 | 871 | |
| 870 | pub fn writeConstType(writer: anytype, die_offset: anytype, value_bytes: []const u8) !void { | |
| 872 | pub fn writeConstType(writer: *Writer, die_offset: anytype, value_bytes: []const u8) !void { | |
| 871 | 873 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 872 | 874 | if (value_bytes.len > 0xff) return error.InvalidTypeLength; |
| 873 | 875 | try writer.writeByte(OP.const_type); |
| 874 | try leb.writeUleb128(writer, die_offset); | |
| 876 | try writer.writeUleb128(die_offset); | |
| 875 | 877 | try writer.writeByte(@intCast(value_bytes.len)); |
| 876 | 878 | try writer.writeAll(value_bytes); |
| 877 | 879 | } |
| 878 | 880 | |
| 879 | pub fn writeAddr(writer: anytype, value: addr_type) !void { | |
| 881 | pub fn writeAddr(writer: *Writer, value: addr_type) !void { | |
| 880 | 882 | try writer.writeByte(OP.addr); |
| 881 | 883 | try writer.writeInt(addr_type, value, options.endian); |
| 882 | 884 | } |
| 883 | 885 | |
| 884 | pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void { | |
| 886 | pub fn writeAddrx(writer: *Writer, debug_addr_offset: anytype) !void { | |
| 885 | 887 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 886 | 888 | try writer.writeByte(OP.addrx); |
| 887 | try leb.writeUleb128(writer, debug_addr_offset); | |
| 889 | try writer.writeUleb128(debug_addr_offset); | |
| 888 | 890 | } |
| 889 | 891 | |
| 890 | 892 | // 2.5.1.2: Register Values |
| 891 | pub fn writeFbreg(writer: anytype, offset: anytype) !void { | |
| 893 | pub fn writeFbreg(writer: *Writer, offset: anytype) !void { | |
| 892 | 894 | try writer.writeByte(OP.fbreg); |
| 893 | 895 | try leb.writeIleb128(writer, offset); |
| 894 | 896 | } |
| 895 | 897 | |
| 896 | pub fn writeBreg(writer: anytype, register: u8, offset: anytype) !void { | |
| 898 | pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void { | |
| 897 | 899 | if (register > 31) return error.InvalidRegister; |
| 898 | 900 | try writer.writeByte(OP.breg0 + register); |
| 899 | 901 | try leb.writeIleb128(writer, offset); |
| 900 | 902 | } |
| 901 | 903 | |
| 902 | pub fn writeBregx(writer: anytype, register: anytype, offset: anytype) !void { | |
| 904 | pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void { | |
| 903 | 905 | try writer.writeByte(OP.bregx); |
| 904 | try leb.writeUleb128(writer, register); | |
| 906 | try writer.writeUleb128(register); | |
| 905 | 907 | try leb.writeIleb128(writer, offset); |
| 906 | 908 | } |
| 907 | 909 | |
| 908 | pub fn writeRegvalType(writer: anytype, register: anytype, offset: anytype) !void { | |
| 910 | pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void { | |
| 909 | 911 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 910 | 912 | try writer.writeByte(OP.regval_type); |
| 911 | try leb.writeUleb128(writer, register); | |
| 912 | try leb.writeUleb128(writer, offset); | |
| 913 | try writer.writeUleb128(register); | |
| 914 | try writer.writeUleb128(offset); | |
| 913 | 915 | } |
| 914 | 916 | |
| 915 | 917 | // 2.5.1.3: Stack Operations |
| 916 | pub fn writePick(writer: anytype, index: u8) !void { | |
| 918 | pub fn writePick(writer: *Writer, index: u8) !void { | |
| 917 | 919 | try writer.writeByte(OP.pick); |
| 918 | 920 | try writer.writeByte(index); |
| 919 | 921 | } |
| 920 | 922 | |
| 921 | pub fn writeDerefSize(writer: anytype, size: u8) !void { | |
| 923 | pub fn writeDerefSize(writer: *Writer, size: u8) !void { | |
| 922 | 924 | try writer.writeByte(OP.deref_size); |
| 923 | 925 | try writer.writeByte(size); |
| 924 | 926 | } |
| 925 | 927 | |
| 926 | pub fn writeXDerefSize(writer: anytype, size: u8) !void { | |
| 928 | pub fn writeXDerefSize(writer: *Writer, size: u8) !void { | |
| 927 | 929 | try writer.writeByte(OP.xderef_size); |
| 928 | 930 | try writer.writeByte(size); |
| 929 | 931 | } |
| 930 | 932 | |
| 931 | pub fn writeDerefType(writer: anytype, size: u8, die_offset: anytype) !void { | |
| 933 | pub fn writeDerefType(writer: *Writer, size: u8, die_offset: anytype) !void { | |
| 932 | 934 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 933 | 935 | try writer.writeByte(OP.deref_type); |
| 934 | 936 | try writer.writeByte(size); |
| 935 | try leb.writeUleb128(writer, die_offset); | |
| 937 | try writer.writeUleb128(die_offset); | |
| 936 | 938 | } |
| 937 | 939 | |
| 938 | pub fn writeXDerefType(writer: anytype, size: u8, die_offset: anytype) !void { | |
| 940 | pub fn writeXDerefType(writer: *Writer, size: u8, die_offset: anytype) !void { | |
| 939 | 941 | try writer.writeByte(OP.xderef_type); |
| 940 | 942 | try writer.writeByte(size); |
| 941 | try leb.writeUleb128(writer, die_offset); | |
| 943 | try writer.writeUleb128(die_offset); | |
| 942 | 944 | } |
| 943 | 945 | |
| 944 | 946 | // 2.5.1.4: Arithmetic and Logical Operations |
| 945 | 947 | |
| 946 | pub fn writePlusUconst(writer: anytype, uint_value: anytype) !void { | |
| 948 | pub fn writePlusUconst(writer: *Writer, uint_value: anytype) !void { | |
| 947 | 949 | try writer.writeByte(OP.plus_uconst); |
| 948 | try leb.writeUleb128(writer, uint_value); | |
| 950 | try writer.writeUleb128(uint_value); | |
| 949 | 951 | } |
| 950 | 952 | |
| 951 | 953 | // 2.5.1.5: Control Flow Operations |
| 952 | 954 | |
| 953 | pub fn writeSkip(writer: anytype, offset: i16) !void { | |
| 955 | pub fn writeSkip(writer: *Writer, offset: i16) !void { | |
| 954 | 956 | try writer.writeByte(OP.skip); |
| 955 | 957 | try writer.writeInt(i16, offset, options.endian); |
| 956 | 958 | } |
| 957 | 959 | |
| 958 | pub fn writeBra(writer: anytype, offset: i16) !void { | |
| 960 | pub fn writeBra(writer: *Writer, offset: i16) !void { | |
| 959 | 961 | try writer.writeByte(OP.bra); |
| 960 | 962 | try writer.writeInt(i16, offset, options.endian); |
| 961 | 963 | } |
| 962 | 964 | |
| 963 | pub fn writeCall(writer: anytype, comptime T: type, offset: T) !void { | |
| 965 | pub fn writeCall(writer: *Writer, comptime T: type, offset: T) !void { | |
| 964 | 966 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 965 | 967 | switch (T) { |
| 966 | 968 | u16 => try writer.writeByte(OP.call2), |
| ... | ... | @@ -971,45 +973,45 @@ pub fn Builder(comptime options: Options) type { |
| 971 | 973 | try writer.writeInt(T, offset, options.endian); |
| 972 | 974 | } |
| 973 | 975 | |
| 974 | pub fn writeCallRef(writer: anytype, comptime is_64: bool, value: if (is_64) u64 else u32) !void { | |
| 976 | pub fn writeCallRef(writer: *Writer, comptime is_64: bool, value: if (is_64) u64 else u32) !void { | |
| 975 | 977 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 976 | 978 | try writer.writeByte(OP.call_ref); |
| 977 | 979 | try writer.writeInt(if (is_64) u64 else u32, value, options.endian); |
| 978 | 980 | } |
| 979 | 981 | |
| 980 | pub fn writeConvert(writer: anytype, die_offset: anytype) !void { | |
| 982 | pub fn writeConvert(writer: *Writer, die_offset: anytype) !void { | |
| 981 | 983 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 982 | 984 | try writer.writeByte(OP.convert); |
| 983 | try leb.writeUleb128(writer, die_offset); | |
| 985 | try writer.writeUleb128(die_offset); | |
| 984 | 986 | } |
| 985 | 987 | |
| 986 | pub fn writeReinterpret(writer: anytype, die_offset: anytype) !void { | |
| 988 | pub fn writeReinterpret(writer: *Writer, die_offset: anytype) !void { | |
| 987 | 989 | if (options.call_frame_context) return error.InvalidCFAOpcode; |
| 988 | 990 | try writer.writeByte(OP.reinterpret); |
| 989 | try leb.writeUleb128(writer, die_offset); | |
| 991 | try writer.writeUleb128(die_offset); | |
| 990 | 992 | } |
| 991 | 993 | |
| 992 | 994 | // 2.5.1.7: Special Operations |
| 993 | 995 | |
| 994 | pub fn writeEntryValue(writer: anytype, expression: []const u8) !void { | |
| 996 | pub fn writeEntryValue(writer: *Writer, expression: []const u8) !void { | |
| 995 | 997 | try writer.writeByte(OP.entry_value); |
| 996 | try leb.writeUleb128(writer, expression.len); | |
| 998 | try writer.writeUleb128(expression.len); | |
| 997 | 999 | try writer.writeAll(expression); |
| 998 | 1000 | } |
| 999 | 1001 | |
| 1000 | 1002 | // 2.6: Location Descriptions |
| 1001 | pub fn writeReg(writer: anytype, register: u8) !void { | |
| 1003 | pub fn writeReg(writer: *Writer, register: u8) !void { | |
| 1002 | 1004 | try writer.writeByte(OP.reg0 + register); |
| 1003 | 1005 | } |
| 1004 | 1006 | |
| 1005 | pub fn writeRegx(writer: anytype, register: anytype) !void { | |
| 1007 | pub fn writeRegx(writer: *Writer, register: anytype) !void { | |
| 1006 | 1008 | try writer.writeByte(OP.regx); |
| 1007 | try leb.writeUleb128(writer, register); | |
| 1009 | try writer.writeUleb128(register); | |
| 1008 | 1010 | } |
| 1009 | 1011 | |
| 1010 | pub fn writeImplicitValue(writer: anytype, value_bytes: []const u8) !void { | |
| 1012 | pub fn writeImplicitValue(writer: *Writer, value_bytes: []const u8) !void { | |
| 1011 | 1013 | try writer.writeByte(OP.implicit_value); |
| 1012 | try leb.writeUleb128(writer, value_bytes.len); | |
| 1014 | try writer.writeUleb128(value_bytes.len); | |
| 1013 | 1015 | try writer.writeAll(value_bytes); |
| 1014 | 1016 | } |
| 1015 | 1017 | }; |
| ... | ... | @@ -1042,8 +1044,7 @@ fn isOpcodeRegisterLocation(opcode: u8) bool { |
| 1042 | 1044 | }; |
| 1043 | 1045 | } |
| 1044 | 1046 | |
| 1045 | const testing = std.testing; | |
| 1046 | test "DWARF expressions" { | |
| 1047 | test "basics" { | |
| 1047 | 1048 | const allocator = std.testing.allocator; |
| 1048 | 1049 | |
| 1049 | 1050 | const options = Options{}; |
| ... | ... | @@ -1052,10 +1053,10 @@ test "DWARF expressions" { |
| 1052 | 1053 | |
| 1053 | 1054 | const b = Builder(options); |
| 1054 | 1055 | |
| 1055 | var program = std.array_list.Managed(u8).init(allocator); | |
| 1056 | var program: std.Io.Writer.Allocating = .init(allocator); | |
| 1056 | 1057 | defer program.deinit(); |
| 1057 | 1058 | |
| 1058 | const writer = program.writer(); | |
| 1059 | const writer = &program.writer; | |
| 1059 | 1060 | |
| 1060 | 1061 | // Literals |
| 1061 | 1062 | { |
| ... | ... | @@ -1064,7 +1065,7 @@ test "DWARF expressions" { |
| 1064 | 1065 | try b.writeLiteral(writer, @intCast(i)); |
| 1065 | 1066 | } |
| 1066 | 1067 | |
| 1067 | _ = try stack_machine.run(program.items, allocator, context, 0); | |
| 1068 | _ = try stack_machine.run(program.written(), allocator, context, 0); | |
| 1068 | 1069 | |
| 1069 | 1070 | for (0..32) |i| { |
| 1070 | 1071 | const expected = 31 - i; |
| ... | ... | @@ -1108,16 +1109,16 @@ test "DWARF expressions" { |
| 1108 | 1109 | var mock_compile_unit: std.debug.Dwarf.CompileUnit = undefined; |
| 1109 | 1110 | mock_compile_unit.addr_base = 1; |
| 1110 | 1111 | |
| 1111 | var mock_debug_addr = std.array_list.Managed(u8).init(allocator); | |
| 1112 | var mock_debug_addr: std.Io.Writer.Allocating = .init(allocator); | |
| 1112 | 1113 | defer mock_debug_addr.deinit(); |
| 1113 | 1114 | |
| 1114 | try mock_debug_addr.writer().writeInt(u16, 0, native_endian); | |
| 1115 | try mock_debug_addr.writer().writeInt(usize, input[11], native_endian); | |
| 1116 | try mock_debug_addr.writer().writeInt(usize, input[12], native_endian); | |
| 1115 | try mock_debug_addr.writer.writeInt(u16, 0, native_endian); | |
| 1116 | try mock_debug_addr.writer.writeInt(usize, input[11], native_endian); | |
| 1117 | try mock_debug_addr.writer.writeInt(usize, input[12], native_endian); | |
| 1117 | 1118 | |
| 1118 | const context = Context{ | |
| 1119 | const context: Context = .{ | |
| 1119 | 1120 | .compile_unit = &mock_compile_unit, |
| 1120 | .debug_addr = mock_debug_addr.items, | |
| 1121 | .debug_addr = mock_debug_addr.written(), | |
| 1121 | 1122 | }; |
| 1122 | 1123 | |
| 1123 | 1124 | try b.writeConstx(writer, @as(usize, 1)); |
| ... | ... | @@ -1127,7 +1128,7 @@ test "DWARF expressions" { |
| 1127 | 1128 | const type_bytes: []const u8 = &.{ 1, 2, 3, 4 }; |
| 1128 | 1129 | try b.writeConstType(writer, die_offset, type_bytes); |
| 1129 | 1130 | |
| 1130 | _ = try stack_machine.run(program.items, allocator, context, 0); | |
| 1131 | _ = try stack_machine.run(program.written(), allocator, context, 0); | |
| 1131 | 1132 | |
| 1132 | 1133 | const const_type = stack_machine.stack.pop().?.const_type; |
| 1133 | 1134 | try testing.expectEqual(die_offset, const_type.type_offset); |
| ... | ... | @@ -1185,7 +1186,7 @@ test "DWARF expressions" { |
| 1185 | 1186 | try b.writeBregx(writer, abi.ipRegNum(native_arch).?, @as(usize, 300)); |
| 1186 | 1187 | try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400)); |
| 1187 | 1188 | |
| 1188 | _ = try stack_machine.run(program.items, allocator, context, 0); | |
| 1189 | _ = try stack_machine.run(program.written(), allocator, context, 0); | |
| 1189 | 1190 | |
| 1190 | 1191 | const regval_type = stack_machine.stack.pop().?.regval_type; |
| 1191 | 1192 | try testing.expectEqual(@as(usize, 400), regval_type.type_offset); |
| ... | ... | @@ -1214,7 +1215,7 @@ test "DWARF expressions" { |
| 1214 | 1215 | program.clearRetainingCapacity(); |
| 1215 | 1216 | try b.writeConst(writer, u8, 1); |
| 1216 | 1217 | try b.writeOpcode(writer, OP.dup); |
| 1217 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1218 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1218 | 1219 | try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic); |
| 1219 | 1220 | try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic); |
| 1220 | 1221 | |
| ... | ... | @@ -1222,7 +1223,7 @@ test "DWARF expressions" { |
| 1222 | 1223 | program.clearRetainingCapacity(); |
| 1223 | 1224 | try b.writeConst(writer, u8, 1); |
| 1224 | 1225 | try b.writeOpcode(writer, OP.drop); |
| 1225 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1226 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1226 | 1227 | try testing.expect(stack_machine.stack.pop() == null); |
| 1227 | 1228 | |
| 1228 | 1229 | stack_machine.reset(); |
| ... | ... | @@ -1231,7 +1232,7 @@ test "DWARF expressions" { |
| 1231 | 1232 | try b.writeConst(writer, u8, 5); |
| 1232 | 1233 | try b.writeConst(writer, u8, 6); |
| 1233 | 1234 | try b.writePick(writer, 2); |
| 1234 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1235 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1235 | 1236 | try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic); |
| 1236 | 1237 | |
| 1237 | 1238 | stack_machine.reset(); |
| ... | ... | @@ -1240,7 +1241,7 @@ test "DWARF expressions" { |
| 1240 | 1241 | try b.writeConst(writer, u8, 5); |
| 1241 | 1242 | try b.writeConst(writer, u8, 6); |
| 1242 | 1243 | try b.writeOpcode(writer, OP.over); |
| 1243 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1244 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1244 | 1245 | try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic); |
| 1245 | 1246 | |
| 1246 | 1247 | stack_machine.reset(); |
| ... | ... | @@ -1248,7 +1249,7 @@ test "DWARF expressions" { |
| 1248 | 1249 | try b.writeConst(writer, u8, 5); |
| 1249 | 1250 | try b.writeConst(writer, u8, 6); |
| 1250 | 1251 | try b.writeOpcode(writer, OP.swap); |
| 1251 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1252 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1252 | 1253 | try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic); |
| 1253 | 1254 | try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic); |
| 1254 | 1255 | |
| ... | ... | @@ -1258,7 +1259,7 @@ test "DWARF expressions" { |
| 1258 | 1259 | try b.writeConst(writer, u8, 5); |
| 1259 | 1260 | try b.writeConst(writer, u8, 6); |
| 1260 | 1261 | try b.writeOpcode(writer, OP.rot); |
| 1261 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1262 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1262 | 1263 | try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic); |
| 1263 | 1264 | try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic); |
| 1264 | 1265 | try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic); |
| ... | ... | @@ -1269,7 +1270,7 @@ test "DWARF expressions" { |
| 1269 | 1270 | program.clearRetainingCapacity(); |
| 1270 | 1271 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1271 | 1272 | try b.writeOpcode(writer, OP.deref); |
| 1272 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1273 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1273 | 1274 | try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic); |
| 1274 | 1275 | |
| 1275 | 1276 | stack_machine.reset(); |
| ... | ... | @@ -1277,14 +1278,14 @@ test "DWARF expressions" { |
| 1277 | 1278 | try b.writeLiteral(writer, 0); |
| 1278 | 1279 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1279 | 1280 | try b.writeOpcode(writer, OP.xderef); |
| 1280 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1281 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1281 | 1282 | try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic); |
| 1282 | 1283 | |
| 1283 | 1284 | stack_machine.reset(); |
| 1284 | 1285 | program.clearRetainingCapacity(); |
| 1285 | 1286 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1286 | 1287 | try b.writeDerefSize(writer, 1); |
| 1287 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1288 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1288 | 1289 | try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic); |
| 1289 | 1290 | |
| 1290 | 1291 | stack_machine.reset(); |
| ... | ... | @@ -1292,7 +1293,7 @@ test "DWARF expressions" { |
| 1292 | 1293 | try b.writeLiteral(writer, 0); |
| 1293 | 1294 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1294 | 1295 | try b.writeXDerefSize(writer, 1); |
| 1295 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1296 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1296 | 1297 | try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic); |
| 1297 | 1298 | |
| 1298 | 1299 | const type_offset: usize = @truncate(0xaabbaabb_aabbaabb); |
| ... | ... | @@ -1301,7 +1302,7 @@ test "DWARF expressions" { |
| 1301 | 1302 | program.clearRetainingCapacity(); |
| 1302 | 1303 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1303 | 1304 | try b.writeDerefType(writer, 1, type_offset); |
| 1304 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1305 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1305 | 1306 | const deref_type = stack_machine.stack.pop().?.regval_type; |
| 1306 | 1307 | try testing.expectEqual(type_offset, deref_type.type_offset); |
| 1307 | 1308 | try testing.expectEqual(@as(u8, 1), deref_type.type_size); |
| ... | ... | @@ -1312,7 +1313,7 @@ test "DWARF expressions" { |
| 1312 | 1313 | try b.writeLiteral(writer, 0); |
| 1313 | 1314 | try b.writeAddr(writer, @intFromPtr(&deref_target)); |
| 1314 | 1315 | try b.writeXDerefType(writer, 1, type_offset); |
| 1315 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1316 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1316 | 1317 | const xderef_type = stack_machine.stack.pop().?.regval_type; |
| 1317 | 1318 | try testing.expectEqual(type_offset, xderef_type.type_offset); |
| 1318 | 1319 | try testing.expectEqual(@as(u8, 1), xderef_type.type_size); |
| ... | ... | @@ -1323,7 +1324,7 @@ test "DWARF expressions" { |
| 1323 | 1324 | stack_machine.reset(); |
| 1324 | 1325 | program.clearRetainingCapacity(); |
| 1325 | 1326 | try b.writeOpcode(writer, OP.push_object_address); |
| 1326 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1327 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1327 | 1328 | try testing.expectEqual(@as(usize, @intFromPtr(context.object_address.?)), stack_machine.stack.pop().?.generic); |
| 1328 | 1329 | |
| 1329 | 1330 | // TODO: Test OP.form_tls_address |
| ... | ... | @@ -1333,7 +1334,7 @@ test "DWARF expressions" { |
| 1333 | 1334 | stack_machine.reset(); |
| 1334 | 1335 | program.clearRetainingCapacity(); |
| 1335 | 1336 | try b.writeOpcode(writer, OP.call_frame_cfa); |
| 1336 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1337 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1337 | 1338 | try testing.expectEqual(context.cfa.?, stack_machine.stack.pop().?.generic); |
| 1338 | 1339 | } |
| 1339 | 1340 | |
| ... | ... | @@ -1345,7 +1346,7 @@ test "DWARF expressions" { |
| 1345 | 1346 | program.clearRetainingCapacity(); |
| 1346 | 1347 | try b.writeConst(writer, i16, -4096); |
| 1347 | 1348 | try b.writeOpcode(writer, OP.abs); |
| 1348 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1349 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1349 | 1350 | try testing.expectEqual(@as(usize, 4096), stack_machine.stack.pop().?.generic); |
| 1350 | 1351 | |
| 1351 | 1352 | stack_machine.reset(); |
| ... | ... | @@ -1353,7 +1354,7 @@ test "DWARF expressions" { |
| 1353 | 1354 | try b.writeConst(writer, u16, 0xff0f); |
| 1354 | 1355 | try b.writeConst(writer, u16, 0xf0ff); |
| 1355 | 1356 | try b.writeOpcode(writer, OP.@"and"); |
| 1356 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1357 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1357 | 1358 | try testing.expectEqual(@as(usize, 0xf00f), stack_machine.stack.pop().?.generic); |
| 1358 | 1359 | |
| 1359 | 1360 | stack_machine.reset(); |
| ... | ... | @@ -1361,7 +1362,7 @@ test "DWARF expressions" { |
| 1361 | 1362 | try b.writeConst(writer, i16, -404); |
| 1362 | 1363 | try b.writeConst(writer, i16, 100); |
| 1363 | 1364 | try b.writeOpcode(writer, OP.div); |
| 1364 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1365 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1365 | 1366 | try testing.expectEqual(@as(isize, -404 / 100), @as(isize, @bitCast(stack_machine.stack.pop().?.generic))); |
| 1366 | 1367 | |
| 1367 | 1368 | stack_machine.reset(); |
| ... | ... | @@ -1369,7 +1370,7 @@ test "DWARF expressions" { |
| 1369 | 1370 | try b.writeConst(writer, u16, 200); |
| 1370 | 1371 | try b.writeConst(writer, u16, 50); |
| 1371 | 1372 | try b.writeOpcode(writer, OP.minus); |
| 1372 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1373 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1373 | 1374 | try testing.expectEqual(@as(usize, 150), stack_machine.stack.pop().?.generic); |
| 1374 | 1375 | |
| 1375 | 1376 | stack_machine.reset(); |
| ... | ... | @@ -1377,7 +1378,7 @@ test "DWARF expressions" { |
| 1377 | 1378 | try b.writeConst(writer, u16, 123); |
| 1378 | 1379 | try b.writeConst(writer, u16, 100); |
| 1379 | 1380 | try b.writeOpcode(writer, OP.mod); |
| 1380 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1381 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1381 | 1382 | try testing.expectEqual(@as(usize, 23), stack_machine.stack.pop().?.generic); |
| 1382 | 1383 | |
| 1383 | 1384 | stack_machine.reset(); |
| ... | ... | @@ -1385,7 +1386,7 @@ test "DWARF expressions" { |
| 1385 | 1386 | try b.writeConst(writer, u16, 0xff); |
| 1386 | 1387 | try b.writeConst(writer, u16, 0xee); |
| 1387 | 1388 | try b.writeOpcode(writer, OP.mul); |
| 1388 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1389 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1389 | 1390 | try testing.expectEqual(@as(usize, 0xed12), stack_machine.stack.pop().?.generic); |
| 1390 | 1391 | |
| 1391 | 1392 | stack_machine.reset(); |
| ... | ... | @@ -1394,7 +1395,7 @@ test "DWARF expressions" { |
| 1394 | 1395 | try b.writeOpcode(writer, OP.neg); |
| 1395 | 1396 | try b.writeConst(writer, i16, -6); |
| 1396 | 1397 | try b.writeOpcode(writer, OP.neg); |
| 1397 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1398 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1398 | 1399 | try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic); |
| 1399 | 1400 | try testing.expectEqual(@as(isize, -5), @as(isize, @bitCast(stack_machine.stack.pop().?.generic))); |
| 1400 | 1401 | |
| ... | ... | @@ -1402,7 +1403,7 @@ test "DWARF expressions" { |
| 1402 | 1403 | program.clearRetainingCapacity(); |
| 1403 | 1404 | try b.writeConst(writer, u16, 0xff0f); |
| 1404 | 1405 | try b.writeOpcode(writer, OP.not); |
| 1405 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1406 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1406 | 1407 | try testing.expectEqual(~@as(usize, 0xff0f), stack_machine.stack.pop().?.generic); |
| 1407 | 1408 | |
| 1408 | 1409 | stack_machine.reset(); |
| ... | ... | @@ -1410,7 +1411,7 @@ test "DWARF expressions" { |
| 1410 | 1411 | try b.writeConst(writer, u16, 0xff0f); |
| 1411 | 1412 | try b.writeConst(writer, u16, 0xf0ff); |
| 1412 | 1413 | try b.writeOpcode(writer, OP.@"or"); |
| 1413 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1414 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1414 | 1415 | try testing.expectEqual(@as(usize, 0xffff), stack_machine.stack.pop().?.generic); |
| 1415 | 1416 | |
| 1416 | 1417 | stack_machine.reset(); |
| ... | ... | @@ -1418,14 +1419,14 @@ test "DWARF expressions" { |
| 1418 | 1419 | try b.writeConst(writer, i16, 402); |
| 1419 | 1420 | try b.writeConst(writer, i16, 100); |
| 1420 | 1421 | try b.writeOpcode(writer, OP.plus); |
| 1421 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1422 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1422 | 1423 | try testing.expectEqual(@as(usize, 502), stack_machine.stack.pop().?.generic); |
| 1423 | 1424 | |
| 1424 | 1425 | stack_machine.reset(); |
| 1425 | 1426 | program.clearRetainingCapacity(); |
| 1426 | 1427 | try b.writeConst(writer, u16, 4096); |
| 1427 | 1428 | try b.writePlusUconst(writer, @as(usize, 8192)); |
| 1428 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1429 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1429 | 1430 | try testing.expectEqual(@as(usize, 4096 + 8192), stack_machine.stack.pop().?.generic); |
| 1430 | 1431 | |
| 1431 | 1432 | stack_machine.reset(); |
| ... | ... | @@ -1433,7 +1434,7 @@ test "DWARF expressions" { |
| 1433 | 1434 | try b.writeConst(writer, u16, 0xfff); |
| 1434 | 1435 | try b.writeConst(writer, u16, 1); |
| 1435 | 1436 | try b.writeOpcode(writer, OP.shl); |
| 1436 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1437 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1437 | 1438 | try testing.expectEqual(@as(usize, 0xfff << 1), stack_machine.stack.pop().?.generic); |
| 1438 | 1439 | |
| 1439 | 1440 | stack_machine.reset(); |
| ... | ... | @@ -1441,7 +1442,7 @@ test "DWARF expressions" { |
| 1441 | 1442 | try b.writeConst(writer, u16, 0xfff); |
| 1442 | 1443 | try b.writeConst(writer, u16, 1); |
| 1443 | 1444 | try b.writeOpcode(writer, OP.shr); |
| 1444 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1445 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1445 | 1446 | try testing.expectEqual(@as(usize, 0xfff >> 1), stack_machine.stack.pop().?.generic); |
| 1446 | 1447 | |
| 1447 | 1448 | stack_machine.reset(); |
| ... | ... | @@ -1449,7 +1450,7 @@ test "DWARF expressions" { |
| 1449 | 1450 | try b.writeConst(writer, u16, 0xfff); |
| 1450 | 1451 | try b.writeConst(writer, u16, 1); |
| 1451 | 1452 | try b.writeOpcode(writer, OP.shr); |
| 1452 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1453 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1453 | 1454 | try testing.expectEqual(@as(usize, @bitCast(@as(isize, 0xfff) >> 1)), stack_machine.stack.pop().?.generic); |
| 1454 | 1455 | |
| 1455 | 1456 | stack_machine.reset(); |
| ... | ... | @@ -1457,7 +1458,7 @@ test "DWARF expressions" { |
| 1457 | 1458 | try b.writeConst(writer, u16, 0xf0ff); |
| 1458 | 1459 | try b.writeConst(writer, u16, 0xff0f); |
| 1459 | 1460 | try b.writeOpcode(writer, OP.xor); |
| 1460 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1461 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1461 | 1462 | try testing.expectEqual(@as(usize, 0x0ff0), stack_machine.stack.pop().?.generic); |
| 1462 | 1463 | } |
| 1463 | 1464 | |
| ... | ... | @@ -1486,7 +1487,7 @@ test "DWARF expressions" { |
| 1486 | 1487 | try b.writeConst(writer, u16, 1); |
| 1487 | 1488 | try b.writeConst(writer, u16, 0); |
| 1488 | 1489 | try b.writeOpcode(writer, e[0]); |
| 1489 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1490 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1490 | 1491 | try testing.expectEqual(@as(usize, e[3]), stack_machine.stack.pop().?.generic); |
| 1491 | 1492 | try testing.expectEqual(@as(usize, e[2]), stack_machine.stack.pop().?.generic); |
| 1492 | 1493 | try testing.expectEqual(@as(usize, e[1]), stack_machine.stack.pop().?.generic); |
| ... | ... | @@ -1497,7 +1498,7 @@ test "DWARF expressions" { |
| 1497 | 1498 | try b.writeLiteral(writer, 2); |
| 1498 | 1499 | try b.writeSkip(writer, 1); |
| 1499 | 1500 | try b.writeLiteral(writer, 3); |
| 1500 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1501 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1501 | 1502 | try testing.expectEqual(@as(usize, 2), stack_machine.stack.pop().?.generic); |
| 1502 | 1503 | |
| 1503 | 1504 | stack_machine.reset(); |
| ... | ... | @@ -1509,7 +1510,7 @@ test "DWARF expressions" { |
| 1509 | 1510 | try b.writeBra(writer, 1); |
| 1510 | 1511 | try b.writeLiteral(writer, 4); |
| 1511 | 1512 | try b.writeLiteral(writer, 5); |
| 1512 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1513 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1513 | 1514 | try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic); |
| 1514 | 1515 | try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic); |
| 1515 | 1516 | try testing.expect(stack_machine.stack.pop() == null); |
| ... | ... | @@ -1535,7 +1536,7 @@ test "DWARF expressions" { |
| 1535 | 1536 | program.clearRetainingCapacity(); |
| 1536 | 1537 | try b.writeConstType(writer, @as(usize, 0), &value_bytes); |
| 1537 | 1538 | try b.writeConvert(writer, @as(usize, 0)); |
| 1538 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1539 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1539 | 1540 | try testing.expectEqual(value, stack_machine.stack.pop().?.generic); |
| 1540 | 1541 | |
| 1541 | 1542 | // Reinterpret to generic type |
| ... | ... | @@ -1543,7 +1544,7 @@ test "DWARF expressions" { |
| 1543 | 1544 | program.clearRetainingCapacity(); |
| 1544 | 1545 | try b.writeConstType(writer, @as(usize, 0), &value_bytes); |
| 1545 | 1546 | try b.writeReinterpret(writer, @as(usize, 0)); |
| 1546 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1547 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1547 | 1548 | try testing.expectEqual(value, stack_machine.stack.pop().?.generic); |
| 1548 | 1549 | |
| 1549 | 1550 | // Reinterpret to new type |
| ... | ... | @@ -1553,7 +1554,7 @@ test "DWARF expressions" { |
| 1553 | 1554 | program.clearRetainingCapacity(); |
| 1554 | 1555 | try b.writeConstType(writer, @as(usize, 0), &value_bytes); |
| 1555 | 1556 | try b.writeReinterpret(writer, die_offset); |
| 1556 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1557 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1557 | 1558 | const const_type = stack_machine.stack.pop().?.const_type; |
| 1558 | 1559 | try testing.expectEqual(die_offset, const_type.type_offset); |
| 1559 | 1560 | |
| ... | ... | @@ -1561,7 +1562,7 @@ test "DWARF expressions" { |
| 1561 | 1562 | program.clearRetainingCapacity(); |
| 1562 | 1563 | try b.writeLiteral(writer, 0); |
| 1563 | 1564 | try b.writeReinterpret(writer, die_offset); |
| 1564 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1565 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1565 | 1566 | const regval_type = stack_machine.stack.pop().?.regval_type; |
| 1566 | 1567 | try testing.expectEqual(die_offset, regval_type.type_offset); |
| 1567 | 1568 | } |
| ... | ... | @@ -1573,20 +1574,20 @@ test "DWARF expressions" { |
| 1573 | 1574 | stack_machine.reset(); |
| 1574 | 1575 | program.clearRetainingCapacity(); |
| 1575 | 1576 | try b.writeOpcode(writer, OP.nop); |
| 1576 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1577 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1577 | 1578 | try testing.expect(stack_machine.stack.pop() == null); |
| 1578 | 1579 | |
| 1579 | 1580 | // Sub-expression |
| 1580 | 1581 | { |
| 1581 | var sub_program = std.array_list.Managed(u8).init(allocator); | |
| 1582 | var sub_program: std.Io.Writer.Allocating = .init(allocator); | |
| 1582 | 1583 | defer sub_program.deinit(); |
| 1583 | const sub_writer = sub_program.writer(); | |
| 1584 | const sub_writer = &sub_program.writer; | |
| 1584 | 1585 | try b.writeLiteral(sub_writer, 3); |
| 1585 | 1586 | |
| 1586 | 1587 | stack_machine.reset(); |
| 1587 | 1588 | program.clearRetainingCapacity(); |
| 1588 | try b.writeEntryValue(writer, sub_program.items); | |
| 1589 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1589 | try b.writeEntryValue(writer, sub_program.written()); | |
| 1590 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1590 | 1591 | try testing.expectEqual(@as(usize, 3), stack_machine.stack.pop().?.generic); |
| 1591 | 1592 | } |
| 1592 | 1593 | |
| ... | ... | @@ -1605,15 +1606,15 @@ test "DWARF expressions" { |
| 1605 | 1606 | if (abi.regBytes(&thread_context, 0, reg_context)) |reg_bytes| { |
| 1606 | 1607 | mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian); |
| 1607 | 1608 | |
| 1608 | var sub_program = std.array_list.Managed(u8).init(allocator); | |
| 1609 | var sub_program: std.Io.Writer.Allocating = .init(allocator); | |
| 1609 | 1610 | defer sub_program.deinit(); |
| 1610 | const sub_writer = sub_program.writer(); | |
| 1611 | const sub_writer = &sub_program.writer; | |
| 1611 | 1612 | try b.writeReg(sub_writer, 0); |
| 1612 | 1613 | |
| 1613 | 1614 | stack_machine.reset(); |
| 1614 | 1615 | program.clearRetainingCapacity(); |
| 1615 | try b.writeEntryValue(writer, sub_program.items); | |
| 1616 | _ = try stack_machine.run(program.items, allocator, context, null); | |
| 1616 | try b.writeEntryValue(writer, sub_program.written()); | |
| 1617 | _ = try stack_machine.run(program.written(), allocator, context, null); | |
| 1617 | 1618 | try testing.expectEqual(@as(usize, 0xee), stack_machine.stack.pop().?.generic); |
| 1618 | 1619 | } else |err| { |
| 1619 | 1620 | switch (err) { |
lib/std/debug/Pdb.zig+185-158| ... | ... | @@ -2,10 +2,11 @@ const std = @import("../std.zig"); |
| 2 | 2 | const File = std.fs.File; |
| 3 | 3 | const Allocator = std.mem.Allocator; |
| 4 | 4 | const pdb = std.pdb; |
| 5 | const assert = std.debug.assert; | |
| 5 | 6 | |
| 6 | 7 | const Pdb = @This(); |
| 7 | 8 | |
| 8 | in_file: File, | |
| 9 | file_reader: *File.Reader, | |
| 9 | 10 | msf: Msf, |
| 10 | 11 | allocator: Allocator, |
| 11 | 12 | string_table: ?*MsfStream, |
| ... | ... | @@ -35,39 +36,38 @@ pub const Module = struct { |
| 35 | 36 | } |
| 36 | 37 | }; |
| 37 | 38 | |
| 38 | pub fn init(allocator: Allocator, path: []const u8) !Pdb { | |
| 39 | const file = try std.fs.cwd().openFile(path, .{}); | |
| 40 | errdefer file.close(); | |
| 41 | ||
| 39 | pub fn init(gpa: Allocator, file_reader: *File.Reader) !Pdb { | |
| 42 | 40 | return .{ |
| 43 | .in_file = file, | |
| 44 | .allocator = allocator, | |
| 41 | .file_reader = file_reader, | |
| 42 | .allocator = gpa, | |
| 45 | 43 | .string_table = null, |
| 46 | 44 | .dbi = null, |
| 47 | .msf = try Msf.init(allocator, file), | |
| 48 | .modules = &[_]Module{}, | |
| 49 | .sect_contribs = &[_]pdb.SectionContribEntry{}, | |
| 45 | .msf = try Msf.init(gpa, file_reader), | |
| 46 | .modules = &.{}, | |
| 47 | .sect_contribs = &.{}, | |
| 50 | 48 | .guid = undefined, |
| 51 | 49 | .age = undefined, |
| 52 | 50 | }; |
| 53 | 51 | } |
| 54 | 52 | |
| 55 | 53 | pub fn deinit(self: *Pdb) void { |
| 56 | self.in_file.close(); | |
| 57 | self.msf.deinit(self.allocator); | |
| 54 | const gpa = self.allocator; | |
| 55 | self.msf.deinit(gpa); | |
| 58 | 56 | for (self.modules) |*module| { |
| 59 | module.deinit(self.allocator); | |
| 57 | module.deinit(gpa); | |
| 60 | 58 | } |
| 61 | self.allocator.free(self.modules); | |
| 62 | self.allocator.free(self.sect_contribs); | |
| 59 | gpa.free(self.modules); | |
| 60 | gpa.free(self.sect_contribs); | |
| 63 | 61 | } |
| 64 | 62 | |
| 65 | 63 | pub fn parseDbiStream(self: *Pdb) !void { |
| 66 | 64 | var stream = self.getStream(pdb.StreamType.dbi) orelse |
| 67 | 65 | return error.InvalidDebugInfo; |
| 68 | const reader = stream.reader(); | |
| 69 | 66 | |
| 70 | const header = try reader.readStruct(std.pdb.DbiStreamHeader); | |
| 67 | const gpa = self.allocator; | |
| 68 | const reader = &stream.interface; | |
| 69 | ||
| 70 | const header = try reader.takeStruct(std.pdb.DbiStreamHeader, .little); | |
| 71 | 71 | if (header.version_header != 19990903) // V70, only value observed by LLVM team |
| 72 | 72 | return error.UnknownPDBVersion; |
| 73 | 73 | // if (header.Age != age) |
| ... | ... | @@ -76,22 +76,28 @@ pub fn parseDbiStream(self: *Pdb) !void { |
| 76 | 76 | const mod_info_size = header.mod_info_size; |
| 77 | 77 | const section_contrib_size = header.section_contribution_size; |
| 78 | 78 | |
| 79 | var modules = std.array_list.Managed(Module).init(self.allocator); | |
| 79 | var modules = std.array_list.Managed(Module).init(gpa); | |
| 80 | 80 | errdefer modules.deinit(); |
| 81 | 81 | |
| 82 | 82 | // Module Info Substream |
| 83 | 83 | var mod_info_offset: usize = 0; |
| 84 | 84 | while (mod_info_offset != mod_info_size) { |
| 85 | const mod_info = try reader.readStruct(pdb.ModInfo); | |
| 85 | const mod_info = try reader.takeStruct(pdb.ModInfo, .little); | |
| 86 | 86 | var this_record_len: usize = @sizeOf(pdb.ModInfo); |
| 87 | 87 | |
| 88 | const module_name = try reader.readUntilDelimiterAlloc(self.allocator, 0, 1024); | |
| 89 | errdefer self.allocator.free(module_name); | |
| 90 | this_record_len += module_name.len + 1; | |
| 88 | var module_name: std.Io.Writer.Allocating = .init(gpa); | |
| 89 | defer module_name.deinit(); | |
| 90 | this_record_len += try reader.streamDelimiterLimit(&module_name.writer, 0, .limited(1024)); | |
| 91 | assert(reader.buffered()[0] == 0); // TODO change streamDelimiterLimit API | |
| 92 | reader.toss(1); | |
| 93 | this_record_len += 1; | |
| 91 | 94 | |
| 92 | const obj_file_name = try reader.readUntilDelimiterAlloc(self.allocator, 0, 1024); | |
| 93 | errdefer self.allocator.free(obj_file_name); | |
| 94 | this_record_len += obj_file_name.len + 1; | |
| 95 | var obj_file_name: std.Io.Writer.Allocating = .init(gpa); | |
| 96 | defer obj_file_name.deinit(); | |
| 97 | this_record_len += try reader.streamDelimiterLimit(&obj_file_name.writer, 0, .limited(1024)); | |
| 98 | assert(reader.buffered()[0] == 0); // TODO change streamDelimiterLimit API | |
| 99 | reader.toss(1); | |
| 100 | this_record_len += 1; | |
| 95 | 101 | |
| 96 | 102 | if (this_record_len % 4 != 0) { |
| 97 | 103 | const round_to_next_4 = (this_record_len | 0x3) + 1; |
| ... | ... | @@ -100,10 +106,10 @@ pub fn parseDbiStream(self: *Pdb) !void { |
| 100 | 106 | this_record_len += march_forward_bytes; |
| 101 | 107 | } |
| 102 | 108 | |
| 103 | try modules.append(Module{ | |
| 109 | try modules.append(.{ | |
| 104 | 110 | .mod_info = mod_info, |
| 105 | .module_name = module_name, | |
| 106 | .obj_file_name = obj_file_name, | |
| 111 | .module_name = try module_name.toOwnedSlice(), | |
| 112 | .obj_file_name = try obj_file_name.toOwnedSlice(), | |
| 107 | 113 | |
| 108 | 114 | .populated = false, |
| 109 | 115 | .symbols = undefined, |
| ... | ... | @@ -117,21 +123,21 @@ pub fn parseDbiStream(self: *Pdb) !void { |
| 117 | 123 | } |
| 118 | 124 | |
| 119 | 125 | // Section Contribution Substream |
| 120 | var sect_contribs = std.array_list.Managed(pdb.SectionContribEntry).init(self.allocator); | |
| 126 | var sect_contribs = std.array_list.Managed(pdb.SectionContribEntry).init(gpa); | |
| 121 | 127 | errdefer sect_contribs.deinit(); |
| 122 | 128 | |
| 123 | 129 | var sect_cont_offset: usize = 0; |
| 124 | 130 | if (section_contrib_size != 0) { |
| 125 | const version = reader.readEnum(std.pdb.SectionContrSubstreamVersion, .little) catch |err| switch (err) { | |
| 126 | error.InvalidValue => return error.InvalidDebugInfo, | |
| 127 | else => |e| return e, | |
| 131 | const version = reader.takeEnum(std.pdb.SectionContrSubstreamVersion, .little) catch |err| switch (err) { | |
| 132 | error.InvalidEnumTag, error.EndOfStream => return error.InvalidDebugInfo, | |
| 133 | error.ReadFailed => return error.ReadFailed, | |
| 128 | 134 | }; |
| 129 | 135 | _ = version; |
| 130 | 136 | sect_cont_offset += @sizeOf(u32); |
| 131 | 137 | } |
| 132 | 138 | while (sect_cont_offset != section_contrib_size) { |
| 133 | 139 | const entry = try sect_contribs.addOne(); |
| 134 | entry.* = try reader.readStruct(pdb.SectionContribEntry); | |
| 140 | entry.* = try reader.takeStruct(pdb.SectionContribEntry, .little); | |
| 135 | 141 | sect_cont_offset += @sizeOf(pdb.SectionContribEntry); |
| 136 | 142 | |
| 137 | 143 | if (sect_cont_offset > section_contrib_size) |
| ... | ... | @@ -143,29 +149,28 @@ pub fn parseDbiStream(self: *Pdb) !void { |
| 143 | 149 | } |
| 144 | 150 | |
| 145 | 151 | pub fn parseInfoStream(self: *Pdb) !void { |
| 146 | var stream = self.getStream(pdb.StreamType.pdb) orelse | |
| 147 | return error.InvalidDebugInfo; | |
| 148 | const reader = stream.reader(); | |
| 152 | var stream = self.getStream(pdb.StreamType.pdb) orelse return error.InvalidDebugInfo; | |
| 153 | const reader = &stream.interface; | |
| 149 | 154 | |
| 150 | 155 | // Parse the InfoStreamHeader. |
| 151 | const version = try reader.readInt(u32, .little); | |
| 152 | const signature = try reader.readInt(u32, .little); | |
| 156 | const version = try reader.takeInt(u32, .little); | |
| 157 | const signature = try reader.takeInt(u32, .little); | |
| 153 | 158 | _ = signature; |
| 154 | const age = try reader.readInt(u32, .little); | |
| 155 | const guid = try reader.readBytesNoEof(16); | |
| 159 | const age = try reader.takeInt(u32, .little); | |
| 160 | const guid = try reader.takeArray(16); | |
| 156 | 161 | |
| 157 | 162 | if (version != 20000404) // VC70, only value observed by LLVM team |
| 158 | 163 | return error.UnknownPDBVersion; |
| 159 | 164 | |
| 160 | self.guid = guid; | |
| 165 | self.guid = guid.*; | |
| 161 | 166 | self.age = age; |
| 162 | 167 | |
| 168 | const gpa = self.allocator; | |
| 169 | ||
| 163 | 170 | // Find the string table. |
| 164 | 171 | const string_table_index = str_tab_index: { |
| 165 | const name_bytes_len = try reader.readInt(u32, .little); | |
| 166 | const name_bytes = try self.allocator.alloc(u8, name_bytes_len); | |
| 167 | defer self.allocator.free(name_bytes); | |
| 168 | try reader.readNoEof(name_bytes); | |
| 172 | const name_bytes_len = try reader.takeInt(u32, .little); | |
| 173 | const name_bytes = try reader.readAlloc(gpa, name_bytes_len); | |
| 169 | 174 | |
| 170 | 175 | const HashTableHeader = extern struct { |
| 171 | 176 | size: u32, |
| ... | ... | @@ -175,23 +180,23 @@ pub fn parseInfoStream(self: *Pdb) !void { |
| 175 | 180 | return cap * 2 / 3 + 1; |
| 176 | 181 | } |
| 177 | 182 | }; |
| 178 | const hash_tbl_hdr = try reader.readStruct(HashTableHeader); | |
| 183 | const hash_tbl_hdr = try reader.takeStruct(HashTableHeader, .little); | |
| 179 | 184 | if (hash_tbl_hdr.capacity == 0) |
| 180 | 185 | return error.InvalidDebugInfo; |
| 181 | 186 | |
| 182 | 187 | if (hash_tbl_hdr.size > HashTableHeader.maxLoad(hash_tbl_hdr.capacity)) |
| 183 | 188 | return error.InvalidDebugInfo; |
| 184 | 189 | |
| 185 | const present = try readSparseBitVector(&reader, self.allocator); | |
| 186 | defer self.allocator.free(present); | |
| 190 | const present = try readSparseBitVector(reader, gpa); | |
| 191 | defer gpa.free(present); | |
| 187 | 192 | if (present.len != hash_tbl_hdr.size) |
| 188 | 193 | return error.InvalidDebugInfo; |
| 189 | const deleted = try readSparseBitVector(&reader, self.allocator); | |
| 190 | defer self.allocator.free(deleted); | |
| 194 | const deleted = try readSparseBitVector(reader, gpa); | |
| 195 | defer gpa.free(deleted); | |
| 191 | 196 | |
| 192 | 197 | for (present) |_| { |
| 193 | const name_offset = try reader.readInt(u32, .little); | |
| 194 | const name_index = try reader.readInt(u32, .little); | |
| 198 | const name_offset = try reader.takeInt(u32, .little); | |
| 199 | const name_index = try reader.takeInt(u32, .little); | |
| 195 | 200 | if (name_offset > name_bytes.len) |
| 196 | 201 | return error.InvalidDebugInfo; |
| 197 | 202 | const name = std.mem.sliceTo(name_bytes[name_offset..], 0); |
| ... | ... | @@ -233,6 +238,7 @@ pub fn getSymbolName(self: *Pdb, module: *Module, address: u64) ?[]const u8 { |
| 233 | 238 | pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.SourceLocation { |
| 234 | 239 | std.debug.assert(module.populated); |
| 235 | 240 | const subsect_info = module.subsect_info; |
| 241 | const gpa = self.allocator; | |
| 236 | 242 | |
| 237 | 243 | var sect_offset: usize = 0; |
| 238 | 244 | var skip_len: usize = undefined; |
| ... | ... | @@ -287,7 +293,16 @@ pub fn getLineNumberInfo(self: *Pdb, module: *Module, address: u64) !std.debug.S |
| 287 | 293 | const chksum_hdr: *align(1) pdb.FileChecksumEntryHeader = @ptrCast(&module.subsect_info[subsect_index]); |
| 288 | 294 | const strtab_offset = @sizeOf(pdb.StringTableHeader) + chksum_hdr.file_name_offset; |
| 289 | 295 | try self.string_table.?.seekTo(strtab_offset); |
| 290 | const source_file_name = try self.string_table.?.reader().readUntilDelimiterAlloc(self.allocator, 0, 1024); | |
| 296 | const source_file_name = s: { | |
| 297 | const string_reader = &self.string_table.?.interface; | |
| 298 | var source_file_name: std.Io.Writer.Allocating = .init(gpa); | |
| 299 | defer source_file_name.deinit(); | |
| 300 | _ = try string_reader.streamDelimiterLimit(&source_file_name.writer, 0, .limited(1024)); | |
| 301 | assert(string_reader.buffered()[0] == 0); // TODO change streamDelimiterLimit API | |
| 302 | string_reader.toss(1); | |
| 303 | break :s try source_file_name.toOwnedSlice(); | |
| 304 | }; | |
| 305 | errdefer gpa.free(source_file_name); | |
| 291 | 306 | |
| 292 | 307 | const line_entry_idx = line_i - 1; |
| 293 | 308 | |
| ... | ... | @@ -341,19 +356,16 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module { |
| 341 | 356 | |
| 342 | 357 | const stream = self.getStreamById(mod.mod_info.module_sym_stream) orelse |
| 343 | 358 | return error.MissingDebugInfo; |
| 344 | const reader = stream.reader(); | |
| 359 | const reader = &stream.interface; | |
| 345 | 360 | |
| 346 | const signature = try reader.readInt(u32, .little); | |
| 361 | const signature = try reader.takeInt(u32, .little); | |
| 347 | 362 | if (signature != 4) |
| 348 | 363 | return error.InvalidDebugInfo; |
| 349 | 364 | |
| 350 | mod.symbols = try self.allocator.alloc(u8, mod.mod_info.sym_byte_size - 4); | |
| 351 | errdefer self.allocator.free(mod.symbols); | |
| 352 | try reader.readNoEof(mod.symbols); | |
| 365 | const gpa = self.allocator; | |
| 353 | 366 | |
| 354 | mod.subsect_info = try self.allocator.alloc(u8, mod.mod_info.c13_byte_size); | |
| 355 | errdefer self.allocator.free(mod.subsect_info); | |
| 356 | try reader.readNoEof(mod.subsect_info); | |
| 367 | mod.symbols = try reader.readAlloc(gpa, mod.mod_info.sym_byte_size - 4); | |
| 368 | mod.subsect_info = try reader.readAlloc(gpa, mod.mod_info.c13_byte_size); | |
| 357 | 369 | |
| 358 | 370 | var sect_offset: usize = 0; |
| 359 | 371 | var skip_len: usize = undefined; |
| ... | ... | @@ -379,8 +391,7 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module { |
| 379 | 391 | } |
| 380 | 392 | |
| 381 | 393 | pub fn getStreamById(self: *Pdb, id: u32) ?*MsfStream { |
| 382 | if (id >= self.msf.streams.len) | |
| 383 | return null; | |
| 394 | if (id >= self.msf.streams.len) return null; | |
| 384 | 395 | return &self.msf.streams[id]; |
| 385 | 396 | } |
| 386 | 397 | |
| ... | ... | @@ -394,17 +405,14 @@ const Msf = struct { |
| 394 | 405 | directory: MsfStream, |
| 395 | 406 | streams: []MsfStream, |
| 396 | 407 | |
| 397 | fn init(allocator: Allocator, file: File) !Msf { | |
| 398 | const in = file.deprecatedReader(); | |
| 399 | ||
| 400 | const superblock = try in.readStruct(pdb.SuperBlock); | |
| 408 | fn init(gpa: Allocator, file_reader: *File.Reader) !Msf { | |
| 409 | const superblock = try file_reader.interface.takeStruct(pdb.SuperBlock, .little); | |
| 401 | 410 | |
| 402 | // Sanity checks | |
| 403 | 411 | if (!std.mem.eql(u8, &superblock.file_magic, pdb.SuperBlock.expect_magic)) |
| 404 | 412 | return error.InvalidDebugInfo; |
| 405 | 413 | if (superblock.free_block_map_block != 1 and superblock.free_block_map_block != 2) |
| 406 | 414 | return error.InvalidDebugInfo; |
| 407 | const file_len = try file.getEndPos(); | |
| 415 | const file_len = try file_reader.getSize(); | |
| 408 | 416 | if (superblock.num_blocks * superblock.block_size != file_len) |
| 409 | 417 | return error.InvalidDebugInfo; |
| 410 | 418 | switch (superblock.block_size) { |
| ... | ... | @@ -417,163 +425,182 @@ const Msf = struct { |
| 417 | 425 | if (dir_block_count > superblock.block_size / @sizeOf(u32)) |
| 418 | 426 | return error.UnhandledBigDirectoryStream; // cf. BlockMapAddr comment. |
| 419 | 427 | |
| 420 | try file.seekTo(superblock.block_size * superblock.block_map_addr); | |
| 421 | const dir_blocks = try allocator.alloc(u32, dir_block_count); | |
| 428 | try file_reader.seekTo(superblock.block_size * superblock.block_map_addr); | |
| 429 | const dir_blocks = try gpa.alloc(u32, dir_block_count); | |
| 422 | 430 | for (dir_blocks) |*b| { |
| 423 | b.* = try in.readInt(u32, .little); | |
| 431 | b.* = try file_reader.interface.takeInt(u32, .little); | |
| 424 | 432 | } |
| 425 | var directory = MsfStream.init( | |
| 426 | superblock.block_size, | |
| 427 | file, | |
| 428 | dir_blocks, | |
| 429 | ); | |
| 433 | var directory_buffer: [64]u8 = undefined; | |
| 434 | var directory = MsfStream.init(superblock.block_size, file_reader, dir_blocks, &directory_buffer); | |
| 430 | 435 | |
| 431 | const begin = directory.pos; | |
| 432 | const stream_count = try directory.reader().readInt(u32, .little); | |
| 433 | const stream_sizes = try allocator.alloc(u32, stream_count); | |
| 434 | defer allocator.free(stream_sizes); | |
| 436 | const begin = directory.logicalPos(); | |
| 437 | const stream_count = try directory.interface.takeInt(u32, .little); | |
| 438 | const stream_sizes = try gpa.alloc(u32, stream_count); | |
| 439 | defer gpa.free(stream_sizes); | |
| 435 | 440 | |
| 436 | 441 | // Microsoft's implementation uses @as(u32, -1) for inexistent streams. |
| 437 | 442 | // These streams are not used, but still participate in the file |
| 438 | 443 | // and must be taken into account when resolving stream indices. |
| 439 | const Nil = 0xFFFFFFFF; | |
| 444 | const nil_size = 0xFFFFFFFF; | |
| 440 | 445 | for (stream_sizes) |*s| { |
| 441 | const size = try directory.reader().readInt(u32, .little); | |
| 442 | s.* = if (size == Nil) 0 else blockCountFromSize(size, superblock.block_size); | |
| 446 | const size = try directory.interface.takeInt(u32, .little); | |
| 447 | s.* = if (size == nil_size) 0 else blockCountFromSize(size, superblock.block_size); | |
| 443 | 448 | } |
| 444 | 449 | |
| 445 | const streams = try allocator.alloc(MsfStream, stream_count); | |
| 450 | const streams = try gpa.alloc(MsfStream, stream_count); | |
| 451 | errdefer gpa.free(streams); | |
| 452 | ||
| 446 | 453 | for (streams, 0..) |*stream, i| { |
| 447 | 454 | const size = stream_sizes[i]; |
| 448 | 455 | if (size == 0) { |
| 449 | stream.* = MsfStream{ | |
| 450 | .blocks = &[_]u32{}, | |
| 451 | }; | |
| 456 | stream.* = .empty; | |
| 452 | 457 | } else { |
| 453 | var blocks = try allocator.alloc(u32, size); | |
| 454 | var j: u32 = 0; | |
| 455 | while (j < size) : (j += 1) { | |
| 456 | const block_id = try directory.reader().readInt(u32, .little); | |
| 458 | const blocks = try gpa.alloc(u32, size); | |
| 459 | errdefer gpa.free(blocks); | |
| 460 | for (blocks) |*block| { | |
| 461 | const block_id = try directory.interface.takeInt(u32, .little); | |
| 457 | 462 | const n = (block_id % superblock.block_size); |
| 458 | 463 | // 0 is for pdb.SuperBlock, 1 and 2 for FPMs. |
| 459 | 464 | if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.block_size > file_len) |
| 460 | 465 | return error.InvalidBlockIndex; |
| 461 | blocks[j] = block_id; | |
| 466 | block.* = block_id; | |
| 462 | 467 | } |
| 463 | ||
| 464 | stream.* = MsfStream.init( | |
| 465 | superblock.block_size, | |
| 466 | file, | |
| 467 | blocks, | |
| 468 | ); | |
| 468 | const buffer = try gpa.alloc(u8, 64); | |
| 469 | errdefer gpa.free(buffer); | |
| 470 | stream.* = .init(superblock.block_size, file_reader, blocks, buffer); | |
| 469 | 471 | } |
| 470 | 472 | } |
| 471 | 473 | |
| 472 | const end = directory.pos; | |
| 474 | const end = directory.logicalPos(); | |
| 473 | 475 | if (end - begin != superblock.num_directory_bytes) |
| 474 | 476 | return error.InvalidStreamDirectory; |
| 475 | 477 | |
| 476 | return Msf{ | |
| 478 | return .{ | |
| 477 | 479 | .directory = directory, |
| 478 | 480 | .streams = streams, |
| 479 | 481 | }; |
| 480 | 482 | } |
| 481 | 483 | |
| 482 | fn deinit(self: *Msf, allocator: Allocator) void { | |
| 483 | allocator.free(self.directory.blocks); | |
| 484 | fn deinit(self: *Msf, gpa: Allocator) void { | |
| 485 | gpa.free(self.directory.blocks); | |
| 484 | 486 | for (self.streams) |*stream| { |
| 485 | allocator.free(stream.blocks); | |
| 487 | gpa.free(stream.interface.buffer); | |
| 488 | gpa.free(stream.blocks); | |
| 486 | 489 | } |
| 487 | allocator.free(self.streams); | |
| 490 | gpa.free(self.streams); | |
| 488 | 491 | } |
| 489 | 492 | }; |
| 490 | 493 | |
| 491 | 494 | const MsfStream = struct { |
| 492 | in_file: File = undefined, | |
| 493 | pos: u64 = undefined, | |
| 494 | blocks: []u32 = undefined, | |
| 495 | block_size: u32 = undefined, | |
| 496 | ||
| 497 | pub const Error = @typeInfo(@typeInfo(@TypeOf(read)).@"fn".return_type.?).error_union.error_set; | |
| 495 | file_reader: *File.Reader, | |
| 496 | next_read_pos: u64, | |
| 497 | blocks: []u32, | |
| 498 | block_size: u32, | |
| 499 | interface: std.Io.Reader, | |
| 500 | err: ?Error, | |
| 501 | ||
| 502 | const Error = File.Reader.SeekError; | |
| 503 | ||
| 504 | const empty: MsfStream = .{ | |
| 505 | .file_reader = undefined, | |
| 506 | .next_read_pos = 0, | |
| 507 | .blocks = &.{}, | |
| 508 | .block_size = undefined, | |
| 509 | .interface = .ending_instance, | |
| 510 | .err = null, | |
| 511 | }; | |
| 498 | 512 | |
| 499 | fn init(block_size: u32, file: File, blocks: []u32) MsfStream { | |
| 500 | const stream = MsfStream{ | |
| 501 | .in_file = file, | |
| 502 | .pos = 0, | |
| 513 | fn init(block_size: u32, file_reader: *File.Reader, blocks: []u32, buffer: []u8) MsfStream { | |
| 514 | return .{ | |
| 515 | .file_reader = file_reader, | |
| 516 | .next_read_pos = 0, | |
| 503 | 517 | .blocks = blocks, |
| 504 | 518 | .block_size = block_size, |
| 519 | .interface = .{ | |
| 520 | .vtable = &.{ .stream = stream }, | |
| 521 | .buffer = buffer, | |
| 522 | .seek = 0, | |
| 523 | .end = 0, | |
| 524 | }, | |
| 525 | .err = null, | |
| 505 | 526 | }; |
| 506 | ||
| 507 | return stream; | |
| 508 | 527 | } |
| 509 | 528 | |
| 510 | fn read(self: *MsfStream, buffer: []u8) !usize { | |
| 511 | var block_id = @as(usize, @intCast(self.pos / self.block_size)); | |
| 512 | if (block_id >= self.blocks.len) return 0; // End of Stream | |
| 513 | var block = self.blocks[block_id]; | |
| 514 | var offset = self.pos % self.block_size; | |
| 529 | fn stream(r: *std.Io.Reader, w: *std.Io.Writer, limit: std.Io.Limit) std.Io.Reader.StreamError!usize { | |
| 530 | const ms: *MsfStream = @alignCast(@fieldParentPtr("interface", r)); | |
| 515 | 531 | |
| 516 | try self.in_file.seekTo(block * self.block_size + offset); | |
| 517 | const in = self.in_file.deprecatedReader(); | |
| 532 | var block_id: usize = @intCast(ms.next_read_pos / ms.block_size); | |
| 533 | if (block_id >= ms.blocks.len) return error.EndOfStream; | |
| 534 | var block = ms.blocks[block_id]; | |
| 535 | var offset = ms.next_read_pos % ms.block_size; | |
| 518 | 536 | |
| 519 | var size: usize = 0; | |
| 520 | var rem_buffer = buffer; | |
| 521 | while (size < buffer.len) { | |
| 522 | const size_to_read = @min(self.block_size - offset, rem_buffer.len); | |
| 523 | size += try in.read(rem_buffer[0..size_to_read]); | |
| 524 | rem_buffer = buffer[size..]; | |
| 525 | offset += size_to_read; | |
| 537 | ms.file_reader.seekTo(block * ms.block_size + offset) catch |err| { | |
| 538 | ms.err = err; | |
| 539 | return error.ReadFailed; | |
| 540 | }; | |
| 541 | ||
| 542 | var remaining = @intFromEnum(limit); | |
| 543 | while (remaining != 0) { | |
| 544 | const stream_len: usize = @min(remaining, ms.block_size - offset); | |
| 545 | const n = try ms.file_reader.interface.stream(w, .limited(stream_len)); | |
| 546 | remaining -= n; | |
| 547 | offset += n; | |
| 526 | 548 | |
| 527 | 549 | // If we're at the end of a block, go to the next one. |
| 528 | if (offset == self.block_size) { | |
| 550 | if (offset == ms.block_size) { | |
| 529 | 551 | offset = 0; |
| 530 | 552 | block_id += 1; |
| 531 | if (block_id >= self.blocks.len) break; // End of Stream | |
| 532 | block = self.blocks[block_id]; | |
| 533 | try self.in_file.seekTo(block * self.block_size); | |
| 553 | if (block_id >= ms.blocks.len) break; // End of Stream | |
| 554 | block = ms.blocks[block_id]; | |
| 555 | ms.file_reader.seekTo(block * ms.block_size) catch |err| { | |
| 556 | ms.err = err; | |
| 557 | return error.ReadFailed; | |
| 558 | }; | |
| 534 | 559 | } |
| 535 | 560 | } |
| 536 | 561 | |
| 537 | self.pos += buffer.len; | |
| 538 | return buffer.len; | |
| 562 | const total = @intFromEnum(limit) - remaining; | |
| 563 | ms.next_read_pos += total; | |
| 564 | return total; | |
| 539 | 565 | } |
| 540 | 566 | |
| 541 | pub fn seekBy(self: *MsfStream, len: i64) !void { | |
| 542 | self.pos = @as(u64, @intCast(@as(i64, @intCast(self.pos)) + len)); | |
| 543 | if (self.pos >= self.blocks.len * self.block_size) | |
| 544 | return error.EOF; | |
| 567 | pub fn logicalPos(ms: *const MsfStream) u64 { | |
| 568 | return ms.next_read_pos - ms.interface.bufferedLen(); | |
| 545 | 569 | } |
| 546 | 570 | |
| 547 | pub fn seekTo(self: *MsfStream, len: u64) !void { | |
| 548 | self.pos = len; | |
| 549 | if (self.pos >= self.blocks.len * self.block_size) | |
| 550 | return error.EOF; | |
| 571 | pub fn seekBy(ms: *MsfStream, len: i64) !void { | |
| 572 | ms.next_read_pos = @as(u64, @intCast(@as(i64, @intCast(ms.logicalPos())) + len)); | |
| 573 | if (ms.next_read_pos >= ms.blocks.len * ms.block_size) return error.EOF; | |
| 574 | ms.interface.tossBuffered(); | |
| 551 | 575 | } |
| 552 | 576 | |
| 553 | fn getSize(self: *const MsfStream) u64 { | |
| 554 | return self.blocks.len * self.block_size; | |
| 577 | pub fn seekTo(ms: *MsfStream, len: u64) !void { | |
| 578 | ms.next_read_pos = len; | |
| 579 | if (ms.next_read_pos >= ms.blocks.len * ms.block_size) return error.EOF; | |
| 580 | ms.interface.tossBuffered(); | |
| 555 | 581 | } |
| 556 | 582 | |
| 557 | fn getFilePos(self: MsfStream) u64 { | |
| 558 | const block_id = self.pos / self.block_size; | |
| 559 | const block = self.blocks[block_id]; | |
| 560 | const offset = self.pos % self.block_size; | |
| 561 | ||
| 562 | return block * self.block_size + offset; | |
| 583 | fn getSize(ms: *const MsfStream) u64 { | |
| 584 | return ms.blocks.len * ms.block_size; | |
| 563 | 585 | } |
| 564 | 586 | |
| 565 | pub fn reader(self: *MsfStream) std.io.GenericReader(*MsfStream, Error, read) { | |
| 566 | return .{ .context = self }; | |
| 587 | fn getFilePos(ms: *const MsfStream) u64 { | |
| 588 | const pos = ms.logicalPos(); | |
| 589 | const block_id = pos / ms.block_size; | |
| 590 | const block = ms.blocks[block_id]; | |
| 591 | const offset = pos % ms.block_size; | |
| 592 | ||
| 593 | return block * ms.block_size + offset; | |
| 567 | 594 | } |
| 568 | 595 | }; |
| 569 | 596 | |
| 570 | fn readSparseBitVector(stream: anytype, allocator: Allocator) ![]u32 { | |
| 571 | const num_words = try stream.readInt(u32, .little); | |
| 597 | fn readSparseBitVector(reader: *std.Io.Reader, allocator: Allocator) ![]u32 { | |
| 598 | const num_words = try reader.takeInt(u32, .little); | |
| 572 | 599 | var list = std.array_list.Managed(u32).init(allocator); |
| 573 | 600 | errdefer list.deinit(); |
| 574 | 601 | var word_i: u32 = 0; |
| 575 | 602 | while (word_i != num_words) : (word_i += 1) { |
| 576 | const word = try stream.readInt(u32, .little); | |
| 603 | const word = try reader.takeInt(u32, .little); | |
| 577 | 604 | var bit_i: u5 = 0; |
| 578 | 605 | while (true) : (bit_i += 1) { |
| 579 | 606 | if (word & (@as(u32, 1) << bit_i) != 0) { |
lib/std/debug/SelfInfo.zig+34-17| ... | ... | @@ -713,22 +713,26 @@ pub const Module = switch (native_os) { |
| 713 | 713 | }, |
| 714 | 714 | .uefi, .windows => struct { |
| 715 | 715 | base_address: usize, |
| 716 | pdb: ?Pdb = null, | |
| 717 | dwarf: ?Dwarf = null, | |
| 716 | pdb: ?Pdb, | |
| 717 | dwarf: ?Dwarf, | |
| 718 | 718 | coff_image_base: u64, |
| 719 | 719 | |
| 720 | 720 | /// Only used if pdb is non-null |
| 721 | 721 | coff_section_headers: []coff.SectionHeader, |
| 722 | 722 | |
| 723 | pub fn deinit(self: *@This(), allocator: Allocator) void { | |
| 723 | pub fn deinit(self: *@This(), gpa: Allocator) void { | |
| 724 | 724 | if (self.dwarf) |*dwarf| { |
| 725 | dwarf.deinit(allocator); | |
| 725 | dwarf.deinit(gpa); | |
| 726 | 726 | } |
| 727 | 727 | |
| 728 | 728 | if (self.pdb) |*p| { |
| 729 | gpa.free(p.file_reader.interface.buffer); | |
| 730 | gpa.destroy(p.file_reader); | |
| 729 | 731 | p.deinit(); |
| 730 | allocator.free(self.coff_section_headers); | |
| 732 | gpa.free(self.coff_section_headers); | |
| 731 | 733 | } |
| 734 | ||
| 735 | self.* = undefined; | |
| 732 | 736 | } |
| 733 | 737 | |
| 734 | 738 | fn getSymbolFromPdb(self: *@This(), relocated_address: usize) !?std.debug.Symbol { |
| ... | ... | @@ -970,23 +974,25 @@ fn readMachODebugInfo(allocator: Allocator, macho_file: File) !Module { |
| 970 | 974 | }; |
| 971 | 975 | } |
| 972 | 976 | |
| 973 | fn readCoffDebugInfo(allocator: Allocator, coff_obj: *coff.Coff) !Module { | |
| 977 | fn readCoffDebugInfo(gpa: Allocator, coff_obj: *coff.Coff) !Module { | |
| 974 | 978 | nosuspend { |
| 975 | 979 | var di: Module = .{ |
| 976 | 980 | .base_address = undefined, |
| 977 | 981 | .coff_image_base = coff_obj.getImageBase(), |
| 978 | 982 | .coff_section_headers = undefined, |
| 983 | .pdb = null, | |
| 984 | .dwarf = null, | |
| 979 | 985 | }; |
| 980 | 986 | |
| 981 | 987 | if (coff_obj.getSectionByName(".debug_info")) |_| { |
| 982 | 988 | // This coff file has embedded DWARF debug info |
| 983 | 989 | var sections: Dwarf.SectionArray = Dwarf.null_section_array; |
| 984 | errdefer for (sections) |section| if (section) |s| if (s.owned) allocator.free(s.data); | |
| 990 | errdefer for (sections) |section| if (section) |s| if (s.owned) gpa.free(s.data); | |
| 985 | 991 | |
| 986 | 992 | inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields, 0..) |section, i| { |
| 987 | 993 | sections[i] = if (coff_obj.getSectionByName("." ++ section.name)) |section_header| blk: { |
| 988 | 994 | break :blk .{ |
| 989 | .data = try coff_obj.getSectionDataAlloc(section_header, allocator), | |
| 995 | .data = try coff_obj.getSectionDataAlloc(section_header, gpa), | |
| 990 | 996 | .virtual_address = section_header.virtual_address, |
| 991 | 997 | .owned = true, |
| 992 | 998 | }; |
| ... | ... | @@ -999,7 +1005,7 @@ fn readCoffDebugInfo(allocator: Allocator, coff_obj: *coff.Coff) !Module { |
| 999 | 1005 | .is_macho = false, |
| 1000 | 1006 | }; |
| 1001 | 1007 | |
| 1002 | try Dwarf.open(&dwarf, allocator); | |
| 1008 | try Dwarf.open(&dwarf, gpa); | |
| 1003 | 1009 | di.dwarf = dwarf; |
| 1004 | 1010 | } |
| 1005 | 1011 | |
| ... | ... | @@ -1008,20 +1014,31 @@ fn readCoffDebugInfo(allocator: Allocator, coff_obj: *coff.Coff) !Module { |
| 1008 | 1014 | if (fs.path.isAbsolute(raw_path)) { |
| 1009 | 1015 | break :blk raw_path; |
| 1010 | 1016 | } else { |
| 1011 | const self_dir = try fs.selfExeDirPathAlloc(allocator); | |
| 1012 | defer allocator.free(self_dir); | |
| 1013 | break :blk try fs.path.join(allocator, &.{ self_dir, raw_path }); | |
| 1017 | const self_dir = try fs.selfExeDirPathAlloc(gpa); | |
| 1018 | defer gpa.free(self_dir); | |
| 1019 | break :blk try fs.path.join(gpa, &.{ self_dir, raw_path }); | |
| 1014 | 1020 | } |
| 1015 | 1021 | }; |
| 1016 | defer if (path.ptr != raw_path.ptr) allocator.free(path); | |
| 1022 | defer if (path.ptr != raw_path.ptr) gpa.free(path); | |
| 1017 | 1023 | |
| 1018 | di.pdb = Pdb.init(allocator, path) catch |err| switch (err) { | |
| 1024 | const pdb_file = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) { | |
| 1019 | 1025 | error.FileNotFound, error.IsDir => { |
| 1020 | 1026 | if (di.dwarf == null) return error.MissingDebugInfo; |
| 1021 | 1027 | return di; |
| 1022 | 1028 | }, |
| 1023 | else => return err, | |
| 1029 | else => |e| return e, | |
| 1024 | 1030 | }; |
| 1031 | errdefer pdb_file.close(); | |
| 1032 | ||
| 1033 | const pdb_file_reader_buffer = try gpa.alloc(u8, 4096); | |
| 1034 | errdefer gpa.free(pdb_file_reader_buffer); | |
| 1035 | ||
| 1036 | const pdb_file_reader = try gpa.create(File.Reader); | |
| 1037 | errdefer gpa.destroy(pdb_file_reader); | |
| 1038 | ||
| 1039 | pdb_file_reader.* = pdb_file.reader(pdb_file_reader_buffer); | |
| 1040 | ||
| 1041 | di.pdb = try Pdb.init(gpa, pdb_file_reader); | |
| 1025 | 1042 | try di.pdb.?.parseInfoStream(); |
| 1026 | 1043 | try di.pdb.?.parseDbiStream(); |
| 1027 | 1044 | |
| ... | ... | @@ -1029,8 +1046,8 @@ fn readCoffDebugInfo(allocator: Allocator, coff_obj: *coff.Coff) !Module { |
| 1029 | 1046 | return error.InvalidDebugInfo; |
| 1030 | 1047 | |
| 1031 | 1048 | // Only used by the pdb path |
| 1032 | di.coff_section_headers = try coff_obj.getSectionHeadersAlloc(allocator); | |
| 1033 | errdefer allocator.free(di.coff_section_headers); | |
| 1049 | di.coff_section_headers = try coff_obj.getSectionHeadersAlloc(gpa); | |
| 1050 | errdefer gpa.free(di.coff_section_headers); | |
| 1034 | 1051 | |
| 1035 | 1052 | return di; |
| 1036 | 1053 | } |
lib/std/fs/File.zig-8| ... | ... | @@ -1097,14 +1097,6 @@ pub fn deprecatedReader(file: File) DeprecatedReader { |
| 1097 | 1097 | return .{ .context = file }; |
| 1098 | 1098 | } |
| 1099 | 1099 | |
| 1100 | /// Deprecated in favor of `Writer`. | |
| 1101 | pub const DeprecatedWriter = io.GenericWriter(File, WriteError, write); | |
| 1102 | ||
| 1103 | /// Deprecated in favor of `Writer`. | |
| 1104 | pub fn deprecatedWriter(file: File) DeprecatedWriter { | |
| 1105 | return .{ .context = file }; | |
| 1106 | } | |
| 1107 | ||
| 1108 | 1100 | /// Memoizes key information about a file handle such as: |
| 1109 | 1101 | /// * The size from calling stat, or the error that occurred therein. |
| 1110 | 1102 | /// * The current seek position. |
lib/std/json.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | //! The high-level `parseFromSlice` and `parseFromTokenSource` deserialize a JSON document into a Zig type. |
| 7 | 7 | //! Parse into a dynamically-typed `Value` to load any JSON value for runtime inspection. |
| 8 | 8 | //! |
| 9 | //! The low-level `writeStream` emits syntax-conformant JSON tokens to a `std.io.GenericWriter`. | |
| 9 | //! The low-level `writeStream` emits syntax-conformant JSON tokens to a `std.Io.Writer`. | |
| 10 | 10 | //! The high-level `stringify` serializes a Zig or `Value` type into JSON. |
| 11 | 11 | |
| 12 | 12 | const builtin = @import("builtin"); |
lib/std/leb128.zig-103| ... | ... | @@ -33,28 +33,6 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T { |
| 33 | 33 | return @as(T, @truncate(value)); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | /// Write a single unsigned integer as unsigned LEB128 to the given writer. | |
| 37 | pub fn writeUleb128(writer: anytype, arg: anytype) !void { | |
| 38 | const Arg = @TypeOf(arg); | |
| 39 | const Int = switch (Arg) { | |
| 40 | comptime_int => std.math.IntFittingRange(arg, arg), | |
| 41 | else => Arg, | |
| 42 | }; | |
| 43 | const Value = if (@typeInfo(Int).int.bits < 8) u8 else Int; | |
| 44 | var value: Value = arg; | |
| 45 | ||
| 46 | while (true) { | |
| 47 | const byte: u8 = @truncate(value & 0x7f); | |
| 48 | value >>= 7; | |
| 49 | if (value == 0) { | |
| 50 | try writer.writeByte(byte); | |
| 51 | break; | |
| 52 | } else { | |
| 53 | try writer.writeByte(byte | 0x80); | |
| 54 | } | |
| 55 | } | |
| 56 | } | |
| 57 | ||
| 58 | 36 | /// Read a single signed LEB128 value from the given reader as type T, |
| 59 | 37 | /// or error.Overflow if the value cannot fit. |
| 60 | 38 | pub fn readIleb128(comptime T: type, reader: anytype) !T { |
| ... | ... | @@ -374,84 +352,3 @@ test "deserialize unsigned LEB128" { |
| 374 | 352 | // Decode sequence of ULEB128 values |
| 375 | 353 | try test_read_uleb128_seq(u64, 4, "\x81\x01\x3f\x80\x7f\x80\x80\x80\x00"); |
| 376 | 354 | } |
| 377 | ||
| 378 | fn test_write_leb128(value: anytype) !void { | |
| 379 | const T = @TypeOf(value); | |
| 380 | const signedness = @typeInfo(T).int.signedness; | |
| 381 | const t_signed = signedness == .signed; | |
| 382 | ||
| 383 | const writeStream = if (t_signed) writeIleb128 else writeUleb128; | |
| 384 | const readStream = if (t_signed) readIleb128 else readUleb128; | |
| 385 | ||
| 386 | // decode to a larger bit size too, to ensure sign extension | |
| 387 | // is working as expected | |
| 388 | const larger_type_bits = ((@typeInfo(T).int.bits + 8) / 8) * 8; | |
| 389 | const B = std.meta.Int(signedness, larger_type_bits); | |
| 390 | ||
| 391 | const bytes_needed = bn: { | |
| 392 | if (@typeInfo(T).int.bits <= 7) break :bn @as(u16, 1); | |
| 393 | ||
| 394 | const unused_bits = if (value < 0) @clz(~value) else @clz(value); | |
| 395 | const used_bits: u16 = (@typeInfo(T).int.bits - unused_bits) + @intFromBool(t_signed); | |
| 396 | if (used_bits <= 7) break :bn @as(u16, 1); | |
| 397 | break :bn ((used_bits + 6) / 7); | |
| 398 | }; | |
| 399 | ||
| 400 | const max_groups = if (@typeInfo(T).int.bits == 0) 1 else (@typeInfo(T).int.bits + 6) / 7; | |
| 401 | ||
| 402 | var buf: [max_groups]u8 = undefined; | |
| 403 | var fbs = std.io.fixedBufferStream(&buf); | |
| 404 | ||
| 405 | // stream write | |
| 406 | try writeStream(fbs.writer(), value); | |
| 407 | const w1_pos = fbs.pos; | |
| 408 | try testing.expect(w1_pos == bytes_needed); | |
| 409 | ||
| 410 | // stream read | |
| 411 | fbs.pos = 0; | |
| 412 | const sr = try readStream(T, fbs.reader()); | |
| 413 | try testing.expect(fbs.pos == w1_pos); | |
| 414 | try testing.expect(sr == value); | |
| 415 | ||
| 416 | // bigger type stream read | |
| 417 | fbs.pos = 0; | |
| 418 | const bsr = try readStream(B, fbs.reader()); | |
| 419 | try testing.expect(fbs.pos == w1_pos); | |
| 420 | try testing.expect(bsr == value); | |
| 421 | } | |
| 422 | ||
| 423 | test "serialize unsigned LEB128" { | |
| 424 | if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest; | |
| 425 | ||
| 426 | const max_bits = 18; | |
| 427 | ||
| 428 | comptime var t = 0; | |
| 429 | inline while (t <= max_bits) : (t += 1) { | |
| 430 | const T = std.meta.Int(.unsigned, t); | |
| 431 | const min = std.math.minInt(T); | |
| 432 | const max = std.math.maxInt(T); | |
| 433 | var i = @as(std.meta.Int(.unsigned, @typeInfo(T).int.bits + 1), min); | |
| 434 | ||
| 435 | while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i))); | |
| 436 | } | |
| 437 | } | |
| 438 | ||
| 439 | test "serialize signed LEB128" { | |
| 440 | if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest; | |
| 441 | ||
| 442 | // explicitly test i0 because starting `t` at 0 | |
| 443 | // will break the while loop | |
| 444 | try test_write_leb128(@as(i0, 0)); | |
| 445 | ||
| 446 | const max_bits = 18; | |
| 447 | ||
| 448 | comptime var t = 1; | |
| 449 | inline while (t <= max_bits) : (t += 1) { | |
| 450 | const T = std.meta.Int(.signed, t); | |
| 451 | const min = std.math.minInt(T); | |
| 452 | const max = std.math.maxInt(T); | |
| 453 | var i = @as(std.meta.Int(.signed, @typeInfo(T).int.bits + 1), min); | |
| 454 | ||
| 455 | while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i))); | |
| 456 | } | |
| 457 | } |
lib/std/macho.zig-2| ... | ... | @@ -1883,10 +1883,8 @@ pub const GenericBlob = extern struct { |
| 1883 | 1883 | pub const data_in_code_entry = extern struct { |
| 1884 | 1884 | /// From mach_header to start of data range. |
| 1885 | 1885 | offset: u32, |
| 1886 | ||
| 1887 | 1886 | /// Number of bytes in data range. |
| 1888 | 1887 | length: u16, |
| 1889 | ||
| 1890 | 1888 | /// A DICE_KIND value. |
| 1891 | 1889 | kind: u16, |
| 1892 | 1890 | }; |
lib/std/posix/test.zig+2-2| ... | ... | @@ -683,11 +683,11 @@ test "mmap" { |
| 683 | 683 | const file = try tmp.dir.createFile(test_out_file, .{}); |
| 684 | 684 | defer file.close(); |
| 685 | 685 | |
| 686 | const stream = file.deprecatedWriter(); | |
| 686 | var stream = file.writer(&.{}); | |
| 687 | 687 | |
| 688 | 688 | var i: u32 = 0; |
| 689 | 689 | while (i < alloc_size / @sizeOf(u32)) : (i += 1) { |
| 690 | try stream.writeInt(u32, i, .little); | |
| 690 | try stream.interface.writeInt(u32, i, .little); | |
| 691 | 691 | } |
| 692 | 692 | } |
| 693 | 693 |
lib/std/tz.zig+45-44| ... | ... | @@ -1,6 +1,12 @@ |
| 1 | const std = @import("std.zig"); | |
| 1 | //! The Time Zone Information Format (TZif) | |
| 2 | //! https://datatracker.ietf.org/doc/html/rfc8536 | |
| 3 | ||
| 2 | 4 | const builtin = @import("builtin"); |
| 3 | 5 | |
| 6 | const std = @import("std.zig"); | |
| 7 | const Reader = std.Io.Reader; | |
| 8 | const Allocator = std.mem.Allocator; | |
| 9 | ||
| 4 | 10 | pub const Transition = struct { |
| 5 | 11 | ts: i64, |
| 6 | 12 | timetype: *Timetype, |
| ... | ... | @@ -34,7 +40,7 @@ pub const Leapsecond = struct { |
| 34 | 40 | }; |
| 35 | 41 | |
| 36 | 42 | pub const Tz = struct { |
| 37 | allocator: std.mem.Allocator, | |
| 43 | allocator: Allocator, | |
| 38 | 44 | transitions: []const Transition, |
| 39 | 45 | timetypes: []const Timetype, |
| 40 | 46 | leapseconds: []const Leapsecond, |
| ... | ... | @@ -54,34 +60,30 @@ pub const Tz = struct { |
| 54 | 60 | }, |
| 55 | 61 | }; |
| 56 | 62 | |
| 57 | pub fn parse(allocator: std.mem.Allocator, reader: anytype) !Tz { | |
| 58 | var legacy_header = try reader.readStruct(Header); | |
| 63 | pub fn parse(allocator: Allocator, reader: *Reader) !Tz { | |
| 64 | const legacy_header = try reader.takeStruct(Header, .big); | |
| 59 | 65 | if (!std.mem.eql(u8, &legacy_header.magic, "TZif")) return error.BadHeader; |
| 60 | if (legacy_header.version != 0 and legacy_header.version != '2' and legacy_header.version != '3') return error.BadVersion; | |
| 61 | ||
| 62 | if (builtin.target.cpu.arch.endian() != std.builtin.Endian.big) { | |
| 63 | std.mem.byteSwapAllFields(@TypeOf(legacy_header.counts), &legacy_header.counts); | |
| 64 | } | |
| 66 | if (legacy_header.version != 0 and legacy_header.version != '2' and legacy_header.version != '3') | |
| 67 | return error.BadVersion; | |
| 65 | 68 | |
| 66 | if (legacy_header.version == 0) { | |
| 69 | if (legacy_header.version == 0) | |
| 67 | 70 | return parseBlock(allocator, reader, legacy_header, true); |
| 68 | } else { | |
| 69 | // If the format is modern, just skip over the legacy data | |
| 70 | const skipv = legacy_header.counts.timecnt * 5 + legacy_header.counts.typecnt * 6 + legacy_header.counts.charcnt + legacy_header.counts.leapcnt * 8 + legacy_header.counts.isstdcnt + legacy_header.counts.isutcnt; | |
| 71 | try reader.skipBytes(skipv, .{}); | |
| 72 | ||
| 73 | var header = try reader.readStruct(Header); | |
| 74 | if (!std.mem.eql(u8, &header.magic, "TZif")) return error.BadHeader; | |
| 75 | if (header.version != '2' and header.version != '3') return error.BadVersion; | |
| 76 | if (builtin.target.cpu.arch.endian() != std.builtin.Endian.big) { | |
| 77 | std.mem.byteSwapAllFields(@TypeOf(header.counts), &header.counts); | |
| 78 | } | |
| 79 | 71 | |
| 80 | return parseBlock(allocator, reader, header, false); | |
| 81 | } | |
| 72 | // If the format is modern, just skip over the legacy data | |
| 73 | const skip_n = legacy_header.counts.timecnt * 5 + | |
| 74 | legacy_header.counts.typecnt * 6 + | |
| 75 | legacy_header.counts.charcnt + legacy_header.counts.leapcnt * 8 + | |
| 76 | legacy_header.counts.isstdcnt + legacy_header.counts.isutcnt; | |
| 77 | try reader.discardAll(skip_n); | |
| 78 | ||
| 79 | var header = try reader.takeStruct(Header, .big); | |
| 80 | if (!std.mem.eql(u8, &header.magic, "TZif")) return error.BadHeader; | |
| 81 | if (header.version != '2' and header.version != '3') return error.BadVersion; | |
| 82 | ||
| 83 | return parseBlock(allocator, reader, header, false); | |
| 82 | 84 | } |
| 83 | 85 | |
| 84 | fn parseBlock(allocator: std.mem.Allocator, reader: anytype, header: Header, legacy: bool) !Tz { | |
| 86 | fn parseBlock(allocator: Allocator, reader: *Reader, header: Header, legacy: bool) !Tz { | |
| 85 | 87 | if (header.counts.isstdcnt != 0 and header.counts.isstdcnt != header.counts.typecnt) return error.Malformed; // rfc8536: isstdcnt [...] MUST either be zero or equal to "typecnt" |
| 86 | 88 | if (header.counts.isutcnt != 0 and header.counts.isutcnt != header.counts.typecnt) return error.Malformed; // rfc8536: isutcnt [...] MUST either be zero or equal to "typecnt" |
| 87 | 89 | if (header.counts.typecnt == 0) return error.Malformed; // rfc8536: typecnt [...] MUST NOT be zero |
| ... | ... | @@ -98,12 +100,12 @@ pub const Tz = struct { |
| 98 | 100 | // Parse transition types |
| 99 | 101 | var i: usize = 0; |
| 100 | 102 | while (i < header.counts.timecnt) : (i += 1) { |
| 101 | transitions[i].ts = if (legacy) try reader.readInt(i32, .big) else try reader.readInt(i64, .big); | |
| 103 | transitions[i].ts = if (legacy) try reader.takeInt(i32, .big) else try reader.takeInt(i64, .big); | |
| 102 | 104 | } |
| 103 | 105 | |
| 104 | 106 | i = 0; |
| 105 | 107 | while (i < header.counts.timecnt) : (i += 1) { |
| 106 | const tt = try reader.readByte(); | |
| 108 | const tt = try reader.takeByte(); | |
| 107 | 109 | if (tt >= timetypes.len) return error.Malformed; // rfc8536: Each type index MUST be in the range [0, "typecnt" - 1] |
| 108 | 110 | transitions[i].timetype = &timetypes[tt]; |
| 109 | 111 | } |
| ... | ... | @@ -111,11 +113,11 @@ pub const Tz = struct { |
| 111 | 113 | // Parse time types |
| 112 | 114 | i = 0; |
| 113 | 115 | while (i < header.counts.typecnt) : (i += 1) { |
| 114 | const offset = try reader.readInt(i32, .big); | |
| 116 | const offset = try reader.takeInt(i32, .big); | |
| 115 | 117 | if (offset < -2147483648) return error.Malformed; // rfc8536: utoff [...] MUST NOT be -2**31 |
| 116 | const dst = try reader.readByte(); | |
| 118 | const dst = try reader.takeByte(); | |
| 117 | 119 | if (dst != 0 and dst != 1) return error.Malformed; // rfc8536: (is)dst [...] The value MUST be 0 or 1. |
| 118 | const idx = try reader.readByte(); | |
| 120 | const idx = try reader.takeByte(); | |
| 119 | 121 | if (idx > header.counts.charcnt - 1) return error.Malformed; // rfc8536: (desig)idx [...] Each index MUST be in the range [0, "charcnt" - 1] |
| 120 | 122 | timetypes[i] = .{ |
| 121 | 123 | .offset = offset, |
| ... | ... | @@ -128,7 +130,7 @@ pub const Tz = struct { |
| 128 | 130 | } |
| 129 | 131 | |
| 130 | 132 | var designators_data: [256 + 6]u8 = undefined; |
| 131 | try reader.readNoEof(designators_data[0..header.counts.charcnt]); | |
| 133 | try reader.readSliceAll(designators_data[0..header.counts.charcnt]); | |
| 132 | 134 | const designators = designators_data[0..header.counts.charcnt]; |
| 133 | 135 | if (designators[designators.len - 1] != 0) return error.Malformed; // rfc8536: charcnt [...] includes the trailing NUL (0x00) octet |
| 134 | 136 | |
| ... | ... | @@ -144,12 +146,12 @@ pub const Tz = struct { |
| 144 | 146 | // Parse leap seconds |
| 145 | 147 | i = 0; |
| 146 | 148 | while (i < header.counts.leapcnt) : (i += 1) { |
| 147 | const occur: i64 = if (legacy) try reader.readInt(i32, .big) else try reader.readInt(i64, .big); | |
| 149 | const occur: i64 = if (legacy) try reader.takeInt(i32, .big) else try reader.takeInt(i64, .big); | |
| 148 | 150 | if (occur < 0) return error.Malformed; // rfc8536: occur [...] MUST be nonnegative |
| 149 | 151 | if (i > 0 and leapseconds[i - 1].occurrence + 2419199 > occur) return error.Malformed; // rfc8536: occur [...] each later value MUST be at least 2419199 greater than the previous value |
| 150 | 152 | if (occur > std.math.maxInt(i48)) return error.Malformed; // Unreasonably far into the future |
| 151 | 153 | |
| 152 | const corr = try reader.readInt(i32, .big); | |
| 154 | const corr = try reader.takeInt(i32, .big); | |
| 153 | 155 | if (i == 0 and corr != -1 and corr != 1) return error.Malformed; // rfc8536: The correction value in the first leap-second record, if present, MUST be either one (1) or minus one (-1) |
| 154 | 156 | if (i > 0 and leapseconds[i - 1].correction != corr + 1 and leapseconds[i - 1].correction != corr - 1) return error.Malformed; // rfc8536: The correction values in adjacent leap-second records MUST differ by exactly one (1) |
| 155 | 157 | if (corr > std.math.maxInt(i16)) return error.Malformed; // Unreasonably large correction |
| ... | ... | @@ -163,7 +165,7 @@ pub const Tz = struct { |
| 163 | 165 | // Parse standard/wall indicators |
| 164 | 166 | i = 0; |
| 165 | 167 | while (i < header.counts.isstdcnt) : (i += 1) { |
| 166 | const stdtime = try reader.readByte(); | |
| 168 | const stdtime = try reader.takeByte(); | |
| 167 | 169 | if (stdtime == 1) { |
| 168 | 170 | timetypes[i].flags |= 0x02; |
| 169 | 171 | } |
| ... | ... | @@ -172,7 +174,7 @@ pub const Tz = struct { |
| 172 | 174 | // Parse UT/local indicators |
| 173 | 175 | i = 0; |
| 174 | 176 | while (i < header.counts.isutcnt) : (i += 1) { |
| 175 | const ut = try reader.readByte(); | |
| 177 | const ut = try reader.takeByte(); | |
| 176 | 178 | if (ut == 1) { |
| 177 | 179 | timetypes[i].flags |= 0x04; |
| 178 | 180 | if (!timetypes[i].standardTimeIndicator()) return error.Malformed; // rfc8536: standard/wall value MUST be one (1) if the UT/local value is one (1) |
| ... | ... | @@ -182,9 +184,8 @@ pub const Tz = struct { |
| 182 | 184 | // Footer |
| 183 | 185 | var footer: ?[]u8 = null; |
| 184 | 186 | if (!legacy) { |
| 185 | if ((try reader.readByte()) != '\n') return error.Malformed; // An rfc8536 footer must start with a newline | |
| 186 | var footerdata_buf: [128]u8 = undefined; | |
| 187 | const footer_mem = reader.readUntilDelimiter(&footerdata_buf, '\n') catch |err| switch (err) { | |
| 187 | if ((try reader.takeByte()) != '\n') return error.Malformed; // An rfc8536 footer must start with a newline | |
| 188 | const footer_mem = reader.takeSentinel('\n') catch |err| switch (err) { | |
| 188 | 189 | error.StreamTooLong => return error.OverlargeFooter, // Read more than 128 bytes, much larger than any reasonable POSIX TZ string |
| 189 | 190 | else => return err, |
| 190 | 191 | }; |
| ... | ... | @@ -194,7 +195,7 @@ pub const Tz = struct { |
| 194 | 195 | } |
| 195 | 196 | errdefer if (footer) |ft| allocator.free(ft); |
| 196 | 197 | |
| 197 | return Tz{ | |
| 198 | return .{ | |
| 198 | 199 | .allocator = allocator, |
| 199 | 200 | .transitions = transitions, |
| 200 | 201 | .timetypes = timetypes, |
| ... | ... | @@ -215,9 +216,9 @@ pub const Tz = struct { |
| 215 | 216 | |
| 216 | 217 | test "slim" { |
| 217 | 218 | const data = @embedFile("tz/asia_tokyo.tzif"); |
| 218 | var in_stream = std.io.fixedBufferStream(data); | |
| 219 | var in_stream: Reader = .fixed(data); | |
| 219 | 220 | |
| 220 | var tz = try std.Tz.parse(std.testing.allocator, in_stream.reader()); | |
| 221 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); | |
| 221 | 222 | defer tz.deinit(); |
| 222 | 223 | |
| 223 | 224 | try std.testing.expectEqual(tz.transitions.len, 9); |
| ... | ... | @@ -228,9 +229,9 @@ test "slim" { |
| 228 | 229 | |
| 229 | 230 | test "fat" { |
| 230 | 231 | const data = @embedFile("tz/antarctica_davis.tzif"); |
| 231 | var in_stream = std.io.fixedBufferStream(data); | |
| 232 | var in_stream: Reader = .fixed(data); | |
| 232 | 233 | |
| 233 | var tz = try std.Tz.parse(std.testing.allocator, in_stream.reader()); | |
| 234 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); | |
| 234 | 235 | defer tz.deinit(); |
| 235 | 236 | |
| 236 | 237 | try std.testing.expectEqual(tz.transitions.len, 8); |
| ... | ... | @@ -241,9 +242,9 @@ test "fat" { |
| 241 | 242 | test "legacy" { |
| 242 | 243 | // Taken from Slackware 8.0, from 2001 |
| 243 | 244 | const data = @embedFile("tz/europe_vatican.tzif"); |
| 244 | var in_stream = std.io.fixedBufferStream(data); | |
| 245 | var in_stream: Reader = .fixed(data); | |
| 245 | 246 | |
| 246 | var tz = try std.Tz.parse(std.testing.allocator, in_stream.reader()); | |
| 247 | var tz = try std.Tz.parse(std.testing.allocator, &in_stream); | |
| 247 | 248 | defer tz.deinit(); |
| 248 | 249 | |
| 249 | 250 | try std.testing.expectEqual(tz.transitions.len, 170); |
src/Compilation.zig+10-9| ... | ... | @@ -5893,15 +5893,16 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std |
| 5893 | 5893 | |
| 5894 | 5894 | fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 5895 | 5895 | defer comp.link_task_queue.finishPrelinkItem(comp); |
| 5896 | if (glibc.buildSharedObjects(comp, prog_node)) |_| { | |
| 5897 | // The job should no longer be queued up since it succeeded. | |
| 5898 | comp.queued_jobs.glibc_shared_objects = false; | |
| 5899 | } else |err| switch (err) { | |
| 5900 | error.AlreadyReported => return, | |
| 5901 | else => comp.lockAndSetMiscFailure(.glibc_shared_objects, "unable to build glibc shared objects: {s}", .{ | |
| 5902 | @errorName(err), | |
| 5903 | }), | |
| 5904 | } | |
| 5896 | glibc.buildSharedObjects(comp, prog_node) catch unreachable; | |
| 5897 | //if (glibc.buildSharedObjects(comp, prog_node)) |_| { | |
| 5898 | // // The job should no longer be queued up since it succeeded. | |
| 5899 | // comp.queued_jobs.glibc_shared_objects = false; | |
| 5900 | //} else |err| switch (err) { | |
| 5901 | // error.AlreadyReported => return, | |
| 5902 | // else => comp.lockAndSetMiscFailure(.glibc_shared_objects, "unable to build glibc shared objects: {s}", .{ | |
| 5903 | // @errorName(err), | |
| 5904 | // }), | |
| 5905 | //} | |
| 5905 | 5906 | } |
| 5906 | 5907 | |
| 5907 | 5908 | fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void { |
src/IncrementalDebugServer.zig+4-4| ... | ... | @@ -76,7 +76,9 @@ fn runThread(ids: *IncrementalDebugServer) void { |
| 76 | 76 | ids.mutex.lock(); |
| 77 | 77 | } |
| 78 | 78 | defer ids.mutex.unlock(); |
| 79 | handleCommand(ids.zcu, &text_out, cmd, arg) catch @panic("IncrementalDebugServer: out of memory"); | |
| 79 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &text_out); | |
| 80 | defer text_out = allocating.toArrayList(); | |
| 81 | handleCommand(ids.zcu, &allocating.writer, cmd, arg) catch @panic("IncrementalDebugServer: out of memory"); | |
| 80 | 82 | } |
| 81 | 83 | text_out.append(gpa, '\n') catch @panic("IncrementalDebugServer: out of memory"); |
| 82 | 84 | conn.stream.writeAll(text_out.items) catch @panic("IncrementalDebugServer: failed to write"); |
| ... | ... | @@ -119,10 +121,8 @@ const help_str: []const u8 = |
| 119 | 121 | \\ |
| 120 | 122 | ; |
| 121 | 123 | |
| 122 | fn handleCommand(zcu: *Zcu, output: *std.ArrayListUnmanaged(u8), cmd_str: []const u8, arg_str: []const u8) Allocator.Error!void { | |
| 124 | fn handleCommand(zcu: *Zcu, w: *std.Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void { | |
| 123 | 125 | const ip = &zcu.intern_pool; |
| 124 | const gpa = zcu.gpa; | |
| 125 | const w = output.writer(gpa); | |
| 126 | 126 | if (std.mem.eql(u8, cmd_str, "help")) { |
| 127 | 127 | try w.writeAll(help_str); |
| 128 | 128 | } else if (std.mem.eql(u8, cmd_str, "summary")) { |
src/Package/Fetch.zig+5-5| ... | ... | @@ -200,7 +200,7 @@ pub const JobQueue = struct { |
| 200 | 200 | |
| 201 | 201 | const hash_slice = hash.toSlice(); |
| 202 | 202 | |
| 203 | try buf.writer().print( | |
| 203 | try buf.print( | |
| 204 | 204 | \\ pub const {f} = struct {{ |
| 205 | 205 | \\ |
| 206 | 206 | , .{std.zig.fmtId(hash_slice)}); |
| ... | ... | @@ -226,13 +226,13 @@ pub const JobQueue = struct { |
| 226 | 226 | } |
| 227 | 227 | } |
| 228 | 228 | |
| 229 | try buf.writer().print( | |
| 229 | try buf.print( | |
| 230 | 230 | \\ pub const build_root = "{f}"; |
| 231 | 231 | \\ |
| 232 | 232 | , .{std.fmt.alt(fetch.package_root, .formatEscapeString)}); |
| 233 | 233 | |
| 234 | 234 | if (fetch.has_build_zig) { |
| 235 | try buf.writer().print( | |
| 235 | try buf.print( | |
| 236 | 236 | \\ pub const build_zig = @import("{f}"); |
| 237 | 237 | \\ |
| 238 | 238 | , .{std.zig.fmtString(hash_slice)}); |
| ... | ... | @@ -245,7 +245,7 @@ pub const JobQueue = struct { |
| 245 | 245 | ); |
| 246 | 246 | for (manifest.dependencies.keys(), manifest.dependencies.values()) |name, dep| { |
| 247 | 247 | const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue; |
| 248 | try buf.writer().print( | |
| 248 | try buf.print( | |
| 249 | 249 | " .{{ \"{f}\", \"{f}\" }},\n", |
| 250 | 250 | .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) }, |
| 251 | 251 | ); |
| ... | ... | @@ -277,7 +277,7 @@ pub const JobQueue = struct { |
| 277 | 277 | |
| 278 | 278 | for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| { |
| 279 | 279 | const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue; |
| 280 | try buf.writer().print( | |
| 280 | try buf.print( | |
| 281 | 281 | " .{{ \"{f}\", \"{f}\" }},\n", |
| 282 | 282 | .{ std.zig.fmtString(name), std.zig.fmtString(h.toSlice()) }, |
| 283 | 283 | ); |
src/arch/riscv64/Emit.zig+1-1| ... | ... | @@ -31,7 +31,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 31 | 31 | var lowered_relocs = lowered.relocs; |
| 32 | 32 | for (lowered.insts, 0..) |lowered_inst, lowered_index| { |
| 33 | 33 | const start_offset: u32 = @intCast(emit.code.items.len); |
| 34 | try lowered_inst.encode(emit.code.writer(gpa)); | |
| 34 | std.mem.writeInt(u32, try emit.code.addManyAsArray(gpa, 4), lowered_inst.toU32(), .little); | |
| 35 | 35 | |
| 36 | 36 | while (lowered_relocs.len > 0 and |
| 37 | 37 | lowered_relocs[0].lowered_inst_index == lowered_index) : ({ |
src/arch/riscv64/encoding.zig+1-1| ... | ... | @@ -518,7 +518,7 @@ pub const Instruction = union(Lir.Format) { |
| 518 | 518 | }; |
| 519 | 519 | } |
| 520 | 520 | |
| 521 | pub fn encode(inst: Instruction, writer: anytype) !void { | |
| 521 | pub fn encode(inst: Instruction, writer: *std.Io.Writer) !void { | |
| 522 | 522 | try writer.writeInt(u32, inst.toU32(), .little); |
| 523 | 523 | } |
| 524 | 524 |
src/arch/wasm/Emit.zig+46-34| ... | ... | @@ -3,7 +3,7 @@ const Emit = @This(); |
| 3 | 3 | const std = @import("std"); |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | 5 | const Allocator = std.mem.Allocator; |
| 6 | const leb = std.leb; | |
| 6 | const ArrayList = std.ArrayList; | |
| 7 | 7 | |
| 8 | 8 | const Wasm = link.File.Wasm; |
| 9 | 9 | const Mir = @import("Mir.zig"); |
| ... | ... | @@ -15,7 +15,7 @@ const codegen = @import("../../codegen.zig"); |
| 15 | 15 | mir: Mir, |
| 16 | 16 | wasm: *Wasm, |
| 17 | 17 | /// The binary representation that will be emitted by this module. |
| 18 | code: *std.ArrayListUnmanaged(u8), | |
| 18 | code: *ArrayList(u8), | |
| 19 | 19 | |
| 20 | 20 | pub const Error = error{ |
| 21 | 21 | OutOfMemory, |
| ... | ... | @@ -85,7 +85,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 85 | 85 | if (is_obj) { |
| 86 | 86 | @panic("TODO"); |
| 87 | 87 | } else { |
| 88 | leb.writeUleb128(code.fixedWriter(), 1 + @intFromEnum(indirect_func_idx)) catch unreachable; | |
| 88 | writeUleb128(code, 1 + @intFromEnum(indirect_func_idx)); | |
| 89 | 89 | } |
| 90 | 90 | inst += 1; |
| 91 | 91 | continue :loop tags[inst]; |
| ... | ... | @@ -99,7 +99,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 99 | 99 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); |
| 100 | 100 | // MIR is lowered during flush, so there is indeed only one thread at this time. |
| 101 | 101 | const errors_len = 1 + comp.zcu.?.intern_pool.global_error_set.getNamesFromMainThread().len; |
| 102 | leb.writeIleb128(code.fixedWriter(), errors_len) catch unreachable; | |
| 102 | writeSleb128(code, errors_len); | |
| 103 | 103 | |
| 104 | 104 | inst += 1; |
| 105 | 105 | continue :loop tags[inst]; |
| ... | ... | @@ -122,7 +122,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 122 | 122 | continue :loop tags[inst]; |
| 123 | 123 | } else { |
| 124 | 124 | const addr: u32 = wasm.errorNameTableAddr(); |
| 125 | leb.writeIleb128(code.fixedWriter(), addr) catch unreachable; | |
| 125 | writeSleb128(code, addr); | |
| 126 | 126 | |
| 127 | 127 | inst += 1; |
| 128 | 128 | continue :loop tags[inst]; |
| ... | ... | @@ -131,7 +131,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 131 | 131 | .br_if, .br, .memory_grow, .memory_size => { |
| 132 | 132 | try code.ensureUnusedCapacity(gpa, 11); |
| 133 | 133 | code.appendAssumeCapacity(@intFromEnum(tags[inst])); |
| 134 | leb.writeUleb128(code.fixedWriter(), datas[inst].label) catch unreachable; | |
| 134 | writeUleb128(code, datas[inst].label); | |
| 135 | 135 | |
| 136 | 136 | inst += 1; |
| 137 | 137 | continue :loop tags[inst]; |
| ... | ... | @@ -140,7 +140,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 140 | 140 | .local_get, .local_set, .local_tee => { |
| 141 | 141 | try code.ensureUnusedCapacity(gpa, 11); |
| 142 | 142 | code.appendAssumeCapacity(@intFromEnum(tags[inst])); |
| 143 | leb.writeUleb128(code.fixedWriter(), datas[inst].local) catch unreachable; | |
| 143 | writeUleb128(code, datas[inst].local); | |
| 144 | 144 | |
| 145 | 145 | inst += 1; |
| 146 | 146 | continue :loop tags[inst]; |
| ... | ... | @@ -153,8 +153,8 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 153 | 153 | try code.ensureUnusedCapacity(gpa, 11 + 10 * labels.len); |
| 154 | 154 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_table)); |
| 155 | 155 | // -1 because default label is not part of length/depth. |
| 156 | leb.writeUleb128(code.fixedWriter(), extra.data.length - 1) catch unreachable; | |
| 157 | for (labels) |label| leb.writeUleb128(code.fixedWriter(), label) catch unreachable; | |
| 156 | writeUleb128(code, extra.data.length - 1); | |
| 157 | for (labels) |label| writeUleb128(code, label); | |
| 158 | 158 | |
| 159 | 159 | inst += 1; |
| 160 | 160 | continue :loop tags[inst]; |
| ... | ... | @@ -199,9 +199,9 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 199 | 199 | code.appendNTimesAssumeCapacity(0, 5); |
| 200 | 200 | } else { |
| 201 | 201 | const index: Wasm.Flush.FuncTypeIndex = .fromTypeIndex(func_ty_index, &wasm.flush_buffer); |
| 202 | leb.writeUleb128(code.fixedWriter(), @intFromEnum(index)) catch unreachable; | |
| 202 | writeUleb128(code, @intFromEnum(index)); | |
| 203 | 203 | } |
| 204 | leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // table index | |
| 204 | writeUleb128(code, @as(u32, 0)); // table index | |
| 205 | 205 | |
| 206 | 206 | inst += 1; |
| 207 | 207 | continue :loop tags[inst]; |
| ... | ... | @@ -263,7 +263,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 263 | 263 | code.appendNTimesAssumeCapacity(0, 5); |
| 264 | 264 | } else { |
| 265 | 265 | const sp_global: Wasm.GlobalIndex = .stack_pointer; |
| 266 | std.leb.writeUleb128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable; | |
| 266 | writeUleb128(code, @intFromEnum(sp_global)); | |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | 269 | inst += 1; |
| ... | ... | @@ -291,7 +291,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 291 | 291 | .i32_const => { |
| 292 | 292 | try code.ensureUnusedCapacity(gpa, 6); |
| 293 | 293 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); |
| 294 | leb.writeIleb128(code.fixedWriter(), datas[inst].imm32) catch unreachable; | |
| 294 | writeSleb128(code, datas[inst].imm32); | |
| 295 | 295 | |
| 296 | 296 | inst += 1; |
| 297 | 297 | continue :loop tags[inst]; |
| ... | ... | @@ -300,7 +300,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 300 | 300 | try code.ensureUnusedCapacity(gpa, 11); |
| 301 | 301 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const)); |
| 302 | 302 | const int64: i64 = @bitCast(mir.extraData(Mir.Imm64, datas[inst].payload).data.toInt()); |
| 303 | leb.writeIleb128(code.fixedWriter(), int64) catch unreachable; | |
| 303 | writeSleb128(code, int64); | |
| 304 | 304 | |
| 305 | 305 | inst += 1; |
| 306 | 306 | continue :loop tags[inst]; |
| ... | ... | @@ -476,33 +476,33 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 476 | 476 | const extra_index = datas[inst].payload; |
| 477 | 477 | const opcode = mir.extra[extra_index]; |
| 478 | 478 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.misc_prefix)); |
| 479 | leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable; | |
| 479 | writeUleb128(code, opcode); | |
| 480 | 480 | switch (@as(std.wasm.MiscOpcode, @enumFromInt(opcode))) { |
| 481 | 481 | // bulk-memory opcodes |
| 482 | 482 | .data_drop => { |
| 483 | 483 | const segment = mir.extra[extra_index + 1]; |
| 484 | leb.writeUleb128(code.fixedWriter(), segment) catch unreachable; | |
| 484 | writeUleb128(code, segment); | |
| 485 | 485 | |
| 486 | 486 | inst += 1; |
| 487 | 487 | continue :loop tags[inst]; |
| 488 | 488 | }, |
| 489 | 489 | .memory_init => { |
| 490 | 490 | const segment = mir.extra[extra_index + 1]; |
| 491 | leb.writeUleb128(code.fixedWriter(), segment) catch unreachable; | |
| 492 | leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // memory index | |
| 491 | writeUleb128(code, segment); | |
| 492 | writeUleb128(code, @as(u32, 0)); // memory index | |
| 493 | 493 | |
| 494 | 494 | inst += 1; |
| 495 | 495 | continue :loop tags[inst]; |
| 496 | 496 | }, |
| 497 | 497 | .memory_fill => { |
| 498 | leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // memory index | |
| 498 | writeUleb128(code, @as(u32, 0)); // memory index | |
| 499 | 499 | |
| 500 | 500 | inst += 1; |
| 501 | 501 | continue :loop tags[inst]; |
| 502 | 502 | }, |
| 503 | 503 | .memory_copy => { |
| 504 | leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // dst memory index | |
| 505 | leb.writeUleb128(code.fixedWriter(), @as(u32, 0)) catch unreachable; // src memory index | |
| 504 | writeUleb128(code, @as(u32, 0)); // dst memory index | |
| 505 | writeUleb128(code, @as(u32, 0)); // src memory index | |
| 506 | 506 | |
| 507 | 507 | inst += 1; |
| 508 | 508 | continue :loop tags[inst]; |
| ... | ... | @@ -538,7 +538,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 538 | 538 | const extra_index = datas[inst].payload; |
| 539 | 539 | const opcode = mir.extra[extra_index]; |
| 540 | 540 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.simd_prefix)); |
| 541 | leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable; | |
| 541 | writeUleb128(code, opcode); | |
| 542 | 542 | switch (@as(std.wasm.SimdOpcode, @enumFromInt(opcode))) { |
| 543 | 543 | .v128_store, |
| 544 | 544 | .v128_load, |
| ... | ... | @@ -824,7 +824,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 824 | 824 | const extra_index = datas[inst].payload; |
| 825 | 825 | const opcode = mir.extra[extra_index]; |
| 826 | 826 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix)); |
| 827 | leb.writeUleb128(code.fixedWriter(), opcode) catch unreachable; | |
| 827 | writeUleb128(code, opcode); | |
| 828 | 828 | switch (@as(std.wasm.AtomicsOpcode, @enumFromInt(opcode))) { |
| 829 | 829 | .i32_atomic_load, |
| 830 | 830 | .i64_atomic_load, |
| ... | ... | @@ -900,7 +900,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 900 | 900 | // Hard-codes memory index 0 since multi-memory proposal is |
| 901 | 901 | // not yet accepted nor implemented. |
| 902 | 902 | const memory_index: u32 = 0; |
| 903 | leb.writeUleb128(code.fixedWriter(), memory_index) catch unreachable; | |
| 903 | writeUleb128(code, memory_index); | |
| 904 | 904 | inst += 1; |
| 905 | 905 | continue :loop tags[inst]; |
| 906 | 906 | }, |
| ... | ... | @@ -915,15 +915,15 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 915 | 915 | } |
| 916 | 916 | |
| 917 | 917 | /// Asserts 20 unused capacity. |
| 918 | fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void { | |
| 918 | fn encodeMemArg(code: *ArrayList(u8), mem_arg: Mir.MemArg) void { | |
| 919 | 919 | assert(code.unusedCapacitySlice().len >= 20); |
| 920 | 920 | // Wasm encodes alignment as power of 2, rather than natural alignment. |
| 921 | 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; | |
| 922 | writeUleb128(code, encoded_alignment); | |
| 923 | writeUleb128(code, mem_arg.offset); | |
| 924 | 924 | } |
| 925 | 925 | |
| 926 | fn uavRefObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { | |
| 926 | fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { | |
| 927 | 927 | const comp = wasm.base.comp; |
| 928 | 928 | const gpa = comp.gpa; |
| 929 | 929 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| ... | ... | @@ -940,7 +940,7 @@ fn uavRefObj(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.I |
| 940 | 940 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| 941 | 941 | } |
| 942 | 942 | |
| 943 | fn uavRefExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { | |
| 943 | fn uavRefExe(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: i32, is_wasm32: bool) !void { | |
| 944 | 944 | const comp = wasm.base.comp; |
| 945 | 945 | const gpa = comp.gpa; |
| 946 | 946 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| ... | ... | @@ -949,10 +949,10 @@ fn uavRefExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), value: InternPool.I |
| 949 | 949 | code.appendAssumeCapacity(@intFromEnum(opcode)); |
| 950 | 950 | |
| 951 | 951 | const addr = wasm.uavAddr(value); |
| 952 | leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + offset))) catch unreachable; | |
| 952 | writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + offset))); | |
| 953 | 953 | } |
| 954 | 954 | |
| 955 | fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff, is_wasm32: bool) !void { | |
| 955 | fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: bool) !void { | |
| 956 | 956 | const comp = wasm.base.comp; |
| 957 | 957 | const zcu = comp.zcu.?; |
| 958 | 958 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -975,10 +975,22 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff |
| 975 | 975 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); |
| 976 | 976 | } else { |
| 977 | 977 | const addr = wasm.navAddr(data.nav_index); |
| 978 | leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; | |
| 978 | writeUleb128(code, @as(u32, @intCast(@as(i64, addr) + data.offset))); | |
| 979 | 979 | } |
| 980 | 980 | } |
| 981 | 981 | |
| 982 | fn appendOutputFunctionIndex(code: *std.ArrayListUnmanaged(u8), i: Wasm.OutputFunctionIndex) void { | |
| 983 | leb.writeUleb128(code.fixedWriter(), @intFromEnum(i)) catch unreachable; | |
| 982 | fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex) void { | |
| 983 | writeUleb128(code, @intFromEnum(i)); | |
| 984 | } | |
| 985 | ||
| 986 | fn writeUleb128(code: *ArrayList(u8), arg: anytype) void { | |
| 987 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); | |
| 988 | w.writeUleb128(arg) catch unreachable; | |
| 989 | code.items.len += w.end; | |
| 990 | } | |
| 991 | ||
| 992 | fn writeSleb128(code: *ArrayList(u8), arg: anytype) void { | |
| 993 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); | |
| 994 | w.writeSleb128(arg) catch unreachable; | |
| 995 | code.items.len += w.end; | |
| 984 | 996 | } |
src/arch/wasm/Mir.zig+22-17| ... | ... | @@ -675,10 +675,13 @@ pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) st |
| 675 | 675 | // Write the locals in the prologue of the function body. |
| 676 | 676 | try code.ensureUnusedCapacity(gpa, 5 + mir.locals.len * 6 + 38); |
| 677 | 677 | |
| 678 | std.leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(mir.locals.len))) catch unreachable; | |
| 678 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); | |
| 679 | ||
| 680 | w.writeLeb128(@as(u32, @intCast(mir.locals.len))) catch unreachable; | |
| 681 | ||
| 679 | 682 | for (mir.locals) |local| { |
| 680 | std.leb.writeUleb128(code.fixedWriter(), @as(u32, 1)) catch unreachable; | |
| 681 | code.appendAssumeCapacity(@intFromEnum(local)); | |
| 683 | w.writeLeb128(@as(u32, 1)) catch unreachable; | |
| 684 | w.writeByte(@intFromEnum(local)) catch unreachable; | |
| 682 | 685 | } |
| 683 | 686 | |
| 684 | 687 | // Stack management section of function prologue. |
| ... | ... | @@ -686,33 +689,35 @@ pub fn lower(mir: *const Mir, wasm: *Wasm, code: *std.ArrayListUnmanaged(u8)) st |
| 686 | 689 | if (stack_alignment.toByteUnits()) |align_bytes| { |
| 687 | 690 | const sp_global: Wasm.GlobalIndex = .stack_pointer; |
| 688 | 691 | // load stack pointer |
| 689 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_get)); | |
| 690 | std.leb.writeUleb128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable; | |
| 692 | w.writeByte(@intFromEnum(std.wasm.Opcode.global_get)) catch unreachable; | |
| 693 | w.writeUleb128(@intFromEnum(sp_global)) catch unreachable; | |
| 691 | 694 | // store stack pointer so we can restore it when we return from the function |
| 692 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee)); | |
| 693 | leb.writeUleb128(code.fixedWriter(), mir.prologue.sp_local) catch unreachable; | |
| 695 | w.writeByte(@intFromEnum(std.wasm.Opcode.local_tee)) catch unreachable; | |
| 696 | w.writeUleb128(mir.prologue.sp_local) catch unreachable; | |
| 694 | 697 | // get the total stack size |
| 695 | 698 | const aligned_stack: i32 = @intCast(stack_alignment.forward(mir.prologue.stack_size)); |
| 696 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); | |
| 697 | leb.writeIleb128(code.fixedWriter(), aligned_stack) catch unreachable; | |
| 699 | w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const)) catch unreachable; | |
| 700 | w.writeSleb128(aligned_stack) catch unreachable; | |
| 698 | 701 | // subtract it from the current stack pointer |
| 699 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_sub)); | |
| 702 | w.writeByte(@intFromEnum(std.wasm.Opcode.i32_sub)) catch unreachable; | |
| 700 | 703 | // Get negative stack alignment |
| 701 | 704 | const neg_stack_align = @as(i32, @intCast(align_bytes)) * -1; |
| 702 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); | |
| 703 | leb.writeIleb128(code.fixedWriter(), neg_stack_align) catch unreachable; | |
| 705 | w.writeByte(@intFromEnum(std.wasm.Opcode.i32_const)) catch unreachable; | |
| 706 | w.writeSleb128(neg_stack_align) catch unreachable; | |
| 704 | 707 | // Bitwise-and the value to get the new stack pointer to ensure the |
| 705 | 708 | // pointers are aligned with the abi alignment. |
| 706 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_and)); | |
| 709 | w.writeByte(@intFromEnum(std.wasm.Opcode.i32_and)) catch unreachable; | |
| 707 | 710 | // The bottom will be used to calculate all stack pointer offsets. |
| 708 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_tee)); | |
| 709 | leb.writeUleb128(code.fixedWriter(), mir.prologue.bottom_stack_local) catch unreachable; | |
| 711 | w.writeByte(@intFromEnum(std.wasm.Opcode.local_tee)) catch unreachable; | |
| 712 | w.writeUleb128(mir.prologue.bottom_stack_local) catch unreachable; | |
| 710 | 713 | // Store the current stack pointer value into the global stack pointer so other function calls will |
| 711 | 714 | // start from this value instead and not overwrite the current stack. |
| 712 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.global_set)); | |
| 713 | std.leb.writeUleb128(code.fixedWriter(), @intFromEnum(sp_global)) catch unreachable; | |
| 715 | w.writeByte(@intFromEnum(std.wasm.Opcode.global_set)) catch unreachable; | |
| 716 | w.writeUleb128(@intFromEnum(sp_global)) catch unreachable; | |
| 714 | 717 | } |
| 715 | 718 | |
| 719 | code.items.len += w.end; | |
| 720 | ||
| 716 | 721 | var emit: Emit = .{ |
| 717 | 722 | .mir = mir.*, |
| 718 | 723 | .wasm = wasm, |
src/codegen.zig+13-12| ... | ... | @@ -6,6 +6,7 @@ const link = @import("link.zig"); |
| 6 | 6 | const log = std.log.scoped(.codegen); |
| 7 | 7 | const mem = std.mem; |
| 8 | 8 | const math = std.math; |
| 9 | const ArrayList = std.ArrayList; | |
| 9 | 10 | const target_util = @import("target.zig"); |
| 10 | 11 | const trace = @import("tracy.zig").trace; |
| 11 | 12 | |
| ... | ... | @@ -179,7 +180,7 @@ pub fn emitFunction( |
| 179 | 180 | src_loc: Zcu.LazySrcLoc, |
| 180 | 181 | func_index: InternPool.Index, |
| 181 | 182 | any_mir: *const AnyMir, |
| 182 | code: *std.ArrayListUnmanaged(u8), | |
| 183 | code: *ArrayList(u8), | |
| 183 | 184 | debug_output: link.File.DebugInfoOutput, |
| 184 | 185 | ) CodeGenError!void { |
| 185 | 186 | const zcu = pt.zcu; |
| ... | ... | @@ -204,7 +205,7 @@ pub fn generateLazyFunction( |
| 204 | 205 | pt: Zcu.PerThread, |
| 205 | 206 | src_loc: Zcu.LazySrcLoc, |
| 206 | 207 | lazy_sym: link.File.LazySymbol, |
| 207 | code: *std.ArrayListUnmanaged(u8), | |
| 208 | code: *ArrayList(u8), | |
| 208 | 209 | debug_output: link.File.DebugInfoOutput, |
| 209 | 210 | ) CodeGenError!void { |
| 210 | 211 | const zcu = pt.zcu; |
| ... | ... | @@ -236,7 +237,7 @@ pub fn generateLazySymbol( |
| 236 | 237 | lazy_sym: link.File.LazySymbol, |
| 237 | 238 | // TODO don't use an "out" parameter like this; put it in the result instead |
| 238 | 239 | alignment: *Alignment, |
| 239 | code: *std.ArrayListUnmanaged(u8), | |
| 240 | code: *ArrayList(u8), | |
| 240 | 241 | debug_output: link.File.DebugInfoOutput, |
| 241 | 242 | reloc_parent: link.File.RelocInfo.Parent, |
| 242 | 243 | ) CodeGenError!void { |
| ... | ... | @@ -311,7 +312,7 @@ pub fn generateSymbol( |
| 311 | 312 | pt: Zcu.PerThread, |
| 312 | 313 | src_loc: Zcu.LazySrcLoc, |
| 313 | 314 | val: Value, |
| 314 | code: *std.ArrayListUnmanaged(u8), | |
| 315 | code: *ArrayList(u8), | |
| 315 | 316 | reloc_parent: link.File.RelocInfo.Parent, |
| 316 | 317 | ) GenerateSymbolError!void { |
| 317 | 318 | const tracy = trace(@src()); |
| ... | ... | @@ -379,7 +380,7 @@ pub fn generateSymbol( |
| 379 | 380 | }, |
| 380 | 381 | .err => |err| { |
| 381 | 382 | const int = try pt.getErrorValue(err.name); |
| 382 | try code.writer(gpa).writeInt(u16, @intCast(int), endian); | |
| 383 | mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(int), endian); | |
| 383 | 384 | }, |
| 384 | 385 | .error_union => |error_union| { |
| 385 | 386 | const payload_ty = ty.errorUnionPayload(zcu); |
| ... | ... | @@ -389,7 +390,7 @@ pub fn generateSymbol( |
| 389 | 390 | }; |
| 390 | 391 | |
| 391 | 392 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 392 | try code.writer(gpa).writeInt(u16, err_val, endian); | |
| 393 | mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); | |
| 393 | 394 | return; |
| 394 | 395 | } |
| 395 | 396 | |
| ... | ... | @@ -399,7 +400,7 @@ pub fn generateSymbol( |
| 399 | 400 | |
| 400 | 401 | // error value first when its type is larger than the error union's payload |
| 401 | 402 | if (error_align.order(payload_align) == .gt) { |
| 402 | try code.writer(gpa).writeInt(u16, err_val, endian); | |
| 403 | mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); | |
| 403 | 404 | } |
| 404 | 405 | |
| 405 | 406 | // emit payload part of the error union |
| ... | ... | @@ -421,7 +422,7 @@ pub fn generateSymbol( |
| 421 | 422 | // Payload size is larger than error set, so emit our error set last |
| 422 | 423 | if (error_align.compare(.lte, payload_align)) { |
| 423 | 424 | const begin = code.items.len; |
| 424 | try code.writer(gpa).writeInt(u16, err_val, endian); | |
| 425 | mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); | |
| 425 | 426 | const unpadded_end = code.items.len - begin; |
| 426 | 427 | const padded_end = abi_align.forward(unpadded_end); |
| 427 | 428 | const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow; |
| ... | ... | @@ -476,7 +477,7 @@ pub fn generateSymbol( |
| 476 | 477 | })); |
| 477 | 478 | try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent); |
| 478 | 479 | } |
| 479 | try code.writer(gpa).writeByte(@intFromBool(payload_val != null)); | |
| 480 | try code.append(gpa, @intFromBool(payload_val != null)); | |
| 480 | 481 | try code.appendNTimes(gpa, 0, padding); |
| 481 | 482 | } |
| 482 | 483 | }, |
| ... | ... | @@ -721,7 +722,7 @@ fn lowerPtr( |
| 721 | 722 | pt: Zcu.PerThread, |
| 722 | 723 | src_loc: Zcu.LazySrcLoc, |
| 723 | 724 | ptr_val: InternPool.Index, |
| 724 | code: *std.ArrayListUnmanaged(u8), | |
| 725 | code: *ArrayList(u8), | |
| 725 | 726 | reloc_parent: link.File.RelocInfo.Parent, |
| 726 | 727 | prev_offset: u64, |
| 727 | 728 | ) GenerateSymbolError!void { |
| ... | ... | @@ -774,7 +775,7 @@ fn lowerUavRef( |
| 774 | 775 | pt: Zcu.PerThread, |
| 775 | 776 | src_loc: Zcu.LazySrcLoc, |
| 776 | 777 | uav: InternPool.Key.Ptr.BaseAddr.Uav, |
| 777 | code: *std.ArrayListUnmanaged(u8), | |
| 778 | code: *ArrayList(u8), | |
| 778 | 779 | reloc_parent: link.File.RelocInfo.Parent, |
| 779 | 780 | offset: u64, |
| 780 | 781 | ) GenerateSymbolError!void { |
| ... | ... | @@ -834,7 +835,7 @@ fn lowerNavRef( |
| 834 | 835 | lf: *link.File, |
| 835 | 836 | pt: Zcu.PerThread, |
| 836 | 837 | nav_index: InternPool.Nav.Index, |
| 837 | code: *std.ArrayListUnmanaged(u8), | |
| 838 | code: *ArrayList(u8), | |
| 838 | 839 | reloc_parent: link.File.RelocInfo.Parent, |
| 839 | 840 | offset: u64, |
| 840 | 841 | ) GenerateSymbolError!void { |
src/libs/freebsd.zig+42-39| ... | ... | @@ -512,7 +512,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 512 | 512 | { |
| 513 | 513 | var map_contents = std.array_list.Managed(u8).init(arena); |
| 514 | 514 | for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| { |
| 515 | try map_contents.writer().print("FBSD_{d}.{d} {{ }};\n", .{ ver.major, ver.minor }); | |
| 515 | try map_contents.print("FBSD_{d}.{d} {{ }};\n", .{ ver.major, ver.minor }); | |
| 516 | 516 | } |
| 517 | 517 | try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items }); |
| 518 | 518 | map_contents.deinit(); |
| ... | ... | @@ -524,20 +524,17 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 524 | 524 | for (libs, 0..) |lib, lib_i| { |
| 525 | 525 | stubs_asm.shrinkRetainingCapacity(0); |
| 526 | 526 | |
| 527 | const stubs_writer = stubs_asm.writer(); | |
| 528 | ||
| 529 | try stubs_writer.writeAll(".text\n"); | |
| 527 | try stubs_asm.appendSlice(".text\n"); | |
| 530 | 528 | |
| 531 | 529 | var sym_i: usize = 0; |
| 532 | var sym_name_buf = std.array_list.Managed(u8).init(arena); | |
| 530 | var sym_name_buf: std.Io.Writer.Allocating = .init(arena); | |
| 533 | 531 | var opt_symbol_name: ?[]const u8 = null; |
| 534 | 532 | var versions = try std.DynamicBitSetUnmanaged.initEmpty(arena, metadata.all_versions.len); |
| 535 | 533 | var weak_linkages = try std.DynamicBitSetUnmanaged.initEmpty(arena, metadata.all_versions.len); |
| 536 | 534 | |
| 537 | var inc_fbs = std.io.fixedBufferStream(metadata.inclusions); | |
| 538 | var inc_reader = inc_fbs.reader(); | |
| 535 | var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); | |
| 539 | 536 | |
| 540 | const fn_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 537 | const fn_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 541 | 538 | |
| 542 | 539 | // Pick the default symbol version: |
| 543 | 540 | // - If there are no versions, don't emit it |
| ... | ... | @@ -550,19 +547,21 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 550 | 547 | while (sym_i < fn_inclusions_len) : (sym_i += 1) { |
| 551 | 548 | const sym_name = opt_symbol_name orelse n: { |
| 552 | 549 | sym_name_buf.clearRetainingCapacity(); |
| 553 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 550 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 551 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 552 | inc_reader.toss(1); | |
| 554 | 553 | |
| 555 | opt_symbol_name = sym_name_buf.items; | |
| 554 | opt_symbol_name = sym_name_buf.written(); | |
| 556 | 555 | versions.unsetAll(); |
| 557 | 556 | weak_linkages.unsetAll(); |
| 558 | 557 | chosen_def_ver_index = 255; |
| 559 | 558 | chosen_unversioned_ver_index = 255; |
| 560 | 559 | |
| 561 | break :n sym_name_buf.items; | |
| 560 | break :n sym_name_buf.written(); | |
| 562 | 561 | }; |
| 563 | 562 | { |
| 564 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 565 | var lib_index = try inc_reader.readByte(); | |
| 563 | const targets = try inc_reader.takeLeb128(u64); | |
| 564 | var lib_index = try inc_reader.takeByte(); | |
| 566 | 565 | |
| 567 | 566 | const is_unversioned = (lib_index & (1 << 5)) != 0; |
| 568 | 567 | const is_weak = (lib_index & (1 << 6)) != 0; |
| ... | ... | @@ -576,7 +575,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 576 | 575 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 577 | 576 | |
| 578 | 577 | while (true) { |
| 579 | const byte = try inc_reader.readByte(); | |
| 578 | const byte = try inc_reader.takeByte(); | |
| 580 | 579 | const last = (byte & 0b1000_0000) != 0; |
| 581 | 580 | const ver_i = @as(u7, @truncate(byte)); |
| 582 | 581 | if (ok_lib_and_target and ver_i <= target_ver_index) { |
| ... | ... | @@ -608,7 +607,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 608 | 607 | // .globl _Exit |
| 609 | 608 | // .type _Exit, %function |
| 610 | 609 | // _Exit: .long 0 |
| 611 | try stubs_writer.print( | |
| 610 | try stubs_asm.print( | |
| 612 | 611 | \\.balign {d} |
| 613 | 612 | \\.{s} {s} |
| 614 | 613 | \\.type {s}, %function |
| ... | ... | @@ -640,7 +639,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 640 | 639 | .{ sym_name, ver.major, ver.minor }, |
| 641 | 640 | ); |
| 642 | 641 | |
| 643 | try stubs_writer.print( | |
| 642 | try stubs_asm.print( | |
| 644 | 643 | \\.balign {d} |
| 645 | 644 | \\.{s} {s} |
| 646 | 645 | \\.type {s}, %function |
| ... | ... | @@ -665,14 +664,14 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 665 | 664 | } |
| 666 | 665 | } |
| 667 | 666 | |
| 668 | try stubs_writer.writeAll(".data\n"); | |
| 667 | try stubs_asm.appendSlice(".data\n"); | |
| 669 | 668 | |
| 670 | 669 | // FreeBSD's `libc.so.7` contains strong references to `__progname` and `environ` which are |
| 671 | 670 | // defined in the statically-linked startup code. Those references cause the linker to put |
| 672 | 671 | // the symbols in the dynamic symbol table. We need to create dummy references to them here |
| 673 | 672 | // to get the same effect. |
| 674 | 673 | if (std.mem.eql(u8, lib.name, "c")) { |
| 675 | try stubs_writer.print( | |
| 674 | try stubs_asm.print( | |
| 676 | 675 | \\.balign {d} |
| 677 | 676 | \\.globl __progname |
| 678 | 677 | \\.globl environ |
| ... | ... | @@ -686,7 +685,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 686 | 685 | }); |
| 687 | 686 | } |
| 688 | 687 | |
| 689 | const obj_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 688 | const obj_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 690 | 689 | |
| 691 | 690 | var sizes = try arena.alloc(u16, metadata.all_versions.len); |
| 692 | 691 | |
| ... | ... | @@ -696,21 +695,23 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 696 | 695 | while (sym_i < obj_inclusions_len) : (sym_i += 1) { |
| 697 | 696 | const sym_name = opt_symbol_name orelse n: { |
| 698 | 697 | sym_name_buf.clearRetainingCapacity(); |
| 699 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 698 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 699 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 700 | inc_reader.toss(1); | |
| 700 | 701 | |
| 701 | opt_symbol_name = sym_name_buf.items; | |
| 702 | opt_symbol_name = sym_name_buf.written(); | |
| 702 | 703 | versions.unsetAll(); |
| 703 | 704 | weak_linkages.unsetAll(); |
| 704 | 705 | chosen_def_ver_index = 255; |
| 705 | 706 | chosen_unversioned_ver_index = 255; |
| 706 | 707 | |
| 707 | break :n sym_name_buf.items; | |
| 708 | break :n sym_name_buf.written(); | |
| 708 | 709 | }; |
| 709 | 710 | |
| 710 | 711 | { |
| 711 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 712 | const size = try std.leb.readUleb128(u16, inc_reader); | |
| 713 | var lib_index = try inc_reader.readByte(); | |
| 712 | const targets = try inc_reader.takeLeb128(u64); | |
| 713 | const size = try inc_reader.takeLeb128(u16); | |
| 714 | var lib_index = try inc_reader.takeByte(); | |
| 714 | 715 | |
| 715 | 716 | const is_unversioned = (lib_index & (1 << 5)) != 0; |
| 716 | 717 | const is_weak = (lib_index & (1 << 6)) != 0; |
| ... | ... | @@ -724,7 +725,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 724 | 725 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 725 | 726 | |
| 726 | 727 | while (true) { |
| 727 | const byte = try inc_reader.readByte(); | |
| 728 | const byte = try inc_reader.takeByte(); | |
| 728 | 729 | const last = (byte & 0b1000_0000) != 0; |
| 729 | 730 | const ver_i = @as(u7, @truncate(byte)); |
| 730 | 731 | if (ok_lib_and_target and ver_i <= target_ver_index) { |
| ... | ... | @@ -758,7 +759,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 758 | 759 | // .type malloc_conf, %object |
| 759 | 760 | // .size malloc_conf, 4 |
| 760 | 761 | // malloc_conf: .fill 4, 1, 0 |
| 761 | try stubs_writer.print( | |
| 762 | try stubs_asm.print( | |
| 762 | 763 | \\.balign {d} |
| 763 | 764 | \\.{s} {s} |
| 764 | 765 | \\.type {s}, %object |
| ... | ... | @@ -794,7 +795,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 794 | 795 | .{ sym_name, ver.major, ver.minor }, |
| 795 | 796 | ); |
| 796 | 797 | |
| 797 | try stubs_asm.writer().print( | |
| 798 | try stubs_asm.print( | |
| 798 | 799 | \\.balign {d} |
| 799 | 800 | \\.{s} {s} |
| 800 | 801 | \\.type {s}, %object |
| ... | ... | @@ -822,9 +823,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 822 | 823 | } |
| 823 | 824 | } |
| 824 | 825 | |
| 825 | try stubs_writer.writeAll(".tdata\n"); | |
| 826 | try stubs_asm.appendSlice(".tdata\n"); | |
| 826 | 827 | |
| 827 | const tls_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 828 | const tls_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 828 | 829 | |
| 829 | 830 | sym_i = 0; |
| 830 | 831 | opt_symbol_name = null; |
| ... | ... | @@ -832,21 +833,23 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 832 | 833 | while (sym_i < tls_inclusions_len) : (sym_i += 1) { |
| 833 | 834 | const sym_name = opt_symbol_name orelse n: { |
| 834 | 835 | sym_name_buf.clearRetainingCapacity(); |
| 835 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 836 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 837 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 838 | inc_reader.toss(1); | |
| 836 | 839 | |
| 837 | opt_symbol_name = sym_name_buf.items; | |
| 840 | opt_symbol_name = sym_name_buf.written(); | |
| 838 | 841 | versions.unsetAll(); |
| 839 | 842 | weak_linkages.unsetAll(); |
| 840 | 843 | chosen_def_ver_index = 255; |
| 841 | 844 | chosen_unversioned_ver_index = 255; |
| 842 | 845 | |
| 843 | break :n sym_name_buf.items; | |
| 846 | break :n sym_name_buf.written(); | |
| 844 | 847 | }; |
| 845 | 848 | |
| 846 | 849 | { |
| 847 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 848 | const size = try std.leb.readUleb128(u16, inc_reader); | |
| 849 | var lib_index = try inc_reader.readByte(); | |
| 850 | const targets = try inc_reader.takeLeb128(u64); | |
| 851 | const size = try inc_reader.takeLeb128(u16); | |
| 852 | var lib_index = try inc_reader.takeByte(); | |
| 850 | 853 | |
| 851 | 854 | const is_unversioned = (lib_index & (1 << 5)) != 0; |
| 852 | 855 | const is_weak = (lib_index & (1 << 6)) != 0; |
| ... | ... | @@ -860,7 +863,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 860 | 863 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 861 | 864 | |
| 862 | 865 | while (true) { |
| 863 | const byte = try inc_reader.readByte(); | |
| 866 | const byte = try inc_reader.takeByte(); | |
| 864 | 867 | const last = (byte & 0b1000_0000) != 0; |
| 865 | 868 | const ver_i = @as(u7, @truncate(byte)); |
| 866 | 869 | if (ok_lib_and_target and ver_i <= target_ver_index) { |
| ... | ... | @@ -894,7 +897,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 894 | 897 | // .type _ThreadRuneLocale, %object |
| 895 | 898 | // .size _ThreadRuneLocale, 4 |
| 896 | 899 | // _ThreadRuneLocale: .fill 4, 1, 0 |
| 897 | try stubs_writer.print( | |
| 900 | try stubs_asm.print( | |
| 898 | 901 | \\.balign {d} |
| 899 | 902 | \\.{s} {s} |
| 900 | 903 | \\.type {s}, %tls_object |
| ... | ... | @@ -930,7 +933,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 930 | 933 | .{ sym_name, ver.major, ver.minor }, |
| 931 | 934 | ); |
| 932 | 935 | |
| 933 | try stubs_writer.print( | |
| 936 | try stubs_asm.print( | |
| 934 | 937 | \\.balign {d} |
| 935 | 938 | \\.{s} {s} |
| 936 | 939 | \\.type {s}, %tls_object |
src/libs/glibc.zig+28-25| ... | ... | @@ -752,9 +752,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 752 | 752 | var map_contents = std.array_list.Managed(u8).init(arena); |
| 753 | 753 | for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| { |
| 754 | 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 | 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 | 760 | try o_directory.handle.writeFile(.{ .sub_path = all_map_basename, .data = map_contents.items }); |
| ... | ... | @@ -773,7 +773,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 773 | 773 | try stubs_asm.appendSlice(".text\n"); |
| 774 | 774 | |
| 775 | 775 | var sym_i: usize = 0; |
| 776 | var sym_name_buf = std.array_list.Managed(u8).init(arena); | |
| 776 | var sym_name_buf: std.Io.Writer.Allocating = .init(arena); | |
| 777 | 777 | var opt_symbol_name: ?[]const u8 = null; |
| 778 | 778 | var versions_buffer: [32]u8 = undefined; |
| 779 | 779 | var versions_len: usize = undefined; |
| ... | ... | @@ -794,24 +794,25 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 794 | 794 | // twice, which causes a "duplicate symbol" assembler error. |
| 795 | 795 | var versions_written = std.AutoArrayHashMap(Version, void).init(arena); |
| 796 | 796 | |
| 797 | var inc_fbs = std.io.fixedBufferStream(metadata.inclusions); | |
| 798 | var inc_reader = inc_fbs.reader(); | |
| 797 | var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); | |
| 799 | 798 | |
| 800 | const fn_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 799 | const fn_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 801 | 800 | |
| 802 | 801 | while (sym_i < fn_inclusions_len) : (sym_i += 1) { |
| 803 | 802 | const sym_name = opt_symbol_name orelse n: { |
| 804 | 803 | sym_name_buf.clearRetainingCapacity(); |
| 805 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 804 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 805 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 806 | inc_reader.toss(1); | |
| 806 | 807 | |
| 807 | opt_symbol_name = sym_name_buf.items; | |
| 808 | opt_symbol_name = sym_name_buf.written(); | |
| 808 | 809 | versions_buffer = undefined; |
| 809 | 810 | versions_len = 0; |
| 810 | 811 | |
| 811 | break :n sym_name_buf.items; | |
| 812 | break :n sym_name_buf.written(); | |
| 812 | 813 | }; |
| 813 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 814 | var lib_index = try inc_reader.readByte(); | |
| 814 | const targets = try inc_reader.takeLeb128(u64); | |
| 815 | var lib_index = try inc_reader.takeByte(); | |
| 815 | 816 | |
| 816 | 817 | const is_terminal = (lib_index & (1 << 7)) != 0; |
| 817 | 818 | if (is_terminal) { |
| ... | ... | @@ -825,7 +826,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 825 | 826 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 826 | 827 | |
| 827 | 828 | while (true) { |
| 828 | const byte = try inc_reader.readByte(); | |
| 829 | const byte = try inc_reader.takeByte(); | |
| 829 | 830 | const last = (byte & 0b1000_0000) != 0; |
| 830 | 831 | const ver_i = @as(u7, @truncate(byte)); |
| 831 | 832 | if (ok_lib_and_target and ver_i <= target_ver_index) { |
| ... | ... | @@ -880,7 +881,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 880 | 881 | "{s}_{d}_{d}", |
| 881 | 882 | .{ sym_name, ver.major, ver.minor }, |
| 882 | 883 | ); |
| 883 | try stubs_asm.writer().print( | |
| 884 | try stubs_asm.print( | |
| 884 | 885 | \\.balign {d} |
| 885 | 886 | \\.globl {s} |
| 886 | 887 | \\.type {s}, %function |
| ... | ... | @@ -905,7 +906,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 905 | 906 | "{s}_{d}_{d}_{d}", |
| 906 | 907 | .{ sym_name, ver.major, ver.minor, ver.patch }, |
| 907 | 908 | ); |
| 908 | try stubs_asm.writer().print( | |
| 909 | try stubs_asm.print( | |
| 909 | 910 | \\.balign {d} |
| 910 | 911 | \\.globl {s} |
| 911 | 912 | \\.type {s}, %function |
| ... | ... | @@ -950,7 +951,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 950 | 951 | // versions where the symbol didn't exist. We only care about modern glibc versions, so use |
| 951 | 952 | // a strong reference. |
| 952 | 953 | if (std.mem.eql(u8, lib.name, "c")) { |
| 953 | try stubs_asm.writer().print( | |
| 954 | try stubs_asm.print( | |
| 954 | 955 | \\.balign {d} |
| 955 | 956 | \\.globl _IO_stdin_used |
| 956 | 957 | \\{s} _IO_stdin_used |
| ... | ... | @@ -963,7 +964,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 963 | 964 | |
| 964 | 965 | try stubs_asm.appendSlice(".data\n"); |
| 965 | 966 | |
| 966 | const obj_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 967 | const obj_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 967 | 968 | |
| 968 | 969 | var sizes = try arena.alloc(u16, metadata.all_versions.len); |
| 969 | 970 | |
| ... | ... | @@ -974,17 +975,19 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 974 | 975 | while (sym_i < obj_inclusions_len) : (sym_i += 1) { |
| 975 | 976 | const sym_name = opt_symbol_name orelse n: { |
| 976 | 977 | sym_name_buf.clearRetainingCapacity(); |
| 977 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 978 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 979 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 980 | inc_reader.toss(1); | |
| 978 | 981 | |
| 979 | opt_symbol_name = sym_name_buf.items; | |
| 982 | opt_symbol_name = sym_name_buf.written(); | |
| 980 | 983 | versions_buffer = undefined; |
| 981 | 984 | versions_len = 0; |
| 982 | 985 | |
| 983 | break :n sym_name_buf.items; | |
| 986 | break :n sym_name_buf.written(); | |
| 984 | 987 | }; |
| 985 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 986 | const size = try std.leb.readUleb128(u16, inc_reader); | |
| 987 | var lib_index = try inc_reader.readByte(); | |
| 988 | const targets = try inc_reader.takeLeb128(u64); | |
| 989 | const size = try inc_reader.takeLeb128(u16); | |
| 990 | var lib_index = try inc_reader.takeByte(); | |
| 988 | 991 | |
| 989 | 992 | const is_terminal = (lib_index & (1 << 7)) != 0; |
| 990 | 993 | if (is_terminal) { |
| ... | ... | @@ -998,7 +1001,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 998 | 1001 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 999 | 1002 | |
| 1000 | 1003 | while (true) { |
| 1001 | const byte = try inc_reader.readByte(); | |
| 1004 | const byte = try inc_reader.takeByte(); | |
| 1002 | 1005 | const last = (byte & 0b1000_0000) != 0; |
| 1003 | 1006 | const ver_i = @as(u7, @truncate(byte)); |
| 1004 | 1007 | if (ok_lib_and_target and ver_i <= target_ver_index) { |
| ... | ... | @@ -1055,7 +1058,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 1055 | 1058 | "{s}_{d}_{d}", |
| 1056 | 1059 | .{ sym_name, ver.major, ver.minor }, |
| 1057 | 1060 | ); |
| 1058 | try stubs_asm.writer().print( | |
| 1061 | try stubs_asm.print( | |
| 1059 | 1062 | \\.balign {d} |
| 1060 | 1063 | \\.globl {s} |
| 1061 | 1064 | \\.type {s}, %object |
| ... | ... | @@ -1083,7 +1086,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 1083 | 1086 | "{s}_{d}_{d}_{d}", |
| 1084 | 1087 | .{ sym_name, ver.major, ver.minor, ver.patch }, |
| 1085 | 1088 | ); |
| 1086 | try stubs_asm.writer().print( | |
| 1089 | try stubs_asm.print( | |
| 1087 | 1090 | \\.balign {d} |
| 1088 | 1091 | \\.globl {s} |
| 1089 | 1092 | \\.type {s}, %object |
src/libs/mingw.zig+12-10| ... | ... | @@ -304,9 +304,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 304 | 304 | const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" }); |
| 305 | 305 | |
| 306 | 306 | if (comp.verbose_cc) print: { |
| 307 | std.debug.lockStdErr(); | |
| 308 | defer std.debug.unlockStdErr(); | |
| 309 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 307 | var stderr = std.debug.lockStderrWriter(&.{}); | |
| 308 | defer std.debug.unlockStderrWriter(); | |
| 310 | 309 | nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print; |
| 311 | 310 | nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print; |
| 312 | 311 | nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print; |
| ... | ... | @@ -335,7 +334,10 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 335 | 334 | // new scope to ensure definition file is written before passing the path to WriteImportLibrary |
| 336 | 335 | const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true }); |
| 337 | 336 | defer def_final_file.close(); |
| 338 | try pp.prettyPrintTokens(def_final_file.deprecatedWriter(), .result_only); | |
| 337 | var buffer: [1024]u8 = undefined; | |
| 338 | var def_final_file_writer = def_final_file.writer(&buffer); | |
| 339 | try pp.prettyPrintTokens(&def_final_file_writer.interface, .result_only); | |
| 340 | try def_final_file_writer.interface.flush(); | |
| 339 | 341 | } |
| 340 | 342 | |
| 341 | 343 | const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }); |
| ... | ... | @@ -410,9 +412,9 @@ fn findDef( |
| 410 | 412 | // Try the archtecture-specific path first. |
| 411 | 413 | const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def"; |
| 412 | 414 | if (zig_lib_directory.path) |p| { |
| 413 | try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name }); | |
| 415 | try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name }); | |
| 414 | 416 | } else { |
| 415 | try override_path.writer().print(fmt_path, .{ lib_path, lib_name }); | |
| 417 | try override_path.print(fmt_path, .{ lib_path, lib_name }); | |
| 416 | 418 | } |
| 417 | 419 | if (std.fs.cwd().access(override_path.items, .{})) |_| { |
| 418 | 420 | return override_path.toOwnedSlice(); |
| ... | ... | @@ -427,9 +429,9 @@ fn findDef( |
| 427 | 429 | override_path.shrinkRetainingCapacity(0); |
| 428 | 430 | const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def"; |
| 429 | 431 | if (zig_lib_directory.path) |p| { |
| 430 | try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); | |
| 432 | try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); | |
| 431 | 433 | } else { |
| 432 | try override_path.writer().print(fmt_path, .{lib_name}); | |
| 434 | try override_path.print(fmt_path, .{lib_name}); | |
| 433 | 435 | } |
| 434 | 436 | if (std.fs.cwd().access(override_path.items, .{})) |_| { |
| 435 | 437 | return override_path.toOwnedSlice(); |
| ... | ... | @@ -444,9 +446,9 @@ fn findDef( |
| 444 | 446 | override_path.shrinkRetainingCapacity(0); |
| 445 | 447 | const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in"; |
| 446 | 448 | if (zig_lib_directory.path) |p| { |
| 447 | try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); | |
| 449 | try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_name }); | |
| 448 | 450 | } else { |
| 449 | try override_path.writer().print(fmt_path, .{lib_name}); | |
| 451 | try override_path.print(fmt_path, .{lib_name}); | |
| 450 | 452 | } |
| 451 | 453 | if (std.fs.cwd().access(override_path.items, .{})) |_| { |
| 452 | 454 | return override_path.toOwnedSlice(); |
src/libs/musl.zig+3-3| ... | ... | @@ -140,21 +140,21 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 140 | 140 | if (!is_arch_specific) { |
| 141 | 141 | // Look for an arch specific override. |
| 142 | 142 | override_path.shrinkRetainingCapacity(0); |
| 143 | try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.s", .{ | |
| 143 | try override_path.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.s", .{ | |
| 144 | 144 | dirname, arch_name, noextbasename, |
| 145 | 145 | }); |
| 146 | 146 | if (source_table.contains(override_path.items)) |
| 147 | 147 | continue; |
| 148 | 148 | |
| 149 | 149 | override_path.shrinkRetainingCapacity(0); |
| 150 | try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.S", .{ | |
| 150 | try override_path.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.S", .{ | |
| 151 | 151 | dirname, arch_name, noextbasename, |
| 152 | 152 | }); |
| 153 | 153 | if (source_table.contains(override_path.items)) |
| 154 | 154 | continue; |
| 155 | 155 | |
| 156 | 156 | override_path.shrinkRetainingCapacity(0); |
| 157 | try override_path.writer().print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.c", .{ | |
| 157 | try override_path.print("{s}" ++ s ++ "{s}" ++ s ++ "{s}.c", .{ | |
| 158 | 158 | dirname, arch_name, noextbasename, |
| 159 | 159 | }); |
| 160 | 160 | if (source_table.contains(override_path.items)) |
src/libs/netbsd.zig+25-24| ... | ... | @@ -460,18 +460,15 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 460 | 460 | for (libs, 0..) |lib, lib_i| { |
| 461 | 461 | stubs_asm.shrinkRetainingCapacity(0); |
| 462 | 462 | |
| 463 | const stubs_writer = stubs_asm.writer(); | |
| 464 | ||
| 465 | try stubs_writer.writeAll(".text\n"); | |
| 463 | try stubs_asm.appendSlice(".text\n"); | |
| 466 | 464 | |
| 467 | 465 | var sym_i: usize = 0; |
| 468 | var sym_name_buf = std.array_list.Managed(u8).init(arena); | |
| 466 | var sym_name_buf: std.Io.Writer.Allocating = .init(arena); | |
| 469 | 467 | var opt_symbol_name: ?[]const u8 = null; |
| 470 | 468 | |
| 471 | var inc_fbs = std.io.fixedBufferStream(metadata.inclusions); | |
| 472 | var inc_reader = inc_fbs.reader(); | |
| 469 | var inc_reader: std.Io.Reader = .fixed(metadata.inclusions); | |
| 473 | 470 | |
| 474 | const fn_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 471 | const fn_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 475 | 472 | |
| 476 | 473 | var chosen_ver_index: usize = 255; |
| 477 | 474 | var chosen_is_weak: bool = undefined; |
| ... | ... | @@ -479,17 +476,19 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 479 | 476 | while (sym_i < fn_inclusions_len) : (sym_i += 1) { |
| 480 | 477 | const sym_name = opt_symbol_name orelse n: { |
| 481 | 478 | sym_name_buf.clearRetainingCapacity(); |
| 482 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 479 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 480 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 481 | inc_reader.toss(1); | |
| 483 | 482 | |
| 484 | opt_symbol_name = sym_name_buf.items; | |
| 483 | opt_symbol_name = sym_name_buf.written(); | |
| 485 | 484 | chosen_ver_index = 255; |
| 486 | 485 | |
| 487 | break :n sym_name_buf.items; | |
| 486 | break :n sym_name_buf.written(); | |
| 488 | 487 | }; |
| 489 | 488 | |
| 490 | 489 | { |
| 491 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 492 | var lib_index = try inc_reader.readByte(); | |
| 490 | const targets = try inc_reader.takeLeb128(u64); | |
| 491 | var lib_index = try inc_reader.takeByte(); | |
| 493 | 492 | |
| 494 | 493 | const is_weak = (lib_index & (1 << 6)) != 0; |
| 495 | 494 | const is_terminal = (lib_index & (1 << 7)) != 0; |
| ... | ... | @@ -502,7 +501,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 502 | 501 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 503 | 502 | |
| 504 | 503 | while (true) { |
| 505 | const byte = try inc_reader.readByte(); | |
| 504 | const byte = try inc_reader.takeByte(); | |
| 506 | 505 | const last = (byte & 0b1000_0000) != 0; |
| 507 | 506 | const ver_i = @as(u7, @truncate(byte)); |
| 508 | 507 | if (ok_lib_and_target and ver_i <= target_ver_index and |
| ... | ... | @@ -525,7 +524,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 525 | 524 | // .globl _Exit |
| 526 | 525 | // .type _Exit, %function |
| 527 | 526 | // _Exit: .long 0 |
| 528 | try stubs_writer.print( | |
| 527 | try stubs_asm.print( | |
| 529 | 528 | \\.balign {d} |
| 530 | 529 | \\.{s} {s} |
| 531 | 530 | \\.type {s}, %function |
| ... | ... | @@ -542,9 +541,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 542 | 541 | } |
| 543 | 542 | } |
| 544 | 543 | |
| 545 | try stubs_writer.writeAll(".data\n"); | |
| 544 | try stubs_asm.appendSlice(".data\n"); | |
| 546 | 545 | |
| 547 | const obj_inclusions_len = try inc_reader.readInt(u16, .little); | |
| 546 | const obj_inclusions_len = try inc_reader.takeInt(u16, .little); | |
| 548 | 547 | |
| 549 | 548 | sym_i = 0; |
| 550 | 549 | opt_symbol_name = null; |
| ... | ... | @@ -554,18 +553,20 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 554 | 553 | while (sym_i < obj_inclusions_len) : (sym_i += 1) { |
| 555 | 554 | const sym_name = opt_symbol_name orelse n: { |
| 556 | 555 | sym_name_buf.clearRetainingCapacity(); |
| 557 | try inc_reader.streamUntilDelimiter(sym_name_buf.writer(), 0, null); | |
| 556 | _ = try inc_reader.streamDelimiter(&sym_name_buf.writer, 0); | |
| 557 | assert(inc_reader.buffered()[0] == 0); // TODO change streamDelimiter API | |
| 558 | inc_reader.toss(1); | |
| 558 | 559 | |
| 559 | opt_symbol_name = sym_name_buf.items; | |
| 560 | opt_symbol_name = sym_name_buf.written(); | |
| 560 | 561 | chosen_ver_index = 255; |
| 561 | 562 | |
| 562 | break :n sym_name_buf.items; | |
| 563 | break :n sym_name_buf.written(); | |
| 563 | 564 | }; |
| 564 | 565 | |
| 565 | 566 | { |
| 566 | const targets = try std.leb.readUleb128(u64, inc_reader); | |
| 567 | const size = try std.leb.readUleb128(u16, inc_reader); | |
| 568 | var lib_index = try inc_reader.readByte(); | |
| 567 | const targets = try inc_reader.takeLeb128(u64); | |
| 568 | const size = try inc_reader.takeLeb128(u16); | |
| 569 | var lib_index = try inc_reader.takeByte(); | |
| 569 | 570 | |
| 570 | 571 | const is_weak = (lib_index & (1 << 6)) != 0; |
| 571 | 572 | const is_terminal = (lib_index & (1 << 7)) != 0; |
| ... | ... | @@ -578,7 +579,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 578 | 579 | ((targets & (@as(u64, 1) << @as(u6, @intCast(target_targ_index)))) != 0); |
| 579 | 580 | |
| 580 | 581 | while (true) { |
| 581 | const byte = try inc_reader.readByte(); | |
| 582 | const byte = try inc_reader.takeByte(); | |
| 582 | 583 | const last = (byte & 0b1000_0000) != 0; |
| 583 | 584 | const ver_i = @as(u7, @truncate(byte)); |
| 584 | 585 | if (ok_lib_and_target and ver_i <= target_ver_index and |
| ... | ... | @@ -603,7 +604,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 603 | 604 | // .type malloc_conf, %object |
| 604 | 605 | // .size malloc_conf, 4 |
| 605 | 606 | // malloc_conf: .fill 4, 1, 0 |
| 606 | try stubs_writer.print( | |
| 607 | try stubs_asm.print( | |
| 607 | 608 | \\.balign {d} |
| 608 | 609 | \\.{s} {s} |
| 609 | 610 | \\.type {s}, %object |
src/link.zig+4-4| ... | ... | @@ -1976,7 +1976,7 @@ fn resolveLibInput( |
| 1976 | 1976 | .root_dir = lib_directory, |
| 1977 | 1977 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.tbd", .{lib_name}), |
| 1978 | 1978 | }; |
| 1979 | try checked_paths.writer(gpa).print("\n {f}", .{test_path}); | |
| 1979 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | |
| 1980 | 1980 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 1981 | 1981 | error.FileNotFound => break :tbd, |
| 1982 | 1982 | else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }), |
| ... | ... | @@ -1995,7 +1995,7 @@ fn resolveLibInput( |
| 1995 | 1995 | }, |
| 1996 | 1996 | }), |
| 1997 | 1997 | }; |
| 1998 | try checked_paths.writer(gpa).print("\n {f}", .{test_path}); | |
| 1998 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | |
| 1999 | 1999 | switch (try resolvePathInputLib(gpa, arena, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ |
| 2000 | 2000 | .path = test_path, |
| 2001 | 2001 | .query = name_query.query, |
| ... | ... | @@ -2012,7 +2012,7 @@ fn resolveLibInput( |
| 2012 | 2012 | .root_dir = lib_directory, |
| 2013 | 2013 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}), |
| 2014 | 2014 | }; |
| 2015 | try checked_paths.writer(gpa).print("\n {f}", .{test_path}); | |
| 2015 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | |
| 2016 | 2016 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 2017 | 2017 | error.FileNotFound => break :so, |
| 2018 | 2018 | else => |e| fatal("unable to search for so library '{f}': {s}", .{ |
| ... | ... | @@ -2030,7 +2030,7 @@ fn resolveLibInput( |
| 2030 | 2030 | .root_dir = lib_directory, |
| 2031 | 2031 | .sub_path = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}), |
| 2032 | 2032 | }; |
| 2033 | try checked_paths.writer(gpa).print("\n {f}", .{test_path}); | |
| 2033 | try checked_paths.print(gpa, "\n {f}", .{test_path}); | |
| 2034 | 2034 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 2035 | 2035 | error.FileNotFound => break :mingw, |
| 2036 | 2036 | else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }), |
src/link/Coff.zig+4-4| ... | ... | @@ -2179,13 +2179,13 @@ fn writeDataDirectoriesHeaders(coff: *Coff) !void { |
| 2179 | 2179 | fn writeHeader(coff: *Coff) !void { |
| 2180 | 2180 | const target = &coff.base.comp.root_mod.resolved_target.result; |
| 2181 | 2181 | const gpa = coff.base.comp.gpa; |
| 2182 | var buffer = std.array_list.Managed(u8).init(gpa); | |
| 2182 | var buffer: std.Io.Writer.Allocating = .init(gpa); | |
| 2183 | 2183 | defer buffer.deinit(); |
| 2184 | const writer = buffer.writer(); | |
| 2184 | const writer = &buffer.writer; | |
| 2185 | 2185 | |
| 2186 | 2186 | try buffer.ensureTotalCapacity(coff.getSizeOfHeaders()); |
| 2187 | 2187 | writer.writeAll(&msdos_stub) catch unreachable; |
| 2188 | mem.writeInt(u32, buffer.items[0x3c..][0..4], msdos_stub.len, .little); | |
| 2188 | mem.writeInt(u32, buffer.writer.buffer[0x3c..][0..4], msdos_stub.len, .little); | |
| 2189 | 2189 | |
| 2190 | 2190 | writer.writeAll("PE\x00\x00") catch unreachable; |
| 2191 | 2191 | var flags = coff_util.CoffHeaderFlags{ |
| ... | ... | @@ -2313,7 +2313,7 @@ fn writeHeader(coff: *Coff) !void { |
| 2313 | 2313 | }, |
| 2314 | 2314 | } |
| 2315 | 2315 | |
| 2316 | try coff.pwriteAll(buffer.items, 0); | |
| 2316 | try coff.pwriteAll(buffer.written(), 0); | |
| 2317 | 2317 | } |
| 2318 | 2318 | |
| 2319 | 2319 | pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
src/link/Elf.zig+34-38| ... | ... | @@ -811,10 +811,6 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 811 | 811 | |
| 812 | 812 | if (self.base.gc_sections) { |
| 813 | 813 | try gc.gcAtoms(self); |
| 814 | ||
| 815 | if (self.base.print_gc_sections) { | |
| 816 | try gc.dumpPrunedAtoms(self); | |
| 817 | } | |
| 818 | 814 | } |
| 819 | 815 | |
| 820 | 816 | self.checkDuplicates() catch |err| switch (err) { |
| ... | ... | @@ -3005,7 +3001,7 @@ fn writeAtoms(self: *Elf) !void { |
| 3005 | 3001 | undefs.deinit(); |
| 3006 | 3002 | } |
| 3007 | 3003 | |
| 3008 | var buffer = std.array_list.Managed(u8).init(gpa); | |
| 3004 | var buffer: std.Io.Writer.Allocating = .init(gpa); | |
| 3009 | 3005 | defer buffer.deinit(); |
| 3010 | 3006 | |
| 3011 | 3007 | const slice = self.sections.slice(); |
| ... | ... | @@ -3032,9 +3028,9 @@ fn writeAtoms(self: *Elf) !void { |
| 3032 | 3028 | try buffer.ensureUnusedCapacity(thunk_size); |
| 3033 | 3029 | const shdr = slice.items(.shdr)[th.output_section_index]; |
| 3034 | 3030 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; |
| 3035 | try th.write(self, buffer.writer()); | |
| 3036 | assert(buffer.items.len == thunk_size); | |
| 3037 | try self.pwriteAll(buffer.items, offset); | |
| 3031 | try th.write(self, &buffer.writer); | |
| 3032 | assert(buffer.written().len == thunk_size); | |
| 3033 | try self.pwriteAll(buffer.written(), offset); | |
| 3038 | 3034 | buffer.clearRetainingCapacity(); |
| 3039 | 3035 | } |
| 3040 | 3036 | } |
| ... | ... | @@ -3166,26 +3162,26 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 3166 | 3162 | |
| 3167 | 3163 | if (self.section_indexes.verneed) |shndx| { |
| 3168 | 3164 | const shdr = slice.items(.shdr)[shndx]; |
| 3169 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.verneed.size()); | |
| 3165 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.verneed.size()); | |
| 3170 | 3166 | defer buffer.deinit(); |
| 3171 | try self.verneed.write(buffer.writer()); | |
| 3172 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3167 | try self.verneed.write(&buffer.writer); | |
| 3168 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3173 | 3169 | } |
| 3174 | 3170 | |
| 3175 | 3171 | if (self.section_indexes.dynamic) |shndx| { |
| 3176 | 3172 | const shdr = slice.items(.shdr)[shndx]; |
| 3177 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynamic.size(self)); | |
| 3173 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynamic.size(self)); | |
| 3178 | 3174 | defer buffer.deinit(); |
| 3179 | try self.dynamic.write(self, buffer.writer()); | |
| 3180 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3175 | try self.dynamic.write(self, &buffer.writer); | |
| 3176 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3181 | 3177 | } |
| 3182 | 3178 | |
| 3183 | 3179 | if (self.section_indexes.dynsymtab) |shndx| { |
| 3184 | 3180 | const shdr = slice.items(.shdr)[shndx]; |
| 3185 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynsym.size()); | |
| 3181 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynsym.size()); | |
| 3186 | 3182 | defer buffer.deinit(); |
| 3187 | try self.dynsym.write(self, buffer.writer()); | |
| 3188 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3183 | try self.dynsym.write(self, &buffer.writer); | |
| 3184 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3189 | 3185 | } |
| 3190 | 3186 | |
| 3191 | 3187 | if (self.section_indexes.dynstrtab) |shndx| { |
| ... | ... | @@ -3201,28 +3197,28 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 3201 | 3197 | }; |
| 3202 | 3198 | const shdr = slice.items(.shdr)[shndx]; |
| 3203 | 3199 | const sh_size = try self.cast(usize, shdr.sh_size); |
| 3204 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); | |
| 3200 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, @intCast(sh_size - existing_size)); | |
| 3205 | 3201 | defer buffer.deinit(); |
| 3206 | try eh_frame.writeEhFrame(self, buffer.writer()); | |
| 3207 | assert(buffer.items.len == sh_size - existing_size); | |
| 3208 | try self.pwriteAll(buffer.items, shdr.sh_offset + existing_size); | |
| 3202 | try eh_frame.writeEhFrame(self, &buffer.writer); | |
| 3203 | assert(buffer.written().len == sh_size - existing_size); | |
| 3204 | try self.pwriteAll(buffer.written(), shdr.sh_offset + existing_size); | |
| 3209 | 3205 | } |
| 3210 | 3206 | |
| 3211 | 3207 | if (self.section_indexes.eh_frame_hdr) |shndx| { |
| 3212 | 3208 | const shdr = slice.items(.shdr)[shndx]; |
| 3213 | 3209 | const sh_size = try self.cast(usize, shdr.sh_size); |
| 3214 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size); | |
| 3210 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, sh_size); | |
| 3215 | 3211 | defer buffer.deinit(); |
| 3216 | try eh_frame.writeEhFrameHdr(self, buffer.writer()); | |
| 3217 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3212 | try eh_frame.writeEhFrameHdr(self, &buffer.writer); | |
| 3213 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3218 | 3214 | } |
| 3219 | 3215 | |
| 3220 | 3216 | if (self.section_indexes.got) |index| { |
| 3221 | 3217 | const shdr = slice.items(.shdr)[index]; |
| 3222 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got.size(self)); | |
| 3218 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got.size(self)); | |
| 3223 | 3219 | defer buffer.deinit(); |
| 3224 | try self.got.write(self, buffer.writer()); | |
| 3225 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3220 | try self.got.write(self, &buffer.writer); | |
| 3221 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3226 | 3222 | } |
| 3227 | 3223 | |
| 3228 | 3224 | if (self.section_indexes.rela_dyn) |shndx| { |
| ... | ... | @@ -3235,26 +3231,26 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 3235 | 3231 | |
| 3236 | 3232 | if (self.section_indexes.plt) |shndx| { |
| 3237 | 3233 | const shdr = slice.items(.shdr)[shndx]; |
| 3238 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt.size(self)); | |
| 3234 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt.size(self)); | |
| 3239 | 3235 | defer buffer.deinit(); |
| 3240 | try self.plt.write(self, buffer.writer()); | |
| 3241 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3236 | try self.plt.write(self, &buffer.writer); | |
| 3237 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3242 | 3238 | } |
| 3243 | 3239 | |
| 3244 | 3240 | if (self.section_indexes.got_plt) |shndx| { |
| 3245 | 3241 | const shdr = slice.items(.shdr)[shndx]; |
| 3246 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got_plt.size(self)); | |
| 3242 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got_plt.size(self)); | |
| 3247 | 3243 | defer buffer.deinit(); |
| 3248 | try self.got_plt.write(self, buffer.writer()); | |
| 3249 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3244 | try self.got_plt.write(self, &buffer.writer); | |
| 3245 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3250 | 3246 | } |
| 3251 | 3247 | |
| 3252 | 3248 | if (self.section_indexes.plt_got) |shndx| { |
| 3253 | 3249 | const shdr = slice.items(.shdr)[shndx]; |
| 3254 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt_got.size(self)); | |
| 3250 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt_got.size(self)); | |
| 3255 | 3251 | defer buffer.deinit(); |
| 3256 | try self.plt_got.write(self, buffer.writer()); | |
| 3257 | try self.pwriteAll(buffer.items, shdr.sh_offset); | |
| 3252 | try self.plt_got.write(self, &buffer.writer); | |
| 3253 | try self.pwriteAll(buffer.written(), shdr.sh_offset); | |
| 3258 | 3254 | } |
| 3259 | 3255 | |
| 3260 | 3256 | if (self.section_indexes.rela_plt) |shndx| { |
| ... | ... | @@ -3757,7 +3753,7 @@ pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { |
| 3757 | 3753 | const gpa = self.base.comp.gpa; |
| 3758 | 3754 | const off = @as(u32, @intCast(self.shstrtab.items.len)); |
| 3759 | 3755 | try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1); |
| 3760 | self.shstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; | |
| 3756 | self.shstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable; | |
| 3761 | 3757 | return off; |
| 3762 | 3758 | } |
| 3763 | 3759 | |
| ... | ... | @@ -3770,7 +3766,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { |
| 3770 | 3766 | const gpa = self.base.comp.gpa; |
| 3771 | 3767 | const off = @as(u32, @intCast(self.dynstrtab.items.len)); |
| 3772 | 3768 | try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1); |
| 3773 | self.dynstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; | |
| 3769 | self.dynstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable; | |
| 3774 | 3770 | return off; |
| 3775 | 3771 | } |
| 3776 | 3772 |
src/link/Elf/Archive.zig+4-5| ... | ... | @@ -123,8 +123,7 @@ pub fn setArHdr(opts: struct { |
| 123 | 123 | @memcpy(&hdr.ar_fmag, elf.ARFMAG); |
| 124 | 124 | |
| 125 | 125 | { |
| 126 | var stream = std.io.fixedBufferStream(&hdr.ar_name); | |
| 127 | const writer = stream.writer(); | |
| 126 | var writer: std.Io.Writer = .fixed(&hdr.ar_name); | |
| 128 | 127 | switch (opts.name) { |
| 129 | 128 | .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable, |
| 130 | 129 | .strtab => writer.print("//", .{}) catch unreachable, |
| ... | ... | @@ -133,8 +132,8 @@ pub fn setArHdr(opts: struct { |
| 133 | 132 | } |
| 134 | 133 | } |
| 135 | 134 | { |
| 136 | var stream = std.io.fixedBufferStream(&hdr.ar_size); | |
| 137 | stream.writer().print("{d}", .{opts.size}) catch unreachable; | |
| 135 | var writer: std.Io.Writer = .fixed(&hdr.ar_size); | |
| 136 | writer.print("{d}", .{opts.size}) catch unreachable; | |
| 138 | 137 | } |
| 139 | 138 | |
| 140 | 139 | return hdr; |
| ... | ... | @@ -246,7 +245,7 @@ pub const ArStrtab = struct { |
| 246 | 245 | |
| 247 | 246 | pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 { |
| 248 | 247 | const off = @as(u32, @intCast(ar.buffer.items.len)); |
| 249 | try ar.buffer.writer(allocator).print("{s}/{c}", .{ name, strtab_delimiter }); | |
| 248 | try ar.buffer.print(allocator, "{s}/{c}", .{ name, strtab_delimiter }); | |
| 250 | 249 | return off; |
| 251 | 250 | } |
| 252 | 251 |
src/link/Elf/Atom.zig+113-142| ... | ... | @@ -621,7 +621,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 621 | 621 | |
| 622 | 622 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 623 | 623 | const file_ptr = self.file(elf_file).?; |
| 624 | var stream = std.io.fixedBufferStream(code); | |
| 625 | 624 | |
| 626 | 625 | const rels = self.relocs(elf_file); |
| 627 | 626 | var it = RelocsIterator{ .relocs = rels }; |
| ... | ... | @@ -661,20 +660,16 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 661 | 660 | target.name(elf_file), |
| 662 | 661 | }); |
| 663 | 662 | |
| 664 | try stream.seekTo(r_offset); | |
| 665 | ||
| 666 | 663 | const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP }; |
| 667 | 664 | |
| 668 | 665 | switch (cpu_arch) { |
| 669 | .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 666 | .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { | |
| 670 | 667 | error.RelocFailure, |
| 671 | 668 | error.RelaxFailure, |
| 672 | error.InvalidInstruction, | |
| 673 | error.CannotEncode, | |
| 674 | 669 | => has_reloc_errors = true, |
| 675 | 670 | else => |e| return e, |
| 676 | 671 | }, |
| 677 | .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 672 | .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { | |
| 678 | 673 | error.RelocFailure, |
| 679 | 674 | error.RelaxFailure, |
| 680 | 675 | error.UnexpectedRemainder, |
| ... | ... | @@ -682,7 +677,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 682 | 677 | => has_reloc_errors = true, |
| 683 | 678 | else => |e| return e, |
| 684 | 679 | }, |
| 685 | .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 680 | .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { | |
| 686 | 681 | error.RelocFailure, |
| 687 | 682 | error.RelaxFailure, |
| 688 | 683 | => has_reloc_errors = true, |
| ... | ... | @@ -701,7 +696,8 @@ fn resolveDynAbsReloc( |
| 701 | 696 | rel: elf.Elf64_Rela, |
| 702 | 697 | action: RelocAction, |
| 703 | 698 | elf_file: *Elf, |
| 704 | writer: anytype, | |
| 699 | code: []u8, | |
| 700 | r_offset: usize, | |
| 705 | 701 | ) !void { |
| 706 | 702 | const comp = elf_file.base.comp; |
| 707 | 703 | const gpa = comp.gpa; |
| ... | ... | @@ -726,7 +722,7 @@ fn resolveDynAbsReloc( |
| 726 | 722 | .copyrel, |
| 727 | 723 | .cplt, |
| 728 | 724 | .none, |
| 729 | => try writer.writeInt(i64, S + A, .little), | |
| 725 | => mem.writeInt(i64, code[r_offset..][0..8], S + A, .little), | |
| 730 | 726 | |
| 731 | 727 | .dyn_copyrel => { |
| 732 | 728 | if (is_writeable or elf_file.z_nocopyreloc) { |
| ... | ... | @@ -737,9 +733,9 @@ fn resolveDynAbsReloc( |
| 737 | 733 | .addend = A, |
| 738 | 734 | .target = target, |
| 739 | 735 | }); |
| 740 | try applyDynamicReloc(A, elf_file, writer); | |
| 736 | applyDynamicReloc(A, code, r_offset); | |
| 741 | 737 | } else { |
| 742 | try writer.writeInt(i64, S + A, .little); | |
| 738 | mem.writeInt(i64, code[r_offset..][0..8], S + A, .little); | |
| 743 | 739 | } |
| 744 | 740 | }, |
| 745 | 741 | |
| ... | ... | @@ -752,9 +748,9 @@ fn resolveDynAbsReloc( |
| 752 | 748 | .addend = A, |
| 753 | 749 | .target = target, |
| 754 | 750 | }); |
| 755 | try applyDynamicReloc(A, elf_file, writer); | |
| 751 | applyDynamicReloc(A, code, r_offset); | |
| 756 | 752 | } else { |
| 757 | try writer.writeInt(i64, S + A, .little); | |
| 753 | mem.writeInt(i64, code[r_offset..][0..8], S + A, .little); | |
| 758 | 754 | } |
| 759 | 755 | }, |
| 760 | 756 | |
| ... | ... | @@ -766,7 +762,7 @@ fn resolveDynAbsReloc( |
| 766 | 762 | .addend = A, |
| 767 | 763 | .target = target, |
| 768 | 764 | }); |
| 769 | try applyDynamicReloc(A, elf_file, writer); | |
| 765 | applyDynamicReloc(A, code, r_offset); | |
| 770 | 766 | }, |
| 771 | 767 | |
| 772 | 768 | .baserel => { |
| ... | ... | @@ -776,7 +772,7 @@ fn resolveDynAbsReloc( |
| 776 | 772 | .addend = S + A, |
| 777 | 773 | .target = target, |
| 778 | 774 | }); |
| 779 | try applyDynamicReloc(S + A, elf_file, writer); | |
| 775 | applyDynamicReloc(S + A, code, r_offset); | |
| 780 | 776 | }, |
| 781 | 777 | |
| 782 | 778 | .ifunc => { |
| ... | ... | @@ -787,16 +783,13 @@ fn resolveDynAbsReloc( |
| 787 | 783 | .addend = S_ + A, |
| 788 | 784 | .target = target, |
| 789 | 785 | }); |
| 790 | try applyDynamicReloc(S_ + A, elf_file, writer); | |
| 786 | applyDynamicReloc(S_ + A, code, r_offset); | |
| 791 | 787 | }, |
| 792 | 788 | } |
| 793 | 789 | } |
| 794 | 790 | |
| 795 | fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void { | |
| 796 | _ = elf_file; | |
| 797 | // if (elf_file.options.apply_dynamic_relocs) { | |
| 798 | try writer.writeInt(i64, value, .little); | |
| 799 | // } | |
| 791 | fn applyDynamicReloc(value: i64, code: []u8, r_offset: usize) void { | |
| 792 | mem.writeInt(i64, code[r_offset..][0..8], value, .little); | |
| 800 | 793 | } |
| 801 | 794 | |
| 802 | 795 | pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void { |
| ... | ... | @@ -804,7 +797,6 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 804 | 797 | |
| 805 | 798 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 806 | 799 | const file_ptr = self.file(elf_file).?; |
| 807 | var stream = std.io.fixedBufferStream(code); | |
| 808 | 800 | |
| 809 | 801 | const rels = self.relocs(elf_file); |
| 810 | 802 | var has_reloc_errors = false; |
| ... | ... | @@ -863,18 +855,16 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 863 | 855 | target.name(elf_file), |
| 864 | 856 | }); |
| 865 | 857 | |
| 866 | try stream.seekTo(r_offset); | |
| 867 | ||
| 868 | 858 | switch (cpu_arch) { |
| 869 | .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 859 | .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { | |
| 870 | 860 | error.RelocFailure => has_reloc_errors = true, |
| 871 | 861 | else => |e| return e, |
| 872 | 862 | }, |
| 873 | .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 863 | .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { | |
| 874 | 864 | error.RelocFailure => has_reloc_errors = true, |
| 875 | 865 | else => |e| return e, |
| 876 | 866 | }, |
| 877 | .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { | |
| 867 | .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { | |
| 878 | 868 | error.RelocFailure => has_reloc_errors = true, |
| 879 | 869 | else => |e| return e, |
| 880 | 870 | }, |
| ... | ... | @@ -915,7 +905,7 @@ const Format = struct { |
| 915 | 905 | atom: Atom, |
| 916 | 906 | elf_file: *Elf, |
| 917 | 907 | |
| 918 | fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { | |
| 908 | fn default(f: Format, w: *Writer) Writer.Error!void { | |
| 919 | 909 | const atom = f.atom; |
| 920 | 910 | const elf_file = f.elf_file; |
| 921 | 911 | try w.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{ |
| ... | ... | @@ -1068,16 +1058,13 @@ const x86_64 = struct { |
| 1068 | 1058 | args: ResolveArgs, |
| 1069 | 1059 | it: *RelocsIterator, |
| 1070 | 1060 | code: []u8, |
| 1071 | stream: anytype, | |
| 1072 | ) (error{ InvalidInstruction, CannotEncode } || RelocError)!void { | |
| 1061 | ) !void { | |
| 1073 | 1062 | dev.check(.x86_64_backend); |
| 1074 | 1063 | const t = &elf_file.base.comp.root_mod.resolved_target.result; |
| 1075 | 1064 | const diags = &elf_file.base.comp.link_diags; |
| 1076 | 1065 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 1077 | 1066 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1078 | 1067 | |
| 1079 | const cwriter = stream.writer(); | |
| 1080 | ||
| 1081 | 1068 | const P, const A, const S, const GOT, const G, const TP, const DTP = args; |
| 1082 | 1069 | |
| 1083 | 1070 | switch (r_type) { |
| ... | ... | @@ -1089,58 +1076,60 @@ const x86_64 = struct { |
| 1089 | 1076 | rel, |
| 1090 | 1077 | dynAbsRelocAction(target, elf_file), |
| 1091 | 1078 | elf_file, |
| 1092 | cwriter, | |
| 1079 | code, | |
| 1080 | r_offset, | |
| 1093 | 1081 | ); |
| 1094 | 1082 | }, |
| 1095 | 1083 | |
| 1096 | .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), | |
| 1097 | .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), | |
| 1084 | .PLT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little), | |
| 1085 | .PC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little), | |
| 1098 | 1086 | |
| 1099 | .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), | |
| 1100 | .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), | |
| 1101 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), | |
| 1087 | .GOTPCREL => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little), | |
| 1088 | .GOTPC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(GOT + A - P)), .little), | |
| 1089 | .GOTPC64 => mem.writeInt(i64, code[r_offset..][0..8], GOT + A - P, .little), | |
| 1102 | 1090 | |
| 1103 | 1091 | .GOTPCRELX => { |
| 1104 | 1092 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 1105 | 1093 | x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk; |
| 1106 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); | |
| 1094 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little); | |
| 1107 | 1095 | return; |
| 1108 | 1096 | } |
| 1109 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); | |
| 1097 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little); | |
| 1110 | 1098 | }, |
| 1111 | 1099 | |
| 1112 | 1100 | .REX_GOTPCRELX => { |
| 1113 | 1101 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 1114 | 1102 | x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk; |
| 1115 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); | |
| 1103 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little); | |
| 1116 | 1104 | return; |
| 1117 | 1105 | } |
| 1118 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); | |
| 1106 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little); | |
| 1119 | 1107 | }, |
| 1120 | 1108 | |
| 1121 | .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | |
| 1122 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little), | |
| 1109 | .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | |
| 1110 | .@"32S" => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little), | |
| 1123 | 1111 | |
| 1124 | .TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), | |
| 1125 | .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), | |
| 1112 | .TPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - TP)), .little), | |
| 1113 | .TPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - TP, .little), | |
| 1126 | 1114 | |
| 1127 | .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), | |
| 1128 | .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), | |
| 1115 | .DTPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - DTP)), .little), | |
| 1116 | .DTPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - DTP, .little), | |
| 1129 | 1117 | |
| 1130 | 1118 | .TLSGD => { |
| 1131 | 1119 | if (target.flags.has_tlsgd) { |
| 1132 | 1120 | const S_ = target.tlsGdAddress(elf_file); |
| 1133 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | |
| 1121 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); | |
| 1134 | 1122 | } else if (target.flags.has_gottp) { |
| 1135 | 1123 | const S_ = target.gotTpAddress(elf_file); |
| 1136 | try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream); | |
| 1124 | try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, code, r_offset); | |
| 1137 | 1125 | } else { |
| 1138 | 1126 | try x86_64.relaxTlsGdToLe( |
| 1139 | 1127 | atom, |
| 1140 | 1128 | &.{ rel, it.next().? }, |
| 1141 | 1129 | @as(i32, @intCast(S - TP)), |
| 1142 | 1130 | elf_file, |
| 1143 | stream, | |
| 1131 | code, | |
| 1132 | r_offset, | |
| 1144 | 1133 | ); |
| 1145 | 1134 | } |
| 1146 | 1135 | }, |
| ... | ... | @@ -1149,14 +1138,15 @@ const x86_64 = struct { |
| 1149 | 1138 | if (elf_file.got.tlsld_index) |entry_index| { |
| 1150 | 1139 | const tlsld_entry = elf_file.got.entries.items[entry_index]; |
| 1151 | 1140 | const S_ = tlsld_entry.address(elf_file); |
| 1152 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | |
| 1141 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); | |
| 1153 | 1142 | } else { |
| 1154 | 1143 | try x86_64.relaxTlsLdToLe( |
| 1155 | 1144 | atom, |
| 1156 | 1145 | &.{ rel, it.next().? }, |
| 1157 | 1146 | @as(i32, @intCast(TP - elf_file.tlsAddress())), |
| 1158 | 1147 | elf_file, |
| 1159 | stream, | |
| 1148 | code, | |
| 1149 | r_offset, | |
| 1160 | 1150 | ); |
| 1161 | 1151 | } |
| 1162 | 1152 | }, |
| ... | ... | @@ -1164,7 +1154,7 @@ const x86_64 = struct { |
| 1164 | 1154 | .GOTPC32_TLSDESC => { |
| 1165 | 1155 | if (target.flags.has_tlsdesc) { |
| 1166 | 1156 | const S_ = target.tlsDescAddress(elf_file); |
| 1167 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | |
| 1157 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); | |
| 1168 | 1158 | } else { |
| 1169 | 1159 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch { |
| 1170 | 1160 | var err = try diags.addErrorWithNotes(1); |
| ... | ... | @@ -1176,26 +1166,26 @@ const x86_64 = struct { |
| 1176 | 1166 | }); |
| 1177 | 1167 | return error.RelaxFailure; |
| 1178 | 1168 | }; |
| 1179 | try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little); | |
| 1169 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little); | |
| 1180 | 1170 | } |
| 1181 | 1171 | }, |
| 1182 | 1172 | |
| 1183 | 1173 | .TLSDESC_CALL => if (!target.flags.has_tlsdesc) { |
| 1184 | 1174 | // call -> nop |
| 1185 | try cwriter.writeAll(&.{ 0x66, 0x90 }); | |
| 1175 | code[r_offset..][0..2].* = .{ 0x66, 0x90 }; | |
| 1186 | 1176 | }, |
| 1187 | 1177 | |
| 1188 | 1178 | .GOTTPOFF => { |
| 1189 | 1179 | if (target.flags.has_gottp) { |
| 1190 | 1180 | const S_ = target.gotTpAddress(elf_file); |
| 1191 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | |
| 1181 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); | |
| 1192 | 1182 | } else { |
| 1193 | 1183 | x86_64.relaxGotTpOff(code[r_offset - 3 ..], t); |
| 1194 | try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little); | |
| 1184 | mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little); | |
| 1195 | 1185 | } |
| 1196 | 1186 | }, |
| 1197 | 1187 | |
| 1198 | .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + A)), .little), | |
| 1188 | .GOT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + A)), .little), | |
| 1199 | 1189 | |
| 1200 | 1190 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1201 | 1191 | } |
| ... | ... | @@ -1207,45 +1197,42 @@ const x86_64 = struct { |
| 1207 | 1197 | rel: elf.Elf64_Rela, |
| 1208 | 1198 | target: *const Symbol, |
| 1209 | 1199 | args: ResolveArgs, |
| 1210 | it: *RelocsIterator, | |
| 1211 | 1200 | code: []u8, |
| 1212 | stream: anytype, | |
| 1213 | 1201 | ) !void { |
| 1214 | 1202 | dev.check(.x86_64_backend); |
| 1215 | _ = code; | |
| 1216 | _ = it; | |
| 1217 | 1203 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 1218 | const cwriter = stream.writer(); | |
| 1219 | 1204 | |
| 1220 | 1205 | _, const A, const S, const GOT, _, _, const DTP = args; |
| 1221 | 1206 | |
| 1207 | var writer: Writer = .fixed(code); | |
| 1208 | ||
| 1222 | 1209 | switch (r_type) { |
| 1223 | 1210 | .NONE => unreachable, |
| 1224 | .@"8" => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), | |
| 1225 | .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), | |
| 1226 | .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), | |
| 1227 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | |
| 1211 | .@"8" => try writer.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), | |
| 1212 | .@"16" => try writer.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), | |
| 1213 | .@"32" => try writer.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), | |
| 1214 | .@"32S" => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little), | |
| 1228 | 1215 | .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1229 | try cwriter.writeInt(u64, value, .little) | |
| 1216 | try writer.writeInt(u64, value, .little) | |
| 1230 | 1217 | else |
| 1231 | try cwriter.writeInt(i64, S + A, .little), | |
| 1218 | try writer.writeInt(i64, S + A, .little), | |
| 1232 | 1219 | .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1233 | try cwriter.writeInt(u64, value, .little) | |
| 1220 | try writer.writeInt(u64, value, .little) | |
| 1234 | 1221 | else |
| 1235 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | |
| 1222 | try writer.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | |
| 1236 | 1223 | .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1237 | try cwriter.writeInt(u64, value, .little) | |
| 1224 | try writer.writeInt(u64, value, .little) | |
| 1238 | 1225 | else |
| 1239 | try cwriter.writeInt(i64, S + A - DTP, .little), | |
| 1240 | .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), | |
| 1241 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), | |
| 1226 | try writer.writeInt(i64, S + A - DTP, .little), | |
| 1227 | .GOTOFF64 => try writer.writeInt(i64, S + A - GOT, .little), | |
| 1228 | .GOTPC64 => try writer.writeInt(i64, GOT + A, .little), | |
| 1242 | 1229 | .SIZE32 => { |
| 1243 | 1230 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1244 | try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little); | |
| 1231 | try writer.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little); | |
| 1245 | 1232 | }, |
| 1246 | 1233 | .SIZE64 => { |
| 1247 | 1234 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1248 | try cwriter.writeInt(i64, @intCast(size + A), .little); | |
| 1235 | try writer.writeInt(i64, @intCast(size + A), .little); | |
| 1249 | 1236 | }, |
| 1250 | 1237 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1251 | 1238 | } |
| ... | ... | @@ -1288,12 +1275,12 @@ const x86_64 = struct { |
| 1288 | 1275 | rels: []const elf.Elf64_Rela, |
| 1289 | 1276 | value: i32, |
| 1290 | 1277 | elf_file: *Elf, |
| 1291 | stream: anytype, | |
| 1278 | code: []u8, | |
| 1279 | r_offset: usize, | |
| 1292 | 1280 | ) !void { |
| 1293 | 1281 | dev.check(.x86_64_backend); |
| 1294 | 1282 | assert(rels.len == 2); |
| 1295 | 1283 | const diags = &elf_file.base.comp.link_diags; |
| 1296 | const writer = stream.writer(); | |
| 1297 | 1284 | const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1298 | 1285 | switch (rel) { |
| 1299 | 1286 | .PC32, |
| ... | ... | @@ -1304,8 +1291,7 @@ const x86_64 = struct { |
| 1304 | 1291 | 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax |
| 1305 | 1292 | }; |
| 1306 | 1293 | std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little); |
| 1307 | try stream.seekBy(-4); | |
| 1308 | try writer.writeAll(&insts); | |
| 1294 | @memcpy(code[r_offset - 4 ..][0..insts.len], &insts); | |
| 1309 | 1295 | }, |
| 1310 | 1296 | |
| 1311 | 1297 | else => { |
| ... | ... | @@ -1329,12 +1315,12 @@ const x86_64 = struct { |
| 1329 | 1315 | rels: []const elf.Elf64_Rela, |
| 1330 | 1316 | value: i32, |
| 1331 | 1317 | elf_file: *Elf, |
| 1332 | stream: anytype, | |
| 1318 | code: []u8, | |
| 1319 | r_offset: usize, | |
| 1333 | 1320 | ) !void { |
| 1334 | 1321 | dev.check(.x86_64_backend); |
| 1335 | 1322 | assert(rels.len == 2); |
| 1336 | 1323 | const diags = &elf_file.base.comp.link_diags; |
| 1337 | const writer = stream.writer(); | |
| 1338 | 1324 | const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1339 | 1325 | switch (rel) { |
| 1340 | 1326 | .PC32, |
| ... | ... | @@ -1346,8 +1332,7 @@ const x86_64 = struct { |
| 1346 | 1332 | 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax |
| 1347 | 1333 | }; |
| 1348 | 1334 | std.mem.writeInt(i32, insts[8..][0..4], value, .little); |
| 1349 | try stream.seekBy(-3); | |
| 1350 | try writer.writeAll(&insts); | |
| 1335 | @memcpy(code[r_offset - 3 ..][0..insts.len], &insts); | |
| 1351 | 1336 | }, |
| 1352 | 1337 | |
| 1353 | 1338 | .GOTPCREL, |
| ... | ... | @@ -1360,8 +1345,7 @@ const x86_64 = struct { |
| 1360 | 1345 | 0x90, // nop |
| 1361 | 1346 | }; |
| 1362 | 1347 | std.mem.writeInt(i32, insts[8..][0..4], value, .little); |
| 1363 | try stream.seekBy(-3); | |
| 1364 | try writer.writeAll(&insts); | |
| 1348 | @memcpy(code[r_offset - 3 ..][0..insts.len], &insts); | |
| 1365 | 1349 | }, |
| 1366 | 1350 | |
| 1367 | 1351 | else => { |
| ... | ... | @@ -1390,7 +1374,7 @@ const x86_64 = struct { |
| 1390 | 1374 | // TODO: hack to force imm32s in the assembler |
| 1391 | 1375 | .{ .imm = .s(-129) }, |
| 1392 | 1376 | }, t) catch return false; |
| 1393 | var trash: std.io.Writer.Discarding = .init(&.{}); | |
| 1377 | var trash: Writer.Discarding = .init(&.{}); | |
| 1394 | 1378 | inst.encode(&trash.writer, .{}) catch return false; |
| 1395 | 1379 | return true; |
| 1396 | 1380 | }, |
| ... | ... | @@ -1437,12 +1421,12 @@ const x86_64 = struct { |
| 1437 | 1421 | rels: []const elf.Elf64_Rela, |
| 1438 | 1422 | value: i32, |
| 1439 | 1423 | elf_file: *Elf, |
| 1440 | stream: anytype, | |
| 1424 | code: []u8, | |
| 1425 | r_offset: usize, | |
| 1441 | 1426 | ) !void { |
| 1442 | 1427 | dev.check(.x86_64_backend); |
| 1443 | 1428 | assert(rels.len == 2); |
| 1444 | 1429 | const diags = &elf_file.base.comp.link_diags; |
| 1445 | const writer = stream.writer(); | |
| 1446 | 1430 | const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1447 | 1431 | switch (rel) { |
| 1448 | 1432 | .PC32, |
| ... | ... | @@ -1455,8 +1439,7 @@ const x86_64 = struct { |
| 1455 | 1439 | 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax |
| 1456 | 1440 | }; |
| 1457 | 1441 | std.mem.writeInt(i32, insts[12..][0..4], value, .little); |
| 1458 | try stream.seekBy(-4); | |
| 1459 | try writer.writeAll(&insts); | |
| 1442 | @memcpy(code[r_offset - 4 ..][0..insts.len], &insts); | |
| 1460 | 1443 | relocs_log.debug(" relaxing {f} and {f}", .{ |
| 1461 | 1444 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), |
| 1462 | 1445 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), |
| ... | ... | @@ -1486,8 +1469,8 @@ const x86_64 = struct { |
| 1486 | 1469 | } |
| 1487 | 1470 | |
| 1488 | 1471 | fn encode(insts: []const Instruction, code: []u8) !void { |
| 1489 | var stream: std.io.Writer = .fixed(code); | |
| 1490 | for (insts) |inst| try inst.encode(&stream, .{}); | |
| 1472 | var writer: Writer = .fixed(code); | |
| 1473 | for (insts) |inst| try inst.encode(&writer, .{}); | |
| 1491 | 1474 | } |
| 1492 | 1475 | |
| 1493 | 1476 | const bits = @import("../../arch/x86_64/bits.zig"); |
| ... | ... | @@ -1592,14 +1575,12 @@ const aarch64 = struct { |
| 1592 | 1575 | args: ResolveArgs, |
| 1593 | 1576 | it: *RelocsIterator, |
| 1594 | 1577 | code_buffer: []u8, |
| 1595 | stream: anytype, | |
| 1596 | 1578 | ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { |
| 1597 | 1579 | _ = it; |
| 1598 | 1580 | |
| 1599 | 1581 | const diags = &elf_file.base.comp.link_diags; |
| 1600 | 1582 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1601 | 1583 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1602 | const cwriter = stream.writer(); | |
| 1603 | 1584 | const code = code_buffer[r_offset..][0..4]; |
| 1604 | 1585 | const file_ptr = atom.file(elf_file).?; |
| 1605 | 1586 | |
| ... | ... | @@ -1614,7 +1595,8 @@ const aarch64 = struct { |
| 1614 | 1595 | rel, |
| 1615 | 1596 | dynAbsRelocAction(target, elf_file), |
| 1616 | 1597 | elf_file, |
| 1617 | cwriter, | |
| 1598 | code_buffer, | |
| 1599 | r_offset, | |
| 1618 | 1600 | ); |
| 1619 | 1601 | }, |
| 1620 | 1602 | |
| ... | ... | @@ -1782,25 +1764,20 @@ const aarch64 = struct { |
| 1782 | 1764 | rel: elf.Elf64_Rela, |
| 1783 | 1765 | target: *const Symbol, |
| 1784 | 1766 | args: ResolveArgs, |
| 1785 | it: *RelocsIterator, | |
| 1786 | 1767 | code: []u8, |
| 1787 | stream: anytype, | |
| 1788 | 1768 | ) !void { |
| 1789 | _ = it; | |
| 1790 | _ = code; | |
| 1791 | ||
| 1792 | 1769 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1793 | const cwriter = stream.writer(); | |
| 1794 | 1770 | |
| 1795 | 1771 | _, const A, const S, _, _, _, _ = args; |
| 1796 | 1772 | |
| 1773 | var writer: Writer = .fixed(code); | |
| 1797 | 1774 | switch (r_type) { |
| 1798 | 1775 | .NONE => unreachable, |
| 1799 | .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | |
| 1776 | .ABS32 => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little), | |
| 1800 | 1777 | .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1801 | try cwriter.writeInt(u64, value, .little) | |
| 1778 | try writer.writeInt(u64, value, .little) | |
| 1802 | 1779 | else |
| 1803 | try cwriter.writeInt(i64, S + A, .little), | |
| 1780 | try writer.writeInt(i64, S + A, .little), | |
| 1804 | 1781 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1805 | 1782 | } |
| 1806 | 1783 | } |
| ... | ... | @@ -1861,12 +1838,10 @@ const riscv = struct { |
| 1861 | 1838 | args: ResolveArgs, |
| 1862 | 1839 | it: *RelocsIterator, |
| 1863 | 1840 | code: []u8, |
| 1864 | stream: anytype, | |
| 1865 | 1841 | ) !void { |
| 1866 | 1842 | const diags = &elf_file.base.comp.link_diags; |
| 1867 | 1843 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); |
| 1868 | 1844 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1869 | const cwriter = stream.writer(); | |
| 1870 | 1845 | |
| 1871 | 1846 | const P, const A, const S, const GOT, const G, const TP, const DTP = args; |
| 1872 | 1847 | _ = TP; |
| ... | ... | @@ -1875,7 +1850,7 @@ const riscv = struct { |
| 1875 | 1850 | switch (r_type) { |
| 1876 | 1851 | .NONE => unreachable, |
| 1877 | 1852 | |
| 1878 | .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | |
| 1853 | .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | |
| 1879 | 1854 | |
| 1880 | 1855 | .@"64" => { |
| 1881 | 1856 | try atom.resolveDynAbsReloc( |
| ... | ... | @@ -1883,7 +1858,8 @@ const riscv = struct { |
| 1883 | 1858 | rel, |
| 1884 | 1859 | dynAbsRelocAction(target, elf_file), |
| 1885 | 1860 | elf_file, |
| 1886 | cwriter, | |
| 1861 | code, | |
| 1862 | r_offset, | |
| 1887 | 1863 | ); |
| 1888 | 1864 | }, |
| 1889 | 1865 | |
| ... | ... | @@ -1997,15 +1973,9 @@ const riscv = struct { |
| 1997 | 1973 | rel: elf.Elf64_Rela, |
| 1998 | 1974 | target: *const Symbol, |
| 1999 | 1975 | args: ResolveArgs, |
| 2000 | it: *RelocsIterator, | |
| 2001 | 1976 | code: []u8, |
| 2002 | stream: anytype, | |
| 2003 | 1977 | ) !void { |
| 2004 | _ = it; | |
| 2005 | ||
| 2006 | 1978 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); |
| 2007 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; | |
| 2008 | const cwriter = stream.writer(); | |
| 2009 | 1979 | |
| 2010 | 1980 | _, const A, const S, const GOT, _, _, const DTP = args; |
| 2011 | 1981 | _ = GOT; |
| ... | ... | @@ -2014,30 +1984,29 @@ const riscv = struct { |
| 2014 | 1984 | switch (r_type) { |
| 2015 | 1985 | .NONE => unreachable, |
| 2016 | 1986 | |
| 2017 | .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | |
| 1987 | .@"32" => mem.writeInt(i32, code[0..4], @intCast(S + A), .little), | |
| 2018 | 1988 | .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 2019 | try cwriter.writeInt(u64, value, .little) | |
| 1989 | mem.writeInt(u64, code[0..8], value, .little) | |
| 2020 | 1990 | else |
| 2021 | try cwriter.writeInt(i64, S + A, .little), | |
| 2022 | ||
| 2023 | .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A), | |
| 2024 | .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A), | |
| 2025 | .ADD16 => riscv_util.writeAddend(i16, .add, code[r_offset..][0..2], S + A), | |
| 2026 | .SUB16 => riscv_util.writeAddend(i16, .sub, code[r_offset..][0..2], S + A), | |
| 2027 | .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A), | |
| 2028 | .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A), | |
| 2029 | .ADD64 => riscv_util.writeAddend(i64, .add, code[r_offset..][0..8], S + A), | |
| 2030 | .SUB64 => riscv_util.writeAddend(i64, .sub, code[r_offset..][0..8], S + A), | |
| 2031 | ||
| 2032 | .SET8 => mem.writeInt(i8, code[r_offset..][0..1], @as(i8, @truncate(S + A)), .little), | |
| 2033 | .SET16 => mem.writeInt(i16, code[r_offset..][0..2], @as(i16, @truncate(S + A)), .little), | |
| 2034 | .SET32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little), | |
| 2035 | ||
| 2036 | .SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A), | |
| 2037 | .SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A), | |
| 2038 | ||
| 2039 | .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A), | |
| 2040 | .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A), | |
| 1991 | mem.writeInt(i64, code[0..8], S + A, .little), | |
| 1992 | .ADD8 => riscv_util.writeAddend(i8, .add, code[0..1], S + A), | |
| 1993 | .SUB8 => riscv_util.writeAddend(i8, .sub, code[0..1], S + A), | |
| 1994 | .ADD16 => riscv_util.writeAddend(i16, .add, code[0..2], S + A), | |
| 1995 | .SUB16 => riscv_util.writeAddend(i16, .sub, code[0..2], S + A), | |
| 1996 | .ADD32 => riscv_util.writeAddend(i32, .add, code[0..4], S + A), | |
| 1997 | .SUB32 => riscv_util.writeAddend(i32, .sub, code[0..4], S + A), | |
| 1998 | .ADD64 => riscv_util.writeAddend(i64, .add, code[0..8], S + A), | |
| 1999 | .SUB64 => riscv_util.writeAddend(i64, .sub, code[0..8], S + A), | |
| 2000 | ||
| 2001 | .SET8 => mem.writeInt(i8, code[0..1], @as(i8, @truncate(S + A)), .little), | |
| 2002 | .SET16 => mem.writeInt(i16, code[0..2], @as(i16, @truncate(S + A)), .little), | |
| 2003 | .SET32 => mem.writeInt(i32, code[0..4], @as(i32, @truncate(S + A)), .little), | |
| 2004 | ||
| 2005 | .SET6 => riscv_util.writeSetSub6(.set, code[0..1], S + A), | |
| 2006 | .SUB6 => riscv_util.writeSetSub6(.sub, code[0..1], S + A), | |
| 2007 | ||
| 2008 | .SET_ULEB128 => riscv_util.writeSetUleb(code, S + A), | |
| 2009 | .SUB_ULEB128 => riscv_util.writeSubUleb(code, S - A), | |
| 2041 | 2010 | |
| 2042 | 2011 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 2043 | 2012 | } |
| ... | ... | @@ -2108,14 +2077,16 @@ pub const Extra = struct { |
| 2108 | 2077 | const std = @import("std"); |
| 2109 | 2078 | const assert = std.debug.assert; |
| 2110 | 2079 | const elf = std.elf; |
| 2111 | const eh_frame = @import("eh_frame.zig"); | |
| 2112 | 2080 | const log = std.log.scoped(.link); |
| 2113 | 2081 | const math = std.math; |
| 2114 | 2082 | const mem = std.mem; |
| 2115 | 2083 | const relocs_log = std.log.scoped(.link_relocs); |
| 2084 | const Allocator = mem.Allocator; | |
| 2085 | const Writer = std.Io.Writer; | |
| 2086 | ||
| 2087 | const eh_frame = @import("eh_frame.zig"); | |
| 2116 | 2088 | const relocation = @import("relocation.zig"); |
| 2117 | 2089 | |
| 2118 | const Allocator = mem.Allocator; | |
| 2119 | 2090 | const Atom = @This(); |
| 2120 | 2091 | const Elf = @import("../Elf.zig"); |
| 2121 | 2092 | const Fde = eh_frame.Fde; |
src/link/Elf/AtomList.zig+4-5| ... | ... | @@ -89,7 +89,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void { |
| 89 | 89 | list.dirty = false; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytype, elf_file: *Elf) !void { | |
| 92 | pub fn write(list: AtomList, buffer: *std.Io.Writer.Allocating, undefs: anytype, elf_file: *Elf) !void { | |
| 93 | 93 | const gpa = elf_file.base.comp.gpa; |
| 94 | 94 | const osec = elf_file.sections.items(.shdr)[list.output_section_index]; |
| 95 | 95 | assert(osec.sh_type != elf.SHT_NOBITS); |
| ... | ... | @@ -98,8 +98,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp |
| 98 | 98 | log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)}); |
| 99 | 99 | |
| 100 | 100 | const list_size = math.cast(usize, list.size) orelse return error.Overflow; |
| 101 | try buffer.ensureUnusedCapacity(list_size); | |
| 102 | buffer.appendNTimesAssumeCapacity(0, list_size); | |
| 101 | try buffer.writer.splatByteAll(0, list_size); | |
| 103 | 102 | |
| 104 | 103 | for (list.atoms.keys()) |ref| { |
| 105 | 104 | const atom_ptr = elf_file.atom(ref).?; |
| ... | ... | @@ -113,7 +112,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp |
| 113 | 112 | const object = atom_ptr.file(elf_file).?.object; |
| 114 | 113 | const code = try object.codeDecompressAlloc(elf_file, ref.index); |
| 115 | 114 | defer gpa.free(code); |
| 116 | const out_code = buffer.items[off..][0..size]; | |
| 115 | const out_code = buffer.written()[off..][0..size]; | |
| 117 | 116 | @memcpy(out_code, code); |
| 118 | 117 | |
| 119 | 118 | if (osec.sh_flags & elf.SHF_ALLOC == 0) |
| ... | ... | @@ -122,7 +121,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp |
| 122 | 121 | try atom_ptr.resolveRelocsAlloc(elf_file, out_code); |
| 123 | 122 | } |
| 124 | 123 | |
| 125 | try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file)); | |
| 124 | try elf_file.base.file.?.pwriteAll(buffer.written(), list.offset(elf_file)); | |
| 126 | 125 | buffer.clearRetainingCapacity(); |
| 127 | 126 | } |
| 128 | 127 |
src/link/Elf/Object.zig+1-1| ... | ... | @@ -952,7 +952,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 952 | 952 | const is_tls = sym.type(elf_file) == elf.STT_TLS; |
| 953 | 953 | const name = if (is_tls) ".tls_common" else ".common"; |
| 954 | 954 | const name_offset = @as(u32, @intCast(self.strtab.items.len)); |
| 955 | try self.strtab.writer(gpa).print("{s}\x00", .{name}); | |
| 955 | try self.strtab.print(gpa, "{s}\x00", .{name}); | |
| 956 | 956 | |
| 957 | 957 | var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE; |
| 958 | 958 | if (is_tls) sh_flags |= elf.SHF_TLS; |
src/link/Elf/gc.zig-16| ... | ... | @@ -162,22 +162,6 @@ fn prune(elf_file: *Elf) void { |
| 162 | 162 | } |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | pub fn dumpPrunedAtoms(elf_file: *Elf) !void { | |
| 166 | const stderr = std.fs.File.stderr().deprecatedWriter(); | |
| 167 | for (elf_file.objects.items) |index| { | |
| 168 | const file = elf_file.file(index).?; | |
| 169 | for (file.atoms()) |atom_index| { | |
| 170 | const atom = file.atom(atom_index) orelse continue; | |
| 171 | if (!atom.alive) | |
| 172 | // TODO should we simply print to stderr? | |
| 173 | try stderr.print("link: removing unused section '{s}' in file '{f}'\n", .{ | |
| 174 | atom.name(elf_file), | |
| 175 | atom.file(elf_file).?.fmtPath(), | |
| 176 | }); | |
| 177 | } | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | 165 | const Level = struct { |
| 182 | 166 | value: usize = 0, |
| 183 | 167 |
src/link/Elf/relocatable.zig+24-21| ... | ... | @@ -100,32 +100,33 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { |
| 100 | 100 | state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | var buffer = std.array_list.Managed(u8).init(gpa); | |
| 104 | defer buffer.deinit(); | |
| 105 | try buffer.ensureTotalCapacityPrecise(total_size); | |
| 103 | const buffer = try gpa.alloc(u8, total_size); | |
| 104 | defer gpa.free(buffer); | |
| 105 | ||
| 106 | var writer: std.Io.Writer = .fixed(buffer); | |
| 106 | 107 | |
| 107 | 108 | // Write magic |
| 108 | try buffer.writer().writeAll(elf.ARMAG); | |
| 109 | try writer.writeAll(elf.ARMAG); | |
| 109 | 110 | |
| 110 | 111 | // Write symtab |
| 111 | try ar_symtab.write(.p64, elf_file, buffer.writer()); | |
| 112 | try ar_symtab.write(.p64, elf_file, &writer); | |
| 112 | 113 | |
| 113 | 114 | // Write strtab |
| 114 | 115 | if (ar_strtab.size() > 0) { |
| 115 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | |
| 116 | try ar_strtab.write(buffer.writer()); | |
| 116 | if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); | |
| 117 | try ar_strtab.write(&writer); | |
| 117 | 118 | } |
| 118 | 119 | |
| 119 | 120 | // Write object files |
| 120 | 121 | for (files.items) |index| { |
| 121 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | |
| 122 | try elf_file.file(index).?.writeAr(elf_file, buffer.writer()); | |
| 122 | if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); | |
| 123 | try elf_file.file(index).?.writeAr(elf_file, &writer); | |
| 123 | 124 | } |
| 124 | 125 | |
| 125 | assert(buffer.items.len == total_size); | |
| 126 | assert(writer.buffered().len == total_size); | |
| 126 | 127 | |
| 127 | 128 | try elf_file.base.file.?.setEndPos(total_size); |
| 128 | try elf_file.base.file.?.pwriteAll(buffer.items, 0); | |
| 129 | try elf_file.base.file.?.pwriteAll(writer.buffered(), 0); | |
| 129 | 130 | |
| 130 | 131 | if (diags.hasErrors()) return error.LinkFailure; |
| 131 | 132 | } |
| ... | ... | @@ -407,15 +408,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 407 | 408 | }; |
| 408 | 409 | const shdr = slice.items(.shdr)[shndx]; |
| 409 | 410 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 410 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); | |
| 411 | defer buffer.deinit(); | |
| 412 | try eh_frame.writeEhFrameRelocatable(elf_file, buffer.writer()); | |
| 411 | const buffer = try gpa.alloc(u8, @intCast(sh_size - existing_size)); | |
| 412 | defer gpa.free(buffer); | |
| 413 | var writer: std.Io.Writer = .fixed(buffer); | |
| 414 | try eh_frame.writeEhFrameRelocatable(elf_file, &writer); | |
| 413 | 415 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ |
| 414 | 416 | shdr.sh_offset + existing_size, |
| 415 | 417 | shdr.sh_offset + sh_size, |
| 416 | 418 | }); |
| 417 | assert(buffer.items.len == sh_size - existing_size); | |
| 418 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); | |
| 419 | assert(writer.buffered().len == sh_size - existing_size); | |
| 420 | try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset + existing_size); | |
| 419 | 421 | } |
| 420 | 422 | if (elf_file.section_indexes.eh_frame_rela) |shndx| { |
| 421 | 423 | const shdr = slice.items(.shdr)[shndx]; |
| ... | ... | @@ -446,15 +448,16 @@ fn writeGroups(elf_file: *Elf) !void { |
| 446 | 448 | for (elf_file.group_sections.items) |cgs| { |
| 447 | 449 | const shdr = elf_file.sections.items(.shdr)[cgs.shndx]; |
| 448 | 450 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 449 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size); | |
| 450 | defer buffer.deinit(); | |
| 451 | try cgs.write(elf_file, buffer.writer()); | |
| 452 | assert(buffer.items.len == sh_size); | |
| 451 | const buffer = try gpa.alloc(u8, sh_size); | |
| 452 | defer gpa.free(buffer); | |
| 453 | var writer: std.Io.Writer = .fixed(buffer); | |
| 454 | try cgs.write(elf_file, &writer); | |
| 455 | assert(writer.buffered().len == sh_size); | |
| 453 | 456 | log.debug("writing group from 0x{x} to 0x{x}", .{ |
| 454 | 457 | shdr.sh_offset, |
| 455 | 458 | shdr.sh_offset + shdr.sh_size, |
| 456 | 459 | }); |
| 457 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | |
| 460 | try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset); | |
| 458 | 461 | } |
| 459 | 462 | } |
| 460 | 463 |
src/link/Elf/synthetic_sections.zig+53-51| ... | ... | @@ -94,134 +94,134 @@ pub const DynamicSection = struct { |
| 94 | 94 | return nentries * @sizeOf(elf.Elf64_Dyn); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void { | |
| 97 | pub fn write(dt: DynamicSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 98 | 98 | const shdrs = elf_file.sections.items(.shdr); |
| 99 | 99 | |
| 100 | 100 | // NEEDED |
| 101 | 101 | for (dt.needed.items) |off| { |
| 102 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off }); | |
| 102 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NEEDED, .d_val = off }), .little); | |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 105 | if (dt.soname) |off| { |
| 106 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off }); | |
| 106 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SONAME, .d_val = off }), .little); | |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | // RUNPATH |
| 110 | 110 | // TODO add option in Options to revert to old RPATH tag |
| 111 | 111 | if (dt.rpath > 0) { |
| 112 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath }); | |
| 112 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath }), .little); | |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | // INIT |
| 116 | 116 | if (elf_file.sectionByName(".init")) |shndx| { |
| 117 | 117 | const addr = shdrs[shndx].sh_addr; |
| 118 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr }); | |
| 118 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT, .d_val = addr }), .little); | |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | // FINI |
| 122 | 122 | if (elf_file.sectionByName(".fini")) |shndx| { |
| 123 | 123 | const addr = shdrs[shndx].sh_addr; |
| 124 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr }); | |
| 124 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little); | |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | // INIT_ARRAY |
| 128 | 128 | if (elf_file.sectionByName(".init_array")) |shndx| { |
| 129 | 129 | const shdr = shdrs[shndx]; |
| 130 | try writer.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 }); | |
| 130 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }), .little); | |
| 131 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }), .little); | |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | // FINI_ARRAY |
| 135 | 135 | if (elf_file.sectionByName(".fini_array")) |shndx| { |
| 136 | 136 | const shdr = shdrs[shndx]; |
| 137 | try writer.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 }); | |
| 137 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }), .little); | |
| 138 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }), .little); | |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | 141 | // RELA |
| 142 | 142 | if (elf_file.section_indexes.rela_dyn) |shndx| { |
| 143 | 143 | const shdr = shdrs[shndx]; |
| 144 | try writer.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 }); | |
| 146 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }); | |
| 144 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }), .little); | |
| 145 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }), .little); | |
| 146 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }), .little); | |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | // JMPREL |
| 150 | 150 | if (elf_file.section_indexes.rela_plt) |shndx| { |
| 151 | 151 | const shdr = shdrs[shndx]; |
| 152 | try writer.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 }); | |
| 154 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }); | |
| 152 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }), .little); | |
| 153 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }), .little); | |
| 154 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }), .little); | |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | // PLTGOT |
| 158 | 158 | if (elf_file.section_indexes.got_plt) |shndx| { |
| 159 | 159 | const addr = shdrs[shndx].sh_addr; |
| 160 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); | |
| 160 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTGOT, .d_val = addr }), .little); | |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | 163 | { |
| 164 | 164 | assert(elf_file.section_indexes.hash != null); |
| 165 | 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 writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_HASH, .d_val = addr }), .little); | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | if (elf_file.section_indexes.gnu_hash) |shndx| { |
| 170 | 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 writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }), .little); | |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | // TEXTREL |
| 175 | 175 | if (elf_file.has_text_reloc) { |
| 176 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }); | |
| 176 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }), .little); | |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 179 | // SYMTAB + SYMENT |
| 180 | 180 | { |
| 181 | 181 | assert(elf_file.section_indexes.dynsymtab != null); |
| 182 | 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 }); | |
| 184 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); | |
| 183 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }), .little); | |
| 184 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }), .little); | |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | 187 | // STRTAB + STRSZ |
| 188 | 188 | { |
| 189 | 189 | assert(elf_file.section_indexes.dynstrtab != null); |
| 190 | 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 }); | |
| 192 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); | |
| 191 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }), .little); | |
| 192 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }), .little); | |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 195 | // VERSYM |
| 196 | 196 | if (elf_file.section_indexes.versym) |shndx| { |
| 197 | 197 | const addr = shdrs[shndx].sh_addr; |
| 198 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); | |
| 198 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERSYM, .d_val = addr }), .little); | |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | 201 | // VERNEED + VERNEEDNUM |
| 202 | 202 | if (elf_file.section_indexes.verneed) |shndx| { |
| 203 | 203 | const addr = shdrs[shndx].sh_addr; |
| 204 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); | |
| 205 | try writer.writeStruct(elf.Elf64_Dyn{ | |
| 204 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERNEED, .d_val = addr }), .little); | |
| 205 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ | |
| 206 | 206 | .d_tag = elf.DT_VERNEEDNUM, |
| 207 | 207 | .d_val = elf_file.verneed.verneed.items.len, |
| 208 | }); | |
| 208 | }), .little); | |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | // FLAGS |
| 212 | 212 | if (dt.getFlags(elf_file)) |flags| { |
| 213 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags }); | |
| 213 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS, .d_val = flags }), .little); | |
| 214 | 214 | } |
| 215 | 215 | // FLAGS_1 |
| 216 | 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 writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 }), .little); | |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | // 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 writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_DEBUG, .d_val = 0 }), .little); | |
| 222 | 222 | |
| 223 | 223 | // NULL |
| 224 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 }); | |
| 224 | try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NULL, .d_val = 0 }), .little); | |
| 225 | 225 | } |
| 226 | 226 | }; |
| 227 | 227 | |
| ... | ... | @@ -360,7 +360,7 @@ pub const GotSection = struct { |
| 360 | 360 | return s; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void { | |
| 363 | pub fn write(got: GotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 364 | 364 | const comp = elf_file.base.comp; |
| 365 | 365 | const is_dyn_lib = elf_file.isEffectivelyDynLib(); |
| 366 | 366 | const apply_relocs = true; // TODO add user option for this |
| ... | ... | @@ -666,7 +666,7 @@ pub const PltSection = struct { |
| 666 | 666 | }; |
| 667 | 667 | } |
| 668 | 668 | |
| 669 | pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | |
| 669 | pub fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 670 | 670 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 671 | 671 | switch (cpu_arch) { |
| 672 | 672 | .x86_64 => try x86_64.write(plt, elf_file, writer), |
| ... | ... | @@ -763,7 +763,7 @@ pub const PltSection = struct { |
| 763 | 763 | } |
| 764 | 764 | |
| 765 | 765 | const x86_64 = struct { |
| 766 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | |
| 766 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 767 | 767 | const shdrs = elf_file.sections.items(.shdr); |
| 768 | 768 | const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr; |
| 769 | 769 | const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr; |
| ... | ... | @@ -778,7 +778,7 @@ pub const PltSection = struct { |
| 778 | 778 | disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4; |
| 779 | 779 | mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little); |
| 780 | 780 | try writer.writeAll(&preamble); |
| 781 | try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len); | |
| 781 | try writer.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len); | |
| 782 | 782 | |
| 783 | 783 | for (plt.symbols.items, 0..) |ref, i| { |
| 784 | 784 | const sym = elf_file.symbol(ref).?; |
| ... | ... | @@ -798,7 +798,7 @@ pub const PltSection = struct { |
| 798 | 798 | }; |
| 799 | 799 | |
| 800 | 800 | const aarch64 = struct { |
| 801 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | |
| 801 | fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 802 | 802 | { |
| 803 | 803 | const shdrs = elf_file.sections.items(.shdr); |
| 804 | 804 | const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr); |
| ... | ... | @@ -853,7 +853,7 @@ pub const GotPltSection = struct { |
| 853 | 853 | return preamble_size + elf_file.plt.symbols.items.len * 8; |
| 854 | 854 | } |
| 855 | 855 | |
| 856 | pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: anytype) !void { | |
| 856 | pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 857 | 857 | _ = got_plt; |
| 858 | 858 | { |
| 859 | 859 | // [0]: _DYNAMIC |
| ... | ... | @@ -904,7 +904,7 @@ pub const PltGotSection = struct { |
| 904 | 904 | }; |
| 905 | 905 | } |
| 906 | 906 | |
| 907 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { | |
| 907 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 908 | 908 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 909 | 909 | switch (cpu_arch) { |
| 910 | 910 | .x86_64 => try x86_64.write(plt_got, elf_file, writer), |
| ... | ... | @@ -940,7 +940,7 @@ pub const PltGotSection = struct { |
| 940 | 940 | } |
| 941 | 941 | |
| 942 | 942 | const x86_64 = struct { |
| 943 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { | |
| 943 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 944 | 944 | for (plt_got.symbols.items) |ref| { |
| 945 | 945 | const sym = elf_file.symbol(ref).?; |
| 946 | 946 | const target_addr = sym.gotAddress(elf_file); |
| ... | ... | @@ -958,7 +958,7 @@ pub const PltGotSection = struct { |
| 958 | 958 | }; |
| 959 | 959 | |
| 960 | 960 | const aarch64 = struct { |
| 961 | fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { | |
| 961 | fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 962 | 962 | for (plt_got.symbols.items) |ref| { |
| 963 | 963 | const sym = elf_file.symbol(ref).?; |
| 964 | 964 | const target_addr = sym.gotAddress(elf_file); |
| ... | ... | @@ -1133,14 +1133,14 @@ pub const DynsymSection = struct { |
| 1133 | 1133 | return @as(u32, @intCast(dynsym.entries.items.len + 1)); |
| 1134 | 1134 | } |
| 1135 | 1135 | |
| 1136 | pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void { | |
| 1137 | try writer.writeStruct(Elf.null_sym); | |
| 1136 | pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 1137 | try writer.writeStruct(Elf.null_sym, .little); | |
| 1138 | 1138 | for (dynsym.entries.items) |entry| { |
| 1139 | 1139 | const sym = elf_file.symbol(entry.ref).?; |
| 1140 | 1140 | var out_sym: elf.Elf64_Sym = Elf.null_sym; |
| 1141 | 1141 | sym.setOutputSym(elf_file, &out_sym); |
| 1142 | 1142 | out_sym.st_name = entry.off; |
| 1143 | try writer.writeStruct(out_sym); | |
| 1143 | try writer.writeStruct(out_sym, .little); | |
| 1144 | 1144 | } |
| 1145 | 1145 | } |
| 1146 | 1146 | }; |
| ... | ... | @@ -1175,10 +1175,12 @@ pub const HashSection = struct { |
| 1175 | 1175 | } |
| 1176 | 1176 | |
| 1177 | 1177 | try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4); |
| 1178 | hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; | |
| 1179 | hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; | |
| 1180 | hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(buckets)) catch unreachable; | |
| 1181 | hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(chains)) catch unreachable; | |
| 1178 | var w: std.Io.Writer = .fixed(hs.buffer.unusedCapacitySlice()); | |
| 1179 | w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; | |
| 1180 | w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; | |
| 1181 | w.writeAll(@ptrCast(buckets)) catch unreachable; | |
| 1182 | w.writeAll(@ptrCast(chains)) catch unreachable; | |
| 1183 | hs.buffer.items.len += w.end; | |
| 1182 | 1184 | } |
| 1183 | 1185 | |
| 1184 | 1186 | pub inline fn size(hs: HashSection) usize { |
| ... | ... | @@ -1439,7 +1441,7 @@ pub const VerneedSection = struct { |
| 1439 | 1441 | return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux); |
| 1440 | 1442 | } |
| 1441 | 1443 | |
| 1442 | pub fn write(vern: VerneedSection, writer: anytype) !void { | |
| 1444 | pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void { | |
| 1443 | 1445 | try writer.writeAll(mem.sliceAsBytes(vern.verneed.items)); |
| 1444 | 1446 | try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items)); |
| 1445 | 1447 | } |
| ... | ... | @@ -1467,7 +1469,7 @@ pub const GroupSection = struct { |
| 1467 | 1469 | return (members.len + 1) * @sizeOf(u32); |
| 1468 | 1470 | } |
| 1469 | 1471 | |
| 1470 | pub fn write(cgs: GroupSection, elf_file: *Elf, writer: anytype) !void { | |
| 1472 | pub fn write(cgs: GroupSection, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 1471 | 1473 | const cg = cgs.group(elf_file); |
| 1472 | 1474 | const object = cg.file(elf_file).object; |
| 1473 | 1475 | const members = cg.members(elf_file); |
| ... | ... | @@ -1495,7 +1497,7 @@ pub const GroupSection = struct { |
| 1495 | 1497 | } |
| 1496 | 1498 | }; |
| 1497 | 1499 | |
| 1498 | fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void { | |
| 1500 | fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void { | |
| 1499 | 1501 | const entry_size = elf_file.archPtrWidthBytes(); |
| 1500 | 1502 | const target = elf_file.getTarget(); |
| 1501 | 1503 | const endian = target.cpu.arch.endian(); |
src/link/MachO.zig+71-65| ... | ... | @@ -589,7 +589,7 @@ pub fn flush( |
| 589 | 589 | ); |
| 590 | 590 | |
| 591 | 591 | const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) { |
| 592 | error.NoSpaceLeft => unreachable, | |
| 592 | error.WriteFailed => unreachable, | |
| 593 | 593 | error.OutOfMemory => return error.OutOfMemory, |
| 594 | 594 | error.LinkFailure => return error.LinkFailure, |
| 595 | 595 | }; |
| ... | ... | @@ -1074,7 +1074,7 @@ fn accessLibPath( |
| 1074 | 1074 | |
| 1075 | 1075 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1076 | 1076 | test_path.clearRetainingCapacity(); |
| 1077 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); | |
| 1077 | try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); | |
| 1078 | 1078 | try checked_paths.append(try arena.dupe(u8, test_path.items)); |
| 1079 | 1079 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| 1080 | 1080 | error.FileNotFound => continue, |
| ... | ... | @@ -1097,7 +1097,7 @@ fn accessFrameworkPath( |
| 1097 | 1097 | |
| 1098 | 1098 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1099 | 1099 | test_path.clearRetainingCapacity(); |
| 1100 | try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ | |
| 1100 | try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ | |
| 1101 | 1101 | search_dir, |
| 1102 | 1102 | name, |
| 1103 | 1103 | name, |
| ... | ... | @@ -1178,9 +1178,9 @@ fn parseDependentDylibs(self: *MachO) !void { |
| 1178 | 1178 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1179 | 1179 | test_path.clearRetainingCapacity(); |
| 1180 | 1180 | if (self.base.comp.sysroot) |root| { |
| 1181 | try test_path.writer().print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); | |
| 1181 | try test_path.print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); | |
| 1182 | 1182 | } else { |
| 1183 | try test_path.writer().print("{s}{s}", .{ path, ext }); | |
| 1183 | try test_path.print("{s}{s}", .{ path, ext }); | |
| 1184 | 1184 | } |
| 1185 | 1185 | try checked_paths.append(try arena.dupe(u8, test_path.items)); |
| 1186 | 1186 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| ... | ... | @@ -2528,8 +2528,8 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void { |
| 2528 | 2528 | fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void { |
| 2529 | 2529 | const off = try macho_file.cast(usize, th.value); |
| 2530 | 2530 | const size = th.size(); |
| 2531 | var stream = std.io.fixedBufferStream(buffer[off..][0..size]); | |
| 2532 | try th.write(macho_file, stream.writer()); | |
| 2531 | var stream: Writer = .fixed(buffer[off..][0..size]); | |
| 2532 | try th.write(macho_file, &stream); | |
| 2533 | 2533 | } |
| 2534 | 2534 | }.doWork; |
| 2535 | 2535 | const out = self.sections.items(.out)[thunk.out_n_sect].items; |
| ... | ... | @@ -2556,15 +2556,15 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void { |
| 2556 | 2556 | |
| 2557 | 2557 | const doWork = struct { |
| 2558 | 2558 | fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void { |
| 2559 | var stream = std.io.fixedBufferStream(buffer); | |
| 2559 | var stream: Writer = .fixed(buffer); | |
| 2560 | 2560 | switch (tag) { |
| 2561 | 2561 | .eh_frame => eh_frame.write(macho_file, buffer), |
| 2562 | 2562 | .unwind_info => try macho_file.unwind_info.write(macho_file, buffer), |
| 2563 | .got => try macho_file.got.write(macho_file, stream.writer()), | |
| 2564 | .stubs => try macho_file.stubs.write(macho_file, stream.writer()), | |
| 2565 | .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()), | |
| 2566 | .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()), | |
| 2567 | .objc_stubs => try macho_file.objc_stubs.write(macho_file, stream.writer()), | |
| 2563 | .got => try macho_file.got.write(macho_file, &stream), | |
| 2564 | .stubs => try macho_file.stubs.write(macho_file, &stream), | |
| 2565 | .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, &stream), | |
| 2566 | .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, &stream), | |
| 2567 | .objc_stubs => try macho_file.objc_stubs.write(macho_file, &stream), | |
| 2568 | 2568 | } |
| 2569 | 2569 | } |
| 2570 | 2570 | }.doWork; |
| ... | ... | @@ -2605,8 +2605,8 @@ fn updateLazyBindSizeWorker(self: *MachO) void { |
| 2605 | 2605 | try macho_file.lazy_bind_section.updateSize(macho_file); |
| 2606 | 2606 | const sect_id = macho_file.stubs_helper_sect_index.?; |
| 2607 | 2607 | const out = &macho_file.sections.items(.out)[sect_id]; |
| 2608 | var stream = std.io.fixedBufferStream(out.items); | |
| 2609 | try macho_file.stubs_helper.write(macho_file, stream.writer()); | |
| 2608 | var stream: Writer = .fixed(out.items); | |
| 2609 | try macho_file.stubs_helper.write(macho_file, &stream); | |
| 2610 | 2610 | } |
| 2611 | 2611 | }.doWork; |
| 2612 | 2612 | doWork(self) catch |err| |
| ... | ... | @@ -2669,18 +2669,17 @@ fn writeDyldInfo(self: *MachO) !void { |
| 2669 | 2669 | defer gpa.free(buffer); |
| 2670 | 2670 | @memset(buffer, 0); |
| 2671 | 2671 | |
| 2672 | var stream = std.io.fixedBufferStream(buffer); | |
| 2673 | const writer = stream.writer(); | |
| 2674 | ||
| 2675 | try self.rebase_section.write(writer); | |
| 2676 | try stream.seekTo(cmd.bind_off - base_off); | |
| 2677 | try self.bind_section.write(writer); | |
| 2678 | try stream.seekTo(cmd.weak_bind_off - base_off); | |
| 2679 | try self.weak_bind_section.write(writer); | |
| 2680 | try stream.seekTo(cmd.lazy_bind_off - base_off); | |
| 2681 | try self.lazy_bind_section.write(writer); | |
| 2682 | try stream.seekTo(cmd.export_off - base_off); | |
| 2683 | try self.export_trie.write(writer); | |
| 2672 | var writer: Writer = .fixed(buffer); | |
| 2673 | ||
| 2674 | try self.rebase_section.write(&writer); | |
| 2675 | writer.end = @intCast(cmd.bind_off - base_off); | |
| 2676 | try self.bind_section.write(&writer); | |
| 2677 | writer.end = @intCast(cmd.weak_bind_off - base_off); | |
| 2678 | try self.weak_bind_section.write(&writer); | |
| 2679 | writer.end = @intCast(cmd.lazy_bind_off - base_off); | |
| 2680 | try self.lazy_bind_section.write(&writer); | |
| 2681 | writer.end = @intCast(cmd.export_off - base_off); | |
| 2682 | try self.export_trie.write(&writer); | |
| 2684 | 2683 | try self.pwriteAll(buffer, cmd.rebase_off); |
| 2685 | 2684 | } |
| 2686 | 2685 | |
| ... | ... | @@ -2689,10 +2688,10 @@ pub fn writeDataInCode(self: *MachO) !void { |
| 2689 | 2688 | defer tracy.end(); |
| 2690 | 2689 | const gpa = self.base.comp.gpa; |
| 2691 | 2690 | const cmd = self.data_in_code_cmd; |
| 2692 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.data_in_code.size()); | |
| 2691 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.data_in_code.size()); | |
| 2693 | 2692 | defer buffer.deinit(); |
| 2694 | try self.data_in_code.write(self, buffer.writer()); | |
| 2695 | try self.pwriteAll(buffer.items, cmd.dataoff); | |
| 2693 | self.data_in_code.write(self, &buffer.writer) catch return error.OutOfMemory; | |
| 2694 | try self.pwriteAll(buffer.written(), cmd.dataoff); | |
| 2696 | 2695 | } |
| 2697 | 2696 | |
| 2698 | 2697 | fn writeIndsymtab(self: *MachO) !void { |
| ... | ... | @@ -2701,10 +2700,11 @@ fn writeIndsymtab(self: *MachO) !void { |
| 2701 | 2700 | const gpa = self.base.comp.gpa; |
| 2702 | 2701 | const cmd = self.dysymtab_cmd; |
| 2703 | 2702 | const needed_size = cmd.nindirectsyms * @sizeOf(u32); |
| 2704 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, needed_size); | |
| 2705 | defer buffer.deinit(); | |
| 2706 | try self.indsymtab.write(self, buffer.writer()); | |
| 2707 | try self.pwriteAll(buffer.items, cmd.indirectsymoff); | |
| 2703 | const buffer = try gpa.alloc(u8, needed_size); | |
| 2704 | defer gpa.free(buffer); | |
| 2705 | var writer: Writer = .fixed(buffer); | |
| 2706 | try self.indsymtab.write(self, &writer); | |
| 2707 | try self.pwriteAll(buffer, cmd.indirectsymoff); | |
| 2708 | 2708 | } |
| 2709 | 2709 | |
| 2710 | 2710 | pub fn writeSymtabToFile(self: *MachO) !void { |
| ... | ... | @@ -2821,8 +2821,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2821 | 2821 | const buffer = try gpa.alloc(u8, needed_size); |
| 2822 | 2822 | defer gpa.free(buffer); |
| 2823 | 2823 | |
| 2824 | var stream = std.io.fixedBufferStream(buffer); | |
| 2825 | const writer = stream.writer(); | |
| 2824 | var writer: Writer = .fixed(buffer); | |
| 2826 | 2825 | |
| 2827 | 2826 | var ncmds: usize = 0; |
| 2828 | 2827 | |
| ... | ... | @@ -2831,26 +2830,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2831 | 2830 | const slice = self.sections.slice(); |
| 2832 | 2831 | var sect_id: usize = 0; |
| 2833 | 2832 | for (self.segments.items) |seg| { |
| 2834 | try writer.writeStruct(seg); | |
| 2833 | try writer.writeStruct(seg, .little); | |
| 2835 | 2834 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { |
| 2836 | try writer.writeStruct(header); | |
| 2835 | try writer.writeStruct(header, .little); | |
| 2837 | 2836 | } |
| 2838 | 2837 | sect_id += seg.nsects; |
| 2839 | 2838 | } |
| 2840 | 2839 | ncmds += self.segments.items.len; |
| 2841 | 2840 | } |
| 2842 | 2841 | |
| 2843 | try writer.writeStruct(self.dyld_info_cmd); | |
| 2842 | try writer.writeStruct(self.dyld_info_cmd, .little); | |
| 2844 | 2843 | ncmds += 1; |
| 2845 | try writer.writeStruct(self.function_starts_cmd); | |
| 2844 | try writer.writeStruct(self.function_starts_cmd, .little); | |
| 2846 | 2845 | ncmds += 1; |
| 2847 | try writer.writeStruct(self.data_in_code_cmd); | |
| 2846 | try writer.writeStruct(self.data_in_code_cmd, .little); | |
| 2848 | 2847 | ncmds += 1; |
| 2849 | try writer.writeStruct(self.symtab_cmd); | |
| 2848 | try writer.writeStruct(self.symtab_cmd, .little); | |
| 2850 | 2849 | ncmds += 1; |
| 2851 | try writer.writeStruct(self.dysymtab_cmd); | |
| 2850 | try writer.writeStruct(self.dysymtab_cmd, .little); | |
| 2852 | 2851 | ncmds += 1; |
| 2853 | try load_commands.writeDylinkerLC(writer); | |
| 2852 | try load_commands.writeDylinkerLC(&writer); | |
| 2854 | 2853 | ncmds += 1; |
| 2855 | 2854 | |
| 2856 | 2855 | if (self.getInternalObject()) |obj| { |
| ... | ... | @@ -2861,44 +2860,44 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2861 | 2860 | 0 |
| 2862 | 2861 | else |
| 2863 | 2862 | @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); |
| 2864 | try writer.writeStruct(macho.entry_point_command{ | |
| 2863 | try writer.writeStruct(@as(macho.entry_point_command, .{ | |
| 2865 | 2864 | .entryoff = entryoff, |
| 2866 | 2865 | .stacksize = self.base.stack_size, |
| 2867 | }); | |
| 2866 | }), .little); | |
| 2868 | 2867 | ncmds += 1; |
| 2869 | 2868 | } |
| 2870 | 2869 | } |
| 2871 | 2870 | |
| 2872 | 2871 | if (self.base.isDynLib()) { |
| 2873 | try load_commands.writeDylibIdLC(self, writer); | |
| 2872 | try load_commands.writeDylibIdLC(self, &writer); | |
| 2874 | 2873 | ncmds += 1; |
| 2875 | 2874 | } |
| 2876 | 2875 | |
| 2877 | 2876 | for (self.rpath_list) |rpath| { |
| 2878 | try load_commands.writeRpathLC(rpath, writer); | |
| 2877 | try load_commands.writeRpathLC(rpath, &writer); | |
| 2879 | 2878 | ncmds += 1; |
| 2880 | 2879 | } |
| 2881 | 2880 | if (comp.config.any_sanitize_thread) { |
| 2882 | 2881 | const path = try comp.tsan_lib.?.full_object_path.toString(gpa); |
| 2883 | 2882 | defer gpa.free(path); |
| 2884 | 2883 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 2885 | try load_commands.writeRpathLC(rpath, writer); | |
| 2884 | try load_commands.writeRpathLC(rpath, &writer); | |
| 2886 | 2885 | ncmds += 1; |
| 2887 | 2886 | } |
| 2888 | 2887 | |
| 2889 | try writer.writeStruct(macho.source_version_command{ .version = 0 }); | |
| 2888 | try writer.writeStruct(@as(macho.source_version_command, .{ .version = 0 }), .little); | |
| 2890 | 2889 | ncmds += 1; |
| 2891 | 2890 | |
| 2892 | 2891 | if (self.platform.isBuildVersionCompatible()) { |
| 2893 | try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, writer); | |
| 2892 | try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, &writer); | |
| 2894 | 2893 | ncmds += 1; |
| 2895 | 2894 | } else { |
| 2896 | try load_commands.writeVersionMinLC(self.platform, self.sdk_version, writer); | |
| 2895 | try load_commands.writeVersionMinLC(self.platform, self.sdk_version, &writer); | |
| 2897 | 2896 | ncmds += 1; |
| 2898 | 2897 | } |
| 2899 | 2898 | |
| 2900 | const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + stream.pos; | |
| 2901 | try writer.writeStruct(self.uuid_cmd); | |
| 2899 | const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + writer.end; | |
| 2900 | try writer.writeStruct(self.uuid_cmd, .little); | |
| 2902 | 2901 | ncmds += 1; |
| 2903 | 2902 | |
| 2904 | 2903 | for (self.dylibs.items) |index| { |
| ... | ... | @@ -2916,16 +2915,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2916 | 2915 | .timestamp = dylib_id.timestamp, |
| 2917 | 2916 | .current_version = dylib_id.current_version, |
| 2918 | 2917 | .compatibility_version = dylib_id.compatibility_version, |
| 2919 | }, writer); | |
| 2918 | }, &writer); | |
| 2920 | 2919 | ncmds += 1; |
| 2921 | 2920 | } |
| 2922 | 2921 | |
| 2923 | 2922 | if (self.requiresCodeSig()) { |
| 2924 | try writer.writeStruct(self.codesig_cmd); | |
| 2923 | try writer.writeStruct(self.codesig_cmd, .little); | |
| 2925 | 2924 | ncmds += 1; |
| 2926 | 2925 | } |
| 2927 | 2926 | |
| 2928 | assert(stream.pos == needed_size); | |
| 2927 | assert(writer.end == needed_size); | |
| 2929 | 2928 | |
| 2930 | 2929 | try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 2931 | 2930 | |
| ... | ... | @@ -3014,25 +3013,32 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { |
| 3014 | 3013 | pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { |
| 3015 | 3014 | const seg = self.getTextSegment(); |
| 3016 | 3015 | const offset = self.codesig_cmd.dataoff; |
| 3016 | const gpa = self.base.comp.gpa; | |
| 3017 | 3017 | |
| 3018 | var buffer = std.array_list.Managed(u8).init(self.base.comp.gpa); | |
| 3018 | var buffer: std.Io.Writer.Allocating = .init(gpa); | |
| 3019 | 3019 | defer buffer.deinit(); |
| 3020 | try buffer.ensureTotalCapacityPrecise(code_sig.size()); | |
| 3021 | try code_sig.writeAdhocSignature(self, .{ | |
| 3020 | // The writeAdhocSignature function internally changes code_sig.size() | |
| 3021 | // during the execution. | |
| 3022 | try buffer.ensureUnusedCapacity(code_sig.size()); | |
| 3023 | ||
| 3024 | code_sig.writeAdhocSignature(self, .{ | |
| 3022 | 3025 | .file = self.base.file.?, |
| 3023 | 3026 | .exec_seg_base = seg.fileoff, |
| 3024 | 3027 | .exec_seg_limit = seg.filesize, |
| 3025 | 3028 | .file_size = offset, |
| 3026 | 3029 | .dylib = self.base.isDynLib(), |
| 3027 | }, buffer.writer()); | |
| 3028 | assert(buffer.items.len == code_sig.size()); | |
| 3030 | }, &buffer.writer) catch |err| switch (err) { | |
| 3031 | error.WriteFailed => return error.OutOfMemory, | |
| 3032 | else => |e| return e, | |
| 3033 | }; | |
| 3034 | assert(buffer.written().len == code_sig.size()); | |
| 3029 | 3035 | |
| 3030 | 3036 | log.debug("writing code signature from 0x{x} to 0x{x}", .{ |
| 3031 | 3037 | offset, |
| 3032 | offset + buffer.items.len, | |
| 3038 | offset + buffer.written().len, | |
| 3033 | 3039 | }); |
| 3034 | 3040 | |
| 3035 | try self.pwriteAll(buffer.items, offset); | |
| 3041 | try self.pwriteAll(buffer.written(), offset); | |
| 3036 | 3042 | } |
| 3037 | 3043 | |
| 3038 | 3044 | pub fn updateFunc( |
| ... | ... | @@ -5372,7 +5378,7 @@ const macho = std.macho; |
| 5372 | 5378 | const math = std.math; |
| 5373 | 5379 | const mem = std.mem; |
| 5374 | 5380 | const meta = std.meta; |
| 5375 | const Writer = std.io.Writer; | |
| 5381 | const Writer = std.Io.Writer; | |
| 5376 | 5382 | |
| 5377 | 5383 | const aarch64 = codegen.aarch64.encoding; |
| 5378 | 5384 | const bind = @import("MachO/dyld_info/bind.zig"); |
src/link/MachO/Archive.zig+18-38| ... | ... | @@ -81,34 +81,20 @@ pub fn writeHeader( |
| 81 | 81 | object_name: []const u8, |
| 82 | 82 | object_size: usize, |
| 83 | 83 | format: Format, |
| 84 | writer: anytype, | |
| 84 | writer: *Writer, | |
| 85 | 85 | ) !void { |
| 86 | var hdr: ar_hdr = .{ | |
| 87 | .ar_name = undefined, | |
| 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); | |
| 86 | var hdr: ar_hdr = .{}; | |
| 101 | 87 | |
| 102 | 88 | const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format)); |
| 103 | 89 | const total_object_size = object_size + object_name_len; |
| 104 | 90 | |
| 105 | 91 | { |
| 106 | var stream = std.io.fixedBufferStream(&hdr.ar_name); | |
| 107 | stream.writer().print("#1/{d}", .{object_name_len}) catch unreachable; | |
| 92 | var stream: Writer = .fixed(&hdr.ar_name); | |
| 93 | stream.print("#1/{d}", .{object_name_len}) catch unreachable; | |
| 108 | 94 | } |
| 109 | 95 | { |
| 110 | var stream = std.io.fixedBufferStream(&hdr.ar_size); | |
| 111 | stream.writer().print("{d}", .{total_object_size}) catch unreachable; | |
| 96 | var stream: Writer = .fixed(&hdr.ar_size); | |
| 97 | stream.print("{d}", .{total_object_size}) catch unreachable; | |
| 112 | 98 | } |
| 113 | 99 | |
| 114 | 100 | try writer.writeAll(mem.asBytes(&hdr)); |
| ... | ... | @@ -116,7 +102,7 @@ pub fn writeHeader( |
| 116 | 102 | |
| 117 | 103 | const padding = object_name_len - object_name.len - 1; |
| 118 | 104 | if (padding > 0) { |
| 119 | try writer.writeByteNTimes(0, padding); | |
| 105 | try writer.splatByteAll(0, padding); | |
| 120 | 106 | } |
| 121 | 107 | } |
| 122 | 108 | |
| ... | ... | @@ -138,25 +124,19 @@ pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; |
| 138 | 124 | |
| 139 | 125 | pub const ar_hdr = extern struct { |
| 140 | 126 | /// Member file name, sometimes / terminated. |
| 141 | ar_name: [16]u8, | |
| 142 | ||
| 127 | ar_name: [16]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, | |
| 143 | 128 | /// File date, decimal seconds since Epoch. |
| 144 | ar_date: [12]u8, | |
| 145 | ||
| 129 | ar_date: [12]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, | |
| 146 | 130 | /// User ID, in ASCII format. |
| 147 | ar_uid: [6]u8, | |
| 148 | ||
| 131 | ar_uid: [6]u8 = "0\x20\x20\x20\x20\x20".*, | |
| 149 | 132 | /// Group ID, in ASCII format. |
| 150 | ar_gid: [6]u8, | |
| 151 | ||
| 133 | ar_gid: [6]u8 = "0\x20\x20\x20\x20\x20".*, | |
| 152 | 134 | /// File mode, in ASCII octal. |
| 153 | ar_mode: [8]u8, | |
| 154 | ||
| 135 | ar_mode: [8]u8 = "0\x20\x20\x20\x20\x20\x20\x20".*, | |
| 155 | 136 | /// File size, in ASCII decimal. |
| 156 | ar_size: [10]u8, | |
| 157 | ||
| 137 | ar_size: [10]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, | |
| 158 | 138 | /// Always contains ARFMAG. |
| 159 | ar_fmag: [2]u8, | |
| 139 | ar_fmag: [2]u8 = ARFMAG.*, | |
| 160 | 140 | |
| 161 | 141 | fn date(self: ar_hdr) !u64 { |
| 162 | 142 | const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{@as(u8, 0x20)}); |
| ... | ... | @@ -201,7 +181,7 @@ pub const ArSymtab = struct { |
| 201 | 181 | return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width); |
| 202 | 182 | } |
| 203 | 183 | |
| 204 | pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: anytype) !void { | |
| 184 | pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: *Writer) !void { | |
| 205 | 185 | const ptr_width = ptrWidth(format); |
| 206 | 186 | // Header |
| 207 | 187 | try writeHeader(SYMDEF, ar.size(format), format, writer); |
| ... | ... | @@ -226,7 +206,7 @@ pub const ArSymtab = struct { |
| 226 | 206 | // Strtab |
| 227 | 207 | try writer.writeAll(ar.strtab.buffer.items); |
| 228 | 208 | if (padding > 0) { |
| 229 | try writer.writeByteNTimes(0, padding); | |
| 209 | try writer.splatByteAll(0, padding); | |
| 230 | 210 | } |
| 231 | 211 | } |
| 232 | 212 | |
| ... | ... | @@ -275,7 +255,7 @@ pub fn ptrWidth(format: Format) usize { |
| 275 | 255 | }; |
| 276 | 256 | } |
| 277 | 257 | |
| 278 | pub fn writeInt(format: Format, value: u64, writer: anytype) !void { | |
| 258 | pub fn writeInt(format: Format, value: u64, writer: *Writer) !void { | |
| 279 | 259 | switch (format) { |
| 280 | 260 | .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), |
| 281 | 261 | .p64 => try writer.writeInt(u64, value, .little), |
| ... | ... | @@ -299,7 +279,7 @@ const mem = std.mem; |
| 299 | 279 | const std = @import("std"); |
| 300 | 280 | const Allocator = std.mem.Allocator; |
| 301 | 281 | const Path = std.Build.Cache.Path; |
| 302 | const Writer = std.io.Writer; | |
| 282 | const Writer = std.Io.Writer; | |
| 303 | 283 | |
| 304 | 284 | const Archive = @This(); |
| 305 | 285 | const File = @import("file.zig").File; |
src/link/MachO/Atom.zig+7-6| ... | ... | @@ -581,19 +581,19 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 581 | 581 | relocs_log.debug("{x}: {s}", .{ self.value, name }); |
| 582 | 582 | |
| 583 | 583 | var has_error = false; |
| 584 | var stream = std.io.fixedBufferStream(buffer); | |
| 584 | var stream: Writer = .fixed(buffer); | |
| 585 | 585 | var i: usize = 0; |
| 586 | 586 | while (i < relocs.len) : (i += 1) { |
| 587 | 587 | const rel = relocs[i]; |
| 588 | const rel_offset = rel.offset - self.off; | |
| 588 | const rel_offset: usize = @intCast(rel.offset - self.off); | |
| 589 | 589 | const subtractor = if (rel.meta.has_subtractor) relocs[i - 1] else null; |
| 590 | 590 | |
| 591 | 591 | if (rel.tag == .@"extern") { |
| 592 | 592 | if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue; |
| 593 | 593 | } |
| 594 | 594 | |
| 595 | try stream.seekTo(rel_offset); | |
| 596 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { | |
| 595 | stream.end = rel_offset; | |
| 596 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, &stream) catch |err| { | |
| 597 | 597 | switch (err) { |
| 598 | 598 | error.RelaxFail => { |
| 599 | 599 | const target = switch (rel.tag) { |
| ... | ... | @@ -630,6 +630,7 @@ const ResolveError = error{ |
| 630 | 630 | UnexpectedRemainder, |
| 631 | 631 | Overflow, |
| 632 | 632 | OutOfMemory, |
| 633 | WriteFailed, | |
| 633 | 634 | }; |
| 634 | 635 | |
| 635 | 636 | fn resolveRelocInner( |
| ... | ... | @@ -638,7 +639,7 @@ fn resolveRelocInner( |
| 638 | 639 | subtractor: ?Relocation, |
| 639 | 640 | code: []u8, |
| 640 | 641 | macho_file: *MachO, |
| 641 | writer: anytype, | |
| 642 | writer: *Writer, | |
| 642 | 643 | ) ResolveError!void { |
| 643 | 644 | const t = &macho_file.base.comp.root_mod.resolved_target.result; |
| 644 | 645 | const cpu_arch = t.cpu.arch; |
| ... | ... | @@ -1147,7 +1148,7 @@ const math = std.math; |
| 1147 | 1148 | const mem = std.mem; |
| 1148 | 1149 | const log = std.log.scoped(.link); |
| 1149 | 1150 | const relocs_log = std.log.scoped(.link_relocs); |
| 1150 | const Writer = std.io.Writer; | |
| 1151 | const Writer = std.Io.Writer; | |
| 1151 | 1152 | const Allocator = mem.Allocator; |
| 1152 | 1153 | const AtomicBool = std.atomic.Value(bool); |
| 1153 | 1154 |
src/link/MachO/CodeSignature.zig+9-9| ... | ... | @@ -263,7 +263,7 @@ pub fn writeAdhocSignature( |
| 263 | 263 | self: *CodeSignature, |
| 264 | 264 | macho_file: *MachO, |
| 265 | 265 | opts: WriteOpts, |
| 266 | writer: anytype, | |
| 266 | writer: *std.Io.Writer, | |
| 267 | 267 | ) !void { |
| 268 | 268 | const tracy = trace(@src()); |
| 269 | 269 | defer tracy.end(); |
| ... | ... | @@ -304,10 +304,10 @@ pub fn writeAdhocSignature( |
| 304 | 304 | var hash: [hash_size]u8 = undefined; |
| 305 | 305 | |
| 306 | 306 | if (self.requirements) |*req| { |
| 307 | var buf = std.array_list.Managed(u8).init(allocator); | |
| 308 | defer buf.deinit(); | |
| 309 | try req.write(buf.writer()); | |
| 310 | Sha256.hash(buf.items, &hash, .{}); | |
| 307 | var a: std.Io.Writer.Allocating = .init(allocator); | |
| 308 | defer a.deinit(); | |
| 309 | try req.write(&a.writer); | |
| 310 | Sha256.hash(a.written(), &hash, .{}); | |
| 311 | 311 | self.code_directory.addSpecialHash(req.slotType(), hash); |
| 312 | 312 | |
| 313 | 313 | try blobs.append(.{ .requirements = req }); |
| ... | ... | @@ -316,10 +316,10 @@ pub fn writeAdhocSignature( |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | 318 | if (self.entitlements) |*ents| { |
| 319 | var buf = std.array_list.Managed(u8).init(allocator); | |
| 320 | defer buf.deinit(); | |
| 321 | try ents.write(buf.writer()); | |
| 322 | Sha256.hash(buf.items, &hash, .{}); | |
| 319 | var a: std.Io.Writer.Allocating = .init(allocator); | |
| 320 | defer a.deinit(); | |
| 321 | try ents.write(&a.writer); | |
| 322 | Sha256.hash(a.written(), &hash, .{}); | |
| 323 | 323 | self.code_directory.addSpecialHash(ents.slotType(), hash); |
| 324 | 324 | |
| 325 | 325 | try blobs.append(.{ .entitlements = ents }); |
src/link/MachO/DebugSymbols.zig+9-10| ... | ... | @@ -273,14 +273,13 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 273 | 273 | const buffer = try gpa.alloc(u8, needed_size); |
| 274 | 274 | defer gpa.free(buffer); |
| 275 | 275 | |
| 276 | var stream = std.io.fixedBufferStream(buffer); | |
| 277 | const writer = stream.writer(); | |
| 276 | var writer: Writer = .fixed(buffer); | |
| 278 | 277 | |
| 279 | 278 | var ncmds: usize = 0; |
| 280 | 279 | |
| 281 | 280 | // UUID comes first presumably to speed up lookup by the consumer like lldb. |
| 282 | 281 | @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); |
| 283 | try writer.writeStruct(self.uuid_cmd); | |
| 282 | try writer.writeStruct(self.uuid_cmd, .little); | |
| 284 | 283 | ncmds += 1; |
| 285 | 284 | |
| 286 | 285 | // Segment and section load commands |
| ... | ... | @@ -293,11 +292,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 293 | 292 | var out_seg = seg; |
| 294 | 293 | out_seg.fileoff = 0; |
| 295 | 294 | out_seg.filesize = 0; |
| 296 | try writer.writeStruct(out_seg); | |
| 295 | try writer.writeStruct(out_seg, .little); | |
| 297 | 296 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { |
| 298 | 297 | var out_header = header; |
| 299 | 298 | out_header.offset = 0; |
| 300 | try writer.writeStruct(out_header); | |
| 299 | try writer.writeStruct(out_header, .little); | |
| 301 | 300 | } |
| 302 | 301 | sect_id += seg.nsects; |
| 303 | 302 | } |
| ... | ... | @@ -306,19 +305,19 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 306 | 305 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. |
| 307 | 306 | sect_id = 0; |
| 308 | 307 | for (self.segments.items) |seg| { |
| 309 | try writer.writeStruct(seg); | |
| 308 | try writer.writeStruct(seg, .little); | |
| 310 | 309 | for (self.sections.items[sect_id..][0..seg.nsects]) |header| { |
| 311 | try writer.writeStruct(header); | |
| 310 | try writer.writeStruct(header, .little); | |
| 312 | 311 | } |
| 313 | 312 | sect_id += seg.nsects; |
| 314 | 313 | } |
| 315 | 314 | ncmds += self.segments.items.len; |
| 316 | 315 | } |
| 317 | 316 | |
| 318 | try writer.writeStruct(self.symtab_cmd); | |
| 317 | try writer.writeStruct(self.symtab_cmd, .little); | |
| 319 | 318 | ncmds += 1; |
| 320 | 319 | |
| 321 | assert(stream.pos == needed_size); | |
| 320 | assert(writer.end == needed_size); | |
| 322 | 321 | |
| 323 | 322 | try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 324 | 323 | |
| ... | ... | @@ -460,7 +459,7 @@ const math = std.math; |
| 460 | 459 | const mem = std.mem; |
| 461 | 460 | const padToIdeal = MachO.padToIdeal; |
| 462 | 461 | const trace = @import("../../tracy.zig").trace; |
| 463 | const Writer = std.io.Writer; | |
| 462 | const Writer = std.Io.Writer; | |
| 464 | 463 | |
| 465 | 464 | const Allocator = mem.Allocator; |
| 466 | 465 | const MachO = @import("../MachO.zig"); |
src/link/MachO/InternalObject.zig+1-1| ... | ... | @@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil |
| 261 | 261 | |
| 262 | 262 | sect.offset = @intCast(self.objc_methnames.items.len); |
| 263 | 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; | |
| 265 | 265 | |
| 266 | 266 | const name_str = try self.addString(gpa, "ltmp"); |
| 267 | 267 | const sym_index = try self.addSymbol(gpa); |
src/link/MachO/UnwindInfo.zig+23-24| ... | ... | @@ -293,8 +293,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 293 | 293 | const seg = macho_file.getTextSegment(); |
| 294 | 294 | const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?]; |
| 295 | 295 | |
| 296 | var stream = std.io.fixedBufferStream(buffer); | |
| 297 | const writer = stream.writer(); | |
| 296 | var writer: Writer = .fixed(buffer); | |
| 298 | 297 | |
| 299 | 298 | const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header); |
| 300 | 299 | const common_encodings_count: u32 = info.common_encodings_count; |
| ... | ... | @@ -303,14 +302,14 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 303 | 302 | const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32); |
| 304 | 303 | const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1)); |
| 305 | 304 | |
| 306 | try writer.writeStruct(macho.unwind_info_section_header{ | |
| 305 | try writer.writeStruct(@as(macho.unwind_info_section_header, .{ | |
| 307 | 306 | .commonEncodingsArraySectionOffset = common_encodings_offset, |
| 308 | 307 | .commonEncodingsArrayCount = common_encodings_count, |
| 309 | 308 | .personalityArraySectionOffset = personalities_offset, |
| 310 | 309 | .personalityArrayCount = personalities_count, |
| 311 | 310 | .indexSectionOffset = indexes_offset, |
| 312 | 311 | .indexCount = indexes_count, |
| 313 | }); | |
| 312 | }), .little); | |
| 314 | 313 | |
| 315 | 314 | try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count])); |
| 316 | 315 | |
| ... | ... | @@ -325,42 +324,42 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 325 | 324 | for (info.pages.items, 0..) |page, i| { |
| 326 | 325 | assert(page.count > 0); |
| 327 | 326 | const rec = info.records.items[page.start].getUnwindRecord(macho_file); |
| 328 | try writer.writeStruct(macho.unwind_info_section_header_index_entry{ | |
| 327 | try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ | |
| 329 | 328 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 330 | 329 | .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)), |
| 331 | 330 | .lsdaIndexArraySectionOffset = lsda_base_offset + |
| 332 | 331 | info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), |
| 333 | }); | |
| 332 | }), .little); | |
| 334 | 333 | } |
| 335 | 334 | |
| 336 | 335 | const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file); |
| 337 | 336 | 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{ | |
| 337 | try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ | |
| 339 | 338 | .functionOffset = sentinel_address, |
| 340 | 339 | .secondLevelPagesSectionOffset = 0, |
| 341 | 340 | .lsdaIndexArraySectionOffset = lsda_base_offset + |
| 342 | 341 | @as(u32, @intCast(info.lsdas.items.len)) * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), |
| 343 | }); | |
| 342 | }), .little); | |
| 344 | 343 | |
| 345 | 344 | for (info.lsdas.items) |index| { |
| 346 | 345 | const rec = info.records.items[index].getUnwindRecord(macho_file); |
| 347 | try writer.writeStruct(macho.unwind_info_section_header_lsda_index_entry{ | |
| 346 | try writer.writeStruct(@as(macho.unwind_info_section_header_lsda_index_entry, .{ | |
| 348 | 347 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 349 | 348 | .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)), |
| 350 | }); | |
| 349 | }), .little); | |
| 351 | 350 | } |
| 352 | 351 | |
| 353 | 352 | for (info.pages.items) |page| { |
| 354 | const start = stream.pos; | |
| 355 | try page.write(info, macho_file, writer); | |
| 356 | const nwritten = stream.pos - start; | |
| 353 | const start = writer.end; | |
| 354 | try page.write(info, macho_file, &writer); | |
| 355 | const nwritten = writer.end - start; | |
| 357 | 356 | if (nwritten < second_level_page_bytes) { |
| 358 | 357 | const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow; |
| 359 | try writer.writeByteNTimes(0, padding); | |
| 358 | try writer.splatByteAll(0, padding); | |
| 360 | 359 | } |
| 361 | 360 | } |
| 362 | 361 | |
| 363 | @memset(buffer[stream.pos..], 0); | |
| 362 | @memset(buffer[writer.end..], 0); | |
| 364 | 363 | } |
| 365 | 364 | |
| 366 | 365 | fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 { |
| ... | ... | @@ -611,33 +610,33 @@ const Page = struct { |
| 611 | 610 | } }; |
| 612 | 611 | } |
| 613 | 612 | |
| 614 | fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: anytype) !void { | |
| 613 | fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: *Writer) !void { | |
| 615 | 614 | const seg = macho_file.getTextSegment(); |
| 616 | 615 | |
| 617 | 616 | switch (page.kind) { |
| 618 | 617 | .regular => { |
| 619 | try writer.writeStruct(macho.unwind_info_regular_second_level_page_header{ | |
| 618 | try writer.writeStruct(@as(macho.unwind_info_regular_second_level_page_header, .{ | |
| 620 | 619 | .entryPageOffset = @sizeOf(macho.unwind_info_regular_second_level_page_header), |
| 621 | 620 | .entryCount = page.count, |
| 622 | }); | |
| 621 | }), .little); | |
| 623 | 622 | |
| 624 | 623 | for (info.records.items[page.start..][0..page.count]) |ref| { |
| 625 | 624 | const rec = ref.getUnwindRecord(macho_file); |
| 626 | try writer.writeStruct(macho.unwind_info_regular_second_level_entry{ | |
| 625 | try writer.writeStruct(@as(macho.unwind_info_regular_second_level_entry, .{ | |
| 627 | 626 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 628 | 627 | .encoding = rec.enc.enc, |
| 629 | }); | |
| 628 | }), .little); | |
| 630 | 629 | } |
| 631 | 630 | }, |
| 632 | 631 | .compressed => { |
| 633 | 632 | const entry_offset = @sizeOf(macho.unwind_info_compressed_second_level_page_header) + |
| 634 | 633 | @as(u16, @intCast(page.page_encodings_count)) * @sizeOf(u32); |
| 635 | try writer.writeStruct(macho.unwind_info_compressed_second_level_page_header{ | |
| 634 | try writer.writeStruct(@as(macho.unwind_info_compressed_second_level_page_header, .{ | |
| 636 | 635 | .entryPageOffset = entry_offset, |
| 637 | 636 | .entryCount = page.count, |
| 638 | 637 | .encodingsPageOffset = @sizeOf(macho.unwind_info_compressed_second_level_page_header), |
| 639 | 638 | .encodingsCount = page.page_encodings_count, |
| 640 | }); | |
| 639 | }), .little); | |
| 641 | 640 | |
| 642 | 641 | for (page.page_encodings[0..page.page_encodings_count]) |enc| { |
| 643 | 642 | try writer.writeInt(u32, enc.enc, .little); |
| ... | ... | @@ -656,7 +655,7 @@ const Page = struct { |
| 656 | 655 | .funcOffset = @as(u24, @intCast(rec.getAtomAddress(macho_file) - first_rec.getAtomAddress(macho_file))), |
| 657 | 656 | .encodingIndex = @as(u8, @intCast(enc_index)), |
| 658 | 657 | }; |
| 659 | try writer.writeStruct(compressed); | |
| 658 | try writer.writeStruct(compressed, .little); | |
| 660 | 659 | } |
| 661 | 660 | }, |
| 662 | 661 | } |
| ... | ... | @@ -673,7 +672,7 @@ const macho = std.macho; |
| 673 | 672 | const math = std.math; |
| 674 | 673 | const mem = std.mem; |
| 675 | 674 | const trace = @import("../../tracy.zig").trace; |
| 676 | const Writer = std.io.Writer; | |
| 675 | const Writer = std.Io.Writer; | |
| 677 | 676 | |
| 678 | 677 | const Allocator = mem.Allocator; |
| 679 | 678 | const Atom = @import("Atom.zig"); |
src/link/MachO/dyld_info/Rebase.zig+10-9| ... | ... | @@ -110,12 +110,14 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { |
| 110 | 110 | fn finalize(rebase: *Rebase, gpa: Allocator) !void { |
| 111 | 111 | if (rebase.entries.items.len == 0) return; |
| 112 | 112 | |
| 113 | const writer = rebase.buffer.writer(gpa); | |
| 114 | ||
| 115 | 113 | log.debug("rebase opcodes", .{}); |
| 116 | 114 | |
| 117 | 115 | std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan); |
| 118 | 116 | |
| 117 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &rebase.buffer); | |
| 118 | defer rebase.buffer = allocating.toArrayList(); | |
| 119 | const writer = &allocating.writer; | |
| 120 | ||
| 119 | 121 | try setTypePointer(writer); |
| 120 | 122 | |
| 121 | 123 | var start: usize = 0; |
| ... | ... | @@ -226,13 +228,13 @@ fn setTypePointer(writer: anytype) !void { |
| 226 | 228 | fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void { |
| 227 | 229 | log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset }); |
| 228 | 230 | try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id))); |
| 229 | try std.leb.writeUleb128(writer, offset); | |
| 231 | try writer.writeUleb128(offset); | |
| 230 | 232 | } |
| 231 | 233 | |
| 232 | 234 | fn rebaseAddAddr(addr: u64, writer: anytype) !void { |
| 233 | 235 | log.debug(">>> rebase with add: {x}", .{addr}); |
| 234 | 236 | try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB); |
| 235 | try std.leb.writeUleb128(writer, addr); | |
| 237 | try writer.writeUleb128(addr); | |
| 236 | 238 | } |
| 237 | 239 | |
| 238 | 240 | fn rebaseTimes(count: usize, writer: anytype) !void { |
| ... | ... | @@ -241,15 +243,15 @@ fn rebaseTimes(count: usize, writer: anytype) !void { |
| 241 | 243 | try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @as(u4, @truncate(count))); |
| 242 | 244 | } else { |
| 243 | 245 | try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES); |
| 244 | try std.leb.writeUleb128(writer, count); | |
| 246 | try writer.writeUleb128(count); | |
| 245 | 247 | } |
| 246 | 248 | } |
| 247 | 249 | |
| 248 | 250 | fn rebaseTimesSkip(count: usize, skip: u64, writer: anytype) !void { |
| 249 | 251 | log.debug(">>> rebase with count: {d} and skip: {x}", .{ count, skip }); |
| 250 | 252 | try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB); |
| 251 | try std.leb.writeUleb128(writer, count); | |
| 252 | try std.leb.writeUleb128(writer, skip); | |
| 253 | try writer.writeUleb128(count); | |
| 254 | try writer.writeUleb128(skip); | |
| 253 | 255 | } |
| 254 | 256 | |
| 255 | 257 | fn addAddr(addr: u64, writer: anytype) !void { |
| ... | ... | @@ -262,7 +264,7 @@ fn addAddr(addr: u64, writer: anytype) !void { |
| 262 | 264 | } |
| 263 | 265 | } |
| 264 | 266 | try writer.writeByte(macho.REBASE_OPCODE_ADD_ADDR_ULEB); |
| 265 | try std.leb.writeUleb128(writer, addr); | |
| 267 | try writer.writeUleb128(addr); | |
| 266 | 268 | } |
| 267 | 269 | |
| 268 | 270 | fn done(writer: anytype) !void { |
| ... | ... | @@ -649,7 +651,6 @@ test "rebase - composite" { |
| 649 | 651 | |
| 650 | 652 | const std = @import("std"); |
| 651 | 653 | const assert = std.debug.assert; |
| 652 | const leb = std.leb; | |
| 653 | 654 | const log = std.log.scoped(.link_dyld_info); |
| 654 | 655 | const macho = std.macho; |
| 655 | 656 | const mem = std.mem; |
src/link/MachO/dyld_info/Trie.zig+16-12| ... | ... | @@ -170,8 +170,13 @@ fn finalize(self: *Trie, allocator: Allocator) !void { |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | try self.buffer.ensureTotalCapacityPrecise(allocator, size); |
| 173 | ||
| 174 | var allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &self.buffer); | |
| 175 | defer self.buffer = allocating.toArrayList(); | |
| 176 | const writer = &allocating.writer; | |
| 177 | ||
| 173 | 178 | for (ordered_nodes.items) |node_index| { |
| 174 | try self.writeNode(node_index, self.buffer.writer(allocator)); | |
| 179 | try self.writeNode(node_index, writer); | |
| 175 | 180 | } |
| 176 | 181 | } |
| 177 | 182 | |
| ... | ... | @@ -232,7 +237,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { |
| 232 | 237 | self.buffer.deinit(allocator); |
| 233 | 238 | } |
| 234 | 239 | |
| 235 | pub fn write(self: Trie, writer: anytype) !void { | |
| 240 | pub fn write(self: Trie, writer: *std.Io.Writer) !void { | |
| 236 | 241 | if (self.buffer.items.len == 0) return; |
| 237 | 242 | try writer.writeAll(self.buffer.items); |
| 238 | 243 | } |
| ... | ... | @@ -243,7 +248,7 @@ pub fn write(self: Trie, writer: anytype) !void { |
| 243 | 248 | /// iterate over `Trie.ordered_nodes` and call this method on each node. |
| 244 | 249 | /// This is one of the requirements of the MachO. |
| 245 | 250 | /// Panics if `finalize` was not called before calling this method. |
| 246 | fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { | |
| 251 | fn writeNode(self: *Trie, node_index: Node.Index, writer: *std.Io.Writer) !void { | |
| 247 | 252 | const slice = self.nodes.slice(); |
| 248 | 253 | const edges = slice.items(.edges)[node_index]; |
| 249 | 254 | const is_terminal = slice.items(.is_terminal)[node_index]; |
| ... | ... | @@ -253,21 +258,21 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { |
| 253 | 258 | if (is_terminal) { |
| 254 | 259 | // Terminal node info: encode export flags and vmaddr offset of this symbol. |
| 255 | 260 | var info_buf: [@sizeOf(u64) * 2]u8 = undefined; |
| 256 | var info_stream = std.io.fixedBufferStream(&info_buf); | |
| 261 | var info_stream: std.Io.Writer = .fixed(&info_buf); | |
| 257 | 262 | // TODO Implement for special flags. |
| 258 | 263 | assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and |
| 259 | 264 | export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0); |
| 260 | try leb.writeUleb128(info_stream.writer(), export_flags); | |
| 261 | try leb.writeUleb128(info_stream.writer(), vmaddr_offset); | |
| 265 | try info_stream.writeUleb128(export_flags); | |
| 266 | try info_stream.writeUleb128(vmaddr_offset); | |
| 262 | 267 | |
| 263 | 268 | // Encode the size of the terminal node info. |
| 264 | 269 | var size_buf: [@sizeOf(u64)]u8 = undefined; |
| 265 | var size_stream = std.io.fixedBufferStream(&size_buf); | |
| 266 | try leb.writeUleb128(size_stream.writer(), info_stream.pos); | |
| 270 | var size_stream: std.Io.Writer = .fixed(&size_buf); | |
| 271 | try size_stream.writeUleb128(info_stream.end); | |
| 267 | 272 | |
| 268 | 273 | // Now, write them to the output stream. |
| 269 | try writer.writeAll(size_buf[0..size_stream.pos]); | |
| 270 | try writer.writeAll(info_buf[0..info_stream.pos]); | |
| 274 | try writer.writeAll(size_buf[0..size_stream.end]); | |
| 275 | try writer.writeAll(info_buf[0..info_stream.end]); | |
| 271 | 276 | } else { |
| 272 | 277 | // Non-terminal node is delimited by 0 byte. |
| 273 | 278 | try writer.writeByte(0); |
| ... | ... | @@ -280,7 +285,7 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { |
| 280 | 285 | // Write edge label and offset to next node in trie. |
| 281 | 286 | try writer.writeAll(edge.label); |
| 282 | 287 | try writer.writeByte(0); |
| 283 | try leb.writeUleb128(writer, slice.items(.trie_offset)[edge.node]); | |
| 288 | try writer.writeUleb128(slice.items(.trie_offset)[edge.node]); | |
| 284 | 289 | } |
| 285 | 290 | } |
| 286 | 291 | |
| ... | ... | @@ -414,7 +419,6 @@ test "ordering bug" { |
| 414 | 419 | } |
| 415 | 420 | |
| 416 | 421 | const assert = std.debug.assert; |
| 417 | const leb = std.leb; | |
| 418 | 422 | const log = std.log.scoped(.macho); |
| 419 | 423 | const macho = std.macho; |
| 420 | 424 | const mem = std.mem; |
src/link/MachO/dyld_info/bind.zig+32-28| ... | ... | @@ -132,12 +132,14 @@ pub const Bind = struct { |
| 132 | 132 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 133 | 133 | if (self.entries.items.len == 0) return; |
| 134 | 134 | |
| 135 | const writer = self.buffer.writer(gpa); | |
| 136 | ||
| 137 | 135 | log.debug("bind opcodes", .{}); |
| 138 | 136 | |
| 139 | 137 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); |
| 140 | 138 | |
| 139 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | |
| 140 | defer self.buffer = allocating.toArrayList(); | |
| 141 | const writer = &allocating.writer; | |
| 142 | ||
| 141 | 143 | var start: usize = 0; |
| 142 | 144 | var seg_id: ?u8 = null; |
| 143 | 145 | for (self.entries.items, 0..) |entry, i| { |
| ... | ... | @@ -151,7 +153,7 @@ pub const Bind = struct { |
| 151 | 153 | try done(writer); |
| 152 | 154 | } |
| 153 | 155 | |
| 154 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { | |
| 156 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { | |
| 155 | 157 | if (entries.len == 0) return; |
| 156 | 158 | |
| 157 | 159 | const seg_id = entries[0].segment_id; |
| ... | ... | @@ -263,7 +265,7 @@ pub const Bind = struct { |
| 263 | 265 | } |
| 264 | 266 | } |
| 265 | 267 | |
| 266 | pub fn write(self: Self, writer: anytype) !void { | |
| 268 | pub fn write(self: Self, writer: *std.Io.Writer) !void { | |
| 267 | 269 | try writer.writeAll(self.buffer.items); |
| 268 | 270 | } |
| 269 | 271 | }; |
| ... | ... | @@ -385,12 +387,14 @@ pub const WeakBind = struct { |
| 385 | 387 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 386 | 388 | if (self.entries.items.len == 0) return; |
| 387 | 389 | |
| 388 | const writer = self.buffer.writer(gpa); | |
| 389 | ||
| 390 | 390 | log.debug("weak bind opcodes", .{}); |
| 391 | 391 | |
| 392 | 392 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); |
| 393 | 393 | |
| 394 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | |
| 395 | defer self.buffer = allocating.toArrayList(); | |
| 396 | const writer = &allocating.writer; | |
| 397 | ||
| 394 | 398 | var start: usize = 0; |
| 395 | 399 | var seg_id: ?u8 = null; |
| 396 | 400 | for (self.entries.items, 0..) |entry, i| { |
| ... | ... | @@ -404,7 +408,7 @@ pub const WeakBind = struct { |
| 404 | 408 | try done(writer); |
| 405 | 409 | } |
| 406 | 410 | |
| 407 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { | |
| 411 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { | |
| 408 | 412 | if (entries.len == 0) return; |
| 409 | 413 | |
| 410 | 414 | const seg_id = entries[0].segment_id; |
| ... | ... | @@ -505,7 +509,7 @@ pub const WeakBind = struct { |
| 505 | 509 | } |
| 506 | 510 | } |
| 507 | 511 | |
| 508 | pub fn write(self: Self, writer: anytype) !void { | |
| 512 | pub fn write(self: Self, writer: *std.Io.Writer) !void { | |
| 509 | 513 | try writer.writeAll(self.buffer.items); |
| 510 | 514 | } |
| 511 | 515 | }; |
| ... | ... | @@ -555,8 +559,6 @@ pub const LazyBind = struct { |
| 555 | 559 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 556 | 560 | try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len); |
| 557 | 561 | |
| 558 | const writer = self.buffer.writer(gpa); | |
| 559 | ||
| 560 | 562 | log.debug("lazy bind opcodes", .{}); |
| 561 | 563 | |
| 562 | 564 | var addend: i64 = 0; |
| ... | ... | @@ -578,6 +580,9 @@ pub const LazyBind = struct { |
| 578 | 580 | break :ord macho.BIND_SPECIAL_DYLIB_SELF; |
| 579 | 581 | }; |
| 580 | 582 | |
| 583 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | |
| 584 | defer self.buffer = allocating.toArrayList(); | |
| 585 | const writer = &allocating.writer; | |
| 581 | 586 | try setSegmentOffset(entry.segment_id, entry.offset, writer); |
| 582 | 587 | try setSymbol(name, flags, writer); |
| 583 | 588 | try setDylibOrdinal(ordinal, writer); |
| ... | ... | @@ -592,30 +597,30 @@ pub const LazyBind = struct { |
| 592 | 597 | } |
| 593 | 598 | } |
| 594 | 599 | |
| 595 | pub fn write(self: Self, writer: anytype) !void { | |
| 600 | pub fn write(self: Self, writer: *std.Io.Writer) !void { | |
| 596 | 601 | try writer.writeAll(self.buffer.items); |
| 597 | 602 | } |
| 598 | 603 | }; |
| 599 | 604 | |
| 600 | fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void { | |
| 605 | fn setSegmentOffset(segment_id: u8, offset: u64, writer: *std.Io.Writer) !void { | |
| 601 | 606 | log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset }); |
| 602 | 607 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id))); |
| 603 | try std.leb.writeUleb128(writer, offset); | |
| 608 | try writer.writeUleb128(offset); | |
| 604 | 609 | } |
| 605 | 610 | |
| 606 | fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void { | |
| 611 | fn setSymbol(name: []const u8, flags: u8, writer: *std.Io.Writer) !void { | |
| 607 | 612 | log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags }); |
| 608 | 613 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags))); |
| 609 | 614 | try writer.writeAll(name); |
| 610 | 615 | try writer.writeByte(0); |
| 611 | 616 | } |
| 612 | 617 | |
| 613 | fn setTypePointer(writer: anytype) !void { | |
| 618 | fn setTypePointer(writer: *std.Io.Writer) !void { | |
| 614 | 619 | log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER}); |
| 615 | 620 | try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER))); |
| 616 | 621 | } |
| 617 | 622 | |
| 618 | fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { | |
| 623 | fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void { | |
| 619 | 624 | if (ordinal <= 0) { |
| 620 | 625 | switch (ordinal) { |
| 621 | 626 | macho.BIND_SPECIAL_DYLIB_SELF, |
| ... | ... | @@ -634,23 +639,23 @@ fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { |
| 634 | 639 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @as(u4, @truncate(cast))); |
| 635 | 640 | } else { |
| 636 | 641 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); |
| 637 | try std.leb.writeUleb128(writer, cast); | |
| 642 | try writer.writeUleb128(cast); | |
| 638 | 643 | } |
| 639 | 644 | } |
| 640 | 645 | } |
| 641 | 646 | |
| 642 | fn setAddend(addend: i64, writer: anytype) !void { | |
| 647 | fn setAddend(addend: i64, writer: *std.Io.Writer) !void { | |
| 643 | 648 | log.debug(">>> set addend: {x}", .{addend}); |
| 644 | 649 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); |
| 645 | 650 | try std.leb.writeIleb128(writer, addend); |
| 646 | 651 | } |
| 647 | 652 | |
| 648 | fn doBind(writer: anytype) !void { | |
| 653 | fn doBind(writer: *std.Io.Writer) !void { | |
| 649 | 654 | log.debug(">>> bind", .{}); |
| 650 | 655 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); |
| 651 | 656 | } |
| 652 | 657 | |
| 653 | fn doBindAddAddr(addr: u64, writer: anytype) !void { | |
| 658 | fn doBindAddAddr(addr: u64, writer: *std.Io.Writer) !void { | |
| 654 | 659 | log.debug(">>> bind with add: {x}", .{addr}); |
| 655 | 660 | if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) { |
| 656 | 661 | const imm = @divExact(addr, @sizeOf(u64)); |
| ... | ... | @@ -662,29 +667,28 @@ fn doBindAddAddr(addr: u64, writer: anytype) !void { |
| 662 | 667 | } |
| 663 | 668 | } |
| 664 | 669 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB); |
| 665 | try std.leb.writeUleb128(writer, addr); | |
| 670 | try writer.writeUleb128(addr); | |
| 666 | 671 | } |
| 667 | 672 | |
| 668 | fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void { | |
| 673 | fn doBindTimesSkip(count: usize, skip: u64, writer: *std.Io.Writer) !void { | |
| 669 | 674 | log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip }); |
| 670 | 675 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB); |
| 671 | try std.leb.writeUleb128(writer, count); | |
| 672 | try std.leb.writeUleb128(writer, skip); | |
| 676 | try writer.writeUleb128(count); | |
| 677 | try writer.writeUleb128(skip); | |
| 673 | 678 | } |
| 674 | 679 | |
| 675 | fn addAddr(addr: u64, writer: anytype) !void { | |
| 680 | fn addAddr(addr: u64, writer: *std.Io.Writer) !void { | |
| 676 | 681 | log.debug(">>> add: {x}", .{addr}); |
| 677 | 682 | try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB); |
| 678 | try std.leb.writeUleb128(writer, addr); | |
| 683 | try writer.writeUleb128(addr); | |
| 679 | 684 | } |
| 680 | 685 | |
| 681 | fn done(writer: anytype) !void { | |
| 686 | fn done(writer: *std.Io.Writer) !void { | |
| 682 | 687 | log.debug(">>> done", .{}); |
| 683 | 688 | try writer.writeByte(macho.BIND_OPCODE_DONE); |
| 684 | 689 | } |
| 685 | 690 | |
| 686 | 691 | const assert = std.debug.assert; |
| 687 | const leb = std.leb; | |
| 688 | 692 | const log = std.log.scoped(.link_dyld_info); |
| 689 | 693 | const macho = std.macho; |
| 690 | 694 | const mem = std.mem; |
src/link/MachO/load_commands.zig+19-19| ... | ... | @@ -3,9 +3,9 @@ const assert = std.debug.assert; |
| 3 | 3 | const log = std.log.scoped(.link); |
| 4 | 4 | const macho = std.macho; |
| 5 | 5 | const mem = std.mem; |
| 6 | const Writer = std.io.Writer; | |
| 6 | const Writer = std.Io.Writer; | |
| 7 | const Allocator = std.mem.Allocator; | |
| 7 | 8 | |
| 8 | const Allocator = mem.Allocator; | |
| 9 | 9 | const DebugSymbols = @import("DebugSymbols.zig"); |
| 10 | 10 | const Dylib = @import("Dylib.zig"); |
| 11 | 11 | const MachO = @import("../MachO.zig"); |
| ... | ... | @@ -181,22 +181,22 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { |
| 181 | 181 | return offset; |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | pub fn writeDylinkerLC(writer: anytype) !void { | |
| 184 | pub fn writeDylinkerLC(writer: *Writer) !void { | |
| 185 | 185 | const name_len = mem.sliceTo(default_dyld_path, 0).len; |
| 186 | 186 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 187 | 187 | u64, |
| 188 | 188 | @sizeOf(macho.dylinker_command) + name_len, |
| 189 | 189 | @sizeOf(u64), |
| 190 | 190 | ))); |
| 191 | try writer.writeStruct(macho.dylinker_command{ | |
| 191 | try writer.writeStruct(@as(macho.dylinker_command, .{ | |
| 192 | 192 | .cmd = .LOAD_DYLINKER, |
| 193 | 193 | .cmdsize = cmdsize, |
| 194 | 194 | .name = @sizeOf(macho.dylinker_command), |
| 195 | }); | |
| 195 | }), .little); | |
| 196 | 196 | try writer.writeAll(mem.sliceTo(default_dyld_path, 0)); |
| 197 | 197 | const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len; |
| 198 | 198 | if (padding > 0) { |
| 199 | try writer.writeByteNTimes(0, padding); | |
| 199 | try writer.splatByteAll(0, padding); | |
| 200 | 200 | } |
| 201 | 201 | } |
| 202 | 202 | |
| ... | ... | @@ -208,14 +208,14 @@ const WriteDylibLCCtx = struct { |
| 208 | 208 | compatibility_version: u32 = 0x10000, |
| 209 | 209 | }; |
| 210 | 210 | |
| 211 | pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { | |
| 211 | pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: *Writer) !void { | |
| 212 | 212 | const name_len = ctx.name.len + 1; |
| 213 | 213 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 214 | 214 | u64, |
| 215 | 215 | @sizeOf(macho.dylib_command) + name_len, |
| 216 | 216 | @sizeOf(u64), |
| 217 | 217 | ))); |
| 218 | try writer.writeStruct(macho.dylib_command{ | |
| 218 | try writer.writeStruct(@as(macho.dylib_command, .{ | |
| 219 | 219 | .cmd = ctx.cmd, |
| 220 | 220 | .cmdsize = cmdsize, |
| 221 | 221 | .dylib = .{ |
| ... | ... | @@ -224,16 +224,16 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { |
| 224 | 224 | .current_version = ctx.current_version, |
| 225 | 225 | .compatibility_version = ctx.compatibility_version, |
| 226 | 226 | }, |
| 227 | }); | |
| 227 | }), .little); | |
| 228 | 228 | try writer.writeAll(ctx.name); |
| 229 | 229 | try writer.writeByte(0); |
| 230 | 230 | const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len; |
| 231 | 231 | if (padding > 0) { |
| 232 | try writer.writeByteNTimes(0, padding); | |
| 232 | try writer.splatByteAll(0, padding); | |
| 233 | 233 | } |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { | |
| 236 | pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { | |
| 237 | 237 | const comp = macho_file.base.comp; |
| 238 | 238 | const gpa = comp.gpa; |
| 239 | 239 | assert(comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); |
| ... | ... | @@ -259,26 +259,26 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { |
| 259 | 259 | }, writer); |
| 260 | 260 | } |
| 261 | 261 | |
| 262 | pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void { | |
| 262 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { | |
| 263 | 263 | const rpath_len = rpath.len + 1; |
| 264 | 264 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 265 | 265 | u64, |
| 266 | 266 | @sizeOf(macho.rpath_command) + rpath_len, |
| 267 | 267 | @sizeOf(u64), |
| 268 | 268 | ))); |
| 269 | try writer.writeStruct(macho.rpath_command{ | |
| 269 | try writer.writeStruct(@as(macho.rpath_command, .{ | |
| 270 | 270 | .cmdsize = cmdsize, |
| 271 | 271 | .path = @sizeOf(macho.rpath_command), |
| 272 | }); | |
| 272 | }), .little); | |
| 273 | 273 | try writer.writeAll(rpath); |
| 274 | 274 | try writer.writeByte(0); |
| 275 | 275 | const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len; |
| 276 | 276 | if (padding > 0) { |
| 277 | try writer.writeByteNTimes(0, padding); | |
| 277 | try writer.splatByteAll(0, padding); | |
| 278 | 278 | } |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { | |
| 281 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { | |
| 282 | 282 | const cmd: macho.LC = switch (platform.os_tag) { |
| 283 | 283 | .macos => .VERSION_MIN_MACOSX, |
| 284 | 284 | .ios => .VERSION_MIN_IPHONEOS, |
| ... | ... | @@ -296,9 +296,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer |
| 296 | 296 | })); |
| 297 | 297 | } |
| 298 | 298 | |
| 299 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { | |
| 299 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { | |
| 300 | 300 | const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); |
| 301 | try writer.writeStruct(macho.build_version_command{ | |
| 301 | try writer.writeStruct(@as(macho.build_version_command, .{ | |
| 302 | 302 | .cmdsize = cmdsize, |
| 303 | 303 | .platform = platform.toApplePlatform(), |
| 304 | 304 | .minos = platform.toAppleVersion(), |
| ... | ... | @@ -307,7 +307,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV |
| 307 | 307 | else |
| 308 | 308 | platform.toAppleVersion(), |
| 309 | 309 | .ntools = 1, |
| 310 | }); | |
| 310 | }), .little); | |
| 311 | 311 | try writer.writeAll(mem.asBytes(&macho.build_tool_version{ |
| 312 | 312 | .tool = .ZIG, |
| 313 | 313 | .version = 0x0, |
src/link/MachO/relocatable.zig+29-33| ... | ... | @@ -205,35 +205,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 205 | 205 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); |
| 206 | 206 | } |
| 207 | 207 | |
| 208 | var buffer = std.array_list.Managed(u8).init(gpa); | |
| 209 | defer buffer.deinit(); | |
| 210 | try buffer.ensureTotalCapacityPrecise(total_size); | |
| 211 | const writer = buffer.writer(); | |
| 208 | const buffer = try gpa.alloc(u8, total_size); | |
| 209 | defer gpa.free(buffer); | |
| 210 | var writer: Writer = .fixed(buffer); | |
| 212 | 211 | |
| 213 | 212 | // Write magic |
| 214 | try writer.writeAll(Archive.ARMAG); | |
| 213 | writer.writeAll(Archive.ARMAG) catch unreachable; | |
| 215 | 214 | |
| 216 | 215 | // Write symtab |
| 217 | ar_symtab.write(format, macho_file, writer) catch |err| switch (err) { | |
| 218 | error.OutOfMemory => return error.OutOfMemory, | |
| 219 | else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}), | |
| 220 | }; | |
| 216 | ar_symtab.write(format, macho_file, &writer) catch |err| | |
| 217 | return diags.fail("failed to write archive symbol table: {t}", .{err}); | |
| 221 | 218 | |
| 222 | 219 | // Write object files |
| 223 | 220 | for (files.items) |index| { |
| 224 | const aligned = mem.alignForward(usize, buffer.items.len, 2); | |
| 225 | const padding = aligned - buffer.items.len; | |
| 221 | const aligned = mem.alignForward(usize, writer.end, 2); | |
| 222 | const padding = aligned - writer.end; | |
| 226 | 223 | if (padding > 0) { |
| 227 | try writer.writeByteNTimes(0, padding); | |
| 224 | writer.splatByteAll(0, padding) catch unreachable; | |
| 228 | 225 | } |
| 229 | macho_file.getFile(index).?.writeAr(format, macho_file, writer) catch |err| | |
| 230 | return diags.fail("failed to write archive: {s}", .{@errorName(err)}); | |
| 226 | macho_file.getFile(index).?.writeAr(format, macho_file, &writer) catch |err| | |
| 227 | return diags.fail("failed to write archive: {t}", .{err}); | |
| 231 | 228 | } |
| 232 | 229 | |
| 233 | assert(buffer.items.len == total_size); | |
| 230 | assert(writer.end == total_size); | |
| 234 | 231 | |
| 235 | 232 | try macho_file.setEndPos(total_size); |
| 236 | try macho_file.pwriteAll(buffer.items, 0); | |
| 233 | try macho_file.pwriteAll(writer.buffered(), 0); | |
| 237 | 234 | |
| 238 | 235 | if (diags.hasErrors()) return error.LinkFailure; |
| 239 | 236 | } |
| ... | ... | @@ -693,8 +690,7 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc |
| 693 | 690 | const buffer = try gpa.alloc(u8, needed_size); |
| 694 | 691 | defer gpa.free(buffer); |
| 695 | 692 | |
| 696 | var stream = std.io.fixedBufferStream(buffer); | |
| 697 | const writer = stream.writer(); | |
| 693 | var writer: Writer = .fixed(buffer); | |
| 698 | 694 | |
| 699 | 695 | var ncmds: usize = 0; |
| 700 | 696 | |
| ... | ... | @@ -702,43 +698,43 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc |
| 702 | 698 | { |
| 703 | 699 | assert(macho_file.segments.items.len == 1); |
| 704 | 700 | const seg = macho_file.segments.items[0]; |
| 705 | writer.writeStruct(seg) catch |err| switch (err) { | |
| 706 | error.NoSpaceLeft => unreachable, | |
| 701 | writer.writeStruct(seg, .little) catch |err| switch (err) { | |
| 702 | error.WriteFailed => unreachable, | |
| 707 | 703 | }; |
| 708 | 704 | for (macho_file.sections.items(.header)) |header| { |
| 709 | writer.writeStruct(header) catch |err| switch (err) { | |
| 710 | error.NoSpaceLeft => unreachable, | |
| 705 | writer.writeStruct(header, .little) catch |err| switch (err) { | |
| 706 | error.WriteFailed => unreachable, | |
| 711 | 707 | }; |
| 712 | 708 | } |
| 713 | 709 | ncmds += 1; |
| 714 | 710 | } |
| 715 | 711 | |
| 716 | writer.writeStruct(macho_file.data_in_code_cmd) catch |err| switch (err) { | |
| 717 | error.NoSpaceLeft => unreachable, | |
| 712 | writer.writeStruct(macho_file.data_in_code_cmd, .little) catch |err| switch (err) { | |
| 713 | error.WriteFailed => unreachable, | |
| 718 | 714 | }; |
| 719 | 715 | ncmds += 1; |
| 720 | writer.writeStruct(macho_file.symtab_cmd) catch |err| switch (err) { | |
| 721 | error.NoSpaceLeft => unreachable, | |
| 716 | writer.writeStruct(macho_file.symtab_cmd, .little) catch |err| switch (err) { | |
| 717 | error.WriteFailed => unreachable, | |
| 722 | 718 | }; |
| 723 | 719 | ncmds += 1; |
| 724 | writer.writeStruct(macho_file.dysymtab_cmd) catch |err| switch (err) { | |
| 725 | error.NoSpaceLeft => unreachable, | |
| 720 | writer.writeStruct(macho_file.dysymtab_cmd, .little) catch |err| switch (err) { | |
| 721 | error.WriteFailed => unreachable, | |
| 726 | 722 | }; |
| 727 | 723 | ncmds += 1; |
| 728 | 724 | |
| 729 | 725 | if (macho_file.platform.isBuildVersionCompatible()) { |
| 730 | load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { | |
| 731 | error.NoSpaceLeft => unreachable, | |
| 726 | load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { | |
| 727 | error.WriteFailed => unreachable, | |
| 732 | 728 | }; |
| 733 | 729 | ncmds += 1; |
| 734 | 730 | } else { |
| 735 | load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { | |
| 736 | error.NoSpaceLeft => unreachable, | |
| 731 | load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { | |
| 732 | error.WriteFailed => unreachable, | |
| 737 | 733 | }; |
| 738 | 734 | ncmds += 1; |
| 739 | 735 | } |
| 740 | 736 | |
| 741 | assert(stream.pos == needed_size); | |
| 737 | assert(writer.end == needed_size); | |
| 742 | 738 | |
| 743 | 739 | try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 744 | 740 |
src/link/MachO/synthetic.zig+12-12| ... | ... | @@ -27,7 +27,7 @@ pub const GotSection = struct { |
| 27 | 27 | return got.symbols.items.len * @sizeOf(u64); |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void { | |
| 30 | pub fn write(got: GotSection, macho_file: *MachO, writer: *Writer) !void { | |
| 31 | 31 | const tracy = trace(@src()); |
| 32 | 32 | defer tracy.end(); |
| 33 | 33 | for (got.symbols.items) |ref| { |
| ... | ... | @@ -89,7 +89,7 @@ pub const StubsSection = struct { |
| 89 | 89 | return stubs.symbols.items.len * header.reserved2; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void { | |
| 92 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: *Writer) !void { | |
| 93 | 93 | const tracy = trace(@src()); |
| 94 | 94 | defer tracy.end(); |
| 95 | 95 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| ... | ... | @@ -174,7 +174,7 @@ pub const StubsHelperSection = struct { |
| 174 | 174 | return s; |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { | |
| 177 | pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { | |
| 178 | 178 | const tracy = trace(@src()); |
| 179 | 179 | defer tracy.end(); |
| 180 | 180 | |
| ... | ... | @@ -217,7 +217,7 @@ pub const StubsHelperSection = struct { |
| 217 | 217 | } |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { | |
| 220 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { | |
| 221 | 221 | _ = stubs_helper; |
| 222 | 222 | const obj = macho_file.getInternalObject().?; |
| 223 | 223 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| ... | ... | @@ -273,7 +273,7 @@ pub const LaSymbolPtrSection = struct { |
| 273 | 273 | return macho_file.stubs.symbols.items.len * @sizeOf(u64); |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: anytype) !void { | |
| 276 | pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: *Writer) !void { | |
| 277 | 277 | const tracy = trace(@src()); |
| 278 | 278 | defer tracy.end(); |
| 279 | 279 | _ = laptr; |
| ... | ... | @@ -323,7 +323,7 @@ pub const TlvPtrSection = struct { |
| 323 | 323 | return tlv.symbols.items.len * @sizeOf(u64); |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: anytype) !void { | |
| 326 | pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: *Writer) !void { | |
| 327 | 327 | const tracy = trace(@src()); |
| 328 | 328 | defer tracy.end(); |
| 329 | 329 | |
| ... | ... | @@ -394,7 +394,7 @@ pub const ObjcStubsSection = struct { |
| 394 | 394 | return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch); |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void { | |
| 397 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: *Writer) !void { | |
| 398 | 398 | const tracy = trace(@src()); |
| 399 | 399 | defer tracy.end(); |
| 400 | 400 | |
| ... | ... | @@ -487,7 +487,7 @@ pub const Indsymtab = struct { |
| 487 | 487 | macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file); |
| 488 | 488 | } |
| 489 | 489 | |
| 490 | pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void { | |
| 490 | pub fn write(ind: Indsymtab, macho_file: *MachO, writer: *Writer) !void { | |
| 491 | 491 | const tracy = trace(@src()); |
| 492 | 492 | defer tracy.end(); |
| 493 | 493 | |
| ... | ... | @@ -564,7 +564,7 @@ pub const DataInCode = struct { |
| 564 | 564 | macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow; |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | pub fn write(dice: DataInCode, macho_file: *MachO, writer: anytype) !void { | |
| 567 | pub fn write(dice: DataInCode, macho_file: *MachO, writer: *Writer) !void { | |
| 568 | 568 | const base_address = if (!macho_file.base.isRelocatable()) |
| 569 | 569 | macho_file.getTextSegment().vmaddr |
| 570 | 570 | else |
| ... | ... | @@ -572,11 +572,11 @@ pub const DataInCode = struct { |
| 572 | 572 | for (dice.entries.items) |entry| { |
| 573 | 573 | const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file); |
| 574 | 574 | const offset = atom_address + entry.offset - base_address; |
| 575 | try writer.writeStruct(macho.data_in_code_entry{ | |
| 575 | try writer.writeStruct(@as(macho.data_in_code_entry, .{ | |
| 576 | 576 | .offset = @intCast(offset), |
| 577 | 577 | .length = entry.length, |
| 578 | 578 | .kind = entry.kind, |
| 579 | }); | |
| 579 | }), .little); | |
| 580 | 580 | } |
| 581 | 581 | } |
| 582 | 582 | |
| ... | ... | @@ -594,7 +594,7 @@ const assert = std.debug.assert; |
| 594 | 594 | const macho = std.macho; |
| 595 | 595 | const math = std.math; |
| 596 | 596 | const Allocator = std.mem.Allocator; |
| 597 | const Writer = std.io.Writer; | |
| 597 | const Writer = std.Io.Writer; | |
| 598 | 598 | |
| 599 | 599 | const trace = @import("../../tracy.zig").trace; |
| 600 | 600 | const MachO = @import("../MachO.zig"); |
src/link/Wasm/Flush.zig+176-149| ... | ... | @@ -19,6 +19,7 @@ const mem = std.mem; |
| 19 | 19 | const leb = std.leb; |
| 20 | 20 | const log = std.log.scoped(.link); |
| 21 | 21 | const assert = std.debug.assert; |
| 22 | const ArrayList = std.ArrayList; | |
| 22 | 23 | |
| 23 | 24 | /// Ordered list of data segments that will appear in the final binary. |
| 24 | 25 | /// When sorted, to-be-merged segments will be made adjacent. |
| ... | ... | @@ -27,9 +28,9 @@ data_segments: std.AutoArrayHashMapUnmanaged(Wasm.DataSegmentId, u32) = .empty, |
| 27 | 28 | /// Each time a `data_segment` offset equals zero it indicates a new group, and |
| 28 | 29 | /// the next element in this array will contain the total merged segment size. |
| 29 | 30 | /// Value is the virtual memory address of the end of the segment. |
| 30 | data_segment_groups: std.ArrayListUnmanaged(DataSegmentGroup) = .empty, | |
| 31 | data_segment_groups: ArrayList(DataSegmentGroup) = .empty, | |
| 31 | 32 | |
| 32 | binary_bytes: std.ArrayListUnmanaged(u8) = .empty, | |
| 33 | binary_bytes: ArrayList(u8) = .empty, | |
| 33 | 34 | missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty, |
| 34 | 35 | function_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.FunctionImportId) = .empty, |
| 35 | 36 | global_imports: std.AutoArrayHashMapUnmanaged(String, Wasm.GlobalImportId) = .empty, |
| ... | ... | @@ -563,8 +564,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 563 | 564 | try binary_bytes.appendSlice(gpa, &std.wasm.magic ++ &std.wasm.version); |
| 564 | 565 | assert(binary_bytes.items.len == 8); |
| 565 | 566 | |
| 566 | const binary_writer = binary_bytes.writer(gpa); | |
| 567 | ||
| 568 | 567 | // Type section. |
| 569 | 568 | for (f.function_imports.values()) |id| { |
| 570 | 569 | try f.func_types.put(gpa, id.functionType(wasm), {}); |
| ... | ... | @@ -576,16 +575,16 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 576 | 575 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 577 | 576 | for (f.func_types.keys()) |func_type_index| { |
| 578 | 577 | const func_type = func_type_index.ptr(wasm); |
| 579 | try leb.writeUleb128(binary_writer, std.wasm.function_type); | |
| 578 | try appendLeb128(gpa, binary_bytes, std.wasm.function_type); | |
| 580 | 579 | const params = func_type.params.slice(wasm); |
| 581 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(params.len))); | |
| 580 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(params.len))); | |
| 582 | 581 | for (params) |param_ty| { |
| 583 | try leb.writeUleb128(binary_writer, @intFromEnum(param_ty)); | |
| 582 | try appendLeb128(gpa, binary_bytes, @intFromEnum(param_ty)); | |
| 584 | 583 | } |
| 585 | 584 | const returns = func_type.returns.slice(wasm); |
| 586 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(returns.len))); | |
| 585 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(returns.len))); | |
| 587 | 586 | for (returns) |ret_ty| { |
| 588 | try leb.writeUleb128(binary_writer, @intFromEnum(ret_ty)); | |
| 587 | try appendLeb128(gpa, binary_bytes, @intFromEnum(ret_ty)); | |
| 589 | 588 | } |
| 590 | 589 | } |
| 591 | 590 | replaceVecSectionHeader(binary_bytes, header_offset, .type, @intCast(f.func_types.entries.len)); |
| ... | ... | @@ -605,31 +604,31 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 605 | 604 | |
| 606 | 605 | for (f.function_imports.values()) |id| { |
| 607 | 606 | const module_name = id.moduleName(wasm).slice(wasm).?; |
| 608 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | |
| 609 | try binary_writer.writeAll(module_name); | |
| 607 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | |
| 608 | try binary_bytes.appendSlice(gpa, module_name); | |
| 610 | 609 | |
| 611 | 610 | const name = id.importName(wasm).slice(wasm); |
| 612 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 613 | try binary_writer.writeAll(name); | |
| 611 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 612 | try binary_bytes.appendSlice(gpa, name); | |
| 614 | 613 | |
| 615 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.function)); | |
| 614 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.function)); | |
| 616 | 615 | const type_index: FuncTypeIndex = .fromTypeIndex(id.functionType(wasm), f); |
| 617 | try leb.writeUleb128(binary_writer, @intFromEnum(type_index)); | |
| 616 | try appendLeb128(gpa, binary_bytes, @intFromEnum(type_index)); | |
| 618 | 617 | } |
| 619 | 618 | total_imports += f.function_imports.entries.len; |
| 620 | 619 | |
| 621 | 620 | for (wasm.table_imports.values()) |id| { |
| 622 | 621 | const table_import = id.value(wasm); |
| 623 | 622 | const module_name = table_import.module_name.slice(wasm); |
| 624 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | |
| 625 | try binary_writer.writeAll(module_name); | |
| 623 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | |
| 624 | try binary_bytes.appendSlice(gpa, module_name); | |
| 626 | 625 | |
| 627 | 626 | const name = table_import.name.slice(wasm); |
| 628 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 629 | try binary_writer.writeAll(name); | |
| 627 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 628 | try binary_bytes.appendSlice(gpa, name); | |
| 630 | 629 | |
| 631 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.table)); | |
| 632 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to()))); | |
| 630 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.table)); | |
| 631 | try appendLeb128(gpa, binary_bytes, @intFromEnum(@as(std.wasm.RefType, table_import.flags.ref_type.to()))); | |
| 633 | 632 | try emitLimits(gpa, binary_bytes, table_import.limits()); |
| 634 | 633 | } |
| 635 | 634 | total_imports += wasm.table_imports.entries.len; |
| ... | ... | @@ -650,17 +649,17 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 650 | 649 | |
| 651 | 650 | for (f.global_imports.values()) |id| { |
| 652 | 651 | const module_name = id.moduleName(wasm).slice(wasm).?; |
| 653 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len))); | |
| 654 | try binary_writer.writeAll(module_name); | |
| 652 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | |
| 653 | try binary_bytes.appendSlice(gpa, module_name); | |
| 655 | 654 | |
| 656 | 655 | const name = id.importName(wasm).slice(wasm); |
| 657 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 658 | try binary_writer.writeAll(name); | |
| 656 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 657 | try binary_bytes.appendSlice(gpa, name); | |
| 659 | 658 | |
| 660 | try binary_writer.writeByte(@intFromEnum(std.wasm.ExternalKind.global)); | |
| 659 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.global)); | |
| 661 | 660 | const global_type = id.globalType(wasm); |
| 662 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.Valtype, global_type.valtype))); | |
| 663 | try binary_writer.writeByte(@intFromBool(global_type.mutable)); | |
| 661 | try appendLeb128(gpa, binary_bytes, @intFromEnum(@as(std.wasm.Valtype, global_type.valtype))); | |
| 662 | try binary_bytes.append(gpa, @intFromBool(global_type.mutable)); | |
| 664 | 663 | } |
| 665 | 664 | total_imports += f.global_imports.entries.len; |
| 666 | 665 | |
| ... | ... | @@ -677,7 +676,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 677 | 676 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 678 | 677 | for (wasm.functions.keys()) |function| { |
| 679 | 678 | const index: FuncTypeIndex = .fromTypeIndex(function.typeIndex(wasm), f); |
| 680 | try leb.writeUleb128(binary_writer, @intFromEnum(index)); | |
| 679 | try appendLeb128(gpa, binary_bytes, @intFromEnum(index)); | |
| 681 | 680 | } |
| 682 | 681 | |
| 683 | 682 | replaceVecSectionHeader(binary_bytes, header_offset, .function, @intCast(wasm.functions.count())); |
| ... | ... | @@ -689,7 +688,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 689 | 688 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 690 | 689 | |
| 691 | 690 | for (wasm.tables.keys()) |table| { |
| 692 | try leb.writeUleb128(binary_writer, @intFromEnum(@as(std.wasm.RefType, table.refType(wasm)))); | |
| 691 | try appendLeb128(gpa, binary_bytes, @intFromEnum(@as(std.wasm.RefType, table.refType(wasm)))); | |
| 693 | 692 | try emitLimits(gpa, binary_bytes, table.limits(wasm)); |
| 694 | 693 | } |
| 695 | 694 | |
| ... | ... | @@ -743,39 +742,39 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 743 | 742 | |
| 744 | 743 | for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| { |
| 745 | 744 | const name = exp_name.slice(wasm); |
| 746 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 745 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 747 | 746 | try binary_bytes.appendSlice(gpa, name); |
| 748 | 747 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.function)); |
| 749 | 748 | const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index); |
| 750 | try leb.writeUleb128(binary_writer, @intFromEnum(func_index)); | |
| 749 | try appendLeb128(gpa, binary_bytes, @intFromEnum(func_index)); | |
| 751 | 750 | } |
| 752 | 751 | exports_len += wasm.function_exports.entries.len; |
| 753 | 752 | |
| 754 | 753 | if (wasm.export_table and f.indirect_function_table.entries.len > 0) { |
| 755 | 754 | const name = "__indirect_function_table"; |
| 756 | 755 | const index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); |
| 757 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 756 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 758 | 757 | try binary_bytes.appendSlice(gpa, name); |
| 759 | 758 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.table)); |
| 760 | try leb.writeUleb128(binary_writer, index); | |
| 759 | try appendLeb128(gpa, binary_bytes, index); | |
| 761 | 760 | exports_len += 1; |
| 762 | 761 | } |
| 763 | 762 | |
| 764 | 763 | if (export_memory) { |
| 765 | 764 | const name = "memory"; |
| 766 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 765 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 767 | 766 | try binary_bytes.appendSlice(gpa, name); |
| 768 | 767 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory)); |
| 769 | try leb.writeUleb128(binary_writer, @as(u32, 0)); | |
| 768 | try appendLeb128(gpa, binary_bytes, @as(u32, 0)); | |
| 770 | 769 | exports_len += 1; |
| 771 | 770 | } |
| 772 | 771 | |
| 773 | 772 | for (wasm.global_exports.items) |exp| { |
| 774 | 773 | const name = exp.name.slice(wasm); |
| 775 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); | |
| 774 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 776 | 775 | try binary_bytes.appendSlice(gpa, name); |
| 777 | 776 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.global)); |
| 778 | try leb.writeUleb128(binary_writer, @intFromEnum(exp.global_index)); | |
| 777 | try appendLeb128(gpa, binary_bytes, @intFromEnum(exp.global_index)); | |
| 779 | 778 | } |
| 780 | 779 | exports_len += wasm.global_exports.items.len; |
| 781 | 780 | |
| ... | ... | @@ -802,18 +801,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 802 | 801 | const table_index: u32 = @intCast(wasm.tables.getIndex(.__indirect_function_table).?); |
| 803 | 802 | // passive with implicit 0-index table or set table index manually |
| 804 | 803 | const flags: u32 = if (table_index == 0) 0x0 else 0x02; |
| 805 | try leb.writeUleb128(binary_writer, flags); | |
| 804 | try appendLeb128(gpa, binary_bytes, flags); | |
| 806 | 805 | if (flags == 0x02) { |
| 807 | try leb.writeUleb128(binary_writer, table_index); | |
| 806 | try appendLeb128(gpa, binary_bytes, table_index); | |
| 808 | 807 | } |
| 809 | 808 | // We start at index 1, so unresolved function pointers are invalid |
| 810 | try emitInit(binary_writer, .{ .i32_const = 1 }); | |
| 809 | { | |
| 810 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, binary_bytes); | |
| 811 | defer binary_bytes.* = aw.toArrayList(); | |
| 812 | try emitInit(&aw.writer, .{ .i32_const = 1 }); | |
| 813 | } | |
| 811 | 814 | if (flags == 0x02) { |
| 812 | try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref | |
| 815 | try appendLeb128(gpa, binary_bytes, @as(u8, 0)); // represents funcref | |
| 813 | 816 | } |
| 814 | try leb.writeUleb128(binary_writer, @as(u32, @intCast(f.indirect_function_table.entries.len))); | |
| 817 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(f.indirect_function_table.entries.len))); | |
| 815 | 818 | for (f.indirect_function_table.keys()) |func_index| { |
| 816 | try leb.writeUleb128(binary_writer, @intFromEnum(func_index)); | |
| 819 | try appendLeb128(gpa, binary_bytes, @intFromEnum(func_index)); | |
| 817 | 820 | } |
| 818 | 821 | |
| 819 | 822 | replaceVecSectionHeader(binary_bytes, header_offset, .element, 1); |
| ... | ... | @@ -851,7 +854,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 851 | 854 | .object_function => |i| { |
| 852 | 855 | const ptr = i.ptr(wasm); |
| 853 | 856 | const code = ptr.code.slice(wasm); |
| 854 | try leb.writeUleb128(binary_writer, code.len); | |
| 857 | try appendLeb128(gpa, binary_bytes, code.len); | |
| 855 | 858 | const code_start = binary_bytes.items.len; |
| 856 | 859 | try binary_bytes.appendSlice(gpa, code); |
| 857 | 860 | if (!is_obj) applyRelocs(binary_bytes.items[code_start..], ptr.offset, ptr.relocations(wasm), wasm); |
| ... | ... | @@ -946,12 +949,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 946 | 949 | const group_size = group_end_addr - group_start_addr; |
| 947 | 950 | log.debug("emit data section group, {d} bytes", .{group_size}); |
| 948 | 951 | const flags: Object.DataSegmentFlags = if (segment_id.isPassive(wasm)) .passive else .active; |
| 949 | try leb.writeUleb128(binary_writer, @intFromEnum(flags)); | |
| 952 | try appendLeb128(gpa, binary_bytes, @intFromEnum(flags)); | |
| 950 | 953 | // Passive segments are initialized at runtime. |
| 951 | 954 | if (flags != .passive) { |
| 952 | try emitInit(binary_writer, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) }); | |
| 955 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, binary_bytes); | |
| 956 | defer binary_bytes.* = aw.toArrayList(); | |
| 957 | try emitInit(&aw.writer, .{ .i32_const = @as(i32, @bitCast(group_start_addr)) }); | |
| 953 | 958 | } |
| 954 | try leb.writeUleb128(binary_writer, group_size); | |
| 959 | try appendLeb128(gpa, binary_bytes, group_size); | |
| 955 | 960 | } |
| 956 | 961 | if (segment_id.isEmpty(wasm)) { |
| 957 | 962 | // It counted for virtual memory but it does not go into the binary. |
| ... | ... | @@ -1077,7 +1082,7 @@ const VirtualAddrs = struct { |
| 1077 | 1082 | fn emitNameSection( |
| 1078 | 1083 | wasm: *Wasm, |
| 1079 | 1084 | data_segment_groups: []const DataSegmentGroup, |
| 1080 | binary_bytes: *std.ArrayListUnmanaged(u8), | |
| 1085 | binary_bytes: *ArrayList(u8), | |
| 1081 | 1086 | ) !void { |
| 1082 | 1087 | const f = &wasm.flush_buffer; |
| 1083 | 1088 | const comp = wasm.base.comp; |
| ... | ... | @@ -1087,7 +1092,7 @@ fn emitNameSection( |
| 1087 | 1092 | defer writeCustomSectionHeader(binary_bytes, header_offset); |
| 1088 | 1093 | |
| 1089 | 1094 | const name_name = "name"; |
| 1090 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, name_name.len)); | |
| 1095 | try appendLeb128(gpa, binary_bytes, @as(u32, name_name.len)); | |
| 1091 | 1096 | try binary_bytes.appendSlice(gpa, name_name); |
| 1092 | 1097 | |
| 1093 | 1098 | { |
| ... | ... | @@ -1095,18 +1100,18 @@ fn emitNameSection( |
| 1095 | 1100 | defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.function)); |
| 1096 | 1101 | |
| 1097 | 1102 | const total_functions: u32 = @intCast(f.function_imports.entries.len + wasm.functions.entries.len); |
| 1098 | try leb.writeUleb128(binary_bytes.writer(gpa), total_functions); | |
| 1103 | try appendLeb128(gpa, binary_bytes, total_functions); | |
| 1099 | 1104 | |
| 1100 | 1105 | for (f.function_imports.keys(), 0..) |name_index, function_index| { |
| 1101 | 1106 | const name = name_index.slice(wasm); |
| 1102 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index))); | |
| 1103 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1107 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | |
| 1108 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1104 | 1109 | try binary_bytes.appendSlice(gpa, name); |
| 1105 | 1110 | } |
| 1106 | 1111 | for (wasm.functions.keys(), f.function_imports.entries.len..) |resolution, function_index| { |
| 1107 | 1112 | const name = resolution.name(wasm).?; |
| 1108 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(function_index))); | |
| 1109 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1113 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); | |
| 1114 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1110 | 1115 | try binary_bytes.appendSlice(gpa, name); |
| 1111 | 1116 | } |
| 1112 | 1117 | } |
| ... | ... | @@ -1116,18 +1121,18 @@ fn emitNameSection( |
| 1116 | 1121 | defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.global)); |
| 1117 | 1122 | |
| 1118 | 1123 | const total_globals: u32 = @intCast(f.global_imports.entries.len + wasm.globals.entries.len); |
| 1119 | try leb.writeUleb128(binary_bytes.writer(gpa), total_globals); | |
| 1124 | try appendLeb128(gpa, binary_bytes, total_globals); | |
| 1120 | 1125 | |
| 1121 | 1126 | for (f.global_imports.keys(), 0..) |name_index, global_index| { |
| 1122 | 1127 | const name = name_index.slice(wasm); |
| 1123 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index))); | |
| 1124 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1128 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); | |
| 1129 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1125 | 1130 | try binary_bytes.appendSlice(gpa, name); |
| 1126 | 1131 | } |
| 1127 | 1132 | for (wasm.globals.keys(), f.global_imports.entries.len..) |resolution, global_index| { |
| 1128 | 1133 | const name = resolution.name(wasm).?; |
| 1129 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(global_index))); | |
| 1130 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1134 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); | |
| 1135 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1131 | 1136 | try binary_bytes.appendSlice(gpa, name); |
| 1132 | 1137 | } |
| 1133 | 1138 | } |
| ... | ... | @@ -1137,12 +1142,12 @@ fn emitNameSection( |
| 1137 | 1142 | defer replaceHeader(binary_bytes, sub_offset, @intFromEnum(std.wasm.NameSubsection.data_segment)); |
| 1138 | 1143 | |
| 1139 | 1144 | const total_data_segments: u32 = @intCast(data_segment_groups.len); |
| 1140 | try leb.writeUleb128(binary_bytes.writer(gpa), total_data_segments); | |
| 1145 | try appendLeb128(gpa, binary_bytes, total_data_segments); | |
| 1141 | 1146 | |
| 1142 | 1147 | for (data_segment_groups, 0..) |group, i| { |
| 1143 | 1148 | const name, _ = splitSegmentName(group.first_segment.name(wasm)); |
| 1144 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(i))); | |
| 1145 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1149 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(i))); | |
| 1150 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1146 | 1151 | try binary_bytes.appendSlice(gpa, name); |
| 1147 | 1152 | } |
| 1148 | 1153 | } |
| ... | ... | @@ -1150,7 +1155,7 @@ fn emitNameSection( |
| 1150 | 1155 | |
| 1151 | 1156 | fn emitFeaturesSection( |
| 1152 | 1157 | gpa: Allocator, |
| 1153 | binary_bytes: *std.ArrayListUnmanaged(u8), | |
| 1158 | binary_bytes: *ArrayList(u8), | |
| 1154 | 1159 | target: *const std.Target, |
| 1155 | 1160 | ) Allocator.Error!void { |
| 1156 | 1161 | const feature_count = target.cpu.features.count(); |
| ... | ... | @@ -1159,87 +1164,84 @@ fn emitFeaturesSection( |
| 1159 | 1164 | const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); |
| 1160 | 1165 | defer writeCustomSectionHeader(binary_bytes, header_offset); |
| 1161 | 1166 | |
| 1162 | const writer = binary_bytes.writer(gpa); | |
| 1163 | 1167 | const target_features = "target_features"; |
| 1164 | try leb.writeUleb128(writer, @as(u32, @intCast(target_features.len))); | |
| 1165 | try writer.writeAll(target_features); | |
| 1168 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(target_features.len))); | |
| 1169 | try binary_bytes.appendSlice(gpa, target_features); | |
| 1166 | 1170 | |
| 1167 | try leb.writeUleb128(writer, @as(u32, @intCast(feature_count))); | |
| 1171 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(feature_count))); | |
| 1168 | 1172 | |
| 1169 | 1173 | var safety_count = feature_count; |
| 1170 | 1174 | for (target.cpu.arch.allFeaturesList(), 0..) |*feature, i| { |
| 1171 | 1175 | if (!target.cpu.has(.wasm, @as(std.Target.wasm.Feature, @enumFromInt(i)))) continue; |
| 1172 | 1176 | safety_count -= 1; |
| 1173 | 1177 | |
| 1174 | try leb.writeUleb128(writer, @as(u32, '+')); | |
| 1178 | try appendLeb128(gpa, binary_bytes, @as(u32, '+')); | |
| 1175 | 1179 | // Depends on llvm_name for the hyphenated version that matches wasm tooling conventions. |
| 1176 | 1180 | const name = feature.llvm_name.?; |
| 1177 | try leb.writeUleb128(writer, @as(u32, @intCast(name.len))); | |
| 1178 | try writer.writeAll(name); | |
| 1181 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1182 | try binary_bytes.appendSlice(gpa, name); | |
| 1179 | 1183 | } |
| 1180 | 1184 | assert(safety_count == 0); |
| 1181 | 1185 | } |
| 1182 | 1186 | |
| 1183 | fn emitBuildIdSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8), build_id: []const u8) !void { | |
| 1187 | fn emitBuildIdSection(gpa: Allocator, binary_bytes: *ArrayList(u8), build_id: []const u8) !void { | |
| 1184 | 1188 | const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); |
| 1185 | 1189 | defer writeCustomSectionHeader(binary_bytes, header_offset); |
| 1186 | 1190 | |
| 1187 | const writer = binary_bytes.writer(gpa); | |
| 1188 | 1191 | const hdr_build_id = "build_id"; |
| 1189 | try leb.writeUleb128(writer, @as(u32, @intCast(hdr_build_id.len))); | |
| 1190 | try writer.writeAll(hdr_build_id); | |
| 1192 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(hdr_build_id.len))); | |
| 1193 | try binary_bytes.appendSlice(gpa, hdr_build_id); | |
| 1191 | 1194 | |
| 1192 | try leb.writeUleb128(writer, @as(u32, 1)); | |
| 1193 | try leb.writeUleb128(writer, @as(u32, @intCast(build_id.len))); | |
| 1194 | try writer.writeAll(build_id); | |
| 1195 | try appendLeb128(gpa, binary_bytes, @as(u32, 1)); | |
| 1196 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(build_id.len))); | |
| 1197 | try binary_bytes.appendSlice(gpa, build_id); | |
| 1195 | 1198 | } |
| 1196 | 1199 | |
| 1197 | fn emitProducerSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8)) !void { | |
| 1200 | fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void { | |
| 1198 | 1201 | const header_offset = try reserveCustomSectionHeader(gpa, binary_bytes); |
| 1199 | 1202 | defer writeCustomSectionHeader(binary_bytes, header_offset); |
| 1200 | 1203 | |
| 1201 | const writer = binary_bytes.writer(gpa); | |
| 1202 | 1204 | const producers = "producers"; |
| 1203 | try leb.writeUleb128(writer, @as(u32, @intCast(producers.len))); | |
| 1204 | try writer.writeAll(producers); | |
| 1205 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(producers.len))); | |
| 1206 | try binary_bytes.appendSlice(gpa, producers); | |
| 1205 | 1207 | |
| 1206 | try leb.writeUleb128(writer, @as(u32, 2)); // 2 fields: Language + processed-by | |
| 1208 | try appendLeb128(gpa, binary_bytes, @as(u32, 2)); // 2 fields: Language + processed-by | |
| 1207 | 1209 | |
| 1208 | 1210 | // language field |
| 1209 | 1211 | { |
| 1210 | 1212 | const language = "language"; |
| 1211 | try leb.writeUleb128(writer, @as(u32, @intCast(language.len))); | |
| 1212 | try writer.writeAll(language); | |
| 1213 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(language.len))); | |
| 1214 | try binary_bytes.appendSlice(gpa, language); | |
| 1213 | 1215 | |
| 1214 | 1216 | // field_value_count (TODO: Parse object files for producer sections to detect their language) |
| 1215 | try leb.writeUleb128(writer, @as(u32, 1)); | |
| 1217 | try appendLeb128(gpa, binary_bytes, @as(u32, 1)); | |
| 1216 | 1218 | |
| 1217 | 1219 | // versioned name |
| 1218 | 1220 | { |
| 1219 | try leb.writeUleb128(writer, @as(u32, 3)); // len of "Zig" | |
| 1220 | try writer.writeAll("Zig"); | |
| 1221 | try appendLeb128(gpa, binary_bytes, @as(u32, 3)); // len of "Zig" | |
| 1222 | try binary_bytes.appendSlice(gpa, "Zig"); | |
| 1221 | 1223 | |
| 1222 | try leb.writeUleb128(writer, @as(u32, @intCast(build_options.version.len))); | |
| 1223 | try writer.writeAll(build_options.version); | |
| 1224 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(build_options.version.len))); | |
| 1225 | try binary_bytes.appendSlice(gpa, build_options.version); | |
| 1224 | 1226 | } |
| 1225 | 1227 | } |
| 1226 | 1228 | |
| 1227 | 1229 | // processed-by field |
| 1228 | 1230 | { |
| 1229 | 1231 | const processed_by = "processed-by"; |
| 1230 | try leb.writeUleb128(writer, @as(u32, @intCast(processed_by.len))); | |
| 1231 | try writer.writeAll(processed_by); | |
| 1232 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(processed_by.len))); | |
| 1233 | try binary_bytes.appendSlice(gpa, processed_by); | |
| 1232 | 1234 | |
| 1233 | 1235 | // field_value_count (TODO: Parse object files for producer sections to detect other used tools) |
| 1234 | try leb.writeUleb128(writer, @as(u32, 1)); | |
| 1236 | try appendLeb128(gpa, binary_bytes, @as(u32, 1)); | |
| 1235 | 1237 | |
| 1236 | 1238 | // versioned name |
| 1237 | 1239 | { |
| 1238 | try leb.writeUleb128(writer, @as(u32, 3)); // len of "Zig" | |
| 1239 | try writer.writeAll("Zig"); | |
| 1240 | try appendLeb128(gpa, binary_bytes, @as(u32, 3)); // len of "Zig" | |
| 1241 | try binary_bytes.appendSlice(gpa, "Zig"); | |
| 1240 | 1242 | |
| 1241 | try leb.writeUleb128(writer, @as(u32, @intCast(build_options.version.len))); | |
| 1242 | try writer.writeAll(build_options.version); | |
| 1243 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(build_options.version.len))); | |
| 1244 | try binary_bytes.appendSlice(gpa, build_options.version); | |
| 1243 | 1245 | } |
| 1244 | 1246 | } |
| 1245 | 1247 | } |
| ... | ... | @@ -1280,99 +1282,97 @@ fn wantSegmentMerge( |
| 1280 | 1282 | const section_header_reserve_size = 1 + 5 + 5; |
| 1281 | 1283 | const section_header_size = 5 + 1; |
| 1282 | 1284 | |
| 1283 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | |
| 1285 | fn reserveVecSectionHeader(gpa: Allocator, bytes: *ArrayList(u8)) Allocator.Error!u32 { | |
| 1284 | 1286 | try bytes.appendNTimes(gpa, 0, section_header_reserve_size); |
| 1285 | 1287 | return @intCast(bytes.items.len - section_header_reserve_size); |
| 1286 | 1288 | } |
| 1287 | 1289 | |
| 1288 | 1290 | fn replaceVecSectionHeader( |
| 1289 | bytes: *std.ArrayListUnmanaged(u8), | |
| 1291 | bytes: *ArrayList(u8), | |
| 1290 | 1292 | offset: u32, |
| 1291 | 1293 | section: std.wasm.Section, |
| 1292 | 1294 | n_items: u32, |
| 1293 | 1295 | ) void { |
| 1294 | 1296 | const size: u32 = @intCast(bytes.items.len - offset - section_header_reserve_size + uleb128size(n_items)); |
| 1295 | 1297 | var buf: [section_header_reserve_size]u8 = undefined; |
| 1296 | var fbw = std.io.fixedBufferStream(&buf); | |
| 1297 | const w = fbw.writer(); | |
| 1298 | var w: std.Io.Writer = .fixed(&buf); | |
| 1298 | 1299 | 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()); | |
| 1300 | w.writeUleb128(size) catch unreachable; | |
| 1301 | w.writeUleb128(n_items) catch unreachable; | |
| 1302 | bytes.replaceRangeAssumeCapacity(offset, section_header_reserve_size, w.buffered()); | |
| 1302 | 1303 | } |
| 1303 | 1304 | |
| 1304 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | |
| 1305 | fn reserveCustomSectionHeader(gpa: Allocator, bytes: *ArrayList(u8)) Allocator.Error!u32 { | |
| 1305 | 1306 | try bytes.appendNTimes(gpa, 0, section_header_size); |
| 1306 | 1307 | return @intCast(bytes.items.len - section_header_size); |
| 1307 | 1308 | } |
| 1308 | 1309 | |
| 1309 | fn writeCustomSectionHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32) void { | |
| 1310 | fn writeCustomSectionHeader(bytes: *ArrayList(u8), offset: u32) void { | |
| 1310 | 1311 | return replaceHeader(bytes, offset, 0); // 0 = 'custom' section |
| 1311 | 1312 | } |
| 1312 | 1313 | |
| 1313 | fn replaceHeader(bytes: *std.ArrayListUnmanaged(u8), offset: u32, tag: u8) void { | |
| 1314 | fn replaceHeader(bytes: *ArrayList(u8), offset: u32, tag: u8) void { | |
| 1314 | 1315 | const size: u32 = @intCast(bytes.items.len - offset - section_header_size); |
| 1315 | 1316 | var buf: [section_header_size]u8 = undefined; |
| 1316 | var fbw = std.io.fixedBufferStream(&buf); | |
| 1317 | const w = fbw.writer(); | |
| 1317 | var w: std.Io.Writer = .fixed(&buf); | |
| 1318 | 1318 | w.writeByte(tag) catch unreachable; |
| 1319 | leb.writeUleb128(w, size) catch unreachable; | |
| 1320 | bytes.replaceRangeAssumeCapacity(offset, section_header_size, fbw.getWritten()); | |
| 1319 | w.writeUleb128(size) catch unreachable; | |
| 1320 | bytes.replaceRangeAssumeCapacity(offset, section_header_size, w.buffered()); | |
| 1321 | 1321 | } |
| 1322 | 1322 | |
| 1323 | 1323 | const max_size_encoding = 5; |
| 1324 | 1324 | |
| 1325 | fn reserveSize(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!u32 { | |
| 1325 | fn reserveSize(gpa: Allocator, bytes: *ArrayList(u8)) Allocator.Error!u32 { | |
| 1326 | 1326 | try bytes.appendNTimes(gpa, 0, max_size_encoding); |
| 1327 | 1327 | return @intCast(bytes.items.len - max_size_encoding); |
| 1328 | 1328 | } |
| 1329 | 1329 | |
| 1330 | fn replaceSize(bytes: *std.ArrayListUnmanaged(u8), offset: u32) void { | |
| 1330 | fn replaceSize(bytes: *ArrayList(u8), offset: u32) void { | |
| 1331 | 1331 | const size: u32 = @intCast(bytes.items.len - offset - max_size_encoding); |
| 1332 | 1332 | var buf: [max_size_encoding]u8 = undefined; |
| 1333 | var fbw = std.io.fixedBufferStream(&buf); | |
| 1334 | leb.writeUleb128(fbw.writer(), size) catch unreachable; | |
| 1335 | bytes.replaceRangeAssumeCapacity(offset, max_size_encoding, fbw.getWritten()); | |
| 1333 | var w: std.Io.Writer = .fixed(&buf); | |
| 1334 | w.writeUleb128(size) catch unreachable; | |
| 1335 | bytes.replaceRangeAssumeCapacity(offset, max_size_encoding, w.buffered()); | |
| 1336 | 1336 | } |
| 1337 | 1337 | |
| 1338 | 1338 | fn emitLimits( |
| 1339 | 1339 | gpa: Allocator, |
| 1340 | binary_bytes: *std.ArrayListUnmanaged(u8), | |
| 1340 | binary_bytes: *ArrayList(u8), | |
| 1341 | 1341 | limits: std.wasm.Limits, |
| 1342 | 1342 | ) Allocator.Error!void { |
| 1343 | 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); | |
| 1344 | try appendLeb128(gpa, binary_bytes, limits.min); | |
| 1345 | if (limits.flags.has_max) try appendLeb128(gpa, binary_bytes, limits.max); | |
| 1346 | 1346 | } |
| 1347 | 1347 | |
| 1348 | 1348 | fn emitMemoryImport( |
| 1349 | 1349 | wasm: *Wasm, |
| 1350 | binary_bytes: *std.ArrayListUnmanaged(u8), | |
| 1350 | binary_bytes: *ArrayList(u8), | |
| 1351 | 1351 | name_index: String, |
| 1352 | 1352 | memory_import: *const Wasm.MemoryImport, |
| 1353 | 1353 | ) Allocator.Error!void { |
| 1354 | 1354 | const gpa = wasm.base.comp.gpa; |
| 1355 | 1355 | const module_name = memory_import.module_name.slice(wasm); |
| 1356 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len))); | |
| 1356 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); | |
| 1357 | 1357 | try binary_bytes.appendSlice(gpa, module_name); |
| 1358 | 1358 | |
| 1359 | 1359 | const name = name_index.slice(wasm); |
| 1360 | try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); | |
| 1360 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); | |
| 1361 | 1361 | try binary_bytes.appendSlice(gpa, name); |
| 1362 | 1362 | |
| 1363 | 1363 | try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.memory)); |
| 1364 | 1364 | try emitLimits(gpa, binary_bytes, memory_import.limits()); |
| 1365 | 1365 | } |
| 1366 | 1366 | |
| 1367 | pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { | |
| 1367 | fn emitInit(writer: *std.Io.Writer, init_expr: std.wasm.InitExpression) !void { | |
| 1368 | 1368 | switch (init_expr) { |
| 1369 | 1369 | .i32_const => |val| { |
| 1370 | 1370 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.i32_const)); |
| 1371 | try leb.writeIleb128(writer, val); | |
| 1371 | try writer.writeSleb128(val); | |
| 1372 | 1372 | }, |
| 1373 | 1373 | .i64_const => |val| { |
| 1374 | 1374 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.i64_const)); |
| 1375 | try leb.writeIleb128(writer, val); | |
| 1375 | try writer.writeSleb128(val); | |
| 1376 | 1376 | }, |
| 1377 | 1377 | .f32_const => |val| { |
| 1378 | 1378 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.f32_const)); |
| ... | ... | @@ -1384,13 +1384,13 @@ pub fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void { |
| 1384 | 1384 | }, |
| 1385 | 1385 | .global_get => |val| { |
| 1386 | 1386 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.global_get)); |
| 1387 | try leb.writeUleb128(writer, val); | |
| 1387 | try writer.writeUleb128(val); | |
| 1388 | 1388 | }, |
| 1389 | 1389 | } |
| 1390 | 1390 | try writer.writeByte(@intFromEnum(std.wasm.Opcode.end)); |
| 1391 | 1391 | } |
| 1392 | 1392 | |
| 1393 | pub fn emitExpr(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), expr: Wasm.Expr) Allocator.Error!void { | |
| 1393 | pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr) Allocator.Error!void { | |
| 1394 | 1394 | const gpa = wasm.base.comp.gpa; |
| 1395 | 1395 | const slice = expr.slice(wasm); |
| 1396 | 1396 | try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode |
| ... | ... | @@ -1398,21 +1398,20 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), ex |
| 1398 | 1398 | |
| 1399 | 1399 | fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.array_list.Managed(u8)) !void { |
| 1400 | 1400 | const gpa = wasm.base.comp.gpa; |
| 1401 | const writer = binary_bytes.writer(gpa); | |
| 1402 | try leb.writeUleb128(writer, @intFromEnum(Wasm.SubsectionType.segment_info)); | |
| 1401 | try appendLeb128(gpa, binary_bytes, @intFromEnum(Wasm.SubsectionType.segment_info)); | |
| 1403 | 1402 | const segment_offset = binary_bytes.items.len; |
| 1404 | 1403 | |
| 1405 | try leb.writeUleb128(writer, @as(u32, @intCast(wasm.segment_info.count()))); | |
| 1404 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(wasm.segment_info.count()))); | |
| 1406 | 1405 | for (wasm.segment_info.values()) |segment_info| { |
| 1407 | 1406 | log.debug("Emit segment: {s} align({d}) flags({b})", .{ |
| 1408 | 1407 | segment_info.name, |
| 1409 | 1408 | segment_info.alignment, |
| 1410 | 1409 | segment_info.flags, |
| 1411 | 1410 | }); |
| 1412 | try leb.writeUleb128(writer, @as(u32, @intCast(segment_info.name.len))); | |
| 1413 | try writer.writeAll(segment_info.name); | |
| 1414 | try leb.writeUleb128(writer, segment_info.alignment.toLog2Units()); | |
| 1415 | try leb.writeUleb128(writer, segment_info.flags); | |
| 1411 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(segment_info.name.len))); | |
| 1412 | try binary_bytes.appendSlice(gpa, segment_info.name); | |
| 1413 | try appendLeb128(gpa, binary_bytes, segment_info.alignment.toLog2Units()); | |
| 1414 | try appendLeb128(gpa, binary_bytes, segment_info.flags); | |
| 1416 | 1415 | } |
| 1417 | 1416 | |
| 1418 | 1417 | var buf: [5]u8 = undefined; |
| ... | ... | @@ -1429,7 +1428,7 @@ fn uleb128size(x: u32) u32 { |
| 1429 | 1428 | |
| 1430 | 1429 | fn emitTagNameTable( |
| 1431 | 1430 | gpa: Allocator, |
| 1432 | code: *std.ArrayListUnmanaged(u8), | |
| 1431 | code: *ArrayList(u8), | |
| 1433 | 1432 | tag_name_offs: []const u32, |
| 1434 | 1433 | tag_name_bytes: []const u8, |
| 1435 | 1434 | base: u32, |
| ... | ... | @@ -1604,7 +1603,7 @@ fn reloc_leb_type(code: []u8, index: FuncTypeIndex) void { |
| 1604 | 1603 | leb.writeUnsignedFixed(5, code[0..5], @intFromEnum(index)); |
| 1605 | 1604 | } |
| 1606 | 1605 | |
| 1607 | fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!void { | |
| 1606 | fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Allocator.Error!void { | |
| 1608 | 1607 | const gpa = wasm.base.comp.gpa; |
| 1609 | 1608 | |
| 1610 | 1609 | try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1); |
| ... | ... | @@ -1631,7 +1630,7 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *std.ArrayListUnmanage |
| 1631 | 1630 | |
| 1632 | 1631 | fn emitInitMemoryFunction( |
| 1633 | 1632 | wasm: *const Wasm, |
| 1634 | binary_bytes: *std.ArrayListUnmanaged(u8), | |
| 1633 | binary_bytes: *ArrayList(u8), | |
| 1635 | 1634 | virtual_addrs: *const VirtualAddrs, |
| 1636 | 1635 | ) Allocator.Error!void { |
| 1637 | 1636 | const comp = wasm.base.comp; |
| ... | ... | @@ -1734,7 +1733,7 @@ fn emitInitMemoryFunction( |
| 1734 | 1733 | // notify any waiters for segment initialization completion |
| 1735 | 1734 | appendReservedI32Const(binary_bytes, flag_address); |
| 1736 | 1735 | binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); |
| 1737 | leb.writeIleb128(binary_bytes.fixedWriter(), @as(i32, -1)) catch unreachable; // number of waiters | |
| 1736 | appendReservedLeb128(binary_bytes, @as(i32, -1)); // number of waiters | |
| 1738 | 1737 | binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix)); |
| 1739 | 1738 | appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_notify)); |
| 1740 | 1739 | appendReservedUleb32(binary_bytes, @as(u32, 2)); // alignment |
| ... | ... | @@ -1750,7 +1749,7 @@ fn emitInitMemoryFunction( |
| 1750 | 1749 | appendReservedI32Const(binary_bytes, flag_address); |
| 1751 | 1750 | appendReservedI32Const(binary_bytes, 1); // expected flag value |
| 1752 | 1751 | binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const)); |
| 1753 | leb.writeIleb128(binary_bytes.fixedWriter(), @as(i64, -1)) catch unreachable; // timeout | |
| 1752 | appendReservedLeb128(binary_bytes, @as(i64, -1)); // timeout | |
| 1754 | 1753 | binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.atomics_prefix)); |
| 1755 | 1754 | appendReservedUleb32(binary_bytes, @intFromEnum(std.wasm.AtomicsOpcode.memory_atomic_wait32)); |
| 1756 | 1755 | appendReservedUleb32(binary_bytes, @as(u32, 2)); // alignment |
| ... | ... | @@ -1779,7 +1778,7 @@ fn emitInitMemoryFunction( |
| 1779 | 1778 | binary_bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1780 | 1779 | } |
| 1781 | 1780 | |
| 1782 | fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Allocator.Error!void { | |
| 1781 | fn emitInitTlsFunction(wasm: *const Wasm, bytes: *ArrayList(u8)) Allocator.Error!void { | |
| 1783 | 1782 | const comp = wasm.base.comp; |
| 1784 | 1783 | const gpa = comp.gpa; |
| 1785 | 1784 | |
| ... | ... | @@ -1840,14 +1839,14 @@ fn emitInitTlsFunction(wasm: *const Wasm, bytes: *std.ArrayListUnmanaged(u8)) Al |
| 1840 | 1839 | bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1841 | 1840 | } |
| 1842 | 1841 | |
| 1843 | fn emitStartSection(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8), i: Wasm.OutputFunctionIndex) !void { | |
| 1842 | fn emitStartSection(gpa: Allocator, bytes: *ArrayList(u8), i: Wasm.OutputFunctionIndex) !void { | |
| 1844 | 1843 | const header_offset = try reserveVecSectionHeader(gpa, bytes); |
| 1845 | 1844 | replaceVecSectionHeader(bytes, header_offset, .start, @intFromEnum(i)); |
| 1846 | 1845 | } |
| 1847 | 1846 | |
| 1848 | 1847 | fn emitTagNameFunction( |
| 1849 | 1848 | wasm: *Wasm, |
| 1850 | code: *std.ArrayListUnmanaged(u8), | |
| 1849 | code: *ArrayList(u8), | |
| 1851 | 1850 | table_base_addr: u32, |
| 1852 | 1851 | table_index: u32, |
| 1853 | 1852 | enum_type_ip: InternPool.Index, |
| ... | ... | @@ -1959,22 +1958,34 @@ fn emitTagNameFunction( |
| 1959 | 1958 | } |
| 1960 | 1959 | |
| 1961 | 1960 | /// Writes an unsigned 32-bit integer as a LEB128-encoded 'i32.const' value. |
| 1962 | fn appendReservedI32Const(bytes: *std.ArrayListUnmanaged(u8), val: u32) void { | |
| 1961 | fn appendReservedI32Const(bytes: *ArrayList(u8), val: u32) void { | |
| 1963 | 1962 | bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_const)); |
| 1964 | leb.writeIleb128(bytes.fixedWriter(), @as(i32, @bitCast(val))) catch unreachable; | |
| 1963 | var w: std.Io.Writer = .fromArrayList(bytes); | |
| 1964 | defer bytes.* = w.toArrayList(); | |
| 1965 | return w.writeSleb128(val) catch |err| switch (err) { | |
| 1966 | error.WriteFailed => unreachable, | |
| 1967 | }; | |
| 1965 | 1968 | } |
| 1966 | 1969 | |
| 1967 | 1970 | /// Writes an unsigned 64-bit integer as a LEB128-encoded 'i64.const' value. |
| 1968 | fn appendReservedI64Const(bytes: *std.ArrayListUnmanaged(u8), val: u64) void { | |
| 1971 | fn appendReservedI64Const(bytes: *ArrayList(u8), val: u64) void { | |
| 1969 | 1972 | bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_const)); |
| 1970 | leb.writeIleb128(bytes.fixedWriter(), @as(i64, @bitCast(val))) catch unreachable; | |
| 1973 | var w: std.Io.Writer = .fromArrayList(bytes); | |
| 1974 | defer bytes.* = w.toArrayList(); | |
| 1975 | return w.writeSleb128(val) catch |err| switch (err) { | |
| 1976 | error.WriteFailed => unreachable, | |
| 1977 | }; | |
| 1971 | 1978 | } |
| 1972 | 1979 | |
| 1973 | fn appendReservedUleb32(bytes: *std.ArrayListUnmanaged(u8), val: u32) void { | |
| 1974 | leb.writeUleb128(bytes.fixedWriter(), val) catch unreachable; | |
| 1980 | fn appendReservedUleb32(bytes: *ArrayList(u8), val: u32) void { | |
| 1981 | var w: std.Io.Writer = .fromArrayList(bytes); | |
| 1982 | defer bytes.* = w.toArrayList(); | |
| 1983 | return w.writeUleb128(val) catch |err| switch (err) { | |
| 1984 | error.WriteFailed => unreachable, | |
| 1985 | }; | |
| 1975 | 1986 | } |
| 1976 | 1987 | |
| 1977 | fn appendGlobal(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8), mutable: u8, val: u32) Allocator.Error!void { | |
| 1988 | fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void { | |
| 1978 | 1989 | try bytes.ensureUnusedCapacity(gpa, 9); |
| 1979 | 1990 | bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Valtype.i32)); |
| 1980 | 1991 | bytes.appendAssumeCapacity(mutable); |
| ... | ... | @@ -1982,3 +1993,19 @@ fn appendGlobal(gpa: Allocator, bytes: *std.ArrayListUnmanaged(u8), mutable: u8, |
| 1982 | 1993 | appendReservedUleb32(bytes, val); |
| 1983 | 1994 | bytes.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1984 | 1995 | } |
| 1996 | ||
| 1997 | fn appendLeb128(gpa: Allocator, bytes: *ArrayList(u8), value: anytype) Allocator.Error!void { | |
| 1998 | var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, bytes); | |
| 1999 | defer bytes.* = aw.toArrayList(); | |
| 2000 | return aw.writer.writeLeb128(value) catch |err| switch (err) { | |
| 2001 | error.WriteFailed => return error.OutOfMemory, | |
| 2002 | }; | |
| 2003 | } | |
| 2004 | ||
| 2005 | fn appendReservedLeb128(bytes: *ArrayList(u8), value: anytype) void { | |
| 2006 | var w: std.Io.Writer = .fromArrayList(bytes); | |
| 2007 | defer bytes.* = w.toArrayList(); | |
| 2008 | return w.writeLeb128(value) catch |err| switch (err) { | |
| 2009 | error.WriteFailed => unreachable, | |
| 2010 | }; | |
| 2011 | } |
src/link/riscv.zig+14-15| ... | ... | @@ -9,29 +9,28 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytyp |
| 9 | 9 | mem.writeInt(u8, code, value, .little); |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void { | |
| 13 | switch (op) { | |
| 14 | .set => try overwriteUleb(stream, @intCast(addend)), | |
| 15 | .sub => { | |
| 16 | const position = try stream.getPos(); | |
| 17 | const value: u64 = try std.leb.readUleb128(u64, stream.reader()); | |
| 18 | try stream.seekTo(position); | |
| 19 | try overwriteUleb(stream, value -% @as(u64, @intCast(addend))); | |
| 20 | }, | |
| 21 | } | |
| 12 | pub fn writeSubUleb(code: []u8, addend: i64) void { | |
| 13 | var reader: std.Io.Reader = .fixed(code); | |
| 14 | const value = reader.takeLeb128(u64) catch unreachable; | |
| 15 | overwriteUleb(code, value -% @as(u64, @intCast(addend))); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn writeSetUleb(code: []u8, addend: i64) void { | |
| 19 | overwriteUleb(code, @intCast(addend)); | |
| 22 | 20 | } |
| 23 | 21 | |
| 24 | fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void { | |
| 22 | fn overwriteUleb(code: []u8, addend: u64) void { | |
| 25 | 23 | var value: u64 = addend; |
| 26 | const writer = stream.writer(); | |
| 24 | var i: usize = 0; | |
| 27 | 25 | |
| 28 | 26 | while (true) { |
| 29 | const byte = stream.buffer[stream.pos]; | |
| 27 | const byte = code[i]; | |
| 30 | 28 | if (byte & 0x80 == 0) break; |
| 31 | try writer.writeByte(0x80 | @as(u8, @truncate(value & 0x7f))); | |
| 29 | code[i] = 0x80 | @as(u8, @truncate(value & 0x7f)); | |
| 30 | i += 1; | |
| 32 | 31 | value >>= 7; |
| 33 | 32 | } |
| 34 | stream.buffer[stream.pos] = @truncate(value & 0x7f); | |
| 33 | code[i] = @truncate(value & 0x7f); | |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | 36 | pub fn writeAddend( |
src/main.zig+2-2| ... | ... | @@ -4230,7 +4230,7 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { |
| 4230 | 4230 | const decl_name = zir.nullTerminatedString(zir.getDeclaration(resolved.inst).name); |
| 4231 | 4231 | |
| 4232 | 4232 | const gop = try files.getOrPut(gpa, resolved.file); |
| 4233 | if (!gop.found_existing) try file_name_bytes.writer(gpa).print("{f}\x00", .{file.path.fmt(comp)}); | |
| 4233 | if (!gop.found_existing) try file_name_bytes.print(gpa, "{f}\x00", .{file.path.fmt(comp)}); | |
| 4234 | 4234 | |
| 4235 | 4235 | const codegen_ns = tr.decl_codegen_ns.get(tracked_inst) orelse 0; |
| 4236 | 4236 | const link_ns = tr.decl_link_ns.get(tracked_inst) orelse 0; |
| ... | ... | @@ -7451,7 +7451,7 @@ const Templates = struct { |
| 7451 | 7451 | i += "_NAME".len; |
| 7452 | 7452 | continue; |
| 7453 | 7453 | } else if (std.mem.startsWith(u8, contents[i + 1 ..], "FINGERPRINT")) { |
| 7454 | try templates.buffer.writer().print("0x{x}", .{fingerprint.int()}); | |
| 7454 | try templates.buffer.print("0x{x}", .{fingerprint.int()}); | |
| 7455 | 7455 | i += "_FINGERPRINT".len; |
| 7456 | 7456 | continue; |
| 7457 | 7457 | } else if (std.mem.startsWith(u8, contents[i + 1 ..], "ZIGVER")) { |
test/behavior/packed-struct.zig-11| ... | ... | @@ -1075,17 +1075,6 @@ test "assigning packed struct inside another packed struct" { |
| 1075 | 1075 | try expect(S.mem.padding == 0); |
| 1076 | 1076 | } |
| 1077 | 1077 | |
| 1078 | test "packed struct used as part of anon decl name" { | |
| 1079 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1080 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | |
| 1081 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | |
| 1082 | ||
| 1083 | const S = packed struct { a: u0 = 0 }; | |
| 1084 | var a: u8 = 0; | |
| 1085 | _ = &a; | |
| 1086 | try std.io.null_writer.print("\n{} {}\n", .{ a, S{} }); | |
| 1087 | } | |
| 1088 | ||
| 1089 | 1078 | test "packed struct acts as a namespace" { |
| 1090 | 1079 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1091 | 1080 |
test/behavior/var_args.zig+21-14| ... | ... | @@ -200,35 +200,42 @@ test "variadic functions" { |
| 200 | 200 | if (builtin.cpu.arch.isSPARC() and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23718 |
| 201 | 201 | |
| 202 | 202 | const S = struct { |
| 203 | fn printf(list_ptr: *std.array_list.Managed(u8), format: [*:0]const u8, ...) callconv(.c) void { | |
| 203 | fn printf(buffer: [*]u8, format: [*:0]const u8, ...) callconv(.c) void { | |
| 204 | 204 | var ap = @cVaStart(); |
| 205 | 205 | defer @cVaEnd(&ap); |
| 206 | vprintf(list_ptr, format, &ap); | |
| 206 | vprintf(buffer, format, &ap); | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | fn vprintf( | |
| 210 | list: *std.array_list.Managed(u8), | |
| 211 | format: [*:0]const u8, | |
| 212 | ap: *std.builtin.VaList, | |
| 213 | ) callconv(.c) void { | |
| 214 | for (std.mem.span(format)) |c| switch (c) { | |
| 209 | fn vprintf(buffer: [*]u8, format: [*:0]const u8, ap: *std.builtin.VaList) callconv(.c) void { | |
| 210 | var i: usize = 0; | |
| 211 | for (format[0..3]) |byte| switch (byte) { | |
| 215 | 212 | 's' => { |
| 216 | 213 | const arg = @cVaArg(ap, [*:0]const u8); |
| 217 | list.writer().print("{s}", .{arg}) catch return; | |
| 214 | buffer[i..][0..5].* = arg[0..5].*; | |
| 215 | i += 5; | |
| 218 | 216 | }, |
| 219 | 217 | 'd' => { |
| 220 | 218 | const arg = @cVaArg(ap, c_int); |
| 221 | list.writer().print("{d}", .{arg}) catch return; | |
| 219 | switch (arg) { | |
| 220 | 1 => { | |
| 221 | buffer[i] = '1'; | |
| 222 | i += 1; | |
| 223 | }, | |
| 224 | 5 => { | |
| 225 | buffer[i] = '5'; | |
| 226 | i += 1; | |
| 227 | }, | |
| 228 | else => unreachable, | |
| 229 | } | |
| 222 | 230 | }, |
| 223 | 231 | else => unreachable, |
| 224 | 232 | }; |
| 225 | 233 | } |
| 226 | 234 | }; |
| 227 | 235 | |
| 228 | var list = std.array_list.Managed(u8).init(std.testing.allocator); | |
| 229 | defer list.deinit(); | |
| 230 | S.printf(&list, "dsd", @as(c_int, 1), @as([*:0]const u8, "hello"), @as(c_int, 5)); | |
| 231 | try std.testing.expectEqualStrings("1hello5", list.items); | |
| 236 | var buffer: [7]u8 = undefined; | |
| 237 | S.printf(&buffer, "dsd", @as(c_int, 1), @as([*:0]const u8, "hello"), @as(c_int, 5)); | |
| 238 | try expect(std.mem.eql(u8, &buffer, "1hello5")); | |
| 232 | 239 | } |
| 233 | 240 | |
| 234 | 241 | test "copy VaList" { |
test/standalone/run_output_paths/create_file.zig+2-1| ... | ... | @@ -10,7 +10,8 @@ pub fn main() !void { |
| 10 | 10 | dir_name, .{}); |
| 11 | 11 | const file_name = args.next().?; |
| 12 | 12 | const file = try dir.createFile(file_name, .{}); |
| 13 | try file.deprecatedWriter().print( | |
| 13 | var file_writer = file.writer(&.{}); | |
| 14 | try file_writer.interface.print( | |
| 14 | 15 | \\{s} |
| 15 | 16 | \\{s} |
| 16 | 17 | \\Hello, world! |
tools/docgen.zig+21-21| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const io = std.io; | |
| 4 | 3 | const fs = std.fs; |
| 5 | 4 | const process = std.process; |
| 6 | 5 | const Progress = std.Progress; |
| ... | ... | @@ -8,8 +7,10 @@ const print = std.debug.print; |
| 8 | 7 | const mem = std.mem; |
| 9 | 8 | const testing = std.testing; |
| 10 | 9 | const Allocator = std.mem.Allocator; |
| 10 | const ArrayList = std.ArrayList; | |
| 11 | 11 | const getExternalExecutor = std.zig.system.getExternalExecutor; |
| 12 | 12 | const fatal = std.process.fatal; |
| 13 | const Writer = std.Io.Writer; | |
| 13 | 14 | |
| 14 | 15 | const max_doc_file_size = 10 * 1024 * 1024; |
| 15 | 16 | |
| ... | ... | @@ -344,10 +345,10 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 344 | 345 | var last_action: Action = .open; |
| 345 | 346 | var last_columns: ?u8 = null; |
| 346 | 347 | |
| 347 | var toc_buf = std.array_list.Managed(u8).init(allocator); | |
| 348 | var toc_buf: Writer.Allocating = .init(allocator); | |
| 348 | 349 | defer toc_buf.deinit(); |
| 349 | 350 | |
| 350 | var toc = toc_buf.writer(); | |
| 351 | const toc = &toc_buf.writer; | |
| 351 | 352 | |
| 352 | 353 | var nodes = std.array_list.Managed(Node).init(allocator); |
| 353 | 354 | defer nodes.deinit(); |
| ... | ... | @@ -422,7 +423,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 422 | 423 | } |
| 423 | 424 | if (last_action == .open) { |
| 424 | 425 | try toc.writeByte('\n'); |
| 425 | try toc.writeByteNTimes(' ', header_stack_size * 4); | |
| 426 | try toc.splatByteAll(' ', header_stack_size * 4); | |
| 426 | 427 | if (last_columns) |n| { |
| 427 | 428 | try toc.print("<ul style=\"columns: {d}\">\n", .{n}); |
| 428 | 429 | } else { |
| ... | ... | @@ -432,7 +433,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 432 | 433 | last_action = .open; |
| 433 | 434 | } |
| 434 | 435 | last_columns = columns; |
| 435 | try toc.writeByteNTimes(' ', 4 + header_stack_size * 4); | |
| 436 | try toc.splatByteAll(' ', 4 + header_stack_size * 4); | |
| 436 | 437 | try toc.print("<li><a id=\"toc-{s}\" href=\"#{s}\">{s}</a>", .{ urlized, urlized, content }); |
| 437 | 438 | } else if (mem.eql(u8, tag_name, "header_close")) { |
| 438 | 439 | if (header_stack_size == 0) { |
| ... | ... | @@ -442,7 +443,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 442 | 443 | _ = try eatToken(tokenizer, .bracket_close); |
| 443 | 444 | |
| 444 | 445 | if (last_action == .close) { |
| 445 | try toc.writeByteNTimes(' ', 8 + header_stack_size * 4); | |
| 446 | try toc.splatByteAll(' ', 8 + header_stack_size * 4); | |
| 446 | 447 | try toc.writeAll("</ul></li>\n"); |
| 447 | 448 | } else { |
| 448 | 449 | try toc.writeAll("</li>\n"); |
| ... | ... | @@ -591,30 +592,29 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 591 | 592 | } |
| 592 | 593 | } |
| 593 | 594 | |
| 594 | return Toc{ | |
| 595 | return .{ | |
| 595 | 596 | .nodes = try nodes.toOwnedSlice(), |
| 596 | 597 | .toc = try toc_buf.toOwnedSlice(), |
| 597 | 598 | .urls = urls, |
| 598 | 599 | }; |
| 599 | 600 | } |
| 600 | 601 | |
| 601 | fn urlize(allocator: Allocator, input: []const u8) ![]u8 { | |
| 602 | var buf = std.array_list.Managed(u8).init(allocator); | |
| 603 | defer buf.deinit(); | |
| 602 | fn urlize(gpa: Allocator, input: []const u8) ![]u8 { | |
| 603 | var buf: ArrayList(u8) = .empty; | |
| 604 | defer buf.deinit(gpa); | |
| 604 | 605 | |
| 605 | const out = buf.writer(); | |
| 606 | 606 | for (input) |c| { |
| 607 | 607 | switch (c) { |
| 608 | 608 | 'a'...'z', 'A'...'Z', '_', '-', '0'...'9' => { |
| 609 | try out.writeByte(c); | |
| 609 | try buf.append(gpa, c); | |
| 610 | 610 | }, |
| 611 | 611 | ' ' => { |
| 612 | try out.writeByte('-'); | |
| 612 | try buf.append(gpa, '-'); | |
| 613 | 613 | }, |
| 614 | 614 | else => {}, |
| 615 | 615 | } |
| 616 | 616 | } |
| 617 | return try buf.toOwnedSlice(); | |
| 617 | return try buf.toOwnedSlice(gpa); | |
| 618 | 618 | } |
| 619 | 619 | |
| 620 | 620 | fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { |
| ... | ... | @@ -626,7 +626,7 @@ fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { |
| 626 | 626 | return try buf.toOwnedSlice(); |
| 627 | 627 | } |
| 628 | 628 | |
| 629 | fn writeEscaped(out: anytype, input: []const u8) !void { | |
| 629 | fn writeEscaped(out: *Writer, input: []const u8) !void { | |
| 630 | 630 | for (input) |c| { |
| 631 | 631 | try switch (c) { |
| 632 | 632 | '&' => out.writeAll("&amp;"), |
| ... | ... | @@ -662,14 +662,14 @@ fn isType(name: []const u8) bool { |
| 662 | 662 | return false; |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | fn writeEscapedLines(out: anytype, text: []const u8) !void { | |
| 665 | fn writeEscapedLines(out: *Writer, text: []const u8) !void { | |
| 666 | 666 | return writeEscaped(out, text); |
| 667 | 667 | } |
| 668 | 668 | |
| 669 | 669 | fn tokenizeAndPrintRaw( |
| 670 | 670 | allocator: Allocator, |
| 671 | 671 | docgen_tokenizer: *Tokenizer, |
| 672 | out: anytype, | |
| 672 | out: *Writer, | |
| 673 | 673 | source_token: Token, |
| 674 | 674 | raw_src: []const u8, |
| 675 | 675 | ) !void { |
| ... | ... | @@ -907,14 +907,14 @@ fn tokenizeAndPrintRaw( |
| 907 | 907 | fn tokenizeAndPrint( |
| 908 | 908 | allocator: Allocator, |
| 909 | 909 | docgen_tokenizer: *Tokenizer, |
| 910 | out: anytype, | |
| 910 | out: *Writer, | |
| 911 | 911 | source_token: Token, |
| 912 | 912 | ) !void { |
| 913 | 913 | const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end]; |
| 914 | 914 | return tokenizeAndPrintRaw(allocator, docgen_tokenizer, out, source_token, raw_src); |
| 915 | 915 | } |
| 916 | 916 | |
| 917 | fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: anytype, syntax_block: SyntaxBlock) !void { | |
| 917 | fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: *Writer, syntax_block: SyntaxBlock) !void { | |
| 918 | 918 | const source_type = @tagName(syntax_block.source_type); |
| 919 | 919 | |
| 920 | 920 | try out.print("<figure><figcaption class=\"{s}-cap\"><cite class=\"file\">{s}</cite></figcaption><pre>", .{ source_type, syntax_block.name }); |
| ... | ... | @@ -932,7 +932,7 @@ fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: any |
| 932 | 932 | try out.writeAll("</pre></figure>"); |
| 933 | 933 | } |
| 934 | 934 | |
| 935 | fn printShell(out: anytype, shell_content: []const u8, escape: bool) !void { | |
| 935 | fn printShell(out: *Writer, shell_content: []const u8, escape: bool) !void { | |
| 936 | 936 | const trimmed_shell_content = mem.trim(u8, shell_content, " \r\n"); |
| 937 | 937 | try out.writeAll("<figure><figcaption class=\"shell-cap\">Shell</figcaption><pre><samp>"); |
| 938 | 938 | var cmd_cont: bool = false; |
| ... | ... | @@ -984,7 +984,7 @@ fn genHtml( |
| 984 | 984 | tokenizer: *Tokenizer, |
| 985 | 985 | toc: *Toc, |
| 986 | 986 | code_dir: std.fs.Dir, |
| 987 | out: anytype, | |
| 987 | out: *Writer, | |
| 988 | 988 | ) !void { |
| 989 | 989 | for (toc.nodes) |node| { |
| 990 | 990 | switch (node) { |
tools/doctest.zig+60-64| ... | ... | @@ -7,6 +7,7 @@ const process = std.process; |
| 7 | 7 | const Allocator = std.mem.Allocator; |
| 8 | 8 | const testing = std.testing; |
| 9 | 9 | const getExternalExecutor = std.zig.system.getExternalExecutor; |
| 10 | const Writer = std.Io.Writer; | |
| 10 | 11 | |
| 11 | 12 | const max_doc_file_size = 10 * 1024 * 1024; |
| 12 | 13 | |
| ... | ... | @@ -108,7 +109,7 @@ pub fn main() !void { |
| 108 | 109 | |
| 109 | 110 | fn printOutput( |
| 110 | 111 | arena: Allocator, |
| 111 | out: anytype, | |
| 112 | out: *Writer, | |
| 112 | 113 | code: Code, |
| 113 | 114 | /// Relative to this process' cwd. |
| 114 | 115 | tmp_dir_path: []const u8, |
| ... | ... | @@ -126,9 +127,9 @@ fn printOutput( |
| 126 | 127 | const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); |
| 127 | 128 | const print = std.debug.print; |
| 128 | 129 | |
| 129 | var shell_buffer = std.array_list.Managed(u8).init(arena); | |
| 130 | var shell_buffer: std.Io.Writer.Allocating = .init(arena); | |
| 130 | 131 | defer shell_buffer.deinit(); |
| 131 | var shell_out = shell_buffer.writer(); | |
| 132 | const shell_out = &shell_buffer.writer; | |
| 132 | 133 | |
| 133 | 134 | const code_name = std.fs.path.stem(input_path); |
| 134 | 135 | |
| ... | ... | @@ -599,7 +600,7 @@ fn printOutput( |
| 599 | 600 | } |
| 600 | 601 | |
| 601 | 602 | if (!code.just_check_syntax) { |
| 602 | try printShell(out, shell_buffer.items, false); | |
| 603 | try printShell(out, shell_buffer.written(), false); | |
| 603 | 604 | } |
| 604 | 605 | } |
| 605 | 606 | |
| ... | ... | @@ -610,7 +611,7 @@ fn dumpArgs(args: []const []const u8) void { |
| 610 | 611 | std.debug.print("\n", .{}); |
| 611 | 612 | } |
| 612 | 613 | |
| 613 | fn printSourceBlock(arena: Allocator, out: anytype, source_bytes: []const u8, name: []const u8) !void { | |
| 614 | fn printSourceBlock(arena: Allocator, out: *Writer, source_bytes: []const u8, name: []const u8) !void { | |
| 614 | 615 | try out.print("<figure><figcaption class=\"{s}-cap\"><cite class=\"file\">{s}</cite></figcaption><pre>", .{ |
| 615 | 616 | "zig", name, |
| 616 | 617 | }); |
| ... | ... | @@ -618,7 +619,7 @@ fn printSourceBlock(arena: Allocator, out: anytype, source_bytes: []const u8, na |
| 618 | 619 | try out.writeAll("</pre></figure>"); |
| 619 | 620 | } |
| 620 | 621 | |
| 621 | fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void { | |
| 622 | fn tokenizeAndPrint(arena: Allocator, out: *Writer, raw_src: []const u8) !void { | |
| 622 | 623 | const src_non_terminated = mem.trim(u8, raw_src, " \r\n"); |
| 623 | 624 | const src = try arena.dupeZ(u8, src_non_terminated); |
| 624 | 625 | |
| ... | ... | @@ -846,7 +847,7 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void { |
| 846 | 847 | try out.writeAll("</code>"); |
| 847 | 848 | } |
| 848 | 849 | |
| 849 | fn writeEscapedLines(out: anytype, text: []const u8) !void { | |
| 850 | fn writeEscapedLines(out: *Writer, text: []const u8) !void { | |
| 850 | 851 | return writeEscaped(out, text); |
| 851 | 852 | } |
| 852 | 853 | |
| ... | ... | @@ -974,25 +975,21 @@ fn skipPrefix(line: []const u8) []const u8 { |
| 974 | 975 | return line[3..]; |
| 975 | 976 | } |
| 976 | 977 | |
| 977 | fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { | |
| 978 | var buf = std.array_list.Managed(u8).init(allocator); | |
| 979 | defer buf.deinit(); | |
| 980 | ||
| 981 | const out = buf.writer(); | |
| 982 | try writeEscaped(out, input); | |
| 983 | return try buf.toOwnedSlice(); | |
| 978 | fn escapeHtml(gpa: Allocator, input: []const u8) ![]u8 { | |
| 979 | var allocating: Writer.Allocating = .init(gpa); | |
| 980 | defer allocating.deinit(); | |
| 981 | try writeEscaped(&allocating.writer, input); | |
| 982 | return allocating.toOwnedSlice(); | |
| 984 | 983 | } |
| 985 | 984 | |
| 986 | fn writeEscaped(out: anytype, input: []const u8) !void { | |
| 987 | for (input) |c| { | |
| 988 | try switch (c) { | |
| 989 | '&' => out.writeAll("&amp;"), | |
| 990 | '<' => out.writeAll("&lt;"), | |
| 991 | '>' => out.writeAll("&gt;"), | |
| 992 | '"' => out.writeAll("&quot;"), | |
| 993 | else => out.writeByte(c), | |
| 994 | }; | |
| 995 | } | |
| 985 | fn writeEscaped(w: *Writer, input: []const u8) !void { | |
| 986 | for (input) |c| try switch (c) { | |
| 987 | '&' => w.writeAll("&amp;"), | |
| 988 | '<' => w.writeAll("&lt;"), | |
| 989 | '>' => w.writeAll("&gt;"), | |
| 990 | '"' => w.writeAll("&quot;"), | |
| 991 | else => w.writeByte(c), | |
| 992 | }; | |
| 996 | 993 | } |
| 997 | 994 | |
| 998 | 995 | fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| ... | ... | @@ -1014,7 +1011,6 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| 1014 | 1011 | var buf = std.array_list.Managed(u8).init(allocator); |
| 1015 | 1012 | defer buf.deinit(); |
| 1016 | 1013 | |
| 1017 | var out = buf.writer(); | |
| 1018 | 1014 | var sgr_param_start_index: usize = undefined; |
| 1019 | 1015 | var sgr_num: u8 = undefined; |
| 1020 | 1016 | var sgr_color: u8 = undefined; |
| ... | ... | @@ -1037,10 +1033,10 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| 1037 | 1033 | .start => switch (c) { |
| 1038 | 1034 | '\x1b' => state = .escape, |
| 1039 | 1035 | '\n' => { |
| 1040 | try out.writeByte(c); | |
| 1036 | try buf.append(c); | |
| 1041 | 1037 | last_new_line = buf.items.len; |
| 1042 | 1038 | }, |
| 1043 | else => try out.writeByte(c), | |
| 1039 | else => try buf.append(c), | |
| 1044 | 1040 | }, |
| 1045 | 1041 | .escape => switch (c) { |
| 1046 | 1042 | '[' => state = .lbracket, |
| ... | ... | @@ -1101,16 +1097,16 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| 1101 | 1097 | 'm' => { |
| 1102 | 1098 | state = .start; |
| 1103 | 1099 | while (open_span_count != 0) : (open_span_count -= 1) { |
| 1104 | try out.writeAll("</span>"); | |
| 1100 | try buf.appendSlice("</span>"); | |
| 1105 | 1101 | } |
| 1106 | 1102 | if (sgr_num == 0) { |
| 1107 | 1103 | if (sgr_color != 0) return error.UnsupportedColor; |
| 1108 | 1104 | continue; |
| 1109 | 1105 | } |
| 1110 | 1106 | if (sgr_color != 0) { |
| 1111 | try out.print("<span class=\"sgr-{d}_{d}m\">", .{ sgr_color, sgr_num }); | |
| 1107 | try buf.print("<span class=\"sgr-{d}_{d}m\">", .{ sgr_color, sgr_num }); | |
| 1112 | 1108 | } else { |
| 1113 | try out.print("<span class=\"sgr-{d}m\">", .{sgr_num}); | |
| 1109 | try buf.print("<span class=\"sgr-{d}m\">", .{sgr_num}); | |
| 1114 | 1110 | } |
| 1115 | 1111 | open_span_count += 1; |
| 1116 | 1112 | }, |
| ... | ... | @@ -1156,7 +1152,7 @@ fn run( |
| 1156 | 1152 | return result; |
| 1157 | 1153 | } |
| 1158 | 1154 | |
| 1159 | fn printShell(out: anytype, shell_content: []const u8, escape: bool) !void { | |
| 1155 | fn printShell(out: *Writer, shell_content: []const u8, escape: bool) !void { | |
| 1160 | 1156 | const trimmed_shell_content = mem.trim(u8, shell_content, " \r\n"); |
| 1161 | 1157 | try out.writeAll("<figure><figcaption class=\"shell-cap\">Shell</figcaption><pre><samp>"); |
| 1162 | 1158 | var cmd_cont: bool = false; |
| ... | ... | @@ -1401,11 +1397,11 @@ test "printShell" { |
| 1401 | 1397 | \\</samp></pre></figure> |
| 1402 | 1398 | ; |
| 1403 | 1399 | |
| 1404 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1400 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1405 | 1401 | defer buffer.deinit(); |
| 1406 | 1402 | |
| 1407 | try printShell(buffer.writer(), shell_out, false); | |
| 1408 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1403 | try printShell(&buffer.writer, shell_out, false); | |
| 1404 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1409 | 1405 | } |
| 1410 | 1406 | { |
| 1411 | 1407 | const shell_out = |
| ... | ... | @@ -1418,11 +1414,11 @@ test "printShell" { |
| 1418 | 1414 | \\</samp></pre></figure> |
| 1419 | 1415 | ; |
| 1420 | 1416 | |
| 1421 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1417 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1422 | 1418 | defer buffer.deinit(); |
| 1423 | 1419 | |
| 1424 | try printShell(buffer.writer(), shell_out, false); | |
| 1425 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1420 | try printShell(&buffer.writer, shell_out, false); | |
| 1421 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1426 | 1422 | } |
| 1427 | 1423 | { |
| 1428 | 1424 | const shell_out = "$ zig build test.zig\r\nbuild output\r\n"; |
| ... | ... | @@ -1432,11 +1428,11 @@ test "printShell" { |
| 1432 | 1428 | \\</samp></pre></figure> |
| 1433 | 1429 | ; |
| 1434 | 1430 | |
| 1435 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1431 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1436 | 1432 | defer buffer.deinit(); |
| 1437 | 1433 | |
| 1438 | try printShell(buffer.writer(), shell_out, false); | |
| 1439 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1434 | try printShell(&buffer.writer, shell_out, false); | |
| 1435 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1440 | 1436 | } |
| 1441 | 1437 | { |
| 1442 | 1438 | const shell_out = |
| ... | ... | @@ -1451,11 +1447,11 @@ test "printShell" { |
| 1451 | 1447 | \\</samp></pre></figure> |
| 1452 | 1448 | ; |
| 1453 | 1449 | |
| 1454 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1450 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1455 | 1451 | defer buffer.deinit(); |
| 1456 | 1452 | |
| 1457 | try printShell(buffer.writer(), shell_out, false); | |
| 1458 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1453 | try printShell(&buffer.writer, shell_out, false); | |
| 1454 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1459 | 1455 | } |
| 1460 | 1456 | { |
| 1461 | 1457 | const shell_out = |
| ... | ... | @@ -1472,11 +1468,11 @@ test "printShell" { |
| 1472 | 1468 | \\</samp></pre></figure> |
| 1473 | 1469 | ; |
| 1474 | 1470 | |
| 1475 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1471 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1476 | 1472 | defer buffer.deinit(); |
| 1477 | 1473 | |
| 1478 | try printShell(buffer.writer(), shell_out, false); | |
| 1479 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1474 | try printShell(&buffer.writer, shell_out, false); | |
| 1475 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1480 | 1476 | } |
| 1481 | 1477 | { |
| 1482 | 1478 | const shell_out = |
| ... | ... | @@ -1491,11 +1487,11 @@ test "printShell" { |
| 1491 | 1487 | \\</samp></pre></figure> |
| 1492 | 1488 | ; |
| 1493 | 1489 | |
| 1494 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1490 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1495 | 1491 | defer buffer.deinit(); |
| 1496 | 1492 | |
| 1497 | try printShell(buffer.writer(), shell_out, false); | |
| 1498 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1493 | try printShell(&buffer.writer, shell_out, false); | |
| 1494 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1499 | 1495 | } |
| 1500 | 1496 | { |
| 1501 | 1497 | const shell_out = |
| ... | ... | @@ -1514,11 +1510,11 @@ test "printShell" { |
| 1514 | 1510 | \\</samp></pre></figure> |
| 1515 | 1511 | ; |
| 1516 | 1512 | |
| 1517 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1513 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1518 | 1514 | defer buffer.deinit(); |
| 1519 | 1515 | |
| 1520 | try printShell(buffer.writer(), shell_out, false); | |
| 1521 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1516 | try printShell(&buffer.writer, shell_out, false); | |
| 1517 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1522 | 1518 | } |
| 1523 | 1519 | { |
| 1524 | 1520 | // intentional space after "--build-option1 \" |
| ... | ... | @@ -1536,11 +1532,11 @@ test "printShell" { |
| 1536 | 1532 | \\</samp></pre></figure> |
| 1537 | 1533 | ; |
| 1538 | 1534 | |
| 1539 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1535 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1540 | 1536 | defer buffer.deinit(); |
| 1541 | 1537 | |
| 1542 | try printShell(buffer.writer(), shell_out, false); | |
| 1543 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1538 | try printShell(&buffer.writer, shell_out, false); | |
| 1539 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1544 | 1540 | } |
| 1545 | 1541 | { |
| 1546 | 1542 | const shell_out = |
| ... | ... | @@ -1553,11 +1549,11 @@ test "printShell" { |
| 1553 | 1549 | \\</samp></pre></figure> |
| 1554 | 1550 | ; |
| 1555 | 1551 | |
| 1556 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1552 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1557 | 1553 | defer buffer.deinit(); |
| 1558 | 1554 | |
| 1559 | try printShell(buffer.writer(), shell_out, false); | |
| 1560 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1555 | try printShell(&buffer.writer, shell_out, false); | |
| 1556 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1561 | 1557 | } |
| 1562 | 1558 | { |
| 1563 | 1559 | const shell_out = |
| ... | ... | @@ -1572,11 +1568,11 @@ test "printShell" { |
| 1572 | 1568 | \\</samp></pre></figure> |
| 1573 | 1569 | ; |
| 1574 | 1570 | |
| 1575 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1571 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1576 | 1572 | defer buffer.deinit(); |
| 1577 | 1573 | |
| 1578 | try printShell(buffer.writer(), shell_out, false); | |
| 1579 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1574 | try printShell(&buffer.writer, shell_out, false); | |
| 1575 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1580 | 1576 | } |
| 1581 | 1577 | { |
| 1582 | 1578 | const shell_out = |
| ... | ... | @@ -1587,10 +1583,10 @@ test "printShell" { |
| 1587 | 1583 | \\</samp></pre></figure> |
| 1588 | 1584 | ; |
| 1589 | 1585 | |
| 1590 | var buffer = std.array_list.Managed(u8).init(test_allocator); | |
| 1586 | var buffer: std.Io.Writer.Allocating = .init(test_allocator); | |
| 1591 | 1587 | defer buffer.deinit(); |
| 1592 | 1588 | |
| 1593 | try printShell(buffer.writer(), shell_out, false); | |
| 1594 | try testing.expectEqualSlices(u8, expected, buffer.items); | |
| 1589 | try printShell(&buffer.writer, shell_out, false); | |
| 1590 | try testing.expectEqualSlices(u8, expected, buffer.written()); | |
| 1595 | 1591 | } |
| 1596 | 1592 | } |
tools/gen_outline_atomics.zig+1-1| ... | ... | @@ -49,7 +49,7 @@ pub fn main() !void { |
| 49 | 49 | @tagName(op), n.toBytes(), @tagName(order), |
| 50 | 50 | }); |
| 51 | 51 | try writeFunction(arena, w, name, op, n, order); |
| 52 | try footer.writer().print(" @export(&{s}, .{{ .name = \"{s}\", .linkage = common.linkage, .visibility = common.visibility }});\n", .{ | |
| 52 | try footer.print(" @export(&{s}, .{{ .name = \"{s}\", .linkage = common.linkage, .visibility = common.visibility }});\n", .{ | |
| 53 | 53 | name, name, |
| 54 | 54 | }); |
| 55 | 55 | } |
tools/gen_spirv_spec.zig+8-11| ... | ... | @@ -82,13 +82,11 @@ pub fn main() !void { |
| 82 | 82 | |
| 83 | 83 | try readExtRegistry(&exts, std.fs.cwd(), args[2]); |
| 84 | 84 | |
| 85 | const output_buf = try allocator.alloc(u8, 1024 * 1024); | |
| 86 | var fbs = std.io.fixedBufferStream(output_buf); | |
| 87 | var adapter = fbs.writer().adaptToNewApi(&.{}); | |
| 88 | const w = &adapter.new_interface; | |
| 89 | try render(w, core_spec, exts.items); | |
| 90 | var output: [:0]u8 = @ptrCast(fbs.getWritten()); | |
| 91 | output[output.len] = 0; | |
| 85 | var allocating: std.Io.Writer.Allocating = .init(allocator); | |
| 86 | defer allocating.deinit(); | |
| 87 | try render(&allocating.writer, core_spec, exts.items); | |
| 88 | try allocating.writer.writeByte(0); | |
| 89 | const output = allocating.written()[0 .. allocating.written().len - 1 :0]; | |
| 92 | 90 | |
| 93 | 91 | var tree = try std.zig.Ast.parse(allocator, output, .zig); |
| 94 | 92 | var color: std.zig.Color = .on; |
| ... | ... | @@ -429,10 +427,9 @@ fn renderClass(writer: *std.io.Writer, instructions: []const Instruction) !void |
| 429 | 427 | const Formatter = struct { |
| 430 | 428 | data: []const u8, |
| 431 | 429 | |
| 432 | fn format(f: Formatter, writer: *std.io.Writer) std.io.Writer.Error!void { | |
| 430 | fn format(f: Formatter, writer: *std.Io.Writer) std.io.Writer.Error!void { | |
| 433 | 431 | var id_buf: [128]u8 = undefined; |
| 434 | var fbs = std.io.fixedBufferStream(&id_buf); | |
| 435 | const fw = fbs.writer(); | |
| 432 | var fw: std.Io.Writer = .fixed(&id_buf); | |
| 436 | 433 | for (f.data, 0..) |c, i| { |
| 437 | 434 | switch (c) { |
| 438 | 435 | '-', '_', '.', '~', ' ' => fw.writeByte('_') catch return error.WriteFailed, |
| ... | ... | @@ -452,7 +449,7 @@ const Formatter = struct { |
| 452 | 449 | } |
| 453 | 450 | |
| 454 | 451 | // make sure that this won't clobber with zig keywords |
| 455 | try writer.print("{f}", .{std.zig.fmtId(fbs.getWritten())}); | |
| 452 | try writer.print("{f}", .{std.zig.fmtId(fw.buffered())}); | |
| 456 | 453 | } |
| 457 | 454 | }; |
| 458 | 455 |
tools/migrate_langref.zig+22-18| ... | ... | @@ -382,46 +382,50 @@ fn walk(arena: Allocator, tokenizer: *Tokenizer, out_dir: std.fs.Dir, w: anytype |
| 382 | 382 | fatal("unable to create file '{s}': {s}", .{ name, @errorName(err) }); |
| 383 | 383 | }; |
| 384 | 384 | defer file.close(); |
| 385 | var file_buffer: [1024]u8 = undefined; | |
| 386 | var file_writer = file.writer(&file_buffer); | |
| 387 | const code = &file_writer.interface; | |
| 385 | 388 | |
| 386 | 389 | const source = tokenizer.buffer[source_token.start..source_token.end]; |
| 387 | try file.writeAll(std.mem.trim(u8, source[1..], " \t\r\n")); | |
| 388 | try file.writeAll("\n\n"); | |
| 390 | try code.writeAll(std.mem.trim(u8, source[1..], " \t\r\n")); | |
| 391 | try code.writeAll("\n\n"); | |
| 389 | 392 | |
| 390 | 393 | if (just_check_syntax) { |
| 391 | try file.deprecatedWriter().print("// syntax\n", .{}); | |
| 394 | try code.print("// syntax\n", .{}); | |
| 392 | 395 | } else switch (code_kind_id) { |
| 393 | .@"test" => try file.deprecatedWriter().print("// test\n", .{}), | |
| 394 | .lib => try file.deprecatedWriter().print("// lib\n", .{}), | |
| 395 | .test_error => |s| try file.deprecatedWriter().print("// test_error={s}\n", .{s}), | |
| 396 | .test_safety => |s| try file.deprecatedWriter().print("// test_safety={s}\n", .{s}), | |
| 397 | .exe => |s| try file.deprecatedWriter().print("// exe={s}\n", .{@tagName(s)}), | |
| 396 | .@"test" => try code.print("// test\n", .{}), | |
| 397 | .lib => try code.print("// lib\n", .{}), | |
| 398 | .test_error => |s| try code.print("// test_error={s}\n", .{s}), | |
| 399 | .test_safety => |s| try code.print("// test_safety={s}\n", .{s}), | |
| 400 | .exe => |s| try code.print("// exe={s}\n", .{@tagName(s)}), | |
| 398 | 401 | .obj => |opt| if (opt) |s| { |
| 399 | try file.deprecatedWriter().print("// obj={s}\n", .{s}); | |
| 402 | try code.print("// obj={s}\n", .{s}); | |
| 400 | 403 | } else { |
| 401 | try file.deprecatedWriter().print("// obj\n", .{}); | |
| 404 | try code.print("// obj\n", .{}); | |
| 402 | 405 | }, |
| 403 | 406 | } |
| 404 | 407 | |
| 405 | 408 | if (mode != .Debug) |
| 406 | try file.deprecatedWriter().print("// optimize={s}\n", .{@tagName(mode)}); | |
| 409 | try code.print("// optimize={s}\n", .{@tagName(mode)}); | |
| 407 | 410 | |
| 408 | 411 | for (link_objects.items) |link_object| { |
| 409 | try file.deprecatedWriter().print("// link_object={s}\n", .{link_object}); | |
| 412 | try code.print("// link_object={s}\n", .{link_object}); | |
| 410 | 413 | } |
| 411 | 414 | |
| 412 | 415 | if (target_str) |s| |
| 413 | try file.deprecatedWriter().print("// target={s}\n", .{s}); | |
| 416 | try code.print("// target={s}\n", .{s}); | |
| 414 | 417 | |
| 415 | if (link_libc) try file.deprecatedWriter().print("// link_libc\n", .{}); | |
| 416 | if (disable_cache) try file.deprecatedWriter().print("// disable_cache\n", .{}); | |
| 417 | if (verbose_cimport) try file.deprecatedWriter().print("// verbose_cimport\n", .{}); | |
| 418 | if (link_libc) try code.print("// link_libc\n", .{}); | |
| 419 | if (disable_cache) try code.print("// disable_cache\n", .{}); | |
| 420 | if (verbose_cimport) try code.print("// verbose_cimport\n", .{}); | |
| 418 | 421 | |
| 419 | 422 | if (link_mode) |m| |
| 420 | try file.deprecatedWriter().print("// link_mode={s}\n", .{@tagName(m)}); | |
| 423 | try code.print("// link_mode={s}\n", .{@tagName(m)}); | |
| 421 | 424 | |
| 422 | 425 | for (additional_options.items) |o| { |
| 423 | try file.deprecatedWriter().print("// additional_option={s}\n", .{o}); | |
| 426 | try code.print("// additional_option={s}\n", .{o}); | |
| 424 | 427 | } |
| 428 | try code.flush(); | |
| 425 | 429 | try w.print("{{#code|{s}#}}\n", .{basename}); |
| 426 | 430 | } else { |
| 427 | 431 | const close_bracket = while (true) { |
tools/update_crc_catalog.zig+2-3| ... | ... | @@ -88,10 +88,9 @@ pub fn main() anyerror!void { |
| 88 | 88 | \\ |
| 89 | 89 | ); |
| 90 | 90 | |
| 91 | var stream = std.io.fixedBufferStream(catalog_txt); | |
| 92 | const reader = stream.reader(); | |
| 91 | var reader: std.Io.Reader = .fixed(catalog_txt); | |
| 93 | 92 | |
| 94 | while (try reader.readUntilDelimiterOrEofAlloc(arena, '\n', std.math.maxInt(usize))) |line| { | |
| 93 | while (try reader.takeDelimiter('\n')) |line| { | |
| 95 | 94 | if (line.len == 0 or line[0] == '#') |
| 96 | 95 | continue; |
| 97 | 96 |