authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-02 17:18:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 22:43:52-07:00
log494819be91be1a320c269207f9bd55a1bc09c60b
treeae2c376087b1d9046629f049a53effa913620142
parent6963a1c7b97e459be0a5f3ca913ffa0862a099a8

cbe: reapply writer changes


2 files changed, 658 insertions(+), 617 deletions(-)

src/codegen/c.zig+486-461
......@@ -56,6 +56,7 @@ pub const Mir = struct {
5656 /// less than the natural alignment.
5757 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
5858 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.
59 code_header: []u8,
5960 code: []u8,
6061 fwd_decl: []u8,
6162 ctype_pool: CType.Pool,
......@@ -63,6 +64,7 @@ pub const Mir = struct {
6364
6465 pub fn deinit(mir: *Mir, gpa: Allocator) void {
6566 mir.uavs.deinit(gpa);
67 gpa.free(mir.code_header);
6668 gpa.free(mir.code);
6769 gpa.free(mir.fwd_decl);
6870 mir.ctype_pool.deinit(gpa);
......@@ -70,6 +72,8 @@ pub const Mir = struct {
7072 }
7173};
7274
75pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};
76
7377pub const CType = @import("c/Type.zig");
7478
7579pub const CValue = union(enum) {
......@@ -449,18 +453,18 @@ pub const Function = struct {
449453 const ty = f.typeOf(ref);
450454
451455 const result: CValue = if (lowersToArray(ty, pt)) result: {
452 const w = f.object.codeHeaderWriter();
456 const ch = &f.object.code_header.writer;
453457 const decl_c_value = try f.allocLocalValue(.{
454458 .ctype = try f.ctypeFromType(ty, .complete),
455459 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),
456460 });
457461 const gpa = f.object.dg.gpa;
458462 try f.allocs.put(gpa, decl_c_value.new_local, false);
459 try w.writeAll("static ");
460 try f.object.dg.renderTypeAndName(w, ty, decl_c_value, Const, .none, .complete);
461 try w.writeAll(" = ");
462 try f.object.dg.renderValue(w, val, .StaticInitializer);
463 try w.writeAll(";\n ");
463 try ch.writeAll("static ");
464 try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete);
465 try ch.writeAll(" = ");
466 try f.object.dg.renderValue(ch, val, .StaticInitializer);
467 try ch.writeAll(";\n ");
464468 break :result .{ .local = decl_c_value.new_local };
465469 } else .{ .constant = val };
466470
......@@ -550,7 +554,7 @@ pub const Function = struct {
550554 w: *Writer,
551555 c_value: CValue,
552556 member: CValue,
553 ) error{ OutOfMemory, AnalysisFail }!void {
557 ) Error!void {
554558 switch (c_value) {
555559 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {
556560 try f.writeCValue(w, c_value, .Other);
......@@ -581,7 +585,7 @@ pub const Function = struct {
581585 try f.writeCValue(w, member, .Other);
582586 }
583587
584 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
588 fn fail(f: *Function, comptime format: []const u8, args: anytype) Error {
585589 return f.object.dg.fail(format, args);
586590 }
587591
......@@ -672,7 +676,7 @@ pub const Function = struct {
672676 },
673677 else => {},
674678 }
675 const w = f.object.writer();
679 const w = &f.object.code.writer;
676680 const a = try Assignment.start(f, w, ctype);
677681 try f.writeCValue(w, dst, .Other);
678682 try a.assign(f, w);
......@@ -706,18 +710,32 @@ pub const Function = struct {
706710/// It is not available when generating .h file.
707711pub const Object = struct {
708712 dg: DeclGen,
709 /// This is a borrowed reference from `link.C`.
710 code: std.ArrayList(u8),
711 /// Goes before code. Initialized and deinitialized in `genFunc`.
712 code_header: std.ArrayList(u8) = undefined,
713 indent_writer: IndentWriter(std.ArrayList(u8).Writer),
714
715 fn w(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {
716 return o.indent_writer.writer();
717 }
718
719 fn codeHeaderWriter(o: *Object) ArrayListWriter {
720 return arrayListWriter(&o.code_header);
713 code_header: std.io.Writer.Allocating,
714 code: std.io.Writer.Allocating,
715 indent_counter: usize,
716
717 const indent_width = 1;
718 const indent_char = ' ';
719
720 fn newline(o: *Object) !void {
721 const w = &o.code.writer;
722 try w.writeByte('\n');
723 try w.splatByteAll(indent_char, o.indent_counter);
724 }
725 fn indent(o: *Object) void {
726 o.indent_counter += indent_width;
727 }
728 fn outdent(o: *Object) !void {
729 o.indent_counter -= indent_width;
730 const written = o.code.getWritten();
731 switch (written[written.len - 1]) {
732 indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width),
733 '\n' => try o.code.writer.splatByteAll(indent_char, o.indent_counter),
734 else => {
735 std.debug.print("\"{f}\"\n", .{std.zig.fmtEscapes(written[written.len -| 100..])});
736 unreachable;
737 },
738 }
721739 }
722740};
723741
......@@ -729,8 +747,7 @@ pub const DeclGen = struct {
729747 pass: Pass,
730748 is_naked_fn: bool,
731749 expected_block: ?u32,
732 /// This is a borrowed reference from `link.C`.
733 fwd_decl: std.ArrayList(u8),
750 fwd_decl: std.io.Writer.Allocating,
734751 error_msg: ?*Zcu.ErrorMsg,
735752 ctype_pool: CType.Pool,
736753 scratch: std.ArrayListUnmanaged(u32),
......@@ -747,11 +764,7 @@ pub const DeclGen = struct {
747764 flush,
748765 };
749766
750 fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter {
751 return arrayListWriter(&dg.fwd_decl);
752 }
753
754 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
767 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
755768 @branchHint(.cold);
756769 const zcu = dg.pt.zcu;
757770 const src_loc = zcu.navSrcLoc(dg.pass.nav);
......@@ -764,7 +777,7 @@ pub const DeclGen = struct {
764777 w: *Writer,
765778 uav: InternPool.Key.Ptr.BaseAddr.Uav,
766779 location: ValueRenderLocation,
767 ) error{ OutOfMemory, AnalysisFail }!void {
780 ) Error!void {
768781 const pt = dg.pt;
769782 const zcu = pt.zcu;
770783 const ip = &zcu.intern_pool;
......@@ -826,7 +839,7 @@ pub const DeclGen = struct {
826839 w: *Writer,
827840 nav_index: InternPool.Nav.Index,
828841 location: ValueRenderLocation,
829 ) error{ OutOfMemory, AnalysisFail }!void {
842 ) Error!void {
830843 _ = location;
831844 const pt = dg.pt;
832845 const zcu = pt.zcu;
......@@ -875,7 +888,7 @@ pub const DeclGen = struct {
875888 w: *Writer,
876889 derivation: Value.PointerDeriveStep,
877890 location: ValueRenderLocation,
878 ) error{ OutOfMemory, AnalysisFail }!void {
891 ) Error!void {
879892 const pt = dg.pt;
880893 const zcu = pt.zcu;
881894 switch (derivation) {
......@@ -977,8 +990,7 @@ pub const DeclGen = struct {
977990 }
978991
979992 fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void {
980 const ip = &dg.pt.zcu.intern_pool;
981 try w.print("zig_error_{}", .{fmtIdentUnsolo(err_name.toSlice(ip))});
993 try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))});
982994 }
983995
984996 fn renderValue(
......@@ -986,7 +998,7 @@ pub const DeclGen = struct {
986998 w: *Writer,
987999 val: Value,
9881000 location: ValueRenderLocation,
989 ) error{ OutOfMemory, AnalysisFail }!void {
1001 ) Error!void {
9901002 const pt = dg.pt;
9911003 const zcu = pt.zcu;
9921004 const ip = &zcu.intern_pool;
......@@ -1056,7 +1068,7 @@ pub const DeclGen = struct {
10561068 .error_union => |error_union| switch (ctype.info(ctype_pool)) {
10571069 .basic => switch (error_union.val) {
10581070 .err_name => |err_name| try dg.renderErrorName(w, err_name),
1059 .payload => try w.writeAll("0"),
1071 .payload => try w.writeByte('0'),
10601072 },
10611073 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
10621074 .aggregate => |aggregate| {
......@@ -1212,7 +1224,7 @@ pub const DeclGen = struct {
12121224 .none => "true",
12131225 else => "false",
12141226 }) else switch (opt.val) {
1215 .none => try w.writeAll("0"),
1227 .none => try w.writeByte('0'),
12161228 else => |payload| switch (ip.indexToKey(payload)) {
12171229 .undef => |err_ty| try dg.renderUndefValue(
12181230 w,
......@@ -1543,7 +1555,7 @@ pub const DeclGen = struct {
15431555 try w.writeByte(')');
15441556 }
15451557 try dg.renderValue(w, Value.fromInterned(un.val), location);
1546 } else try w.writeAll("0");
1558 } else try w.writeByte('0');
15471559 return;
15481560 }
15491561
......@@ -1595,7 +1607,7 @@ pub const DeclGen = struct {
15951607 w: *Writer,
15961608 ty: Type,
15971609 location: ValueRenderLocation,
1598 ) error{ OutOfMemory, AnalysisFail }!void {
1610 ) Error!void {
15991611 const pt = dg.pt;
16001612 const zcu = pt.zcu;
16011613 const ip = &zcu.intern_pool;
......@@ -1938,11 +1950,11 @@ pub const DeclGen = struct {
19381950 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});
19391951
19401952 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
1941 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
1953 try w.print("{f}zig_callconv({s})", .{ trailing, call_conv });
19421954 trailing = .maybe_space;
19431955 }
19441956
1945 try w.print("{}", .{trailing});
1957 try w.print("{f}", .{trailing});
19461958 switch (name) {
19471959 .nav => |nav| try dg.renderNavName(w, nav),
19481960 .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}),
......@@ -2016,11 +2028,11 @@ pub const DeclGen = struct {
20162028 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
20172029 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
20182030 ///
2019 fn renderType(dg: *DeclGen, w: *Writer, t: Type) error{OutOfMemory}!void {
2031 fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void {
20202032 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));
20212033 }
20222034
2023 fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) error{OutOfMemory}!void {
2035 fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void {
20242036 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
20252037 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
20262038 }
......@@ -2171,7 +2183,7 @@ pub const DeclGen = struct {
21712183 qualifiers: CQualifiers,
21722184 alignment: Alignment,
21732185 kind: CType.Kind,
2174 ) error{ OutOfMemory, AnalysisFail }!void {
2186 ) !void {
21752187 try dg.renderCTypeAndName(
21762188 w,
21772189 try dg.ctypeFromType(ty, kind),
......@@ -2191,7 +2203,7 @@ pub const DeclGen = struct {
21912203 name: CValue,
21922204 qualifiers: CQualifiers,
21932205 alignas: CType.AlignAs,
2194 ) error{ OutOfMemory, AnalysisFail }!void {
2206 ) !void {
21952207 const zcu = dg.pt.zcu;
21962208 switch (alignas.abiOrder()) {
21972209 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
......@@ -2199,7 +2211,7 @@ pub const DeclGen = struct {
21992211 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
22002212 }
22012213
2202 try w.print("{}", .{
2214 try w.print("{f}", .{
22032215 try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),
22042216 });
22052217 try dg.writeName(w, name);
......@@ -2216,7 +2228,7 @@ pub const DeclGen = struct {
22162228 }
22172229 }
22182230
2219 fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
2231 fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void {
22202232 switch (c_value) {
22212233 .none, .new_local, .local, .local_ref => unreachable,
22222234 .constant => |uav| try renderUavName(w, uav),
......@@ -2271,13 +2283,18 @@ pub const DeclGen = struct {
22712283 w: *Writer,
22722284 c_value: CValue,
22732285 member: CValue,
2274 ) error{ OutOfMemory, AnalysisFail }!void {
2286 ) Error!void {
22752287 try dg.writeCValue(w, c_value);
22762288 try w.writeByte('.');
22772289 try dg.writeCValue(w, member);
22782290 }
22792291
2280 fn writeCValueDerefMember(dg: *DeclGen, w: *Writer, c_value: CValue, member: CValue) !void {
2292 fn writeCValueDerefMember(
2293 dg: *DeclGen,
2294 w: *Writer,
2295 c_value: CValue,
2296 member: CValue,
2297 ) !void {
22812298 switch (c_value) {
22822299 .none,
22832300 .new_local,
......@@ -2315,7 +2332,7 @@ pub const DeclGen = struct {
23152332 const zcu = dg.pt.zcu;
23162333 const ip = &zcu.intern_pool;
23172334 const nav = ip.getNav(nav_index);
2318 const fwd = dg.fwdDeclWriter();
2335 const fwd = &dg.fwd_decl.writer;
23192336 try fwd.writeAll(switch (flags.linkage) {
23202337 .internal => "static ",
23212338 .strong, .weak, .link_once => "zig_extern ",
......@@ -2353,7 +2370,7 @@ pub const DeclGen = struct {
23532370 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
23542371 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
23552372 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
2356 try w.print("{}__{d}", .{
2373 try w.print("{f}__{d}", .{
23572374 fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]),
23582375 @intFromEnum(nav_index),
23592376 });
......@@ -2484,7 +2501,7 @@ fn renderFwdDeclTypeName(
24842501 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });
24852502 switch (fwd_decl.name) {
24862503 .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),
2487 .index => |index| try w.print("{}__{d}", .{
2504 .index => |index| try w.print("{f}__{d}", .{
24882505 fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),
24892506 @intFromEnum(index),
24902507 }),
......@@ -2498,13 +2515,13 @@ fn renderTypePrefix(
24982515 ctype: CType,
24992516 parent_fix: CTypeFix,
25002517 qualifiers: CQualifiers,
2501) @TypeOf(w).Error!RenderCTypeTrailing {
2518) Writer.Error!RenderCTypeTrailing {
25022519 var trailing = RenderCTypeTrailing.maybe_space;
25032520 switch (ctype.info(ctype_pool)) {
25042521 .basic => |basic_info| try w.writeAll(@tagName(basic_info)),
25052522
25062523 .pointer => |pointer_info| {
2507 try w.print("{}*", .{try renderTypePrefix(
2524 try w.print("{f}*", .{try renderTypePrefix(
25082525 pass,
25092526 ctype_pool,
25102527 zcu,
......@@ -2541,7 +2558,7 @@ fn renderTypePrefix(
25412558 );
25422559 switch (parent_fix) {
25432560 .prefix => {
2544 try w.print("{}(", .{child_trailing});
2561 try w.print("{f}(", .{child_trailing});
25452562 return .no_space;
25462563 },
25472564 .suffix => return child_trailing,
......@@ -2593,7 +2610,7 @@ fn renderTypePrefix(
25932610 );
25942611 switch (parent_fix) {
25952612 .prefix => {
2596 try w.print("{}(", .{child_trailing});
2613 try w.print("{f}(", .{child_trailing});
25972614 return .no_space;
25982615 },
25992616 .suffix => return child_trailing,
......@@ -2602,7 +2619,7 @@ fn renderTypePrefix(
26022619 }
26032620 var qualifier_it = qualifiers.iterator();
26042621 while (qualifier_it.next()) |qualifier| {
2605 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });
2622 try w.print("{f}{s}", .{ trailing, @tagName(qualifier) });
26062623 trailing = .maybe_space;
26072624 }
26082625 return trailing;
......@@ -2615,7 +2632,7 @@ fn renderTypeSuffix(
26152632 ctype: CType,
26162633 parent_fix: CTypeFix,
26172634 qualifiers: CQualifiers,
2618) @TypeOf(w).Error!void {
2635) Writer.Error!void {
26192636 switch (ctype.info(ctype_pool)) {
26202637 .basic, .aligned, .fwd_decl, .aggregate => {},
26212638 .pointer => |pointer_info| try renderTypeSuffix(
......@@ -2650,7 +2667,7 @@ fn renderTypeSuffix(
26502667 need_comma = true;
26512668 const trailing =
26522669 try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);
2653 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index });
2670 if (qualifiers.contains(.@"const")) try w.print("{f}a{d}", .{ trailing, param_index });
26542671 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});
26552672 }
26562673 if (function_info.varargs) {
......@@ -2675,7 +2692,7 @@ fn renderFields(
26752692 try w.writeAll("{\n");
26762693 for (0..aggregate_info.fields.len) |field_index| {
26772694 const field_info = aggregate_info.fields.at(field_index, ctype_pool);
2678 try w.writeByteNTimes(' ', indent + 1);
2695 try w.splatByteAll(' ', indent + 1);
26792696 switch (field_info.alignas.abiOrder()) {
26802697 .lt => {
26812698 std.debug.assert(aggregate_info.@"packed");
......@@ -2699,11 +2716,11 @@ fn renderFields(
26992716 .suffix,
27002717 .{},
27012718 );
2702 try w.print("{}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });
2719 try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });
27032720 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});
27042721 try w.writeAll(";\n");
27052722 }
2706 try w.writeByteNTimes(' ', indent);
2723 try w.splatByteAll(' ', indent);
27072724 try w.writeByte('}');
27082725}
27092726
......@@ -2723,7 +2740,7 @@ pub fn genTypeDecl(
27232740 if (!found_existing) {
27242741 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
27252742 try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
2726 try w.print("{}", .{try renderTypePrefix(
2743 try w.print("{f}", .{try renderTypePrefix(
27272744 .flush,
27282745 global_ctype_pool,
27292746 zcu,
......@@ -2764,7 +2781,7 @@ pub fn genTypeDecl(
27642781 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
27652782 try w.writeByte(';');
27662783 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);
2767 if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {} */", .{
2784 if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {f} */", .{
27682785 ty.containerTypeName(ip).fmt(ip),
27692786 });
27702787 try w.writeByte('\n');
......@@ -2795,18 +2812,19 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
27952812 }
27962813}
27972814
2798pub fn genErrDecls(o: *Object) !void {
2815pub fn genErrDecls(o: *Object) Error!void {
27992816 const pt = o.dg.pt;
28002817 const zcu = pt.zcu;
28012818 const ip = &zcu.intern_pool;
2802 const w = o.writer();
2819 const w = &o.code.writer;
28032820
28042821 var max_name_len: usize = 0;
28052822 // do not generate an invalid empty enum when the global error set is empty
28062823 const names = ip.global_error_set.getNamesFromMainThread();
28072824 if (names.len > 0) {
2808 try w.writeAll("enum {\n");
2809 o.indent_writer.pushIndent();
2825 try w.writeAll("enum {");
2826 o.indent();
2827 try o.newline();
28102828 for (names, 1..) |name_nts, value| {
28112829 const name = name_nts.toSlice(ip);
28122830 max_name_len = @max(name.len, max_name_len);
......@@ -2815,10 +2833,12 @@ pub fn genErrDecls(o: *Object) !void {
28152833 .name = name_nts,
28162834 } });
28172835 try o.dg.renderValue(w, Value.fromInterned(err_val), .Other);
2818 try w.print(" = {d}u,\n", .{value});
2836 try w.print(" = {d}u,", .{value});
2837 try o.newline();
28192838 }
2820 o.indent_writer.popIndent();
2821 try w.writeAll("};\n");
2839 try o.outdent();
2840 try w.writeAll("};");
2841 try o.newline();
28222842 }
28232843 const array_identifier = "zig_errorName";
28242844 const name_prefix = array_identifier ++ "_";
......@@ -2852,7 +2872,8 @@ pub fn genErrDecls(o: *Object) !void {
28522872 );
28532873 try w.writeAll(" = ");
28542874 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
2855 try w.writeAll(";\n");
2875 try w.writeByte(';');
2876 try o.newline();
28562877 }
28572878
28582879 const name_array_ty = try pt.arrayType(.{
......@@ -2878,15 +2899,16 @@ pub fn genErrDecls(o: *Object) !void {
28782899 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer),
28792900 });
28802901 }
2881 try w.writeAll("};\n");
2902 try w.writeAll("};");
2903 try o.newline();
28822904}
28832905
2884pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
2906pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void {
28852907 const pt = o.dg.pt;
28862908 const zcu = pt.zcu;
28872909 const ip = &zcu.intern_pool;
28882910 const ctype_pool = &o.dg.ctype_pool;
2889 const w = o.writer();
2911 const w = &o.code.writer;
28902912 const key = lazy_fn.key_ptr.*;
28912913 const val = lazy_fn.value_ptr;
28922914 switch (key) {
......@@ -2896,9 +2918,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28962918
28972919 try w.writeAll("static ");
28982920 try o.dg.renderType(w, name_slice_ty);
2899 try w.print(" {}(", .{val.fn_name.fmt(lazy_ctype_pool)});
2921 try w.print(" {f}(", .{val.fn_name.fmt(lazy_ctype_pool)});
29002922 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
2901 try w.writeAll(") {\n switch (tag) {\n");
2923 try w.writeAll(") {");
2924 o.indent();
2925 try o.newline();
2926 try w.writeAll("switch (tag) {");
2927 o.indent();
2928 try o.newline();
29022929 const tag_names = enum_ty.enumFields(zcu);
29032930 for (0..tag_names.len) |tag_index| {
29042931 const tag_name = tag_names.get(ip)[tag_index];
......@@ -2915,26 +2942,35 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
29152942 .storage = .{ .bytes = tag_name.toString() },
29162943 } });
29172944
2918 try w.print(" case {f}: {{\n static ", .{
2945 try w.print("case {f}: {{", .{
29192946 try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other),
29202947 });
2948 o.indent();
2949 try o.newline();
2950 try w.writeAll("static ");
29212951 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
29222952 try w.writeAll(" = ");
29232953 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
2924 try w.writeAll(";\n return (");
2954 try w.writeByte(';');
2955 try o.newline();
2956 try w.writeAll("return (");
29252957 try o.dg.renderType(w, name_slice_ty);
2926 try w.print("){{{f}, {f}}};\n", .{
2958 try w.print("){{{f}, {f}}};", .{
29272959 fmtIdentUnsolo("name"),
29282960 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other),
29292961 });
2930
2931 try w.writeAll(" }\n");
2962 try o.newline();
2963 try o.outdent();
2964 try w.writeByte('}');
2965 try o.newline();
29322966 }
2933 try w.writeAll(" }\n while (");
2934 try o.dg.renderValue(w, Value.true, .Other);
2935 try w.writeAll(") ");
2936 _ = try airBreakpoint(w);
2937 try w.writeAll("}\n");
2967 try o.outdent();
2968 try w.writeByte('}');
2969 try o.newline();
2970 try airUnreach(o);
2971 try o.outdent();
2972 try w.writeByte('}');
2973 try o.newline();
29382974 },
29392975 .never_tail, .never_inline => |fn_nav_index| {
29402976 const fn_val = zcu.navValue(fn_nav_index);
......@@ -2942,7 +2978,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
29422978 const fn_info = fn_ctype.info(ctype_pool).function;
29432979 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true);
29442980
2945 const fwd = o.dg.fwdDeclWriter();
2981 const fwd = &o.dg.fwd_decl.writer;
29462982 try fwd.print("static zig_{s} ", .{@tagName(key)});
29472983 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
29482984 .fmt_ctype_pool_string = fn_name,
......@@ -2953,14 +2989,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
29532989 try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{
29542990 .fmt_ctype_pool_string = fn_name,
29552991 });
2956 try w.writeAll(" {\n return ");
2992 try w.writeAll(" {");
2993 o.indent();
2994 try o.newline();
2995 try w.writeAll("return ");
29572996 try o.dg.renderNavName(w, fn_nav_index);
29582997 try w.writeByte('(');
29592998 for (0..fn_info.param_ctypes.len) |arg| {
29602999 if (arg > 0) try w.writeAll(", ");
29613000 try w.print("a{d}", .{arg});
29623001 }
2963 try w.writeAll(");\n}\n");
3002 try w.writeAll(");");
3003 try o.newline();
3004 try o.outdent();
3005 try w.writeByte('}');
3006 try o.newline();
29643007 },
29653008 }
29663009}
......@@ -2995,18 +3038,20 @@ pub fn generate(
29953038 .pass = .{ .nav = func.owner_nav },
29963039 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
29973040 .expected_block = null,
2998 .fwd_decl = .init(gpa),
3041 .fwd_decl = undefined,
29993042 .ctype_pool = .empty,
30003043 .scratch = .empty,
30013044 .uavs = .empty,
30023045 },
3003 .code = .init(gpa),
3004 .indent_writer = undefined, // set later so we can get a pointer to object.code
3046 .code_header = undefined,
3047 .code = undefined,
3048 .indent_counter = 0,
30053049 },
30063050 .lazy_fns = .empty,
30073051 };
30083052 defer {
3009 function.object.code.deinit();
3053 function.object.code_header.init(gpa);
3054 function.object.code.init(gpa);
30103055 function.object.dg.fwd_decl.deinit();
30113056 function.object.dg.ctype_pool.deinit(gpa);
30123057 function.object.dg.scratch.deinit(gpa);
......@@ -3014,7 +3059,9 @@ pub fn generate(
30143059 function.deinit();
30153060 }
30163061 try function.object.dg.ctype_pool.init(gpa);
3017 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
3062 function.object.dg.fwd_decl.init(gpa);
3063 function.object.code_header.init(gpa);
3064 function.object.code.init(gpa);
30183065
30193066 genFunc(&function) catch |err| switch (err) {
30203067 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
......@@ -3030,6 +3077,7 @@ pub fn generate(
30303077 };
30313078 errdefer mir.deinit(gpa);
30323079 mir.uavs = function.object.dg.uavs.move();
3080 mir.code_header = try function.object.code_header.toOwnedSlice();
30333081 mir.code = try function.object.code.toOwnedSlice();
30343082 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
30353083 mir.ctype_pool = function.object.dg.ctype_pool.move();
......@@ -3037,7 +3085,7 @@ pub fn generate(
30373085 return mir;
30383086}
30393087
3040fn genFunc(f: *Function) !void {
3088pub fn genFunc(f: *Function) Error!void {
30413089 const tracy = trace(@src());
30423090 defer tracy.end();
30433091
......@@ -3049,10 +3097,7 @@ fn genFunc(f: *Function) !void {
30493097 const nav_val = zcu.navValue(nav_index);
30503098 const nav = ip.getNav(nav_index);
30513099
3052 o.code_header = std.ArrayList(u8).init(gpa);
3053 defer o.code_header.deinit();
3054
3055 const fwd = o.dg.fwdDeclWriter();
3100 const fwd = &o.dg.fwd_decl.writer;
30563101 try fwd.writeAll("static ");
30573102 try o.dg.renderFunctionSignature(
30583103 fwd,
......@@ -3063,29 +3108,26 @@ fn genFunc(f: *Function) !void {
30633108 );
30643109 try fwd.writeAll(";\n");
30653110
3111 const ch = &o.code_header.writer;
30663112 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|
3067 try o.writer().print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
3113 try ch.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
30683114 try o.dg.renderFunctionSignature(
3069 o.writer(),
3115 ch,
30703116 nav_val,
30713117 .none,
30723118 .complete,
30733119 .{ .nav = nav_index },
30743120 );
3075 try o.writer().writeByte(' ');
3076
3077 // In case we need to use the header, populate it with a copy of the function
3078 // signature here. We anticipate a brace, newline, and space.
3079 try o.code_header.ensureUnusedCapacity(o.code.items.len + 3);
3080 o.code_header.appendSliceAssumeCapacity(o.code.items);
3081 o.code_header.appendSliceAssumeCapacity("{\n ");
3082 const empty_header_len = o.code_header.items.len;
3121 try ch.writeAll(" {\n ");
30833122
30843123 f.free_locals_map.clearRetainingCapacity();
30853124
30863125 const main_body = f.air.getMainBody();
3087 try genBodyResolveState(f, undefined, &.{}, main_body, false);
3088 try o.indent_writer.insertNewline();
3126 o.indent();
3127 try genBodyResolveState(f, undefined, &.{}, main_body, true);
3128 try o.outdent();
3129 try o.code.writer.writeByte('}');
3130 try o.newline();
30893131 if (o.dg.expected_block) |_|
30903132 return f.fail("runtime code not allowed in naked function", .{});
30913133
......@@ -3116,24 +3158,16 @@ fn genFunc(f: *Function) !void {
31163158 };
31173159 free_locals.sort(SortContext{ .keys = free_locals.keys() });
31183160
3119 const w = o.codeHeaderWriter();
31203161 for (free_locals.values()) |list| {
31213162 for (list.keys()) |local_index| {
31223163 const local = f.locals.items[local_index];
3123 try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
3124 try w.writeAll(";\n ");
3164 try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
3165 try ch.writeAll(";\n ");
31253166 }
31263167 }
3127
3128 // If we have a header to insert, append the body to the header
3129 // and then return the result, freeing the body.
3130 if (o.code_header.items.len > empty_header_len) {
3131 try o.code_header.appendSlice(o.code.items[empty_header_len..]);
3132 mem.swap(std.ArrayList(u8), &o.code, &o.code_header);
3133 }
31343168}
31353169
3136pub fn genDecl(o: *Object) !void {
3170pub fn genDecl(o: *Object) Error!void {
31373171 const tracy = trace(@src());
31383172 defer tracy.end();
31393173
......@@ -3153,7 +3187,7 @@ pub fn genDecl(o: *Object) !void {
31533187 .visibility = @"extern".visibility,
31543188 });
31553189
3156 const fwd = o.dg.fwdDeclWriter();
3190 const fwd = &o.dg.fwd_decl.writer;
31573191 try fwd.writeAll("zig_extern ");
31583192 try o.dg.renderFunctionSignature(
31593193 fwd,
......@@ -3174,7 +3208,7 @@ pub fn genDecl(o: *Object) !void {
31743208 .linkage = .internal,
31753209 .visibility = .default,
31763210 });
3177 const w = o.writer();
3211 const w = &o.code.writer;
31783212 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
31793213 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
31803214 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
......@@ -3189,7 +3223,7 @@ pub fn genDecl(o: *Object) !void {
31893223 try w.writeAll(" = ");
31903224 try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);
31913225 try w.writeByte(';');
3192 try o.indent_writer.insertNewline();
3226 try o.newline();
31933227 },
31943228 else => try genDeclValue(
31953229 o,
......@@ -3207,28 +3241,29 @@ pub fn genDeclValue(
32073241 decl_c_value: CValue,
32083242 alignment: Alignment,
32093243 @"linksection": InternPool.OptionalNullTerminatedString,
3210) !void {
3244) Error!void {
32113245 const zcu = o.dg.pt.zcu;
32123246 const ty = val.typeOf(zcu);
32133247
3214 const fwd = o.dg.fwdDeclWriter();
3248 const fwd = &o.dg.fwd_decl.writer;
32153249 try fwd.writeAll("static ");
32163250 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
32173251 try fwd.writeAll(";\n");
32183252
3219 const w = o.writer();
3253 const w = &o.code.writer;
32203254 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
32213255 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
32223256 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
32233257 try w.writeAll(" = ");
32243258 try o.dg.renderValue(w, val, .StaticInitializer);
3225 try w.writeAll(";\n");
3259 try w.writeByte(';');
3260 try o.newline();
32263261}
32273262
32283263pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {
32293264 const zcu = dg.pt.zcu;
32303265 const ip = &zcu.intern_pool;
3231 const fwd = dg.fwdDeclWriter();
3266 const fwd = &dg.fwd_decl.writer;
32323267
32333268 const main_name = export_indices[0].ptr(zcu).opts.name;
32343269 try fwd.writeAll("#define ");
......@@ -3305,15 +3340,16 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
33053340/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not
33063341/// have been added to `free_locals_map`. For a version of this function that restores this state,
33073342/// see `genBodyResolveState`.
3308fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
3309 const w = f.object.writer();
3343fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void {
3344 const w = &f.object.code.writer;
33103345 if (body.len == 0) {
33113346 try w.writeAll("{}");
33123347 } else {
3313 try w.writeAll("{\n");
3314 f.object.indent_writer.pushIndent();
3348 try w.writeByte('{');
3349 f.object.indent();
3350 try f.object.newline();
33153351 try genBodyInner(f, body);
3316 f.object.indent_writer.popIndent();
3352 try f.object.outdent();
33173353 try w.writeByte('}');
33183354 }
33193355}
......@@ -3324,10 +3360,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
33243360/// `leading_deaths` have their deaths processed before the body is generated.
33253361/// A scope is introduced (using braces) only if `inner` is `false`.
33263362/// If `leading_deaths` is empty, `inst` may be `undefined`.
3327fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void {
3363fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void {
33283364 if (body.len == 0) {
33293365 // Don't go to the expense of cloning everything!
3330 if (!inner) try f.object.writer().writeAll("{}");
3366 if (!inner) try f.object.code.writer.writeAll("{}");
33313367 return;
33323368 }
33333369
......@@ -3373,7 +3409,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
33733409 }
33743410}
33753411
3376fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
3412fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
33773413 const zcu = f.object.dg.pt.zcu;
33783414 const ip = &zcu.intern_pool;
33793415 const air_tags = f.air.instructions.items(.tag);
......@@ -3391,7 +3427,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
33913427
33923428 .arg => try airArg(f, inst),
33933429
3394 .breakpoint => try airBreakpoint(f.object.writer()),
3430 .breakpoint => try airBreakpoint(f),
33953431 .ret_addr => try airRetAddr(f, inst),
33963432 .frame_addr => try airFrameAddress(f, inst),
33973433
......@@ -3644,8 +3680,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
36443680 .ret => return airRet(f, inst, false),
36453681 .ret_safe => return airRet(f, inst, false), // TODO
36463682 .ret_load => return airRet(f, inst, true),
3647 .trap => return airTrap(f, f.object.writer()),
3648 .unreach => return airUnreach(f),
3683 .trap => return airTrap(f, &f.object.code.writer),
3684 .unreach => return airUnreach(&f.object),
36493685
36503686 // Instructions which may be `noreturn`.
36513687 .block => res: {
......@@ -3688,7 +3724,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
36883724 const operand = try f.resolveInst(ty_op.operand);
36893725 try reap(f, inst, &.{ty_op.operand});
36903726
3691 const w = f.object.writer();
3727 const w = &f.object.code.writer;
36923728 const local = try f.allocLocal(inst, inst_ty);
36933729 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
36943730 try f.writeCValue(w, local, .Other);
......@@ -3714,7 +3750,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
37143750 const index = try f.resolveInst(bin_op.rhs);
37153751 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37163752
3717 const w = f.object.writer();
3753 const w = &f.object.code.writer;
37183754 const local = try f.allocLocal(inst, inst_ty);
37193755 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
37203756 try f.writeCValue(w, local, .Other);
......@@ -3741,7 +3777,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
37413777 const index = try f.resolveInst(bin_op.rhs);
37423778 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37433779
3744 const w = f.object.writer();
3780 const w = &f.object.code.writer;
37453781 const local = try f.allocLocal(inst, inst_ty);
37463782 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
37473783 try f.writeCValue(w, local, .Other);
......@@ -3776,7 +3812,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
37763812 const index = try f.resolveInst(bin_op.rhs);
37773813 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37783814
3779 const w = f.object.writer();
3815 const w = &f.object.code.writer;
37803816 const local = try f.allocLocal(inst, inst_ty);
37813817 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
37823818 try f.writeCValue(w, local, .Other);
......@@ -3804,7 +3840,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
38043840 const index = try f.resolveInst(bin_op.rhs);
38053841 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38063842
3807 const w = f.object.writer();
3843 const w = &f.object.code.writer;
38083844 const local = try f.allocLocal(inst, inst_ty);
38093845 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
38103846 try f.writeCValue(w, local, .Other);
......@@ -3833,7 +3869,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
38333869 const index = try f.resolveInst(bin_op.rhs);
38343870 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38353871
3836 const w = f.object.writer();
3872 const w = &f.object.code.writer;
38373873 const local = try f.allocLocal(inst, inst_ty);
38383874 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
38393875 try f.writeCValue(w, local, .Other);
......@@ -3896,12 +3932,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
38963932 .{ .arg_array = i };
38973933
38983934 if (f.liveness.isUnused(inst)) {
3899 const w = f.object.writer();
3935 const w = &f.object.code.writer;
39003936 try w.writeByte('(');
39013937 try f.renderType(w, .void);
39023938 try w.writeByte(')');
39033939 try f.writeCValue(w, result, .Other);
3904 try w.writeAll(";\n");
3940 try w.writeByte(';');
3941 try f.object.newline();
39053942 return .none;
39063943 }
39073944
......@@ -3934,7 +3971,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
39343971 const is_array = lowersToArray(src_ty, pt);
39353972 const need_memcpy = !is_aligned or is_array;
39363973
3937 const w = f.object.writer();
3974 const w = &f.object.code.writer;
39383975 const local = try f.allocLocal(inst, src_ty);
39393976 const v = try Vectorize.start(f, inst, w, ptr_ty);
39403977
......@@ -3979,7 +4016,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
39794016 try w.writeByte('(');
39804017 try f.writeCValueDeref(w, operand);
39814018 try v.elem(f, w);
3982 try w.print(", {f})", .{try f.fmtIntLiteralDec(bit_offset_val)});
4019 try w.print(", {f})", .{try f.fmtIntLiteral(bit_offset_val)});
39834020 if (cant_cast) try w.writeByte(')');
39844021 try f.object.dg.renderBuiltinInfo(w, field_ty, .bits);
39854022 try w.writeByte(')');
......@@ -3990,7 +4027,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
39904027 try f.writeCValueDeref(w, operand);
39914028 try v.elem(f, w);
39924029 }
3993 try w.writeAll(";\n");
4030 try w.writeByte(';');
4031 try f.object.newline();
39944032 try v.end(f, inst, w);
39954033
39964034 return local;
......@@ -4000,7 +4038,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
40004038 const pt = f.object.dg.pt;
40014039 const zcu = pt.zcu;
40024040 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4003 const w = f.object.writer();
4041 const w = &f.object.code.writer;
40044042 const op_inst = un_op.toIndex();
40054043 const op_ty = f.typeOf(un_op);
40064044 const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;
......@@ -4029,7 +4067,8 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
40294067 deref = false;
40304068 try w.writeAll(", sizeof(");
40314069 try f.renderType(w, ret_ty);
4032 try w.writeAll("));\n");
4070 try w.writeAll("));");
4071 try f.object.newline();
40334072 break :ret_val array_local;
40344073 } else operand;
40354074
......@@ -4038,7 +4077,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
40384077 try f.writeCValueDeref(w, ret_val)
40394078 else
40404079 try f.writeCValue(w, ret_val, .Other);
4041 try w.writeAll(";\n");
4080 try w.write(";\n");
40424081 if (is_array) {
40434082 try freeLocal(f, inst, ret_val.new_local, null);
40444083 }
......@@ -4064,7 +4103,7 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
40644103
40654104 if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);
40664105
4067 const w = f.object.writer();
4106 const w = &f.object.code.writer;
40684107 const local = try f.allocLocal(inst, inst_ty);
40694108 const v = try Vectorize.start(f, inst, w, operand_ty);
40704109 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
......@@ -4100,7 +4139,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
41004139 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
41014140 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
41024141
4103 const w = f.object.writer();
4142 const w = &f.object.code.writer;
41044143 const local = try f.allocLocal(inst, inst_ty);
41054144 const v = try Vectorize.start(f, inst, w, operand_ty);
41064145 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
......@@ -4178,15 +4217,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
41784217
41794218 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false;
41804219
4220 const w = &f.object.code.writer;
41814221 if (val_is_undef) {
41824222 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41834223 if (safety and ptr_info.packed_offset.host_size == 0) {
4184 const w = f.object.writer();
41854224 try w.writeAll("memset(");
41864225 try f.writeCValue(w, ptr_val, .FunctionArgument);
41874226 try w.writeAll(", 0xaa, sizeof(");
41884227 try f.renderType(w, .fromInterned(ptr_info.child));
4189 try w.writeAll("));\n");
4228 try w.writeAll("));");
4229 try f.object.newline();
41904230 }
41914231 return .none;
41924232 }
......@@ -4202,7 +4242,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
42024242 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
42034243
42044244 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);
4205 const w = f.object.writer();
42064245 if (need_memcpy) {
42074246 // For this memcpy to safely work we need the rhs to have the same
42084247 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
......@@ -4216,7 +4255,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
42164255 try f.writeCValue(w, new_local, .Other);
42174256 try w.writeAll(" = ");
42184257 try f.writeCValue(w, src_val, .Other);
4219 try w.writeAll(";\n");
4258 try w.writeByte(';');
4259 try f.object.newline();
42204260
42214261 break :blk new_local;
42224262 } else src_val;
......@@ -4233,7 +4273,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
42334273 try f.renderType(w, src_ty);
42344274 try w.writeAll("))");
42354275 try f.freeCValue(inst, array_src);
4236 try w.writeAll(";\n");
4276 try w.writeByte(';');
4277 try f.object.newline();
42374278 try v.end(f, inst, w);
42384279 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
42394280 const host_bits = ptr_info.packed_offset.host_size * 8;
......@@ -4251,7 +4292,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
42514292 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
42524293 defer mask.deinit();
42534294
4254 try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits)));
4295 try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits));
42554296 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
42564297 try mask.bitNotWrap(&mask, .unsigned, host_bits);
42574298
......@@ -4331,7 +4372,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
43314372 const operand_ty = f.typeOf(bin_op.lhs);
43324373 const scalar_ty = operand_ty.scalarType(zcu);
43334374
4334 const w = f.object.writer();
4375 const w = &f.object.code.writer;
43354376 const local = try f.allocLocal(inst, inst_ty);
43364377 const v = try Vectorize.start(f, inst, w, operand_ty);
43374378 try f.writeCValueMember(w, local, .{ .field = 1 });
......@@ -4350,7 +4391,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
43504391 try f.writeCValue(w, rhs, .FunctionArgument);
43514392 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
43524393 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
4353 try w.writeAll(");\n");
4394 try w.writeAll(");");
4395 try f.object.newline();
43544396 try v.end(f, inst, w);
43554397
43564398 return local;
......@@ -4369,7 +4411,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
43694411
43704412 const inst_ty = f.typeOfIndex(inst);
43714413
4372 const w = f.object.writer();
4414 const w = &f.object.code.writer;
43734415 const local = try f.allocLocal(inst, inst_ty);
43744416 const v = try Vectorize.start(f, inst, w, operand_ty);
43754417 try f.writeCValue(w, local, .Other);
......@@ -4378,7 +4420,8 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
43784420 try w.writeByte('!');
43794421 try f.writeCValue(w, op, .Other);
43804422 try v.elem(f, w);
4381 try w.writeAll(";\n");
4423 try w.writeByte(';');
4424 try f.object.newline();
43824425 try v.end(f, inst, w);
43834426
43844427 return local;
......@@ -4405,7 +4448,7 @@ fn airBinOp(
44054448
44064449 const inst_ty = f.typeOfIndex(inst);
44074450
4408 const w = f.object.writer();
4451 const w = &f.object.code.writer;
44094452 const local = try f.allocLocal(inst, inst_ty);
44104453 const v = try Vectorize.start(f, inst, w, operand_ty);
44114454 try f.writeCValue(w, local, .Other);
......@@ -4418,7 +4461,8 @@ fn airBinOp(
44184461 try w.writeByte(' ');
44194462 try f.writeCValue(w, rhs, .Other);
44204463 try v.elem(f, w);
4421 try w.writeAll(";\n");
4464 try w.writeByte(';');
4465 try f.object.newline();
44224466 try v.end(f, inst, w);
44234467
44244468 return local;
......@@ -4455,7 +4499,7 @@ fn airCmpOp(
44554499
44564500 const rhs_ty = f.typeOf(data.rhs);
44574501 const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);
4458 const w = f.object.writer();
4502 const w = &f.object.code.writer;
44594503 const local = try f.allocLocal(inst, inst_ty);
44604504 const v = try Vectorize.start(f, inst, w, lhs_ty);
44614505 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
......@@ -4508,7 +4552,7 @@ fn airEquality(
45084552 const rhs = try f.resolveInst(bin_op.rhs);
45094553 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
45104554
4511 const w = f.object.writer();
4555 const w = &f.object.code.writer;
45124556 const local = try f.allocLocal(inst, .bool);
45134557 const a = try Assignment.start(f, w, .bool);
45144558 try f.writeCValue(w, local, .Other);
......@@ -4566,12 +4610,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
45664610 const operand = try f.resolveInst(un_op);
45674611 try reap(f, inst, &.{un_op});
45684612
4569 const w = f.object.writer();
4613 const w = &f.object.code.writer;
45704614 const local = try f.allocLocal(inst, .bool);
45714615 try f.writeCValue(w, local, .Other);
45724616 try w.writeAll(" = ");
45734617 try f.writeCValue(w, operand, .Other);
4574 try w.print(" < sizeof({f}) / sizeof(*{0f});\n", .{fmtIdentSolo("zig_errorName")});
4618 try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")});
4619 try f.object.newline();
45754620 return local;
45764621}
45774622
......@@ -4592,7 +4637,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
45924637 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
45934638
45944639 const local = try f.allocLocal(inst, inst_ty);
4595 const w = f.object.writer();
4640 const w = &f.object.code.writer;
45964641 const v = try Vectorize.start(f, inst, w, inst_ty);
45974642 const a = try Assignment.start(f, w, inst_scalar_ctype);
45984643 try f.writeCValue(w, local, .Other);
......@@ -4634,7 +4679,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
46344679 const rhs = try f.resolveInst(bin_op.rhs);
46354680 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
46364681
4637 const w = f.object.writer();
4682 const w = &f.object.code.writer;
46384683 const local = try f.allocLocal(inst, inst_ty);
46394684 const v = try Vectorize.start(f, inst, w, inst_ty);
46404685 try f.writeCValue(w, local, .Other);
......@@ -4654,7 +4699,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
46544699 try w.writeAll(" : ");
46554700 try f.writeCValue(w, rhs, .Other);
46564701 try v.elem(f, w);
4657 try w.writeAll(";\n");
4702 try w.writeByte(';');
4703 try f.object.newline();
46584704 try v.end(f, inst, w);
46594705
46604706 return local;
......@@ -4673,7 +4719,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
46734719 const inst_ty = f.typeOfIndex(inst);
46744720 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
46754721
4676 const w = f.object.writer();
4722 const w = &f.object.code.writer;
46774723 const local = try f.allocLocal(inst, inst_ty);
46784724 {
46794725 const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
......@@ -4704,7 +4750,7 @@ fn airCall(
47044750 if (f.object.dg.is_naked_fn) return .none;
47054751
47064752 const gpa = f.object.dg.gpa;
4707 const w = f.object.writer();
4753 const w = &f.object.code.writer;
47084754
47094755 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
47104756 const extra = f.air.extraData(Air.Call, pl_op.payload);
......@@ -4731,7 +4777,8 @@ fn airCall(
47314777 try f.writeCValue(w, resolved_arg.*, .FunctionArgument);
47324778 try w.writeAll(", sizeof(");
47334779 try f.renderCType(w, arg_ctype);
4734 try w.writeAll("));\n");
4780 try w.writeAll("));");
4781 try f.object.newline();
47354782 resolved_arg.* = array_local;
47364783 }
47374784 }
......@@ -4826,7 +4873,11 @@ fn airCall(
48264873 try f.writeCValue(w, resolved_arg, .FunctionArgument);
48274874 try f.freeCValue(inst, resolved_arg);
48284875 }
4829 try w.writeAll(");\n");
4876 try w.writeAll(");");
4877 switch (modifier) {
4878 .always_tail => try w.writeByte('\n'),
4879 else => try f.object.newline(),
4880 }
48304881
48314882 const result = result: {
48324883 if (result_local == .none or !lowersToArray(ret_ty, pt))
......@@ -4839,7 +4890,8 @@ fn airCall(
48394890 try f.writeCValueMember(w, result_local, .{ .identifier = "array" });
48404891 try w.writeAll(", sizeof(");
48414892 try f.renderType(w, ret_ty);
4842 try w.writeAll("));\n");
4893 try w.writeAll("));");
4894 try f.object.newline();
48434895 try freeLocal(f, inst, result_local.new_local, null);
48444896 break :result array_local;
48454897 };
......@@ -4849,7 +4901,7 @@ fn airCall(
48494901
48504902fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
48514903 const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
4852 const w = f.object.writer();
4904 const w = &f.object.code.writer;
48534905 // TODO re-evaluate whether to emit these or not. If we naively emit
48544906 // these directives, the output file will report bogus line numbers because
48554907 // every newline after the #line directive adds one to the line.
......@@ -4857,13 +4909,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
48574909 // If we wanted to go this route, we would need to go all the way and not output
48584910 // newlines until the next dbg_stmt occurs.
48594911 // Perhaps an additional compilation option is in order?
4860 //try w.print("#line {d}\n", .{dbg_stmt.line + 1});
4861 try w.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
4912 //try w.print("#line {d}", .{dbg_stmt.line + 1});
4913 //try f.object.newline();
4914 try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
4915 try f.object.newline();
48624916 return .none;
48634917}
48644918
48654919fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {
4866 try f.object.writer().writeAll("(void)0;\n");
4920 try f.object.code.writer.writeAll("(void)0;");
4921 try f.object.newline();
48674922 return .none;
48684923}
48694924
......@@ -4874,8 +4929,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
48744929 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
48754930 const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
48764931 const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);
4877 const w = f.object.writer();
4878 try w.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
4932 const w = &f.object.code.writer;
4933 try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
4934 try f.object.newline();
48794935 return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
48804936}
48814937
......@@ -4889,8 +4945,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
48894945 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
48904946
48914947 try reap(f, inst, &.{pl_op.operand});
4892 const w = f.object.writer();
4893 try w.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });
4948 const w = &f.object.code.writer;
4949 try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) });
4950 try f.object.newline();
48944951 return .none;
48954952}
48964953
......@@ -4907,7 +4964,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
49074964
49084965 const block_id = f.next_block_index;
49094966 f.next_block_index += 1;
4910 const w = f.object.writer();
4967 const w = &f.object.code.writer;
49114968
49124969 const inst_ty = f.typeOfIndex(inst);
49134970 const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))
......@@ -4929,8 +4986,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
49294986 try die(f, inst, death.toRef());
49304987 }
49314988
4932 try f.object.indent_writer.insertNewline();
4933
49344989 // noreturn blocks have no `br` instructions reaching them, so we don't want a label
49354990 if (f.object.dg.is_naked_fn) {
49364991 if (f.object.dg.expected_block) |expected_block| {
......@@ -4940,7 +4995,8 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
49404995 }
49414996 } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
49424997 // label must be followed by an expression, include an empty one.
4943 try w.print("zig_block_{d}:;\n", .{block_id});
4998 try w.print("\nzig_block_{d}:;", .{block_id});
4999 try f.object.newline();
49445000 }
49455001
49465002 return result;
......@@ -4977,7 +5033,7 @@ fn lowerTry(
49775033 const err_union = try f.resolveInst(operand);
49785034 const inst_ty = f.typeOfIndex(inst);
49795035 const liveness_condbr = f.liveness.getCondBr(inst);
4980 const w = f.object.writer();
5036 const w = &f.object.code.writer;
49815037 const payload_ty = err_union_ty.errorUnionPayload(zcu);
49825038 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
49835039
......@@ -5001,7 +5057,7 @@ fn lowerTry(
50015057 try w.writeAll(") ");
50025058
50035059 try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);
5004 try f.object.indent_writer.insertNewline();
5060 try f.object.newline();
50055061 if (f.object.dg.expected_block) |_|
50065062 return f.fail("runtime code not allowed in naked function", .{});
50075063 }
......@@ -5039,7 +5095,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
50395095 const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
50405096 const block = f.blocks.get(branch.block_inst).?;
50415097 const result = block.result;
5042 const w = f.object.writer();
5098 const w = &f.object.code.writer;
50435099
50445100 if (f.object.dg.is_naked_fn) {
50455101 if (result != .none) return f.fail("runtime code not allowed in naked function", .{});
......@@ -5065,15 +5121,14 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
50655121
50665122fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {
50675123 const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
5068 const w = f.object.writer();
5069 try w.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
5124 try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
50705125}
50715126
50725127fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
50735128 const pt = f.object.dg.pt;
50745129 const zcu = pt.zcu;
50755130 const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
5076 const w = f.object.writer();
5131 const w = &f.object.code.writer;
50775132
50785133 if (try f.air.value(br.operand, pt)) |cond_val| {
50795134 // Comptime-known dispatch. Iterate the cases to find the correct
......@@ -5105,8 +5160,9 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
51055160 try f.writeCValue(w, .{ .local = cond_local }, .Other);
51065161 try w.writeAll(" = ");
51075162 try f.writeCValue(w, cond, .Other);
5108 try w.writeAll(";\n");
5109 try w.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)});
5163 try w.writeByte(';');
5164 try f.object.newline();
5165 try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
51105166}
51115167
51125168fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -5126,7 +5182,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
51265182 const zcu = pt.zcu;
51275183 const target = &f.object.dg.mod.resolved_target.result;
51285184 const ctype_pool = &f.object.dg.ctype_pool;
5129 const w = f.object.writer();
5185 const w = &f.object.code.writer;
51305186
51315187 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
51325188 const src_info = dest_ty.intInfo(zcu);
......@@ -5142,16 +5198,24 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
51425198 try f.renderType(w, dest_ty);
51435199 try w.writeByte(')');
51445200 try f.writeCValue(w, operand, .Other);
5145 try w.writeAll(";\n");
5201 try w.writeByte(';');
5202 try f.object.newline();
51465203 return local;
51475204 }
51485205
51495206 const operand_lval = if (operand == .constant) blk: {
51505207 const operand_local = try f.allocLocal(null, operand_ty);
51515208 try f.writeCValue(w, operand_local, .Other);
5152 try w.writeAll(" = ");
5209 if (operand_ty.isAbiInt(zcu)) {
5210 try w.writeAll(" = ");
5211 } else {
5212 try w.writeAll(" = (");
5213 try f.renderType(w, operand_ty);
5214 try w.writeByte(')');
5215 }
51535216 try f.writeCValue(w, operand, .Other);
5154 try w.writeAll(";\n");
5217 try w.writeByte(';');
5218 try f.object.newline();
51555219 break :blk operand_local;
51565220 } else operand;
51575221
......@@ -5165,7 +5229,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
51655229 w,
51665230 if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
51675231 );
5168 try w.writeAll("));\n");
5232 try w.writeAll("));");
5233 try f.object.newline();
51695234
51705235 // Ensure padding bits have the expected value.
51715236 if (dest_ty.isAbiInt(zcu)) {
......@@ -5221,7 +5286,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
52215286 if (need_bitcasts) try w.writeByte(')');
52225287 try f.object.dg.renderBuiltinInfo(w, info_ty, .bits);
52235288 if (need_bitcasts) try w.writeByte(')');
5224 try w.writeAll(");\n");
5289 try w.writeAll(");");
5290 try f.object.newline();
52255291 }
52265292
52275293 try f.freeCValue(null, operand_lval);
......@@ -5234,48 +5300,53 @@ fn airTrap(f: *Function, w: *Writer) !void {
52345300 try w.writeAll("zig_trap();\n");
52355301}
52365302
5237fn airBreakpoint(w: *Writer) !CValue {
5238 try w.writeAll("zig_breakpoint();\n");
5303fn airBreakpoint(f: *Function) !CValue {
5304 const w = &f.object.code.writer;
5305 try w.writeAll("zig_breakpoint();");
5306 try f.object.newline();
52395307 return .none;
52405308}
52415309
52425310fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {
5243 const w = f.object.writer();
5311 const w = &f.object.code.writer;
52445312 const local = try f.allocLocal(inst, .usize);
52455313 try f.writeCValue(w, local, .Other);
52465314 try w.writeAll(" = (");
52475315 try f.renderType(w, .usize);
5248 try w.writeAll(")zig_return_address();\n");
5316 try w.writeAll(")zig_return_address();");
5317 try f.object.newline();
52495318 return local;
52505319}
52515320
52525321fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
5253 const w = f.object.writer();
5322 const w = &f.object.code.writer;
52545323 const local = try f.allocLocal(inst, .usize);
52555324 try f.writeCValue(w, local, .Other);
52565325 try w.writeAll(" = (");
52575326 try f.renderType(w, .usize);
5258 try w.writeAll(")zig_frame_address();\n");
5327 try w.writeAll(")zig_frame_address();");
5328 try f.object.newline();
52595329 return local;
52605330}
52615331
5262fn airUnreach(f: *Function) !void {
5332fn airUnreach(o: *Object) !void {
52635333 // Not even allowed to call unreachable in a naked function.
5264 if (f.object.dg.is_naked_fn) return;
5265 try f.object.writer().writeAll("zig_unreachable();\n");
5334 if (o.dg.is_naked_fn) return;
5335 try o.code.writer.writeAll("zig_unreachable();\n");
52665336}
52675337
52685338fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
52695339 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
52705340 const loop = f.air.extraData(Air.Block, ty_pl.payload);
52715341 const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);
5272 const w = f.object.writer();
5342 const w = &f.object.code.writer;
52735343
52745344 // `repeat` instructions matching this loop will branch to
52755345 // this label. Since we need a label for arbitrary `repeat`
52765346 // anyway, there's actually no need to use a "real" looping
52775347 // construct at all!
5278 try w.print("zig_loop_{d}:\n", .{@intFromEnum(inst)});
5348 try w.print("zig_loop_{d}:", .{@intFromEnum(inst)});
5349 try f.object.newline();
52795350 try genBodyInner(f, body); // no need to restore state, we're noreturn
52805351}
52815352
......@@ -5287,14 +5358,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {
52875358 const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);
52885359 const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);
52895360 const liveness_condbr = f.liveness.getCondBr(inst);
5290 const w = f.object.writer();
5361 const w = &f.object.code.writer;
52915362
52925363 try w.writeAll("if (");
52935364 try f.writeCValue(w, cond, .Other);
52945365 try w.writeAll(") ");
52955366
52965367 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
5297 try w.writeByte('\n');
5368 try f.object.newline();
52985369 if (else_body.len > 0) if (f.object.dg.expected_block) |_|
52995370 return f.fail("runtime code not allowed in naked function", .{});
53005371
......@@ -5320,7 +5391,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
53205391 const init_condition = try f.resolveInst(switch_br.operand);
53215392 try reap(f, inst, &.{switch_br.operand});
53225393 const condition_ty = f.typeOf(switch_br.operand);
5323 const w = f.object.writer();
5394 const w = &f.object.code.writer;
53245395
53255396 // For dispatches, we will create a local alloc to contain the condition value.
53265397 // This may not result in optimal codegen for switch loops, but it minimizes the
......@@ -5328,7 +5399,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
53285399 const condition = if (is_dispatch_loop) cond: {
53295400 const new_local = try f.allocLocal(inst, condition_ty);
53305401 try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition);
5331 try w.print("zig_switch_{d}_loop:\n", .{@intFromEnum(inst)});
5402 try w.print("zig_switch_{d}_loop:", .{@intFromEnum(inst)});
5403 try f.object.newline();
53325404 try f.loop_switch_conds.put(gpa, inst, new_local.new_local);
53335405 break :cond new_local;
53345406 } else init_condition;
......@@ -5352,7 +5424,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
53525424 }
53535425 try f.writeCValue(w, condition, .Other);
53545426 try w.writeAll(") {");
5355 f.object.indent_writer.pushIndent();
5427 f.object.indent();
53565428
53575429 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);
53585430 defer gpa.free(liveness.deaths);
......@@ -5365,7 +5437,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
53655437 continue;
53665438 }
53675439 for (case.items) |item| {
5368 try f.object.indent_writer.insertNewline();
5440 try f.object.newline();
53695441 try w.writeAll("case ");
53705442 const item_value = try f.air.value(item, pt);
53715443 // If `item_value` is a pointer with a known integer address, print the address
......@@ -5386,13 +5458,15 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
53865458 }
53875459 try w.writeByte(':');
53885460 }
5389 try w.writeAll(" {\n");
5390 f.object.indent_writer.pushIndent();
5461 try w.writeAll(" {");
5462 f.object.indent();
5463 try f.object.newline();
53915464 if (is_dispatch_loop) {
5392 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
5465 try w.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx });
5466 try f.object.newline();
53935467 }
53945468 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5395 f.object.indent_writer.popIndent();
5469 try f.object.outdent();
53965470 try w.writeByte('}');
53975471 if (f.object.dg.expected_block) |_|
53985472 return f.fail("runtime code not allowed in naked function", .{});
......@@ -5401,7 +5475,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
54015475 }
54025476
54035477 const else_body = it.elseBody();
5404 try f.object.indent_writer.insertNewline();
5478 try f.object.newline();
54055479
54065480 try w.writeAll("default: ");
54075481 if (any_range_cases) {
......@@ -5431,13 +5505,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
54315505 try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other);
54325506 try w.writeByte(')');
54335507 }
5434 try w.writeAll(") {\n");
5435 f.object.indent_writer.pushIndent();
5508 try w.writeAll(") {");
5509 f.object.indent();
5510 try f.object.newline();
54365511 if (is_dispatch_loop) {
54375512 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
54385513 }
54395514 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5440 f.object.indent_writer.popIndent();
5515 try f.object.outdent();
54415516 try w.writeByte('}');
54425517 if (f.object.dg.expected_block) |_|
54435518 return f.fail("runtime code not allowed in naked function", .{});
......@@ -5455,12 +5530,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
54555530 try genBody(f, else_body);
54565531 if (f.object.dg.expected_block) |_|
54575532 return f.fail("runtime code not allowed in naked function", .{});
5458 } else {
5459 try w.writeAll("zig_unreachable();");
5460 }
5461 try f.object.indent_writer.insertNewline();
5462
5463 f.object.indent_writer.popIndent();
5533 } else try airUnreach(&f.object);
5534 try f.object.newline();
5535 try f.object.outdent();
54645536 try w.writeAll("}\n");
54655537}
54665538
......@@ -5499,7 +5571,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
54995571 extra_i += inputs.len;
55005572
55015573 const result = result: {
5502 const w = f.object.writer();
5574 const w = &f.object.code.writer;
55035575 const inst_ty = f.typeOfIndex(inst);
55045576 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
55055577 const inst_local = try f.allocLocalValue(.{
......@@ -5510,7 +5582,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
55105582 try f.writeCValue(w, inst_local, .Other);
55115583 try w.writeAll(" = ");
55125584 try f.writeCValue(w, .{ .undef = inst_ty }, .Other);
5513 try w.writeAll(";\n");
5585 try w.writeByte(';');
5586 try f.object.newline();
55145587 }
55155588 break :local inst_local;
55165589 } else .none;
......@@ -5548,7 +5621,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
55485621 try w.writeAll(" = ");
55495622 try f.writeCValue(w, .{ .undef = output_ty }, .Other);
55505623 }
5551 try w.writeAll(";\n");
5624 try w.writeByte(';');
5625 try f.object.newline();
55525626 }
55535627 }
55545628 for (inputs) |input| {
......@@ -5583,7 +5657,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
55835657 }
55845658 try w.writeAll(" = ");
55855659 try f.writeCValue(w, input_val, .Other);
5586 try w.writeAll(";\n");
5660 try w.writeByte(';');
5661 try f.object.newline();
55875662 }
55885663 }
55895664 for (0..clobbers_len) |_| {
......@@ -5709,7 +5784,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
57095784 if (clobber_i > 0) try w.writeByte(',');
57105785 try w.print(" {f}", .{fmtStringLiteral(clobber, null)});
57115786 }
5712 try w.writeAll(");\n");
5787 try w.writeAll(");");
5788 try f.object.newline();
57135789
57145790 extra_i = constraints_extra_begin;
57155791 locals_index = locals_begin;
......@@ -5730,7 +5806,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
57305806 try w.writeAll(" = ");
57315807 try f.writeCValue(w, .{ .local = locals_index }, .Other);
57325808 locals_index += 1;
5733 try w.writeAll(";\n");
5809 try w.writeByte(';');
5810 try f.object.newline();
57345811 }
57355812 }
57365813
......@@ -5760,7 +5837,7 @@ fn airIsNull(
57605837 const ctype_pool = &f.object.dg.ctype_pool;
57615838 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
57625839
5763 const w = f.object.writer();
5840 const w = &f.object.code.writer;
57645841 const operand = try f.resolveInst(un_op);
57655842 try reap(f, inst, &.{un_op});
57665843
......@@ -5828,7 +5905,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue
58285905 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
58295906 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
58305907 .is_null, .payload => {
5831 const w = f.object.writer();
5908 const w = &f.object.code.writer;
58325909 const local = try f.allocLocal(inst, inst_ty);
58335910 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
58345911 try f.writeCValue(w, local, .Other);
......@@ -5850,7 +5927,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
58505927 const pt = f.object.dg.pt;
58515928 const zcu = pt.zcu;
58525929 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5853 const w = f.object.writer();
5930 const w = &f.object.code.writer;
58545931 const operand = try f.resolveInst(ty_op.operand);
58555932 try reap(f, inst, &.{ty_op.operand});
58565933 const operand_ty = f.typeOf(ty_op.operand);
......@@ -6000,7 +6077,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
60006077 const field_ptr_val = try f.resolveInst(extra.field_ptr);
60016078 try reap(f, inst, &.{extra.field_ptr});
60026079
6003 const w = f.object.writer();
6080 const w = &f.object.code.writer;
60046081 const local = try f.allocLocal(inst, container_ptr_ty);
60056082 try f.writeCValue(w, local, .Other);
60066083 try w.writeAll(" = (");
......@@ -6035,7 +6112,8 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
60356112 },
60366113 }
60376114
6038 try w.writeAll(";\n");
6115 try w.writeByte(';');
6116 try f.object.newline();
60396117 return local;
60406118}
60416119
......@@ -6054,7 +6132,7 @@ fn fieldPtr(
60546132 // Ensure complete type definition is visible before accessing fields.
60556133 _ = try f.ctypeFromType(container_ty, .complete);
60566134
6057 const w = f.object.writer();
6135 const w = &f.object.code.writer;
60586136 const local = try f.allocLocal(inst, field_ptr_ty);
60596137 try f.writeCValue(w, local, .Other);
60606138 try w.writeAll(" = (");
......@@ -6080,7 +6158,8 @@ fn fieldPtr(
60806158 },
60816159 }
60826160
6083 try w.writeAll(";\n");
6161 try w.writeByte(';');
6162 try f.object.newline();
60846163 return local;
60856164}
60866165
......@@ -6100,7 +6179,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
61006179 const struct_byval = try f.resolveInst(extra.struct_operand);
61016180 try reap(f, inst, &.{extra.struct_operand});
61026181 const struct_ty = f.typeOf(extra.struct_operand);
6103 const w = f.object.writer();
6182 const w = &f.object.code.writer;
61046183
61056184 // Ensure complete type definition is visible before accessing fields.
61066185 _ = try f.ctypeFromType(struct_ty, .complete);
......@@ -6151,7 +6230,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
61516230 });
61526231 if (cant_cast) try w.writeByte(')');
61536232 try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits);
6154 try w.writeAll(");\n");
6233 try w.writeAll(");");
6234 try f.object.newline();
61556235 if (inst_ty.eql(field_int_ty, zcu)) return temp_local;
61566236
61576237 const local = try f.allocLocal(inst, inst_ty);
......@@ -6162,7 +6242,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
61626242 try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
61636243 try w.writeAll(", sizeof(");
61646244 try f.renderType(w, inst_ty);
6165 try w.writeAll("));\n");
6245 try w.writeAll("));");
6246 try f.object.newline();
61666247 }
61676248 try freeLocal(f, inst, temp_local.new_local, null);
61686249 return local;
......@@ -6186,7 +6267,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
61866267 try f.writeCValue(w, operand_local, .Other);
61876268 try w.writeAll(" = ");
61886269 try f.writeCValue(w, struct_byval, .Other);
6189 try w.writeAll(";\n");
6270 try w.writeByte(';');
6271 try f.object.newline();
61906272 break :blk operand_local;
61916273 } else struct_byval;
61926274 const local = try f.allocLocal(inst, inst_ty);
......@@ -6203,7 +6285,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
62036285 try f.writeCValue(w, operand_lval, .Other);
62046286 try w.writeAll(", sizeof(");
62056287 try f.renderType(w, inst_ty);
6206 try w.writeAll("));\n");
6288 try w.writeAll("));");
6289 try f.object.newline();
62076290 }
62086291 try f.freeCValue(inst, operand_lval);
62096292 return local;
......@@ -6245,7 +6328,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
62456328 return local;
62466329 }
62476330
6248 const w = f.object.writer();
6331 const w = &f.object.code.writer;
62496332 try f.writeCValue(w, local, .Other);
62506333 try w.writeAll(" = ");
62516334
......@@ -6259,7 +6342,8 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
62596342 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
62606343 else
62616344 try f.writeCValueMember(w, operand, .{ .identifier = "error" });
6262 try w.writeAll(";\n");
6345 try w.writeByte(';');
6346 try f.object.newline();
62636347 return local;
62646348}
62656349
......@@ -6274,7 +6358,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
62746358 const operand_ty = f.typeOf(ty_op.operand);
62756359 const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
62766360
6277 const w = f.object.writer();
6361 const w = &f.object.code.writer;
62786362 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
62796363 if (!is_ptr) return .none;
62806364
......@@ -6284,7 +6368,8 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
62846368 try f.renderType(w, inst_ty);
62856369 try w.writeByte(')');
62866370 try f.writeCValue(w, operand, .Other);
6287 try w.writeAll(";\n");
6371 try w.writeByte(';');
6372 try f.object.newline();
62886373 return local;
62896374 }
62906375
......@@ -6315,7 +6400,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
63156400 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
63166401 .is_null, .payload => {
63176402 const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);
6318 const w = f.object.writer();
6403 const w = &f.object.code.writer;
63196404 const local = try f.allocLocal(inst, inst_ty);
63206405 {
63216406 const a = try Assignment.start(f, w, .bool);
......@@ -6351,7 +6436,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
63516436 const err = try f.resolveInst(ty_op.operand);
63526437 try reap(f, inst, &.{ty_op.operand});
63536438
6354 const w = f.object.writer();
6439 const w = &f.object.code.writer;
63556440 const local = try f.allocLocal(inst, inst_ty);
63566441
63576442 if (repr_is_err and err == .local and err.local == local.new_local) {
......@@ -6382,7 +6467,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
63826467fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
63836468 const pt = f.object.dg.pt;
63846469 const zcu = pt.zcu;
6385 const w = f.object.writer();
6470 const w = &f.object.code.writer;
63866471 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
63876472 const inst_ty = f.typeOfIndex(inst);
63886473 const operand = try f.resolveInst(ty_op.operand);
......@@ -6451,7 +6536,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
64516536 const err_ty = inst_ty.errorUnionSet(zcu);
64526537 try reap(f, inst, &.{ty_op.operand});
64536538
6454 const w = f.object.writer();
6539 const w = &f.object.code.writer;
64556540 const local = try f.allocLocal(inst, inst_ty);
64566541 if (!repr_is_err) {
64576542 const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
......@@ -6478,7 +6563,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
64786563 const zcu = pt.zcu;
64796564 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
64806565
6481 const w = f.object.writer();
6566 const w = &f.object.code.writer;
64826567 const operand = try f.resolveInst(un_op);
64836568 try reap(f, inst, &.{un_op});
64846569 const operand_ty = f.typeOf(un_op);
......@@ -6519,7 +6604,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
65196604 try reap(f, inst, &.{ty_op.operand});
65206605 const inst_ty = f.typeOfIndex(inst);
65216606 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
6522 const w = f.object.writer();
6607 const w = &f.object.code.writer;
65236608 const local = try f.allocLocal(inst, inst_ty);
65246609 const operand_ty = f.typeOf(ty_op.operand);
65256610 const array_ty = operand_ty.childType(zcu);
......@@ -6584,7 +6669,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
65846669 else
65856670 unreachable;
65866671
6587 const w = f.object.writer();
6672 const w = &f.object.code.writer;
65886673 const local = try f.allocLocal(inst, inst_ty);
65896674 const v = try Vectorize.start(f, inst, w, operand_ty);
65906675 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
......@@ -6634,7 +6719,7 @@ fn airUnBuiltinCall(
66346719 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
66356720 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
66366721
6637 const w = f.object.writer();
6722 const w = &f.object.code.writer;
66386723 const local = try f.allocLocal(inst, inst_ty);
66396724 const v = try Vectorize.start(f, inst, w, operand_ty);
66406725 if (!ref_ret) {
......@@ -6653,7 +6738,8 @@ fn airUnBuiltinCall(
66536738 try f.writeCValue(w, operand, .FunctionArgument);
66546739 try v.elem(f, w);
66556740 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
6656 try w.writeAll(");\n");
6741 try w.writeAll(");");
6742 try f.object.newline();
66576743 try v.end(f, inst, w);
66586744
66596745 return local;
......@@ -6684,7 +6770,7 @@ fn airBinBuiltinCall(
66846770 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
66856771 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
66866772
6687 const w = f.object.writer();
6773 const w = &f.object.code.writer;
66886774 const local = try f.allocLocal(inst, inst_ty);
66896775 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
66906776 const v = try Vectorize.start(f, inst, w, operand_ty);
......@@ -6735,7 +6821,7 @@ fn airCmpBuiltinCall(
67356821 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
67366822 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
67376823
6738 const w = f.object.writer();
6824 const w = &f.object.code.writer;
67396825 const local = try f.allocLocal(inst, inst_ty);
67406826 const v = try Vectorize.start(f, inst, w, operand_ty);
67416827 if (!ref_ret) {
......@@ -6765,7 +6851,8 @@ fn airCmpBuiltinCall(
67656851 compareOperatorC(operator),
67666852 try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)),
67676853 });
6768 try w.writeAll(";\n");
6854 try w.writeByte(';');
6855 try f.object.newline();
67696856 try v.end(f, inst, w);
67706857
67716858 return local;
......@@ -6784,7 +6871,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
67846871 const ty = ptr_ty.childType(zcu);
67856872 const ctype = try f.ctypeFromType(ty, .complete);
67866873
6787 const w = f.object.writer();
6874 const w = &f.object.code.writer;
67886875 const new_value_mat = try Materialize.start(f, inst, ty, new_value);
67896876 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
67906877
......@@ -6823,8 +6910,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
68236910 try w.writeAll(", ");
68246911 try f.renderType(w, repr_ty);
68256912 try w.writeByte(')');
6826 try w.writeAll(") {\n");
6827 f.object.indent_writer.pushIndent();
6913 try w.writeAll(") {");
6914 f.object.indent();
6915 try f.object.newline();
68286916 {
68296917 const a = try Assignment.start(f, w, ctype);
68306918 try f.writeCValue(w, local, .Other);
......@@ -6832,8 +6920,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
68326920 try w.writeAll("NULL");
68336921 try a.end(f, w);
68346922 }
6835 f.object.indent_writer.popIndent();
6836 try w.writeAll("}\n");
6923 try f.object.outdent();
6924 try w.writeByte('}');
6925 try f.object.newline();
68376926 } else {
68386927 {
68396928 const a = try Assignment.start(f, w, ctype);
......@@ -6889,7 +6978,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
68896978 const ptr = try f.resolveInst(pl_op.operand);
68906979 const operand = try f.resolveInst(extra.operand);
68916980
6892 const w = f.object.writer();
6981 const w = &f.object.code.writer;
68936982 const operand_mat = try Materialize.start(f, inst, ty, operand);
68946983 try reap(f, inst, &.{ pl_op.operand, extra.operand });
68956984
......@@ -6923,7 +7012,8 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
69237012 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
69247013 try w.writeAll(", ");
69257014 try f.renderType(w, repr_ty);
6926 try w.writeAll(");\n");
7015 try w.writeAll(");");
7016 try f.object.newline();
69277017 try operand_mat.end(f, inst);
69287018
69297019 if (f.liveness.isUnused(inst)) {
......@@ -6949,7 +7039,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
69497039 ty;
69507040
69517041 const inst_ty = f.typeOfIndex(inst);
6952 const w = f.object.writer();
7042 const w = &f.object.code.writer;
69537043 const local = try f.allocLocal(inst, inst_ty);
69547044
69557045 try w.writeAll("zig_atomic_load(");
......@@ -6966,7 +7056,8 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
69667056 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
69677057 try w.writeAll(", ");
69687058 try f.renderType(w, repr_ty);
6969 try w.writeAll(");\n");
7059 try w.writeAll(");");
7060 try f.object.newline();
69707061
69717062 return local;
69727063}
......@@ -6980,7 +7071,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
69807071 const ptr = try f.resolveInst(bin_op.lhs);
69817072 const element = try f.resolveInst(bin_op.rhs);
69827073
6983 const w = f.object.writer();
7074 const w = &f.object.code.writer;
69847075 const element_mat = try Materialize.start(f, inst, ty, element);
69857076 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
69867077
......@@ -7001,7 +7092,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
70017092 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
70027093 try w.writeAll(", ");
70037094 try f.renderType(w, repr_ty);
7004 try w.writeAll(");\n");
7095 try w.writeAll(");");
7096 try f.object.newline();
70057097 try element_mat.end(f, inst);
70067098
70077099 return .none;
......@@ -7027,7 +7119,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
70277119 const elem_ty = f.typeOf(bin_op.rhs);
70287120 const elem_abi_size = elem_ty.abiSize(zcu);
70297121 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(zcu) else false;
7030 const w = f.object.writer();
7122 const w = &f.object.code.writer;
70317123
70327124 if (val_is_undef) {
70337125 if (!safety) {
......@@ -7042,17 +7134,18 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
70427134 try w.writeAll(", 0xaa, ");
70437135 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
70447136 if (elem_abi_size > 1) {
7045 try w.print(" * {d});\n", .{elem_abi_size});
7046 } else {
7047 try w.writeAll(");\n");
7137 try w.print(" * {d}", .{elem_abi_size});
70487138 }
7139 try w.writeAll(");");
7140 try f.object.newline();
70497141 },
70507142 .one => {
70517143 const array_ty = dest_ty.childType(zcu);
70527144 const len = array_ty.arrayLen(zcu) * elem_abi_size;
70537145
70547146 try f.writeCValue(w, dest_slice, .FunctionArgument);
7055 try w.print(", 0xaa, {d});\n", .{len});
7147 try w.print(", 0xaa, {d});", .{len});
7148 try f.object.newline();
70567149 },
70577150 .many, .c => unreachable,
70587151 }
......@@ -7122,7 +7215,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
71227215 try f.writeCValue(w, bitcasted, .FunctionArgument);
71237216 try w.writeAll(", ");
71247217 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7125 try w.writeAll(");\n");
7218 try w.writeAll(");");
7219 try f.object.newline();
71267220 },
71277221 .one => {
71287222 const array_ty = dest_ty.childType(zcu);
......@@ -7131,7 +7225,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
71317225 try f.writeCValue(w, dest_slice, .FunctionArgument);
71327226 try w.writeAll(", ");
71337227 try f.writeCValue(w, bitcasted, .FunctionArgument);
7134 try w.print(", {d});\n", .{len});
7228 try w.print(", {d});", .{len});
7229 try f.object.newline();
71357230 },
71367231 .many, .c => unreachable,
71377232 }
......@@ -7148,11 +7243,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
71487243 const src_ptr = try f.resolveInst(bin_op.rhs);
71497244 const dest_ty = f.typeOf(bin_op.lhs);
71507245 const src_ty = f.typeOf(bin_op.rhs);
7151 const w = f.object.writer();
7246 const w = &f.object.code.writer;
71527247
71537248 if (dest_ty.ptrSize(zcu) != .one) {
71547249 try w.writeAll("if (");
7155 try writeArrayLen(f, w, dest_ptr, dest_ty);
7250 try writeArrayLen(f, dest_ptr, dest_ty);
71567251 try w.writeAll(" != 0) ");
71577252 }
71587253 try w.writeAll(function_paren);
......@@ -7160,24 +7255,26 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
71607255 try w.writeAll(", ");
71617256 try writeSliceOrPtr(f, w, src_ptr, src_ty);
71627257 try w.writeAll(", ");
7163 try writeArrayLen(f, w, dest_ptr, dest_ty);
7258 try writeArrayLen(f, dest_ptr, dest_ty);
71647259 try w.writeAll(" * sizeof(");
71657260 try f.renderType(w, dest_ty.elemType2(zcu));
7166 try w.writeAll("));\n");
7261 try w.writeAll("));");
7262 try f.object.newline();
71677263
71687264 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
71697265 return .none;
71707266}
71717267
7172fn writeArrayLen(f: *Function, alw: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void {
7268fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void {
71737269 const pt = f.object.dg.pt;
71747270 const zcu = pt.zcu;
7271 const w = &f.object.code.writer;
71757272 switch (dest_ty.ptrSize(zcu)) {
7176 .one => try alw.print("{f}", .{
7273 .one => try w.print("{f}", .{
71777274 try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
71787275 }),
71797276 .many, .c => unreachable,
7180 .slice => try f.writeCValueMember(alw, dest_ptr, .{ .identifier = "len" }),
7277 .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }),
71817278 }
71827279}
71837280
......@@ -7194,7 +7291,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
71947291 if (layout.tag_size == 0) return .none;
71957292 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
71967293
7197 const w = f.object.writer();
7294 const w = &f.object.code.writer;
71987295 const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
71997296 try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" });
72007297 try a.assign(f, w);
......@@ -7216,7 +7313,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
72167313 if (layout.tag_size == 0) return .none;
72177314
72187315 const inst_ty = f.typeOfIndex(inst);
7219 const w = f.object.writer();
7316 const w = &f.object.code.writer;
72207317 const local = try f.allocLocal(inst, inst_ty);
72217318 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
72227319 try f.writeCValue(w, local, .Other);
......@@ -7234,14 +7331,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
72347331 const operand = try f.resolveInst(un_op);
72357332 try reap(f, inst, &.{un_op});
72367333
7237 const w = f.object.writer();
7334 const w = &f.object.code.writer;
72387335 const local = try f.allocLocal(inst, inst_ty);
72397336 try f.writeCValue(w, local, .Other);
72407337 try w.print(" = {s}(", .{
72417338 try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),
72427339 });
72437340 try f.writeCValue(w, operand, .Other);
7244 try w.writeAll(");\n");
7341 try w.writeAll(");");
7342 try f.object.newline();
72457343
72467344 return local;
72477345}
......@@ -7249,7 +7347,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
72497347fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
72507348 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
72517349
7252 const w = f.object.writer();
7350 const w = &f.object.code.writer;
72537351 const inst_ty = f.typeOfIndex(inst);
72547352 const operand = try f.resolveInst(un_op);
72557353 try reap(f, inst, &.{un_op});
......@@ -7258,7 +7356,8 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
72587356
72597357 try w.writeAll(" = zig_errorName[");
72607358 try f.writeCValue(w, operand, .Other);
7261 try w.writeAll(" - 1];\n");
7359 try w.writeAll(" - 1];");
7360 try f.object.newline();
72627361 return local;
72637362}
72647363
......@@ -7273,7 +7372,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
72737372 const inst_ty = f.typeOfIndex(inst);
72747373 const inst_scalar_ty = inst_ty.scalarType(zcu);
72757374
7276 const w = f.object.writer();
7375 const w = &f.object.code.writer;
72777376 const local = try f.allocLocal(inst, inst_ty);
72787377 const v = try Vectorize.start(f, inst, w, inst_ty);
72797378 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
......@@ -7298,7 +7397,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
72987397
72997398 const inst_ty = f.typeOfIndex(inst);
73007399
7301 const w = f.object.writer();
7400 const w = &f.object.code.writer;
73027401 const local = try f.allocLocal(inst, inst_ty);
73037402 const v = try Vectorize.start(f, inst, w, inst_ty);
73047403 try f.writeCValue(w, local, .Other);
......@@ -7312,7 +7411,8 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
73127411 try w.writeAll(" : ");
73137412 try f.writeCValue(w, rhs, .Other);
73147413 try v.elem(f, w);
7315 try w.writeAll(";\n");
7414 try w.writeByte(';');
7415 try f.object.newline();
73167416 try v.end(f, inst, w);
73177417
73187418 return local;
......@@ -7327,7 +7427,7 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
73277427 const operand = try f.resolveInst(unwrapped.operand);
73287428 const inst_ty = unwrapped.result_ty;
73297429
7330 const w = f.object.writer();
7430 const w = &f.object.code.writer;
73317431 const local = try f.allocLocal(inst, inst_ty);
73327432 try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand
73337433 for (mask, 0..) |mask_elem, out_idx| {
......@@ -7361,7 +7461,7 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
73617461 const inst_ty = unwrapped.result_ty;
73627462 const elem_ty = inst_ty.childType(zcu);
73637463
7364 const w = f.object.writer();
7464 const w = &f.object.code.writer;
73657465 const local = try f.allocLocal(inst, inst_ty);
73667466 try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands
73677467 for (mask, 0..) |mask_elem, out_idx| {
......@@ -7384,7 +7484,8 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
73847484 },
73857485 .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other),
73867486 }
7387 try w.writeAll(";\n");
7487 try w.writeByte(';');
7488 try f.object.newline();
73887489 }
73897490
73907491 return local;
......@@ -7399,7 +7500,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
73997500 const operand = try f.resolveInst(reduce.operand);
74007501 try reap(f, inst, &.{reduce.operand});
74017502 const operand_ty = f.typeOf(reduce.operand);
7402 const w = f.object.writer();
7503 const w = &f.object.code.writer;
74037504
74047505 const use_operator = scalar_ty.bitSize(zcu) <= 64;
74057506 const op: union(enum) {
......@@ -7486,7 +7587,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
74867587 else => unreachable,
74877588 },
74887589 }, .Other);
7489 try w.writeAll(";\n");
7590 try w.writeByte(';');
7591 try f.object.newline();
74907592
74917593 const v = try Vectorize.start(f, inst, w, operand_ty);
74927594 try f.writeCValue(w, accum, .Other);
......@@ -7520,7 +7622,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
75207622 try v.elem(f, w);
75217623 },
75227624 }
7523 try w.writeAll(";\n");
7625 try w.writeByte(';');
7626 try f.object.newline();
75247627 try v.end(f, inst, w);
75257628
75267629 return accum;
......@@ -7547,7 +7650,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
75477650 }
75487651 }
75497652
7550 const w = f.object.writer();
7653 const w = &f.object.code.writer;
75517654 const local = try f.allocLocal(inst, inst_ty);
75527655 switch (ip.indexToKey(inst_ty.toIntern())) {
75537656 inline .array_type, .vector_type => |info, tag| {
......@@ -7670,7 +7773,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
76707773 bit_offset += field_ty.bitSize(zcu);
76717774 empty = false;
76727775 }
7673 try w.writeAll(";\n");
7776 try w.writeByte(';');
7777 try f.object.newline();
76747778 },
76757779 }
76767780 },
......@@ -7705,7 +7809,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
77057809 const payload = try f.resolveInst(extra.init);
77067810 try reap(f, inst, &.{extra.init});
77077811
7708 const w = f.object.writer();
7812 const w = &f.object.code.writer;
77097813 const local = try f.allocLocal(inst, union_ty);
77107814 if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload);
77117815
......@@ -7741,7 +7845,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
77417845 const ptr = try f.resolveInst(prefetch.ptr);
77427846 try reap(f, inst, &.{prefetch.ptr});
77437847
7744 const w = f.object.writer();
7848 const w = &f.object.code.writer;
77457849 switch (prefetch.cache) {
77467850 .data => {
77477851 try w.writeAll("zig_prefetch(");
......@@ -7749,7 +7853,8 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
77497853 try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" })
77507854 else
77517855 try f.writeCValue(w, ptr, .FunctionArgument);
7752 try w.print(", {d}, {d});\n", .{ @intFromEnum(prefetch.rw), prefetch.locality });
7856 try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality });
7857 try f.object.newline();
77537858 },
77547859 // The available prefetch intrinsics do not accept a cache argument; only
77557860 // address, rw, and locality.
......@@ -7762,13 +7867,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
77627867fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
77637868 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
77647869
7765 const w = f.object.writer();
7870 const w = &f.object.code.writer;
77667871 const inst_ty = f.typeOfIndex(inst);
77677872 const local = try f.allocLocal(inst, inst_ty);
77687873 try f.writeCValue(w, local, .Other);
77697874
77707875 try w.writeAll(" = ");
7771 try w.print("zig_wasm_memory_size({d});\n", .{pl_op.payload});
7876 try w.print("zig_wasm_memory_size({d});", .{pl_op.payload});
7877 try f.object.newline();
77727878
77737879 return local;
77747880}
......@@ -7776,7 +7882,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
77767882fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
77777883 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
77787884
7779 const w = f.object.writer();
7885 const w = &f.object.code.writer;
77807886 const inst_ty = f.typeOfIndex(inst);
77817887 const operand = try f.resolveInst(pl_op.operand);
77827888 try reap(f, inst, &.{pl_op.operand});
......@@ -7786,7 +7892,8 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
77867892 try w.writeAll(" = ");
77877893 try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
77887894 try f.writeCValue(w, operand, .FunctionArgument);
7789 try w.writeAll(");\n");
7895 try w.writeAll(");");
7896 try f.object.newline();
77907897 return local;
77917898}
77927899
......@@ -7804,7 +7911,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
78047911 const inst_ty = f.typeOfIndex(inst);
78057912 const inst_scalar_ty = inst_ty.scalarType(zcu);
78067913
7807 const w = f.object.writer();
7914 const w = &f.object.code.writer;
78087915 const local = try f.allocLocal(inst, inst_ty);
78097916 const v = try Vectorize.start(f, inst, w, inst_ty);
78107917 try f.writeCValue(w, local, .Other);
......@@ -7820,7 +7927,8 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
78207927 try w.writeAll(", ");
78217928 try f.writeCValue(w, addend, .FunctionArgument);
78227929 try v.elem(f, w);
7823 try w.writeAll(");\n");
7930 try w.writeAll(");");
7931 try f.object.newline();
78247932 try v.end(f, inst, w);
78257933
78267934 return local;
......@@ -7828,12 +7936,13 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
78287936
78297937fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {
78307938 const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;
7831 const w = f.object.writer();
7939 const w = &f.object.code.writer;
78327940 const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));
78337941 try f.writeCValue(w, local, .Other);
78347942 try w.writeAll(" = ");
78357943 try f.object.dg.renderNav(w, ty_nav.nav, .Other);
7836 try w.writeAll(";\n");
7944 try w.writeByte(';');
7945 try f.object.newline();
78377946 return local;
78387947}
78397948
......@@ -7845,7 +7954,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
78457954 const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;
78467955 assert(function_info.varargs);
78477956
7848 const w = f.object.writer();
7957 const w = &f.object.code.writer;
78497958 const local = try f.allocLocal(inst, inst_ty);
78507959 try w.writeAll("va_start(*(va_list *)&");
78517960 try f.writeCValue(w, local, .Other);
......@@ -7853,7 +7962,8 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
78537962 try w.writeAll(", ");
78547963 try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);
78557964 }
7856 try w.writeAll(");\n");
7965 try w.writeAll(");");
7966 try f.object.newline();
78577967 return local;
78587968}
78597969
......@@ -7864,14 +7974,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
78647974 const va_list = try f.resolveInst(ty_op.operand);
78657975 try reap(f, inst, &.{ty_op.operand});
78667976
7867 const w = f.object.writer();
7977 const w = &f.object.code.writer;
78687978 const local = try f.allocLocal(inst, inst_ty);
78697979 try f.writeCValue(w, local, .Other);
78707980 try w.writeAll(" = va_arg(*(va_list *)");
78717981 try f.writeCValue(w, va_list, .Other);
78727982 try w.writeAll(", ");
78737983 try f.renderType(w, ty_op.ty.toType());
7874 try w.writeAll(");\n");
7984 try w.writeAll(");");
7985 try f.object.newline();
78757986 return local;
78767987}
78777988
......@@ -7881,10 +7992,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
78817992 const va_list = try f.resolveInst(un_op);
78827993 try reap(f, inst, &.{un_op});
78837994
7884 const w = f.object.writer();
7995 const w = &f.object.code.writer;
78857996 try w.writeAll("va_end(*(va_list *)");
78867997 try f.writeCValue(w, va_list, .Other);
7887 try w.writeAll(");\n");
7998 try w.writeAll(");");
7999 try f.object.newline();
78888000 return .none;
78898001}
78908002
......@@ -7895,13 +8007,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
78958007 const va_list = try f.resolveInst(ty_op.operand);
78968008 try reap(f, inst, &.{ty_op.operand});
78978009
7898 const w = f.object.writer();
8010 const w = &f.object.code.writer;
78998011 const local = try f.allocLocal(inst, inst_ty);
79008012 try w.writeAll("va_copy(*(va_list *)&");
79018013 try f.writeCValue(w, local, .Other);
79028014 try w.writeAll(", *(va_list *)");
79038015 try f.writeCValue(w, va_list, .Other);
7904 try w.writeAll(");\n");
8016 try w.writeAll(");");
8017 try f.object.newline();
79058018 return local;
79068019}
79078020
......@@ -8003,93 +8116,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {
80038116 };
80048117}
80058118
8006const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error);
8007
8008fn arrayListWriter(list: *std.ArrayList(u8)) ArrayListWriter {
8009 return .{ .context = .{
8010 .context = list,
8011 .writeFn = struct {
8012 fn write(context: *const anyopaque, bytes: []const u8) anyerror!usize {
8013 const l: *std.ArrayList(u8) = @alignCast(@constCast(@ptrCast(context)));
8014 return l.writer().write(bytes);
8015 }
8016 }.write,
8017 } };
8018}
8019
8020fn IndentWriter(comptime UnderlyingWriter: type) type {
8021 return struct {
8022 const Self = @This();
8023 pub const Error = UnderlyingWriter.Error;
8024 pub const Writer = ErrorOnlyGenericWriter(Error);
8025
8026 pub const indent_delta = 1;
8027
8028 underlying_writer: UnderlyingWriter,
8029 indent_count: usize = 0,
8030 current_line_empty: bool = true,
8031
8032 pub fn w(self: *Self) Writer {
8033 return .{ .context = .{
8034 .context = self,
8035 .writeFn = writeAny,
8036 } };
8037 }
8038
8039 pub fn write(self: *Self, bytes: []const u8) Error!usize {
8040 if (bytes.len == 0) return 0;
8041
8042 const current_indent = self.indent_count * Self.indent_delta;
8043 if (self.current_line_empty and current_indent > 0) {
8044 try self.underlying_writer.writeByteNTimes(' ', current_indent);
8045 }
8046 self.current_line_empty = false;
8047
8048 return self.writeNoIndent(bytes);
8049 }
8050
8051 fn writeAny(context: *const anyopaque, bytes: []const u8) anyerror!usize {
8052 const self: *Self = @alignCast(@constCast(@ptrCast(context)));
8053 return self.write(bytes);
8054 }
8055
8056 pub fn insertNewline(self: *Self) Error!void {
8057 _ = try self.writeNoIndent("\n");
8058 }
8059
8060 pub fn pushIndent(self: *Self) void {
8061 self.indent_count += 1;
8062 }
8063
8064 pub fn popIndent(self: *Self) void {
8065 assert(self.indent_count != 0);
8066 self.indent_count -= 1;
8067 }
8068
8069 fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
8070 if (bytes.len == 0) return 0;
8071
8072 try self.underlying_writer.writeAll(bytes);
8073 if (bytes[bytes.len - 1] == '\n') {
8074 self.current_line_empty = true;
8075 }
8076 return bytes.len;
8077 }
8078 };
8079}
8080
8081/// A wrapper around `std.io.AnyWriter` that maintains a generic error set while
8082/// erasing the rest of the implementation. This is intended to avoid duplicate
8083/// generic instantiations for w types which share the same error set, while
8084/// maintaining ease of error handling.
8085fn ErrorOnlyGenericWriter(comptime Error: type) type {
8086 return std.io.GenericWriter(std.io.AnyWriter, Error, struct {
8087 fn write(context: std.io.AnyWriter, bytes: []const u8) Error!usize {
8088 return @errorCast(context.write(bytes));
8089 }
8090 }.write);
8091}
8092
80938119fn toCIntBits(zig_bits: u32) ?u32 {
80948120 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {
80958121 if (zig_bits <= c_bits) {
......@@ -8148,7 +8174,7 @@ const StringLiteral = struct {
81488174 len: usize,
81498175 cur_len: usize,
81508176 start_count: usize,
8151 writer: *std.io.Writer,
8177 w: *Writer,
81528178
81538179 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
81548180 // regardless of the length of the string literal initializing it. Array initializer syntax is
......@@ -8161,63 +8187,63 @@ const StringLiteral = struct {
81618187 const max_char_len = 4;
81628188 const max_literal_len = @min(16380 - max_char_len, 4095);
81638189
8164 fn init(w: *std.io.Writer, len: usize) StringLiteral {
8190 fn init(w: *Writer, len: usize) StringLiteral {
81658191 return .{
81668192 .cur_len = 0,
81678193 .len = len,
81688194 .start_count = w.count,
8169 .writer = w,
8195 .w = w,
81708196 };
81718197 }
81728198
8173 pub fn start(sl: *StringLiteral) std.io.Writer.Error!void {
8199 pub fn start(sl: *StringLiteral) Writer.Error!void {
81748200 if (sl.len <= max_string_initializer_len) {
8175 try sl.writer.writeByte('\"');
8201 try sl.w.writeByte('\"');
81768202 } else {
8177 try sl.writer.writeByte('{');
8203 try sl.w.writeByte('{');
81788204 }
81798205 }
81808206
8181 pub fn end(sl: *StringLiteral) std.io.Writer.Error!void {
8207 pub fn end(sl: *StringLiteral) Writer.Error!void {
81828208 if (sl.len <= max_string_initializer_len) {
8183 try sl.writer.writeByte('\"');
8209 try sl.w.writeByte('\"');
81848210 } else {
8185 try sl.writer.writeByte('}');
8211 try sl.w.writeByte('}');
81868212 }
81878213 }
81888214
8189 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {
8215 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!void {
81908216 switch (c) {
8191 7 => try sl.writer.writeAll("\\a"),
8192 8 => try sl.writer.writeAll("\\b"),
8193 '\t' => try sl.writer.writeAll("\\t"),
8194 '\n' => try sl.writer.writeAll("\\n"),
8195 11 => try sl.writer.writeAll("\\v"),
8196 12 => try sl.writer.writeAll("\\f"),
8197 '\r' => try sl.writer.writeAll("\\r"),
8198 '"', '\'', '?', '\\' => try sl.writer.print("\\{c}", .{c}),
8217 7 => try sl.w.writeAll("\\a"),
8218 8 => try sl.w.writeAll("\\b"),
8219 '\t' => try sl.w.writeAll("\\t"),
8220 '\n' => try sl.w.writeAll("\\n"),
8221 11 => try sl.w.writeAll("\\v"),
8222 12 => try sl.w.writeAll("\\f"),
8223 '\r' => try sl.w.writeAll("\\r"),
8224 '"', '\'', '?', '\\' => try sl.w.print("\\{c}", .{c}),
81998225 else => switch (c) {
8200 ' '...'~' => try sl.writer.writeByte(c),
8201 else => try sl.writer.print("\\{o:0>3}", .{c}),
8226 ' '...'~' => try sl.w.writeByte(c),
8227 else => try sl.w.print("\\{o:0>3}", .{c}),
82028228 },
82038229 }
82048230 }
82058231
8206 pub fn writeChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {
8232 pub fn writeChar(sl: *StringLiteral, c: u8) Writer.Error!void {
82078233 if (sl.len <= max_string_initializer_len) {
8208 if (sl.cur_len == 0 and sl.writer.count - sl.start_count > 1)
8209 try sl.writer.writeAll("\"\"");
8234 if (sl.cur_len == 0 and sl.w.count - sl.start_count > 1)
8235 try sl.w.writeAll("\"\"");
82108236
8211 const count = sl.writer.count;
8237 const count = sl.w.count;
82128238 try sl.writeStringLiteralChar(c);
8213 const char_len = sl.writer.count - count;
8239 const char_len = sl.w.count - count;
82148240 assert(char_len <= max_char_len);
82158241 sl.cur_len += char_len;
82168242
82178243 if (sl.cur_len >= max_literal_len) sl.cur_len = 0;
82188244 } else {
8219 if (sl.writer.count - sl.start_count > 1) try sl.writer.writeByte(',');
8220 try sl.writer.print("'\\x{x}'", .{c});
8245 if (sl.w.count - sl.start_count > 1) try sl.w.writeByte(',');
8246 try sl.w.print("'\\x{x}'", .{c});
82218247 }
82228248 }
82238249};
......@@ -8279,7 +8305,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
82798305
82808306 var int_buf: Value.BigIntSpace = undefined;
82818307 const int = if (data.val.isUndefDeep(zcu)) blk: {
8282 undef_limbs = try oom(allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)));
8308 undef_limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)) catch return error.WriteFailed;
82838309 @memset(undef_limbs, undefPattern(BigIntLimb));
82848310
82858311 var undef_int = BigInt.Mutable{
......@@ -8297,7 +8323,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
82978323 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
82988324
82998325 var wrap = BigInt.Mutable{
8300 .limbs = try oom(allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits))),
8326 .limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)) catch return error.WriteFailed,
83018327 .len = undefined,
83028328 .positive = undefined,
83038329 };
......@@ -8351,7 +8377,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
83518377 16 => try w.writeAll("0x"),
83528378 else => unreachable,
83538379 }
8354 const string = try oom(int.abs().toStringAlloc(allocator, data.base, data.case));
8380 const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch
8381 return error.WriteFailed;
83558382 defer allocator.free(string);
83568383 try w.writeAll(string);
83578384 } else {
......@@ -8404,7 +8431,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
84048431 .int_info = c_limb_int_info,
84058432 .kind = data.kind,
84068433 .ctype = c_limb_ctype,
8407 .val = try oom(pt.intValue_big(.comptime_int, c_limb_mut.toConst())),
8434 .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch
8435 return error.WriteFailed,
84088436 .base = data.base,
84098437 .case = data.case,
84108438 }, w);
......@@ -8465,7 +8493,8 @@ const Assignment = struct {
84658493 try w.writeAll("))");
84668494 },
84678495 }
8468 try w.writeAll(";\n");
8496 try w.writeByte(';');
8497 try f.object.newline();
84698498 }
84708499
84718500 fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {
......@@ -8492,7 +8521,8 @@ const Vectorize = struct {
84928521 try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))});
84938522 try f.writeCValue(w, local, .Other);
84948523 try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)});
8495 f.object.indent_writer.pushIndent();
8524 f.object.indent();
8525 try f.object.newline();
84968526
84978527 break :index .{ .index = local };
84988528 } else .{};
......@@ -8508,8 +8538,9 @@ const Vectorize = struct {
85088538
85098539 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void {
85108540 if (self.index != .none) {
8511 f.object.indent_writer.popIndent();
8512 try w.writeAll("}\n");
8541 try f.object.outdent();
8542 try w.writeByte('}');
8543 try f.object.newline();
85138544 try freeLocal(f, inst, self.index.new_local, null);
85148545 }
85158546 }
......@@ -8617,9 +8648,3 @@ fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void {
86178648 }
86188649 map.deinit(gpa);
86198650}
8620
8621fn oom(x: anytype) error{WriteFailed}!@typeInfo(@TypeOf(x)).error_union.payload {
8622 return x catch |err| switch (err) {
8623 error.OutOfMemory => error.WriteFailed,
8624 };
8625}
src/link/C.zig+172-156
......@@ -25,34 +25,34 @@ base: link.File,
2525/// This linker backend does not try to incrementally link output C source code.
2626/// Instead, it tracks all declarations in this table, and iterates over it
2727/// in the flush function, stitching pre-rendered pieces of C code together.
28navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock) = .empty,
28navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock),
2929/// All the string bytes of rendered C code, all squished into one array.
3030/// While in progress, a separate buffer is used, and then when finished, the
3131/// buffer is copied into this one.
32string_bytes: std.ArrayListUnmanaged(u8) = .empty,
32string_bytes: std.ArrayListUnmanaged(u8),
3333/// Tracks all the anonymous decls that are used by all the decls so they can
3434/// be rendered during flush().
35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock) = .empty,
35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock),
3636/// Sparse set of uavs that are overaligned. Underaligned anon decls are
3737/// lowered the same as ABI-aligned anon decls. The keys here are a subset of
3838/// the keys of `uavs`.
39aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty,
39aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
4040
41exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock) = .empty,
42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .empty,
41exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock),
42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock),
4343
4444/// Optimization, `updateDecl` reuses this buffer rather than creating a new
4545/// one with every call.
46fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,
46fwd_decl_buf: []u8,
4747/// Optimization, `updateDecl` reuses this buffer rather than creating a new
4848/// one with every call.
49code_buf: std.ArrayListUnmanaged(u8) = .empty,
50/// Optimization, `flush` reuses this buffer rather than creating a new
49code_header_buf: []u8,
50/// Optimization, `updateDecl` reuses this buffer rather than creating a new
5151/// one with every call.
52lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,
52code_buf: []u8,
5353/// Optimization, `flush` reuses this buffer rather than creating a new
5454/// one with every call.
55lazy_code_buf: std.ArrayListUnmanaged(u8) = .empty,
55scratch_buf: []u32,
5656
5757/// A reference into `string_bytes`.
5858const String = extern struct {
......@@ -67,11 +67,11 @@ const String = extern struct {
6767
6868/// Per-declaration data.
6969pub const AvBlock = struct {
70 code: String = String.empty,
71 fwd_decl: String = String.empty,
70 fwd_decl: String = .empty,
71 code: String = .empty,
7272 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
7373 /// over each `Decl` and generate the definition for each used `CType` once.
74 ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty,
74 ctype_pool: codegen.CType.Pool = .empty,
7575 /// May contain string references to ctype_pool
7676 lazy_fns: codegen.LazyFnMap = .{},
7777
......@@ -84,20 +84,21 @@ pub const AvBlock = struct {
8484
8585/// Per-exported-symbol data.
8686pub const ExportedBlock = struct {
87 fwd_decl: String = String.empty,
87 fwd_decl: String = .empty,
8888};
8989
9090pub fn getString(this: C, s: String) []const u8 {
9191 return this.string_bytes.items[s.start..][0..s.len];
9292}
9393
94pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
94pub fn addString(this: *C, writers: []const *std.io.Writer.Allocating) Allocator.Error!String {
9595 const comp = this.base.comp;
9696 const gpa = comp.gpa;
97 try this.string_bytes.appendSlice(gpa, s);
97 const start = this.string_bytes.items.len;
98 for (writers) |writer| try this.string_bytes.appendSlice(gpa, writer.getWritten());
9899 return .{
99 .start = @intCast(this.string_bytes.items.len - s.len),
100 .len = @intCast(s.len),
100 .start = @intCast(start),
101 .len = @intCast(this.string_bytes.items.len - start),
101102 };
102103}
103104
......@@ -147,6 +148,16 @@ pub fn createEmpty(
147148 .file = file,
148149 .build_id = options.build_id,
149150 },
151 .navs = .empty,
152 .string_bytes = .empty,
153 .uavs = .empty,
154 .aligned_uavs = .empty,
155 .exported_navs = .empty,
156 .exported_uavs = .empty,
157 .fwd_decl_buf = &.{},
158 .code_header_buf = &.{},
159 .code_buf = &.{},
160 .scratch_buf = &.{},
150161 };
151162
152163 return c_file;
......@@ -170,10 +181,10 @@ pub fn deinit(self: *C) void {
170181 self.exported_uavs.deinit(gpa);
171182
172183 self.string_bytes.deinit(gpa);
173 self.fwd_decl_buf.deinit(gpa);
174 self.code_buf.deinit(gpa);
175 self.lazy_fwd_decl_buf.deinit(gpa);
176 self.lazy_code_buf.deinit(gpa);
184 gpa.free(self.fwd_decl_buf);
185 gpa.free(self.code_header_buf);
186 gpa.free(self.code_buf);
187 gpa.free(self.scratch_buf);
177188}
178189
179190pub fn updateFunc(
......@@ -196,18 +207,14 @@ pub fn updateFunc(
196207 };
197208 gop.value_ptr.code = try self.addString(mir.c.code);
198209 gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);
210 gop.value_ptr.code_header = try self.addString(mir.c.code_header);
199211 try self.addUavsFromCodegen(&mir.c.uavs);
200212}
201213
202fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
214fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void {
203215 const gpa = self.base.comp.gpa;
204216 const uav = self.uavs.keys()[i];
205217
206 const fwd_decl = &self.fwd_decl_buf;
207 const code = &self.code_buf;
208 fwd_decl.clearRetainingCapacity();
209 code.clearRetainingCapacity();
210
211218 var object: codegen.Object = .{
212219 .dg = .{
213220 .gpa = gpa,
......@@ -217,21 +224,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
217224 .pass = .{ .uav = uav },
218225 .is_naked_fn = false,
219226 .expected_block = null,
220 .fwd_decl = fwd_decl.toManaged(gpa),
221 .ctype_pool = codegen.CType.Pool.empty,
222 .scratch = .{},
227 .fwd_decl = undefined,
228 .ctype_pool = .empty,
229 .scratch = .initBuffer(self.scratch_buf),
223230 .uavs = .empty,
224231 },
225 .code = code.toManaged(gpa),
226 .indent_writer = undefined, // set later so we can get a pointer to object.code
232 .code_header = undefined,
233 .code = undefined,
234 .indent_counter = 0,
227235 };
228 object.indent_writer = .{ .underlying_writer = object.code.writer() };
236 object.dg.fwd_decl.initOwnedSlice(gpa, self.fwd_decl_buf);
237 object.code.initOwnedSlice(gpa, self.code_buf);
229238 defer {
230239 object.dg.uavs.deinit(gpa);
231 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
232240 object.dg.ctype_pool.deinit(object.dg.gpa);
233 object.dg.scratch.deinit(gpa);
234 code.* = object.code.moveToUnmanaged();
241
242 self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice();
243 self.code_buf = object.code.toArrayList().allocatedSlice();
244 self.scratch_buf = object.dg.scratch.allocatedSlice();
235245 }
236246 try object.dg.ctype_pool.init(gpa);
237247
......@@ -243,15 +253,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
243253 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
244254 //return;
245255 },
246 else => |e| return e,
256 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
247257 };
248258
249259 try self.addUavsFromCodegen(&object.dg.uavs);
250260
251261 object.dg.ctype_pool.freeUnusedCapacity(gpa);
252262 self.uavs.values()[i] = .{
253 .code = try self.addString(object.code.items),
254 .fwd_decl = try self.addString(object.dg.fwd_decl.items),
263 .fwd_decl = try self.addString(&.{&object.dg.fwd_decl}),
264 .code = try self.addString(&.{&object.code}),
255265 .ctype_pool = object.dg.ctype_pool.move(),
256266 };
257267}
......@@ -277,12 +287,8 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
277287 errdefer _ = self.navs.pop();
278288 if (!gop.found_existing) gop.value_ptr.* = .{};
279289 const ctype_pool = &gop.value_ptr.ctype_pool;
280 const fwd_decl = &self.fwd_decl_buf;
281 const code = &self.code_buf;
282290 try ctype_pool.init(gpa);
283291 ctype_pool.clearRetainingCapacity();
284 fwd_decl.clearRetainingCapacity();
285 code.clearRetainingCapacity();
286292
287293 var object: codegen.Object = .{
288294 .dg = .{
......@@ -293,22 +299,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
293299 .pass = .{ .nav = nav_index },
294300 .is_naked_fn = false,
295301 .expected_block = null,
296 .fwd_decl = fwd_decl.toManaged(gpa),
302 .fwd_decl = undefined,
297303 .ctype_pool = ctype_pool.*,
298 .scratch = .{},
304 .scratch = .initBuffer(self.scratch_buf),
299305 .uavs = .empty,
300306 },
301 .code = code.toManaged(gpa),
302 .indent_writer = undefined, // set later so we can get a pointer to object.code
307 .code_header = undefined,
308 .code = undefined,
309 .indent_counter = 0,
303310 };
304 object.indent_writer = .{ .underlying_writer = object.code.writer() };
311 object.dg.fwd_decl.initOwnedSlice(gpa, self.fwd_decl_buf);
312 object.code.initOwnedSlice(gpa, self.code_buf);
305313 defer {
306314 object.dg.uavs.deinit(gpa);
307 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
308315 ctype_pool.* = object.dg.ctype_pool.move();
309316 ctype_pool.freeUnusedCapacity(gpa);
310 object.dg.scratch.deinit(gpa);
311 code.* = object.code.moveToUnmanaged();
317
318 self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice();
319 self.code_buf = object.code.toArrayList().allocatedSlice();
320 self.scratch_buf = object.dg.scratch.allocatedSlice();
312321 }
313322
314323 codegen.genDecl(&object) catch |err| switch (err) {
......@@ -316,10 +325,10 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
316325 error.CodegenFail => return,
317326 error.OutOfMemory => |e| return e,
318327 },
319 else => |e| return e,
328 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
320329 };
321 gop.value_ptr.code = try self.addString(object.code.items);
322 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
330 gop.value_ptr.fwd_decl = try self.addString(&.{&object.dg.fwd_decl});
331 gop.value_ptr.code = try self.addString(&.{&object.code});
323332 try self.addUavsFromCodegen(&object.dg.uavs);
324333}
325334
......@@ -331,19 +340,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
331340 _ = ti_id;
332341}
333342
334fn abiDefines(self: *C, target: *const std.Target) !std.ArrayList(u8) {
335 const gpa = self.base.comp.gpa;
336 var defines = std.ArrayList(u8).init(gpa);
337 errdefer defines.deinit();
338 const writer = defines.writer();
343fn abiDefines(w: *std.io.Writer, target: std.Target) !void {
339344 switch (target.abi) {
340 .msvc, .itanium => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
345 .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"),
341346 else => {},
342347 }
343 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
348 try w.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
344349 target.cMaxIntAlignment(),
345350 });
346 return defines;
347351}
348352
349353pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
......@@ -374,37 +378,47 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
374378 // emit-h is in `flushEmitH` below.
375379
376380 var f: Flush = .{
377 .ctype_pool = codegen.CType.Pool.empty,
378 .lazy_ctype_pool = codegen.CType.Pool.empty,
381 .ctype_pool = .empty,
382 .ctype_global_from_decl_map = .empty,
383 .ctypes = .empty,
384
385 .lazy_ctype_pool = .empty,
386 .lazy_fns = .empty,
387 .lazy_fwd_decl = .empty,
388 .lazy_code = .empty,
389
390 .all_buffers = .empty,
391 .file_size = 0,
379392 };
380393 defer f.deinit(gpa);
381394
382 const abi_defines = try self.abiDefines(zcu.getTarget());
383 defer abi_defines.deinit();
395 var abi_defines_aw: std.io.Writer.Allocating = .init(gpa);
396 defer abi_defines_aw.deinit();
397 abiDefines(&abi_defines_aw.writer, zcu.getTarget()) catch |err| switch (err) {
398 error.WriteFailed => return error.OutOfMemory,
399 };
384400
385401 // Covers defines, zig.h, ctypes, asm, lazy fwd.
386402 try f.all_buffers.ensureUnusedCapacity(gpa, 5);
387403
388 f.appendBufAssumeCapacity(abi_defines.items);
404 f.appendBufAssumeCapacity(abi_defines_aw.getWritten());
389405 f.appendBufAssumeCapacity(zig_h);
390406
391407 const ctypes_index = f.all_buffers.items.len;
392408 f.all_buffers.items.len += 1;
393409
394 {
395 var asm_buf = f.asm_buf.toManaged(gpa);
396 defer f.asm_buf = asm_buf.moveToUnmanaged();
397 try codegen.genGlobalAsm(zcu, asm_buf.writer());
398 f.appendBufAssumeCapacity(asm_buf.items);
399 }
410 var asm_aw: std.io.Writer.Allocating = .init(gpa);
411 defer asm_aw.deinit();
412 codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) {
413 error.WriteFailed => return error.OutOfMemory,
414 };
415 f.appendBufAssumeCapacity(asm_aw.getWritten());
400416
401417 const lazy_index = f.all_buffers.items.len;
402418 f.all_buffers.items.len += 1;
403419
404 self.lazy_fwd_decl_buf.clearRetainingCapacity();
405 self.lazy_code_buf.clearRetainingCapacity();
406420 try f.lazy_ctype_pool.init(gpa);
407 try self.flushErrDecls(pt, &f.lazy_ctype_pool);
421 try self.flushErrDecls(pt, &f);
408422
409423 // Unlike other backends, the .c code we are emitting has order-dependent decls.
410424 // `CType`s, forward decls, and non-functions first.
......@@ -462,22 +476,15 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
462476 }
463477 }
464478
465 f.all_buffers.items[ctypes_index] = .{
466 .base = if (f.ctypes_buf.items.len > 0) f.ctypes_buf.items.ptr else "",
467 .len = f.ctypes_buf.items.len,
468 };
469 f.file_size += f.ctypes_buf.items.len;
479 f.all_buffers.items[ctypes_index] = f.ctypes.items;
480 f.file_size += f.ctypes.items.len;
470481
471 const lazy_fwd_decl_len = self.lazy_fwd_decl_buf.items.len;
472 f.all_buffers.items[lazy_index] = .{
473 .base = if (lazy_fwd_decl_len > 0) self.lazy_fwd_decl_buf.items.ptr else "",
474 .len = lazy_fwd_decl_len,
475 };
476 f.file_size += lazy_fwd_decl_len;
482 f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items;
483 f.file_size += f.lazy_fwd_decl.items.len;
477484
478485 // Now the code.
479486 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2);
480 f.appendBufAssumeCapacity(self.lazy_code_buf.items);
487 f.appendBufAssumeCapacity(f.lazy_code.items);
481488 for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity(
482489 if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) {
483490 .@"extern" => .zig_extern,
......@@ -493,31 +500,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
493500
494501 const file = self.base.file.?;
495502 file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)});
496 file.pwritevAll(f.all_buffers.items, 0) catch |err| return diags.fail("failed to write to '{f'}': {s}", .{
497 self.base.emit, @errorName(err),
498 });
503 var fw = file.writer(&.{});
504 var w = &fw.interface;
505 w.writeVecAll(f.all_buffers.items) catch |err| switch (err) {
506 error.WriteFailed => return diags.fail("failed to write to '{f'}': {s}", .{
507 self.base.emit, @errorName(fw.err.?),
508 }),
509 };
499510}
500511
501512const Flush = struct {
502513 ctype_pool: codegen.CType.Pool,
503 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .empty,
504 ctypes_buf: std.ArrayListUnmanaged(u8) = .empty,
514 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType),
515 ctypes: std.ArrayListUnmanaged(u8),
505516
506517 lazy_ctype_pool: codegen.CType.Pool,
507 lazy_fns: LazyFns = .{},
508
509 asm_buf: std.ArrayListUnmanaged(u8) = .empty,
518 lazy_fns: LazyFns,
519 lazy_fwd_decl: std.ArrayListUnmanaged(u8),
520 lazy_code: std.ArrayListUnmanaged(u8),
510521
511522 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
512 all_buffers: std.ArrayListUnmanaged(std.posix.iovec_const) = .empty,
523 all_buffers: std.ArrayListUnmanaged([]const u8),
513524 /// Keeps track of the total bytes of `all_buffers`.
514 file_size: u64 = 0,
525 file_size: u64,
515526
516527 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);
517528
518529 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
519530 if (buf.len == 0) return;
520 f.all_buffers.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len });
531 f.all_buffers.appendAssumeCapacity(buf);
521532 f.file_size += buf.len;
522533 }
523534
......@@ -532,14 +543,15 @@ const Flush = struct {
532543 }
533544
534545 fn deinit(f: *Flush, gpa: Allocator) void {
535 f.all_buffers.deinit(gpa);
536 f.asm_buf.deinit(gpa);
537 f.lazy_fns.deinit(gpa);
538 f.lazy_ctype_pool.deinit(gpa);
539 f.ctypes_buf.deinit(gpa);
546 f.ctype_pool.deinit(gpa);
540547 assert(f.ctype_global_from_decl_map.items.len == 0);
541548 f.ctype_global_from_decl_map.deinit(gpa);
542 f.ctype_pool.deinit(gpa);
549 f.ctypes.deinit(gpa);
550 f.lazy_ctype_pool.deinit(gpa);
551 f.lazy_fns.deinit(gpa);
552 f.lazy_fwd_decl.deinit(gpa);
553 f.lazy_code.deinit(gpa);
554 f.all_buffers.deinit(gpa);
543555 }
544556};
545557
......@@ -562,9 +574,9 @@ fn flushCTypes(
562574 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);
563575 defer global_from_decl_map.clearRetainingCapacity();
564576
565 var ctypes_buf = f.ctypes_buf.toManaged(gpa);
566 defer f.ctypes_buf = ctypes_buf.moveToUnmanaged();
567 const writer = ctypes_buf.writer();
577 var ctypes_aw: std.io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes);
578 const ctypes_bw = &ctypes_aw.writer;
579 defer f.ctypes = ctypes_aw.toArrayList();
568580
569581 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {
570582 const PoolAdapter = struct {
......@@ -591,26 +603,25 @@ fn flushCTypes(
591603 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },
592604 );
593605 global_from_decl_map.appendAssumeCapacity(global_ctype);
594 try codegen.genTypeDecl(
606 codegen.genTypeDecl(
595607 zcu,
596 writer,
608 ctypes_bw,
597609 global_ctype_pool,
598610 global_ctype,
599611 pass,
600612 decl_ctype_pool,
601613 decl_ctype,
602614 found_existing,
603 );
615 ) catch |err| switch (err) {
616 error.WriteFailed => return error.OutOfMemory,
617 };
604618 }
605619}
606620
607fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) FlushDeclError!void {
621fn flushErrDecls(self: *C, pt: Zcu.PerThread, f: *Flush) FlushDeclError!void {
608622 const gpa = self.base.comp.gpa;
609623
610 const fwd_decl = &self.lazy_fwd_decl_buf;
611 const code = &self.lazy_code_buf;
612
613 var object = codegen.Object{
624 var object: codegen.Object = .{
614625 .dg = .{
615626 .gpa = gpa,
616627 .pt = pt,
......@@ -619,27 +630,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
619630 .pass = .flush,
620631 .is_naked_fn = false,
621632 .expected_block = null,
622 .fwd_decl = fwd_decl.toManaged(gpa),
623 .ctype_pool = ctype_pool.*,
624 .scratch = .{},
633 .fwd_decl = undefined,
634 .ctype_pool = f.lazy_ctype_pool,
635 .scratch = .initBuffer(self.scratch_buf),
625636 .uavs = .empty,
626637 },
627 .code = code.toManaged(gpa),
628 .indent_writer = undefined, // set later so we can get a pointer to object.code
638 .code_header = undefined,
639 .code = undefined,
640 .indent_counter = 0,
629641 };
630 object.indent_writer = .{ .underlying_writer = object.code.writer() };
642 _ = object.dg.fwd_decl.fromArrayList(gpa, &f.lazy_fwd_decl);
643 _ = object.code.fromArrayList(gpa, &f.lazy_code);
631644 defer {
632645 object.dg.uavs.deinit(gpa);
633 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
634 ctype_pool.* = object.dg.ctype_pool.move();
635 ctype_pool.freeUnusedCapacity(gpa);
636 object.dg.scratch.deinit(gpa);
637 code.* = object.code.moveToUnmanaged();
646 f.lazy_ctype_pool = object.dg.ctype_pool.move();
647 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
648
649 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
650 f.lazy_code = object.code.toArrayList();
651 self.scratch_buf = object.dg.scratch.allocatedSlice();
638652 }
639653
640654 codegen.genErrDecls(&object) catch |err| switch (err) {
641655 error.AnalysisFail => unreachable,
642 else => |e| return e,
656 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
643657 };
644658
645659 try self.addUavsFromCodegen(&object.dg.uavs);
......@@ -649,16 +663,13 @@ fn flushLazyFn(
649663 self: *C,
650664 pt: Zcu.PerThread,
651665 mod: *Module,
652 ctype_pool: *codegen.CType.Pool,
666 f: *Flush,
653667 lazy_ctype_pool: *const codegen.CType.Pool,
654668 lazy_fn: codegen.LazyFnMap.Entry,
655669) FlushDeclError!void {
656670 const gpa = self.base.comp.gpa;
657671
658 const fwd_decl = &self.lazy_fwd_decl_buf;
659 const code = &self.lazy_code_buf;
660
661 var object = codegen.Object{
672 var object: codegen.Object = .{
662673 .dg = .{
663674 .gpa = gpa,
664675 .pt = pt,
......@@ -667,29 +678,32 @@ fn flushLazyFn(
667678 .pass = .flush,
668679 .is_naked_fn = false,
669680 .expected_block = null,
670 .fwd_decl = fwd_decl.toManaged(gpa),
671 .ctype_pool = ctype_pool.*,
672 .scratch = .{},
681 .fwd_decl = undefined,
682 .ctype_pool = f.lazy_ctype_pool,
683 .scratch = .initBuffer(self.scratch_buf),
673684 .uavs = .empty,
674685 },
675 .code = code.toManaged(gpa),
676 .indent_writer = undefined, // set later so we can get a pointer to object.code
686 .code_header = undefined,
687 .code = undefined,
688 .indent_counter = 0,
677689 };
678 object.indent_writer = .{ .underlying_writer = object.code.writer() };
690 _ = object.dg.fwd_decl.fromArrayList(gpa, &f.lazy_fwd_decl);
691 _ = object.code.fromArrayList(gpa, &f.lazy_code);
679692 defer {
680693 // If this assert trips just handle the anon_decl_deps the same as
681694 // `updateFunc()` does.
682695 assert(object.dg.uavs.count() == 0);
683 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
684 ctype_pool.* = object.dg.ctype_pool.move();
685 ctype_pool.freeUnusedCapacity(gpa);
686 object.dg.scratch.deinit(gpa);
687 code.* = object.code.moveToUnmanaged();
696 f.lazy_ctype_pool = object.dg.ctype_pool.move();
697 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
698
699 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
700 f.lazy_code = object.code.toArrayList();
701 self.scratch_buf = object.dg.scratch.allocatedSlice();
688702 }
689703
690704 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {
691705 error.AnalysisFail => unreachable,
692 else => |e| return e,
706 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
693707 };
694708}
695709
......@@ -709,7 +723,7 @@ fn flushLazyFns(
709723 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
710724 if (gop.found_existing) continue;
711725 gop.value_ptr.* = {};
712 try self.flushLazyFn(pt, mod, &f.lazy_ctype_pool, lazy_ctype_pool, entry);
726 try self.flushLazyFn(pt, mod, f, lazy_ctype_pool, entry);
713727 }
714728}
715729
......@@ -802,8 +816,6 @@ pub fn updateExports(
802816 },
803817 };
804818 const ctype_pool = &decl_block.ctype_pool;
805 const fwd_decl = &self.fwd_decl_buf;
806 fwd_decl.clearRetainingCapacity();
807819 var dg: codegen.DeclGen = .{
808820 .gpa = gpa,
809821 .pt = pt,
......@@ -812,20 +824,24 @@ pub fn updateExports(
812824 .pass = pass,
813825 .is_naked_fn = false,
814826 .expected_block = null,
815 .fwd_decl = fwd_decl.toManaged(gpa),
827 .fwd_decl = undefined,
816828 .ctype_pool = decl_block.ctype_pool,
817 .scratch = .{},
829 .scratch = .initBuffer(self.scratch_buf),
818830 .uavs = .empty,
819831 };
832 dg.fwd_decl.initOwnedSlice(gpa, self.fwd_decl_buf);
820833 defer {
821834 assert(dg.uavs.count() == 0);
822 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
823835 ctype_pool.* = dg.ctype_pool.move();
824836 ctype_pool.freeUnusedCapacity(gpa);
825 dg.scratch.deinit(gpa);
837
838 self.fwd_decl_buf = dg.fwd_decl.toArrayList().allocatedSlice();
839 self.scratch_buf = dg.scratch.allocatedSlice();
826840 }
827 try codegen.genExports(&dg, exported, export_indices);
828 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) };
841 codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) {
842 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
843 };
844 exported_block.* = .{ .fwd_decl = try self.addString(&.{&dg.fwd_decl}) };
829845}
830846
831847pub fn deleteExport(