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 {...@@ -56,6 +56,7 @@ pub const Mir = struct {
56 /// less than the natural alignment.56 /// less than the natural alignment.
57 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),57 uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
58 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.58 // These remaining fields are essentially just an owned version of `link.C.AvBlock`.
59 code_header: []u8,
59 code: []u8,60 code: []u8,
60 fwd_decl: []u8,61 fwd_decl: []u8,
61 ctype_pool: CType.Pool,62 ctype_pool: CType.Pool,
...@@ -63,6 +64,7 @@ pub const Mir = struct {...@@ -63,6 +64,7 @@ pub const Mir = struct {
6364
64 pub fn deinit(mir: *Mir, gpa: Allocator) void {65 pub fn deinit(mir: *Mir, gpa: Allocator) void {
65 mir.uavs.deinit(gpa);66 mir.uavs.deinit(gpa);
67 gpa.free(mir.code_header);
66 gpa.free(mir.code);68 gpa.free(mir.code);
67 gpa.free(mir.fwd_decl);69 gpa.free(mir.fwd_decl);
68 mir.ctype_pool.deinit(gpa);70 mir.ctype_pool.deinit(gpa);
...@@ -70,6 +72,8 @@ pub const Mir = struct {...@@ -70,6 +72,8 @@ pub const Mir = struct {
70 }72 }
71};73};
7274
75pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};
76
73pub const CType = @import("c/Type.zig");77pub const CType = @import("c/Type.zig");
7478
75pub const CValue = union(enum) {79pub const CValue = union(enum) {
...@@ -449,18 +453,18 @@ pub const Function = struct {...@@ -449,18 +453,18 @@ pub const Function = struct {
449 const ty = f.typeOf(ref);453 const ty = f.typeOf(ref);
450454
451 const result: CValue = if (lowersToArray(ty, pt)) result: {455 const result: CValue = if (lowersToArray(ty, pt)) result: {
452 const w = f.object.codeHeaderWriter();456 const ch = &f.object.code_header.writer;
453 const decl_c_value = try f.allocLocalValue(.{457 const decl_c_value = try f.allocLocalValue(.{
454 .ctype = try f.ctypeFromType(ty, .complete),458 .ctype = try f.ctypeFromType(ty, .complete),
455 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),459 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),
456 });460 });
457 const gpa = f.object.dg.gpa;461 const gpa = f.object.dg.gpa;
458 try f.allocs.put(gpa, decl_c_value.new_local, false);462 try f.allocs.put(gpa, decl_c_value.new_local, false);
459 try w.writeAll("static ");463 try ch.writeAll("static ");
460 try f.object.dg.renderTypeAndName(w, ty, decl_c_value, Const, .none, .complete);464 try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete);
461 try w.writeAll(" = ");465 try ch.writeAll(" = ");
462 try f.object.dg.renderValue(w, val, .StaticInitializer);466 try f.object.dg.renderValue(ch, val, .StaticInitializer);
463 try w.writeAll(";\n ");467 try ch.writeAll(";\n ");
464 break :result .{ .local = decl_c_value.new_local };468 break :result .{ .local = decl_c_value.new_local };
465 } else .{ .constant = val };469 } else .{ .constant = val };
466470
...@@ -550,7 +554,7 @@ pub const Function = struct {...@@ -550,7 +554,7 @@ pub const Function = struct {
550 w: *Writer,554 w: *Writer,
551 c_value: CValue,555 c_value: CValue,
552 member: CValue,556 member: CValue,
553 ) error{ OutOfMemory, AnalysisFail }!void {557 ) Error!void {
554 switch (c_value) {558 switch (c_value) {
555 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {559 .new_local, .local, .local_ref, .constant, .arg, .arg_array => {
556 try f.writeCValue(w, c_value, .Other);560 try f.writeCValue(w, c_value, .Other);
...@@ -581,7 +585,7 @@ pub const Function = struct {...@@ -581,7 +585,7 @@ pub const Function = struct {
581 try f.writeCValue(w, member, .Other);585 try f.writeCValue(w, member, .Other);
582 }586 }
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 {
585 return f.object.dg.fail(format, args);589 return f.object.dg.fail(format, args);
586 }590 }
587591
...@@ -672,7 +676,7 @@ pub const Function = struct {...@@ -672,7 +676,7 @@ pub const Function = struct {
672 },676 },
673 else => {},677 else => {},
674 }678 }
675 const w = f.object.writer();679 const w = &f.object.code.writer;
676 const a = try Assignment.start(f, w, ctype);680 const a = try Assignment.start(f, w, ctype);
677 try f.writeCValue(w, dst, .Other);681 try f.writeCValue(w, dst, .Other);
678 try a.assign(f, w);682 try a.assign(f, w);
...@@ -706,18 +710,32 @@ pub const Function = struct {...@@ -706,18 +710,32 @@ pub const Function = struct {
706/// It is not available when generating .h file.710/// It is not available when generating .h file.
707pub const Object = struct {711pub const Object = struct {
708 dg: DeclGen,712 dg: DeclGen,
709 /// This is a borrowed reference from `link.C`.713 code_header: std.io.Writer.Allocating,
710 code: std.ArrayList(u8),714 code: std.io.Writer.Allocating,
711 /// Goes before code. Initialized and deinitialized in `genFunc`.715 indent_counter: usize,
712 code_header: std.ArrayList(u8) = undefined,716
713 indent_writer: IndentWriter(std.ArrayList(u8).Writer),717 const indent_width = 1;
714718 const indent_char = ' ';
715 fn w(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {719
716 return o.indent_writer.writer();720 fn newline(o: *Object) !void {
717 }721 const w = &o.code.writer;
718722 try w.writeByte('\n');
719 fn codeHeaderWriter(o: *Object) ArrayListWriter {723 try w.splatByteAll(indent_char, o.indent_counter);
720 return arrayListWriter(&o.code_header);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 }
721 }739 }
722};740};
723741
...@@ -729,8 +747,7 @@ pub const DeclGen = struct {...@@ -729,8 +747,7 @@ pub const DeclGen = struct {
729 pass: Pass,747 pass: Pass,
730 is_naked_fn: bool,748 is_naked_fn: bool,
731 expected_block: ?u32,749 expected_block: ?u32,
732 /// This is a borrowed reference from `link.C`.750 fwd_decl: std.io.Writer.Allocating,
733 fwd_decl: std.ArrayList(u8),
734 error_msg: ?*Zcu.ErrorMsg,751 error_msg: ?*Zcu.ErrorMsg,
735 ctype_pool: CType.Pool,752 ctype_pool: CType.Pool,
736 scratch: std.ArrayListUnmanaged(u32),753 scratch: std.ArrayListUnmanaged(u32),
...@@ -747,11 +764,7 @@ pub const DeclGen = struct {...@@ -747,11 +764,7 @@ pub const DeclGen = struct {
747 flush,764 flush,
748 };765 };
749766
750 fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter {767 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
751 return arrayListWriter(&dg.fwd_decl);
752 }
753
754 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
755 @branchHint(.cold);768 @branchHint(.cold);
756 const zcu = dg.pt.zcu;769 const zcu = dg.pt.zcu;
757 const src_loc = zcu.navSrcLoc(dg.pass.nav);770 const src_loc = zcu.navSrcLoc(dg.pass.nav);
...@@ -764,7 +777,7 @@ pub const DeclGen = struct {...@@ -764,7 +777,7 @@ pub const DeclGen = struct {
764 w: *Writer,777 w: *Writer,
765 uav: InternPool.Key.Ptr.BaseAddr.Uav,778 uav: InternPool.Key.Ptr.BaseAddr.Uav,
766 location: ValueRenderLocation,779 location: ValueRenderLocation,
767 ) error{ OutOfMemory, AnalysisFail }!void {780 ) Error!void {
768 const pt = dg.pt;781 const pt = dg.pt;
769 const zcu = pt.zcu;782 const zcu = pt.zcu;
770 const ip = &zcu.intern_pool;783 const ip = &zcu.intern_pool;
...@@ -826,7 +839,7 @@ pub const DeclGen = struct {...@@ -826,7 +839,7 @@ pub const DeclGen = struct {
826 w: *Writer,839 w: *Writer,
827 nav_index: InternPool.Nav.Index,840 nav_index: InternPool.Nav.Index,
828 location: ValueRenderLocation,841 location: ValueRenderLocation,
829 ) error{ OutOfMemory, AnalysisFail }!void {842 ) Error!void {
830 _ = location;843 _ = location;
831 const pt = dg.pt;844 const pt = dg.pt;
832 const zcu = pt.zcu;845 const zcu = pt.zcu;
...@@ -875,7 +888,7 @@ pub const DeclGen = struct {...@@ -875,7 +888,7 @@ pub const DeclGen = struct {
875 w: *Writer,888 w: *Writer,
876 derivation: Value.PointerDeriveStep,889 derivation: Value.PointerDeriveStep,
877 location: ValueRenderLocation,890 location: ValueRenderLocation,
878 ) error{ OutOfMemory, AnalysisFail }!void {891 ) Error!void {
879 const pt = dg.pt;892 const pt = dg.pt;
880 const zcu = pt.zcu;893 const zcu = pt.zcu;
881 switch (derivation) {894 switch (derivation) {
...@@ -977,8 +990,7 @@ pub const DeclGen = struct {...@@ -977,8 +990,7 @@ pub const DeclGen = struct {
977 }990 }
978991
979 fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void {992 fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void {
980 const ip = &dg.pt.zcu.intern_pool;993 try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))});
981 try w.print("zig_error_{}", .{fmtIdentUnsolo(err_name.toSlice(ip))});
982 }994 }
983995
984 fn renderValue(996 fn renderValue(
...@@ -986,7 +998,7 @@ pub const DeclGen = struct {...@@ -986,7 +998,7 @@ pub const DeclGen = struct {
986 w: *Writer,998 w: *Writer,
987 val: Value,999 val: Value,
988 location: ValueRenderLocation,1000 location: ValueRenderLocation,
989 ) error{ OutOfMemory, AnalysisFail }!void {1001 ) Error!void {
990 const pt = dg.pt;1002 const pt = dg.pt;
991 const zcu = pt.zcu;1003 const zcu = pt.zcu;
992 const ip = &zcu.intern_pool;1004 const ip = &zcu.intern_pool;
...@@ -1056,7 +1068,7 @@ pub const DeclGen = struct {...@@ -1056,7 +1068,7 @@ pub const DeclGen = struct {
1056 .error_union => |error_union| switch (ctype.info(ctype_pool)) {1068 .error_union => |error_union| switch (ctype.info(ctype_pool)) {
1057 .basic => switch (error_union.val) {1069 .basic => switch (error_union.val) {
1058 .err_name => |err_name| try dg.renderErrorName(w, err_name),1070 .err_name => |err_name| try dg.renderErrorName(w, err_name),
1059 .payload => try w.writeAll("0"),1071 .payload => try w.writeByte('0'),
1060 },1072 },
1061 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,1073 .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
1062 .aggregate => |aggregate| {1074 .aggregate => |aggregate| {
...@@ -1212,7 +1224,7 @@ pub const DeclGen = struct {...@@ -1212,7 +1224,7 @@ pub const DeclGen = struct {
1212 .none => "true",1224 .none => "true",
1213 else => "false",1225 else => "false",
1214 }) else switch (opt.val) {1226 }) else switch (opt.val) {
1215 .none => try w.writeAll("0"),1227 .none => try w.writeByte('0'),
1216 else => |payload| switch (ip.indexToKey(payload)) {1228 else => |payload| switch (ip.indexToKey(payload)) {
1217 .undef => |err_ty| try dg.renderUndefValue(1229 .undef => |err_ty| try dg.renderUndefValue(
1218 w,1230 w,
...@@ -1543,7 +1555,7 @@ pub const DeclGen = struct {...@@ -1543,7 +1555,7 @@ pub const DeclGen = struct {
1543 try w.writeByte(')');1555 try w.writeByte(')');
1544 }1556 }
1545 try dg.renderValue(w, Value.fromInterned(un.val), location);1557 try dg.renderValue(w, Value.fromInterned(un.val), location);
1546 } else try w.writeAll("0");1558 } else try w.writeByte('0');
1547 return;1559 return;
1548 }1560 }
15491561
...@@ -1595,7 +1607,7 @@ pub const DeclGen = struct {...@@ -1595,7 +1607,7 @@ pub const DeclGen = struct {
1595 w: *Writer,1607 w: *Writer,
1596 ty: Type,1608 ty: Type,
1597 location: ValueRenderLocation,1609 location: ValueRenderLocation,
1598 ) error{ OutOfMemory, AnalysisFail }!void {1610 ) Error!void {
1599 const pt = dg.pt;1611 const pt = dg.pt;
1600 const zcu = pt.zcu;1612 const zcu = pt.zcu;
1601 const ip = &zcu.intern_pool;1613 const ip = &zcu.intern_pool;
...@@ -1938,11 +1950,11 @@ pub const DeclGen = struct {...@@ -1938,11 +1950,11 @@ pub const DeclGen = struct {
1938 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});1950 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});
19391951
1940 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {1952 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 });
1942 trailing = .maybe_space;1954 trailing = .maybe_space;
1943 }1955 }
19441956
1945 try w.print("{}", .{trailing});1957 try w.print("{f}", .{trailing});
1946 switch (name) {1958 switch (name) {
1947 .nav => |nav| try dg.renderNavName(w, nav),1959 .nav => |nav| try dg.renderNavName(w, nav),
1948 .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}),1960 .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}),
...@@ -2016,11 +2028,11 @@ pub const DeclGen = struct {...@@ -2016,11 +2028,11 @@ pub const DeclGen = struct {
2016 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |2028 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2017 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |2029 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2018 ///2030 ///
2019 fn renderType(dg: *DeclGen, w: *Writer, t: Type) error{OutOfMemory}!void {2031 fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void {
2020 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));2032 try dg.renderCType(w, try dg.ctypeFromType(t, .complete));
2021 }2033 }
20222034
2023 fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) error{OutOfMemory}!void {2035 fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void {
2024 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});2036 _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
2025 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});2037 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
2026 }2038 }
...@@ -2171,7 +2183,7 @@ pub const DeclGen = struct {...@@ -2171,7 +2183,7 @@ pub const DeclGen = struct {
2171 qualifiers: CQualifiers,2183 qualifiers: CQualifiers,
2172 alignment: Alignment,2184 alignment: Alignment,
2173 kind: CType.Kind,2185 kind: CType.Kind,
2174 ) error{ OutOfMemory, AnalysisFail }!void {2186 ) !void {
2175 try dg.renderCTypeAndName(2187 try dg.renderCTypeAndName(
2176 w,2188 w,
2177 try dg.ctypeFromType(ty, kind),2189 try dg.ctypeFromType(ty, kind),
...@@ -2191,7 +2203,7 @@ pub const DeclGen = struct {...@@ -2191,7 +2203,7 @@ pub const DeclGen = struct {
2191 name: CValue,2203 name: CValue,
2192 qualifiers: CQualifiers,2204 qualifiers: CQualifiers,
2193 alignas: CType.AlignAs,2205 alignas: CType.AlignAs,
2194 ) error{ OutOfMemory, AnalysisFail }!void {2206 ) !void {
2195 const zcu = dg.pt.zcu;2207 const zcu = dg.pt.zcu;
2196 switch (alignas.abiOrder()) {2208 switch (alignas.abiOrder()) {
2197 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),2209 .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
...@@ -2199,7 +2211,7 @@ pub const DeclGen = struct {...@@ -2199,7 +2211,7 @@ pub const DeclGen = struct {
2199 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),2211 .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
2200 }2212 }
22012213
2202 try w.print("{}", .{2214 try w.print("{f}", .{
2203 try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),2215 try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),
2204 });2216 });
2205 try dg.writeName(w, name);2217 try dg.writeName(w, name);
...@@ -2216,7 +2228,7 @@ pub const DeclGen = struct {...@@ -2216,7 +2228,7 @@ pub const DeclGen = struct {
2216 }2228 }
2217 }2229 }
22182230
2219 fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) !void {2231 fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void {
2220 switch (c_value) {2232 switch (c_value) {
2221 .none, .new_local, .local, .local_ref => unreachable,2233 .none, .new_local, .local, .local_ref => unreachable,
2222 .constant => |uav| try renderUavName(w, uav),2234 .constant => |uav| try renderUavName(w, uav),
...@@ -2271,13 +2283,18 @@ pub const DeclGen = struct {...@@ -2271,13 +2283,18 @@ pub const DeclGen = struct {
2271 w: *Writer,2283 w: *Writer,
2272 c_value: CValue,2284 c_value: CValue,
2273 member: CValue,2285 member: CValue,
2274 ) error{ OutOfMemory, AnalysisFail }!void {2286 ) Error!void {
2275 try dg.writeCValue(w, c_value);2287 try dg.writeCValue(w, c_value);
2276 try w.writeByte('.');2288 try w.writeByte('.');
2277 try dg.writeCValue(w, member);2289 try dg.writeCValue(w, member);
2278 }2290 }
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 {
2281 switch (c_value) {2298 switch (c_value) {
2282 .none,2299 .none,
2283 .new_local,2300 .new_local,
...@@ -2315,7 +2332,7 @@ pub const DeclGen = struct {...@@ -2315,7 +2332,7 @@ pub const DeclGen = struct {
2315 const zcu = dg.pt.zcu;2332 const zcu = dg.pt.zcu;
2316 const ip = &zcu.intern_pool;2333 const ip = &zcu.intern_pool;
2317 const nav = ip.getNav(nav_index);2334 const nav = ip.getNav(nav_index);
2318 const fwd = dg.fwdDeclWriter();2335 const fwd = &dg.fwd_decl.writer;
2319 try fwd.writeAll(switch (flags.linkage) {2336 try fwd.writeAll(switch (flags.linkage) {
2320 .internal => "static ",2337 .internal => "static ",
2321 .strong, .weak, .link_once => "zig_extern ",2338 .strong, .weak, .link_once => "zig_extern ",
...@@ -2353,7 +2370,7 @@ pub const DeclGen = struct {...@@ -2353,7 +2370,7 @@ pub const DeclGen = struct {
2353 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2370 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2354 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2371 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
2355 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);2372 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
2356 try w.print("{}__{d}", .{2373 try w.print("{f}__{d}", .{
2357 fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]),2374 fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]),
2358 @intFromEnum(nav_index),2375 @intFromEnum(nav_index),
2359 });2376 });
...@@ -2484,7 +2501,7 @@ fn renderFwdDeclTypeName(...@@ -2484,7 +2501,7 @@ fn renderFwdDeclTypeName(
2484 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });2501 try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });
2485 switch (fwd_decl.name) {2502 switch (fwd_decl.name) {
2486 .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),2503 .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}", .{
2488 fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),2505 fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),
2489 @intFromEnum(index),2506 @intFromEnum(index),
2490 }),2507 }),
...@@ -2498,13 +2515,13 @@ fn renderTypePrefix(...@@ -2498,13 +2515,13 @@ fn renderTypePrefix(
2498 ctype: CType,2515 ctype: CType,
2499 parent_fix: CTypeFix,2516 parent_fix: CTypeFix,
2500 qualifiers: CQualifiers,2517 qualifiers: CQualifiers,
2501) @TypeOf(w).Error!RenderCTypeTrailing {2518) Writer.Error!RenderCTypeTrailing {
2502 var trailing = RenderCTypeTrailing.maybe_space;2519 var trailing = RenderCTypeTrailing.maybe_space;
2503 switch (ctype.info(ctype_pool)) {2520 switch (ctype.info(ctype_pool)) {
2504 .basic => |basic_info| try w.writeAll(@tagName(basic_info)),2521 .basic => |basic_info| try w.writeAll(@tagName(basic_info)),
25052522
2506 .pointer => |pointer_info| {2523 .pointer => |pointer_info| {
2507 try w.print("{}*", .{try renderTypePrefix(2524 try w.print("{f}*", .{try renderTypePrefix(
2508 pass,2525 pass,
2509 ctype_pool,2526 ctype_pool,
2510 zcu,2527 zcu,
...@@ -2541,7 +2558,7 @@ fn renderTypePrefix(...@@ -2541,7 +2558,7 @@ fn renderTypePrefix(
2541 );2558 );
2542 switch (parent_fix) {2559 switch (parent_fix) {
2543 .prefix => {2560 .prefix => {
2544 try w.print("{}(", .{child_trailing});2561 try w.print("{f}(", .{child_trailing});
2545 return .no_space;2562 return .no_space;
2546 },2563 },
2547 .suffix => return child_trailing,2564 .suffix => return child_trailing,
...@@ -2593,7 +2610,7 @@ fn renderTypePrefix(...@@ -2593,7 +2610,7 @@ fn renderTypePrefix(
2593 );2610 );
2594 switch (parent_fix) {2611 switch (parent_fix) {
2595 .prefix => {2612 .prefix => {
2596 try w.print("{}(", .{child_trailing});2613 try w.print("{f}(", .{child_trailing});
2597 return .no_space;2614 return .no_space;
2598 },2615 },
2599 .suffix => return child_trailing,2616 .suffix => return child_trailing,
...@@ -2602,7 +2619,7 @@ fn renderTypePrefix(...@@ -2602,7 +2619,7 @@ fn renderTypePrefix(
2602 }2619 }
2603 var qualifier_it = qualifiers.iterator();2620 var qualifier_it = qualifiers.iterator();
2604 while (qualifier_it.next()) |qualifier| {2621 while (qualifier_it.next()) |qualifier| {
2605 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });2622 try w.print("{f}{s}", .{ trailing, @tagName(qualifier) });
2606 trailing = .maybe_space;2623 trailing = .maybe_space;
2607 }2624 }
2608 return trailing;2625 return trailing;
...@@ -2615,7 +2632,7 @@ fn renderTypeSuffix(...@@ -2615,7 +2632,7 @@ fn renderTypeSuffix(
2615 ctype: CType,2632 ctype: CType,
2616 parent_fix: CTypeFix,2633 parent_fix: CTypeFix,
2617 qualifiers: CQualifiers,2634 qualifiers: CQualifiers,
2618) @TypeOf(w).Error!void {2635) Writer.Error!void {
2619 switch (ctype.info(ctype_pool)) {2636 switch (ctype.info(ctype_pool)) {
2620 .basic, .aligned, .fwd_decl, .aggregate => {},2637 .basic, .aligned, .fwd_decl, .aggregate => {},
2621 .pointer => |pointer_info| try renderTypeSuffix(2638 .pointer => |pointer_info| try renderTypeSuffix(
...@@ -2650,7 +2667,7 @@ fn renderTypeSuffix(...@@ -2650,7 +2667,7 @@ fn renderTypeSuffix(
2650 need_comma = true;2667 need_comma = true;
2651 const trailing =2668 const trailing =
2652 try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);2669 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 });
2654 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});2671 try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});
2655 }2672 }
2656 if (function_info.varargs) {2673 if (function_info.varargs) {
...@@ -2675,7 +2692,7 @@ fn renderFields(...@@ -2675,7 +2692,7 @@ fn renderFields(
2675 try w.writeAll("{\n");2692 try w.writeAll("{\n");
2676 for (0..aggregate_info.fields.len) |field_index| {2693 for (0..aggregate_info.fields.len) |field_index| {
2677 const field_info = aggregate_info.fields.at(field_index, ctype_pool);2694 const field_info = aggregate_info.fields.at(field_index, ctype_pool);
2678 try w.writeByteNTimes(' ', indent + 1);2695 try w.splatByteAll(' ', indent + 1);
2679 switch (field_info.alignas.abiOrder()) {2696 switch (field_info.alignas.abiOrder()) {
2680 .lt => {2697 .lt => {
2681 std.debug.assert(aggregate_info.@"packed");2698 std.debug.assert(aggregate_info.@"packed");
...@@ -2699,11 +2716,11 @@ fn renderFields(...@@ -2699,11 +2716,11 @@ fn renderFields(
2699 .suffix,2716 .suffix,
2700 .{},2717 .{},
2701 );2718 );
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) });
2703 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});2720 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});
2704 try w.writeAll(";\n");2721 try w.writeAll(";\n");
2705 }2722 }
2706 try w.writeByteNTimes(' ', indent);2723 try w.splatByteAll(' ', indent);
2707 try w.writeByte('}');2724 try w.writeByte('}');
2708}2725}
27092726
...@@ -2723,7 +2740,7 @@ pub fn genTypeDecl(...@@ -2723,7 +2740,7 @@ pub fn genTypeDecl(
2723 if (!found_existing) {2740 if (!found_existing) {
2724 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));2741 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
2725 try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});2742 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(
2727 .flush,2744 .flush,
2728 global_ctype_pool,2745 global_ctype_pool,
2729 zcu,2746 zcu,
...@@ -2764,7 +2781,7 @@ pub fn genTypeDecl(...@@ -2764,7 +2781,7 @@ pub fn genTypeDecl(
2764 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});2781 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
2765 try w.writeByte(';');2782 try w.writeByte(';');
2766 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);2783 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} */", .{
2768 ty.containerTypeName(ip).fmt(ip),2785 ty.containerTypeName(ip).fmt(ip),
2769 });2786 });
2770 try w.writeByte('\n');2787 try w.writeByte('\n');
...@@ -2795,18 +2812,19 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {...@@ -2795,18 +2812,19 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
2795 }2812 }
2796}2813}
27972814
2798pub fn genErrDecls(o: *Object) !void {2815pub fn genErrDecls(o: *Object) Error!void {
2799 const pt = o.dg.pt;2816 const pt = o.dg.pt;
2800 const zcu = pt.zcu;2817 const zcu = pt.zcu;
2801 const ip = &zcu.intern_pool;2818 const ip = &zcu.intern_pool;
2802 const w = o.writer();2819 const w = &o.code.writer;
28032820
2804 var max_name_len: usize = 0;2821 var max_name_len: usize = 0;
2805 // do not generate an invalid empty enum when the global error set is empty2822 // do not generate an invalid empty enum when the global error set is empty
2806 const names = ip.global_error_set.getNamesFromMainThread();2823 const names = ip.global_error_set.getNamesFromMainThread();
2807 if (names.len > 0) {2824 if (names.len > 0) {
2808 try w.writeAll("enum {\n");2825 try w.writeAll("enum {");
2809 o.indent_writer.pushIndent();2826 o.indent();
2827 try o.newline();
2810 for (names, 1..) |name_nts, value| {2828 for (names, 1..) |name_nts, value| {
2811 const name = name_nts.toSlice(ip);2829 const name = name_nts.toSlice(ip);
2812 max_name_len = @max(name.len, max_name_len);2830 max_name_len = @max(name.len, max_name_len);
...@@ -2815,10 +2833,12 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2815,10 +2833,12 @@ pub fn genErrDecls(o: *Object) !void {
2815 .name = name_nts,2833 .name = name_nts,
2816 } });2834 } });
2817 try o.dg.renderValue(w, Value.fromInterned(err_val), .Other);2835 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();
2819 }2838 }
2820 o.indent_writer.popIndent();2839 try o.outdent();
2821 try w.writeAll("};\n");2840 try w.writeAll("};");
2841 try o.newline();
2822 }2842 }
2823 const array_identifier = "zig_errorName";2843 const array_identifier = "zig_errorName";
2824 const name_prefix = array_identifier ++ "_";2844 const name_prefix = array_identifier ++ "_";
...@@ -2852,7 +2872,8 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2852,7 +2872,8 @@ pub fn genErrDecls(o: *Object) !void {
2852 );2872 );
2853 try w.writeAll(" = ");2873 try w.writeAll(" = ");
2854 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);2874 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
2855 try w.writeAll(";\n");2875 try w.writeByte(';');
2876 try o.newline();
2856 }2877 }
28572878
2858 const name_array_ty = try pt.arrayType(.{2879 const name_array_ty = try pt.arrayType(.{
...@@ -2878,15 +2899,16 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2878,15 +2899,16 @@ pub fn genErrDecls(o: *Object) !void {
2878 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer),2899 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer),
2879 });2900 });
2880 }2901 }
2881 try w.writeAll("};\n");2902 try w.writeAll("};");
2903 try o.newline();
2882}2904}
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 {
2885 const pt = o.dg.pt;2907 const pt = o.dg.pt;
2886 const zcu = pt.zcu;2908 const zcu = pt.zcu;
2887 const ip = &zcu.intern_pool;2909 const ip = &zcu.intern_pool;
2888 const ctype_pool = &o.dg.ctype_pool;2910 const ctype_pool = &o.dg.ctype_pool;
2889 const w = o.writer();2911 const w = &o.code.writer;
2890 const key = lazy_fn.key_ptr.*;2912 const key = lazy_fn.key_ptr.*;
2891 const val = lazy_fn.value_ptr;2913 const val = lazy_fn.value_ptr;
2892 switch (key) {2914 switch (key) {
...@@ -2896,9 +2918,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2896,9 +2918,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28962918
2897 try w.writeAll("static ");2919 try w.writeAll("static ");
2898 try o.dg.renderType(w, name_slice_ty);2920 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)});
2900 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);2922 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();
2902 const tag_names = enum_ty.enumFields(zcu);2929 const tag_names = enum_ty.enumFields(zcu);
2903 for (0..tag_names.len) |tag_index| {2930 for (0..tag_names.len) |tag_index| {
2904 const tag_name = tag_names.get(ip)[tag_index];2931 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...@@ -2915,26 +2942,35 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2915 .storage = .{ .bytes = tag_name.toString() },2942 .storage = .{ .bytes = tag_name.toString() },
2916 } });2943 } });
29172944
2918 try w.print(" case {f}: {{\n static ", .{2945 try w.print("case {f}: {{", .{
2919 try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other),2946 try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other),
2920 });2947 });
2948 o.indent();
2949 try o.newline();
2950 try w.writeAll("static ");
2921 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);2951 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
2922 try w.writeAll(" = ");2952 try w.writeAll(" = ");
2923 try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);2953 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 (");
2925 try o.dg.renderType(w, name_slice_ty);2957 try o.dg.renderType(w, name_slice_ty);
2926 try w.print("){{{f}, {f}}};\n", .{2958 try w.print("){{{f}, {f}}};", .{
2927 fmtIdentUnsolo("name"),2959 fmtIdentUnsolo("name"),
2928 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other),2960 try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other),
2929 });2961 });
29302962 try o.newline();
2931 try w.writeAll(" }\n");2963 try o.outdent();
2964 try w.writeByte('}');
2965 try o.newline();
2932 }2966 }
2933 try w.writeAll(" }\n while (");2967 try o.outdent();
2934 try o.dg.renderValue(w, Value.true, .Other);2968 try w.writeByte('}');
2935 try w.writeAll(") ");2969 try o.newline();
2936 _ = try airBreakpoint(w);2970 try airUnreach(o);
2937 try w.writeAll("}\n");2971 try o.outdent();
2972 try w.writeByte('}');
2973 try o.newline();
2938 },2974 },
2939 .never_tail, .never_inline => |fn_nav_index| {2975 .never_tail, .never_inline => |fn_nav_index| {
2940 const fn_val = zcu.navValue(fn_nav_index);2976 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...@@ -2942,7 +2978,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2942 const fn_info = fn_ctype.info(ctype_pool).function;2978 const fn_info = fn_ctype.info(ctype_pool).function;
2943 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true);2979 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;
2946 try fwd.print("static zig_{s} ", .{@tagName(key)});2982 try fwd.print("static zig_{s} ", .{@tagName(key)});
2947 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{2983 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
2948 .fmt_ctype_pool_string = fn_name,2984 .fmt_ctype_pool_string = fn_name,
...@@ -2953,14 +2989,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2953,14 +2989,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2953 try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{2989 try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{
2954 .fmt_ctype_pool_string = fn_name,2990 .fmt_ctype_pool_string = fn_name,
2955 });2991 });
2956 try w.writeAll(" {\n return ");2992 try w.writeAll(" {");
2993 o.indent();
2994 try o.newline();
2995 try w.writeAll("return ");
2957 try o.dg.renderNavName(w, fn_nav_index);2996 try o.dg.renderNavName(w, fn_nav_index);
2958 try w.writeByte('(');2997 try w.writeByte('(');
2959 for (0..fn_info.param_ctypes.len) |arg| {2998 for (0..fn_info.param_ctypes.len) |arg| {
2960 if (arg > 0) try w.writeAll(", ");2999 if (arg > 0) try w.writeAll(", ");
2961 try w.print("a{d}", .{arg});3000 try w.print("a{d}", .{arg});
2962 }3001 }
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();
2964 },3007 },
2965 }3008 }
2966}3009}
...@@ -2995,18 +3038,20 @@ pub fn generate(...@@ -2995,18 +3038,20 @@ pub fn generate(
2995 .pass = .{ .nav = func.owner_nav },3038 .pass = .{ .nav = func.owner_nav },
2996 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,3039 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
2997 .expected_block = null,3040 .expected_block = null,
2998 .fwd_decl = .init(gpa),3041 .fwd_decl = undefined,
2999 .ctype_pool = .empty,3042 .ctype_pool = .empty,
3000 .scratch = .empty,3043 .scratch = .empty,
3001 .uavs = .empty,3044 .uavs = .empty,
3002 },3045 },
3003 .code = .init(gpa),3046 .code_header = undefined,
3004 .indent_writer = undefined, // set later so we can get a pointer to object.code3047 .code = undefined,
3048 .indent_counter = 0,
3005 },3049 },
3006 .lazy_fns = .empty,3050 .lazy_fns = .empty,
3007 };3051 };
3008 defer {3052 defer {
3009 function.object.code.deinit();3053 function.object.code_header.init(gpa);
3054 function.object.code.init(gpa);
3010 function.object.dg.fwd_decl.deinit();3055 function.object.dg.fwd_decl.deinit();
3011 function.object.dg.ctype_pool.deinit(gpa);3056 function.object.dg.ctype_pool.deinit(gpa);
3012 function.object.dg.scratch.deinit(gpa);3057 function.object.dg.scratch.deinit(gpa);
...@@ -3014,7 +3059,9 @@ pub fn generate(...@@ -3014,7 +3059,9 @@ pub fn generate(
3014 function.deinit();3059 function.deinit();
3015 }3060 }
3016 try function.object.dg.ctype_pool.init(gpa);3061 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
3019 genFunc(&function) catch |err| switch (err) {3066 genFunc(&function) catch |err| switch (err) {
3020 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),3067 error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
...@@ -3030,6 +3077,7 @@ pub fn generate(...@@ -3030,6 +3077,7 @@ pub fn generate(
3030 };3077 };
3031 errdefer mir.deinit(gpa);3078 errdefer mir.deinit(gpa);
3032 mir.uavs = function.object.dg.uavs.move();3079 mir.uavs = function.object.dg.uavs.move();
3080 mir.code_header = try function.object.code_header.toOwnedSlice();
3033 mir.code = try function.object.code.toOwnedSlice();3081 mir.code = try function.object.code.toOwnedSlice();
3034 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();3082 mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
3035 mir.ctype_pool = function.object.dg.ctype_pool.move();3083 mir.ctype_pool = function.object.dg.ctype_pool.move();
...@@ -3037,7 +3085,7 @@ pub fn generate(...@@ -3037,7 +3085,7 @@ pub fn generate(
3037 return mir;3085 return mir;
3038}3086}
30393087
3040fn genFunc(f: *Function) !void {3088pub fn genFunc(f: *Function) Error!void {
3041 const tracy = trace(@src());3089 const tracy = trace(@src());
3042 defer tracy.end();3090 defer tracy.end();
30433091
...@@ -3049,10 +3097,7 @@ fn genFunc(f: *Function) !void {...@@ -3049,10 +3097,7 @@ fn genFunc(f: *Function) !void {
3049 const nav_val = zcu.navValue(nav_index);3097 const nav_val = zcu.navValue(nav_index);
3050 const nav = ip.getNav(nav_index);3098 const nav = ip.getNav(nav_index);
30513099
3052 o.code_header = std.ArrayList(u8).init(gpa);3100 const fwd = &o.dg.fwd_decl.writer;
3053 defer o.code_header.deinit();
3054
3055 const fwd = o.dg.fwdDeclWriter();
3056 try fwd.writeAll("static ");3101 try fwd.writeAll("static ");
3057 try o.dg.renderFunctionSignature(3102 try o.dg.renderFunctionSignature(
3058 fwd,3103 fwd,
...@@ -3063,29 +3108,26 @@ fn genFunc(f: *Function) !void {...@@ -3063,29 +3108,26 @@ fn genFunc(f: *Function) !void {
3063 );3108 );
3064 try fwd.writeAll(";\n");3109 try fwd.writeAll(";\n");
30653110
3111 const ch = &o.code_header.writer;
3066 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|3112 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)});
3068 try o.dg.renderFunctionSignature(3114 try o.dg.renderFunctionSignature(
3069 o.writer(),3115 ch,
3070 nav_val,3116 nav_val,
3071 .none,3117 .none,
3072 .complete,3118 .complete,
3073 .{ .nav = nav_index },3119 .{ .nav = nav_index },
3074 );3120 );
3075 try o.writer().writeByte(' ');3121 try ch.writeAll(" {\n ");
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;
30833122
3084 f.free_locals_map.clearRetainingCapacity();3123 f.free_locals_map.clearRetainingCapacity();
30853124
3086 const main_body = f.air.getMainBody();3125 const main_body = f.air.getMainBody();
3087 try genBodyResolveState(f, undefined, &.{}, main_body, false);3126 o.indent();
3088 try o.indent_writer.insertNewline();3127 try genBodyResolveState(f, undefined, &.{}, main_body, true);
3128 try o.outdent();
3129 try o.code.writer.writeByte('}');
3130 try o.newline();
3089 if (o.dg.expected_block) |_|3131 if (o.dg.expected_block) |_|
3090 return f.fail("runtime code not allowed in naked function", .{});3132 return f.fail("runtime code not allowed in naked function", .{});
30913133
...@@ -3116,24 +3158,16 @@ fn genFunc(f: *Function) !void {...@@ -3116,24 +3158,16 @@ fn genFunc(f: *Function) !void {
3116 };3158 };
3117 free_locals.sort(SortContext{ .keys = free_locals.keys() });3159 free_locals.sort(SortContext{ .keys = free_locals.keys() });
31183160
3119 const w = o.codeHeaderWriter();
3120 for (free_locals.values()) |list| {3161 for (free_locals.values()) |list| {
3121 for (list.keys()) |local_index| {3162 for (list.keys()) |local_index| {
3122 const local = f.locals.items[local_index];3163 const local = f.locals.items[local_index];
3123 try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);3164 try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
3124 try w.writeAll(";\n ");3165 try ch.writeAll(";\n ");
3125 }3166 }
3126 }3167 }
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 }
3134}3168}
31353169
3136pub fn genDecl(o: *Object) !void {3170pub fn genDecl(o: *Object) Error!void {
3137 const tracy = trace(@src());3171 const tracy = trace(@src());
3138 defer tracy.end();3172 defer tracy.end();
31393173
...@@ -3153,7 +3187,7 @@ pub fn genDecl(o: *Object) !void {...@@ -3153,7 +3187,7 @@ pub fn genDecl(o: *Object) !void {
3153 .visibility = @"extern".visibility,3187 .visibility = @"extern".visibility,
3154 });3188 });
31553189
3156 const fwd = o.dg.fwdDeclWriter();3190 const fwd = &o.dg.fwd_decl.writer;
3157 try fwd.writeAll("zig_extern ");3191 try fwd.writeAll("zig_extern ");
3158 try o.dg.renderFunctionSignature(3192 try o.dg.renderFunctionSignature(
3159 fwd,3193 fwd,
...@@ -3174,7 +3208,7 @@ pub fn genDecl(o: *Object) !void {...@@ -3174,7 +3208,7 @@ pub fn genDecl(o: *Object) !void {
3174 .linkage = .internal,3208 .linkage = .internal,
3175 .visibility = .default,3209 .visibility = .default,
3176 });3210 });
3177 const w = o.writer();3211 const w = &o.code.writer;
3178 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");3212 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
3179 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|3213 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
3180 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});3214 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
...@@ -3189,7 +3223,7 @@ pub fn genDecl(o: *Object) !void {...@@ -3189,7 +3223,7 @@ pub fn genDecl(o: *Object) !void {
3189 try w.writeAll(" = ");3223 try w.writeAll(" = ");
3190 try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);3224 try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);
3191 try w.writeByte(';');3225 try w.writeByte(';');
3192 try o.indent_writer.insertNewline();3226 try o.newline();
3193 },3227 },
3194 else => try genDeclValue(3228 else => try genDeclValue(
3195 o,3229 o,
...@@ -3207,28 +3241,29 @@ pub fn genDeclValue(...@@ -3207,28 +3241,29 @@ pub fn genDeclValue(
3207 decl_c_value: CValue,3241 decl_c_value: CValue,
3208 alignment: Alignment,3242 alignment: Alignment,
3209 @"linksection": InternPool.OptionalNullTerminatedString,3243 @"linksection": InternPool.OptionalNullTerminatedString,
3210) !void {3244) Error!void {
3211 const zcu = o.dg.pt.zcu;3245 const zcu = o.dg.pt.zcu;
3212 const ty = val.typeOf(zcu);3246 const ty = val.typeOf(zcu);
32133247
3214 const fwd = o.dg.fwdDeclWriter();3248 const fwd = &o.dg.fwd_decl.writer;
3215 try fwd.writeAll("static ");3249 try fwd.writeAll("static ");
3216 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);3250 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
3217 try fwd.writeAll(";\n");3251 try fwd.writeAll(";\n");
32183252
3219 const w = o.writer();3253 const w = &o.code.writer;
3220 if (@"linksection".toSlice(&zcu.intern_pool)) |s|3254 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
3221 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});3255 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
3222 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);3256 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
3223 try w.writeAll(" = ");3257 try w.writeAll(" = ");
3224 try o.dg.renderValue(w, val, .StaticInitializer);3258 try o.dg.renderValue(w, val, .StaticInitializer);
3225 try w.writeAll(";\n");3259 try w.writeByte(';');
3260 try o.newline();
3226}3261}
32273262
3228pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {3263pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {
3229 const zcu = dg.pt.zcu;3264 const zcu = dg.pt.zcu;
3230 const ip = &zcu.intern_pool;3265 const ip = &zcu.intern_pool;
3231 const fwd = dg.fwdDeclWriter();3266 const fwd = &dg.fwd_decl.writer;
32323267
3233 const main_name = export_indices[0].ptr(zcu).opts.name;3268 const main_name = export_indices[0].ptr(zcu).opts.name;
3234 try fwd.writeAll("#define ");3269 try fwd.writeAll("#define ");
...@@ -3305,15 +3340,16 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3305,15 +3340,16 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3305/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not3340/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not
3306/// have been added to `free_locals_map`. For a version of this function that restores this state,3341/// have been added to `free_locals_map`. For a version of this function that restores this state,
3307/// see `genBodyResolveState`.3342/// see `genBodyResolveState`.
3308fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {3343fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void {
3309 const w = f.object.writer();3344 const w = &f.object.code.writer;
3310 if (body.len == 0) {3345 if (body.len == 0) {
3311 try w.writeAll("{}");3346 try w.writeAll("{}");
3312 } else {3347 } else {
3313 try w.writeAll("{\n");3348 try w.writeByte('{');
3314 f.object.indent_writer.pushIndent();3349 f.object.indent();
3350 try f.object.newline();
3315 try genBodyInner(f, body);3351 try genBodyInner(f, body);
3316 f.object.indent_writer.popIndent();3352 try f.object.outdent();
3317 try w.writeByte('}');3353 try w.writeByte('}');
3318 }3354 }
3319}3355}
...@@ -3324,10 +3360,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -3324,10 +3360,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
3324/// `leading_deaths` have their deaths processed before the body is generated.3360/// `leading_deaths` have their deaths processed before the body is generated.
3325/// A scope is introduced (using braces) only if `inner` is `false`.3361/// A scope is introduced (using braces) only if `inner` is `false`.
3326/// If `leading_deaths` is empty, `inst` may be `undefined`.3362/// 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 {
3328 if (body.len == 0) {3364 if (body.len == 0) {
3329 // Don't go to the expense of cloning everything!3365 // 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("{}");
3331 return;3367 return;
3332 }3368 }
33333369
...@@ -3373,7 +3409,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con...@@ -3373,7 +3409,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
3373 }3409 }
3374}3410}
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 {
3377 const zcu = f.object.dg.pt.zcu;3413 const zcu = f.object.dg.pt.zcu;
3378 const ip = &zcu.intern_pool;3414 const ip = &zcu.intern_pool;
3379 const air_tags = f.air.instructions.items(.tag);3415 const air_tags = f.air.instructions.items(.tag);
...@@ -3391,7 +3427,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3391,7 +3427,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
33913427
3392 .arg => try airArg(f, inst),3428 .arg => try airArg(f, inst),
33933429
3394 .breakpoint => try airBreakpoint(f.object.writer()),3430 .breakpoint => try airBreakpoint(f),
3395 .ret_addr => try airRetAddr(f, inst),3431 .ret_addr => try airRetAddr(f, inst),
3396 .frame_addr => try airFrameAddress(f, inst),3432 .frame_addr => try airFrameAddress(f, inst),
33973433
...@@ -3644,8 +3680,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3644,8 +3680,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3644 .ret => return airRet(f, inst, false),3680 .ret => return airRet(f, inst, false),
3645 .ret_safe => return airRet(f, inst, false), // TODO3681 .ret_safe => return airRet(f, inst, false), // TODO
3646 .ret_load => return airRet(f, inst, true),3682 .ret_load => return airRet(f, inst, true),
3647 .trap => return airTrap(f, f.object.writer()),3683 .trap => return airTrap(f, &f.object.code.writer),
3648 .unreach => return airUnreach(f),3684 .unreach => return airUnreach(&f.object),
36493685
3650 // Instructions which may be `noreturn`.3686 // Instructions which may be `noreturn`.
3651 .block => res: {3687 .block => res: {
...@@ -3688,7 +3724,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -3688,7 +3724,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
3688 const operand = try f.resolveInst(ty_op.operand);3724 const operand = try f.resolveInst(ty_op.operand);
3689 try reap(f, inst, &.{ty_op.operand});3725 try reap(f, inst, &.{ty_op.operand});
36903726
3691 const w = f.object.writer();3727 const w = &f.object.code.writer;
3692 const local = try f.allocLocal(inst, inst_ty);3728 const local = try f.allocLocal(inst, inst_ty);
3693 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3729 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3694 try f.writeCValue(w, local, .Other);3730 try f.writeCValue(w, local, .Other);
...@@ -3714,7 +3750,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3714,7 +3750,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3714 const index = try f.resolveInst(bin_op.rhs);3750 const index = try f.resolveInst(bin_op.rhs);
3715 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3751 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37163752
3717 const w = f.object.writer();3753 const w = &f.object.code.writer;
3718 const local = try f.allocLocal(inst, inst_ty);3754 const local = try f.allocLocal(inst, inst_ty);
3719 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3755 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3720 try f.writeCValue(w, local, .Other);3756 try f.writeCValue(w, local, .Other);
...@@ -3741,7 +3777,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3741,7 +3777,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3741 const index = try f.resolveInst(bin_op.rhs);3777 const index = try f.resolveInst(bin_op.rhs);
3742 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3778 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37433779
3744 const w = f.object.writer();3780 const w = &f.object.code.writer;
3745 const local = try f.allocLocal(inst, inst_ty);3781 const local = try f.allocLocal(inst, inst_ty);
3746 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3782 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3747 try f.writeCValue(w, local, .Other);3783 try f.writeCValue(w, local, .Other);
...@@ -3776,7 +3812,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3776,7 +3812,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3776 const index = try f.resolveInst(bin_op.rhs);3812 const index = try f.resolveInst(bin_op.rhs);
3777 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3813 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37783814
3779 const w = f.object.writer();3815 const w = &f.object.code.writer;
3780 const local = try f.allocLocal(inst, inst_ty);3816 const local = try f.allocLocal(inst, inst_ty);
3781 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3817 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3782 try f.writeCValue(w, local, .Other);3818 try f.writeCValue(w, local, .Other);
...@@ -3804,7 +3840,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3804,7 +3840,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3804 const index = try f.resolveInst(bin_op.rhs);3840 const index = try f.resolveInst(bin_op.rhs);
3805 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3841 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38063842
3807 const w = f.object.writer();3843 const w = &f.object.code.writer;
3808 const local = try f.allocLocal(inst, inst_ty);3844 const local = try f.allocLocal(inst, inst_ty);
3809 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3845 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3810 try f.writeCValue(w, local, .Other);3846 try f.writeCValue(w, local, .Other);
...@@ -3833,7 +3869,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3833,7 +3869,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3833 const index = try f.resolveInst(bin_op.rhs);3869 const index = try f.resolveInst(bin_op.rhs);
3834 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3870 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38353871
3836 const w = f.object.writer();3872 const w = &f.object.code.writer;
3837 const local = try f.allocLocal(inst, inst_ty);3873 const local = try f.allocLocal(inst, inst_ty);
3838 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));3874 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
3839 try f.writeCValue(w, local, .Other);3875 try f.writeCValue(w, local, .Other);
...@@ -3896,12 +3932,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3896,12 +3932,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3896 .{ .arg_array = i };3932 .{ .arg_array = i };
38973933
3898 if (f.liveness.isUnused(inst)) {3934 if (f.liveness.isUnused(inst)) {
3899 const w = f.object.writer();3935 const w = &f.object.code.writer;
3900 try w.writeByte('(');3936 try w.writeByte('(');
3901 try f.renderType(w, .void);3937 try f.renderType(w, .void);
3902 try w.writeByte(')');3938 try w.writeByte(')');
3903 try f.writeCValue(w, result, .Other);3939 try f.writeCValue(w, result, .Other);
3904 try w.writeAll(";\n");3940 try w.writeByte(';');
3941 try f.object.newline();
3905 return .none;3942 return .none;
3906 }3943 }
39073944
...@@ -3934,7 +3971,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3934,7 +3971,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3934 const is_array = lowersToArray(src_ty, pt);3971 const is_array = lowersToArray(src_ty, pt);
3935 const need_memcpy = !is_aligned or is_array;3972 const need_memcpy = !is_aligned or is_array;
39363973
3937 const w = f.object.writer();3974 const w = &f.object.code.writer;
3938 const local = try f.allocLocal(inst, src_ty);3975 const local = try f.allocLocal(inst, src_ty);
3939 const v = try Vectorize.start(f, inst, w, ptr_ty);3976 const v = try Vectorize.start(f, inst, w, ptr_ty);
39403977
...@@ -3979,7 +4016,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3979,7 +4016,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3979 try w.writeByte('(');4016 try w.writeByte('(');
3980 try f.writeCValueDeref(w, operand);4017 try f.writeCValueDeref(w, operand);
3981 try v.elem(f, w);4018 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)});
3983 if (cant_cast) try w.writeByte(')');4020 if (cant_cast) try w.writeByte(')');
3984 try f.object.dg.renderBuiltinInfo(w, field_ty, .bits);4021 try f.object.dg.renderBuiltinInfo(w, field_ty, .bits);
3985 try w.writeByte(')');4022 try w.writeByte(')');
...@@ -3990,7 +4027,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3990,7 +4027,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3990 try f.writeCValueDeref(w, operand);4027 try f.writeCValueDeref(w, operand);
3991 try v.elem(f, w);4028 try v.elem(f, w);
3992 }4029 }
3993 try w.writeAll(";\n");4030 try w.writeByte(';');
4031 try f.object.newline();
3994 try v.end(f, inst, w);4032 try v.end(f, inst, w);
39954033
3996 return local;4034 return local;
...@@ -4000,7 +4038,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -4000,7 +4038,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
4000 const pt = f.object.dg.pt;4038 const pt = f.object.dg.pt;
4001 const zcu = pt.zcu;4039 const zcu = pt.zcu;
4002 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;4040 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;
4004 const op_inst = un_op.toIndex();4042 const op_inst = un_op.toIndex();
4005 const op_ty = f.typeOf(un_op);4043 const op_ty = f.typeOf(un_op);
4006 const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;4044 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 {...@@ -4029,7 +4067,8 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
4029 deref = false;4067 deref = false;
4030 try w.writeAll(", sizeof(");4068 try w.writeAll(", sizeof(");
4031 try f.renderType(w, ret_ty);4069 try f.renderType(w, ret_ty);
4032 try w.writeAll("));\n");4070 try w.writeAll("));");
4071 try f.object.newline();
4033 break :ret_val array_local;4072 break :ret_val array_local;
4034 } else operand;4073 } else operand;
40354074
...@@ -4038,7 +4077,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -4038,7 +4077,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
4038 try f.writeCValueDeref(w, ret_val)4077 try f.writeCValueDeref(w, ret_val)
4039 else4078 else
4040 try f.writeCValue(w, ret_val, .Other);4079 try f.writeCValue(w, ret_val, .Other);
4041 try w.writeAll(";\n");4080 try w.write(";\n");
4042 if (is_array) {4081 if (is_array) {
4043 try freeLocal(f, inst, ret_val.new_local, null);4082 try freeLocal(f, inst, ret_val.new_local, null);
4044 }4083 }
...@@ -4064,7 +4103,7 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4064,7 +4103,7 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
40644103
4065 if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);4104 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;
4068 const local = try f.allocLocal(inst, inst_ty);4107 const local = try f.allocLocal(inst, inst_ty);
4069 const v = try Vectorize.start(f, inst, w, operand_ty);4108 const v = try Vectorize.start(f, inst, w, operand_ty);
4070 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));4109 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 {...@@ -4100,7 +4139,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
4100 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);4139 const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
4101 if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);4140 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;
4104 const local = try f.allocLocal(inst, inst_ty);4143 const local = try f.allocLocal(inst, inst_ty);
4105 const v = try Vectorize.start(f, inst, w, operand_ty);4144 const v = try Vectorize.start(f, inst, w, operand_ty);
4106 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));4145 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 {...@@ -4178,15 +4217,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
41784217
4179 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false;4218 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;
4181 if (val_is_undef) {4221 if (val_is_undef) {
4182 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4222 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
4183 if (safety and ptr_info.packed_offset.host_size == 0) {4223 if (safety and ptr_info.packed_offset.host_size == 0) {
4184 const w = f.object.writer();
4185 try w.writeAll("memset(");4224 try w.writeAll("memset(");
4186 try f.writeCValue(w, ptr_val, .FunctionArgument);4225 try f.writeCValue(w, ptr_val, .FunctionArgument);
4187 try w.writeAll(", 0xaa, sizeof(");4226 try w.writeAll(", 0xaa, sizeof(");
4188 try f.renderType(w, .fromInterned(ptr_info.child));4227 try f.renderType(w, .fromInterned(ptr_info.child));
4189 try w.writeAll("));\n");4228 try w.writeAll("));");
4229 try f.object.newline();
4190 }4230 }
4191 return .none;4231 return .none;
4192 }4232 }
...@@ -4202,7 +4242,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4202,7 +4242,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4202 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4242 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
42034243
4204 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);4244 const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);
4205 const w = f.object.writer();
4206 if (need_memcpy) {4245 if (need_memcpy) {
4207 // For this memcpy to safely work we need the rhs to have the same4246 // For this memcpy to safely work we need the rhs to have the same
4208 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).4247 // 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 {...@@ -4216,7 +4255,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4216 try f.writeCValue(w, new_local, .Other);4255 try f.writeCValue(w, new_local, .Other);
4217 try w.writeAll(" = ");4256 try w.writeAll(" = ");
4218 try f.writeCValue(w, src_val, .Other);4257 try f.writeCValue(w, src_val, .Other);
4219 try w.writeAll(";\n");4258 try w.writeByte(';');
4259 try f.object.newline();
42204260
4221 break :blk new_local;4261 break :blk new_local;
4222 } else src_val;4262 } else src_val;
...@@ -4233,7 +4273,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4233,7 +4273,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4233 try f.renderType(w, src_ty);4273 try f.renderType(w, src_ty);
4234 try w.writeAll("))");4274 try w.writeAll("))");
4235 try f.freeCValue(inst, array_src);4275 try f.freeCValue(inst, array_src);
4236 try w.writeAll(";\n");4276 try w.writeByte(';');
4277 try f.object.newline();
4237 try v.end(f, inst, w);4278 try v.end(f, inst, w);
4238 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {4279 } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
4239 const host_bits = ptr_info.packed_offset.host_size * 8;4280 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 {...@@ -4251,7 +4292,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4251 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));4292 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
4252 defer mask.deinit();4293 defer mask.deinit();
42534294
4254 try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits)));4295 try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits));
4255 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);4296 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
4256 try mask.bitNotWrap(&mask, .unsigned, host_bits);4297 try mask.bitNotWrap(&mask, .unsigned, host_bits);
42574298
...@@ -4331,7 +4372,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -4331,7 +4372,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
4331 const operand_ty = f.typeOf(bin_op.lhs);4372 const operand_ty = f.typeOf(bin_op.lhs);
4332 const scalar_ty = operand_ty.scalarType(zcu);4373 const scalar_ty = operand_ty.scalarType(zcu);
43334374
4334 const w = f.object.writer();4375 const w = &f.object.code.writer;
4335 const local = try f.allocLocal(inst, inst_ty);4376 const local = try f.allocLocal(inst, inst_ty);
4336 const v = try Vectorize.start(f, inst, w, operand_ty);4377 const v = try Vectorize.start(f, inst, w, operand_ty);
4337 try f.writeCValueMember(w, local, .{ .field = 1 });4378 try f.writeCValueMember(w, local, .{ .field = 1 });
...@@ -4350,7 +4391,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -4350,7 +4391,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
4350 try f.writeCValue(w, rhs, .FunctionArgument);4391 try f.writeCValue(w, rhs, .FunctionArgument);
4351 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);4392 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
4352 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);4393 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
4353 try w.writeAll(");\n");4394 try w.writeAll(");");
4395 try f.object.newline();
4354 try v.end(f, inst, w);4396 try v.end(f, inst, w);
43554397
4356 return local;4398 return local;
...@@ -4369,7 +4411,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4369,7 +4411,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
43694411
4370 const inst_ty = f.typeOfIndex(inst);4412 const inst_ty = f.typeOfIndex(inst);
43714413
4372 const w = f.object.writer();4414 const w = &f.object.code.writer;
4373 const local = try f.allocLocal(inst, inst_ty);4415 const local = try f.allocLocal(inst, inst_ty);
4374 const v = try Vectorize.start(f, inst, w, operand_ty);4416 const v = try Vectorize.start(f, inst, w, operand_ty);
4375 try f.writeCValue(w, local, .Other);4417 try f.writeCValue(w, local, .Other);
...@@ -4378,7 +4420,8 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4378,7 +4420,8 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
4378 try w.writeByte('!');4420 try w.writeByte('!');
4379 try f.writeCValue(w, op, .Other);4421 try f.writeCValue(w, op, .Other);
4380 try v.elem(f, w);4422 try v.elem(f, w);
4381 try w.writeAll(";\n");4423 try w.writeByte(';');
4424 try f.object.newline();
4382 try v.end(f, inst, w);4425 try v.end(f, inst, w);
43834426
4384 return local;4427 return local;
...@@ -4405,7 +4448,7 @@ fn airBinOp(...@@ -4405,7 +4448,7 @@ fn airBinOp(
44054448
4406 const inst_ty = f.typeOfIndex(inst);4449 const inst_ty = f.typeOfIndex(inst);
44074450
4408 const w = f.object.writer();4451 const w = &f.object.code.writer;
4409 const local = try f.allocLocal(inst, inst_ty);4452 const local = try f.allocLocal(inst, inst_ty);
4410 const v = try Vectorize.start(f, inst, w, operand_ty);4453 const v = try Vectorize.start(f, inst, w, operand_ty);
4411 try f.writeCValue(w, local, .Other);4454 try f.writeCValue(w, local, .Other);
...@@ -4418,7 +4461,8 @@ fn airBinOp(...@@ -4418,7 +4461,8 @@ fn airBinOp(
4418 try w.writeByte(' ');4461 try w.writeByte(' ');
4419 try f.writeCValue(w, rhs, .Other);4462 try f.writeCValue(w, rhs, .Other);
4420 try v.elem(f, w);4463 try v.elem(f, w);
4421 try w.writeAll(";\n");4464 try w.writeByte(';');
4465 try f.object.newline();
4422 try v.end(f, inst, w);4466 try v.end(f, inst, w);
44234467
4424 return local;4468 return local;
...@@ -4455,7 +4499,7 @@ fn airCmpOp(...@@ -4455,7 +4499,7 @@ fn airCmpOp(
44554499
4456 const rhs_ty = f.typeOf(data.rhs);4500 const rhs_ty = f.typeOf(data.rhs);
4457 const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);4501 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;
4459 const local = try f.allocLocal(inst, inst_ty);4503 const local = try f.allocLocal(inst, inst_ty);
4460 const v = try Vectorize.start(f, inst, w, lhs_ty);4504 const v = try Vectorize.start(f, inst, w, lhs_ty);
4461 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));4505 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
...@@ -4508,7 +4552,7 @@ fn airEquality(...@@ -4508,7 +4552,7 @@ fn airEquality(
4508 const rhs = try f.resolveInst(bin_op.rhs);4552 const rhs = try f.resolveInst(bin_op.rhs);
4509 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4553 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
45104554
4511 const w = f.object.writer();4555 const w = &f.object.code.writer;
4512 const local = try f.allocLocal(inst, .bool);4556 const local = try f.allocLocal(inst, .bool);
4513 const a = try Assignment.start(f, w, .bool);4557 const a = try Assignment.start(f, w, .bool);
4514 try f.writeCValue(w, local, .Other);4558 try f.writeCValue(w, local, .Other);
...@@ -4566,12 +4610,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4566,12 +4610,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
4566 const operand = try f.resolveInst(un_op);4610 const operand = try f.resolveInst(un_op);
4567 try reap(f, inst, &.{un_op});4611 try reap(f, inst, &.{un_op});
45684612
4569 const w = f.object.writer();4613 const w = &f.object.code.writer;
4570 const local = try f.allocLocal(inst, .bool);4614 const local = try f.allocLocal(inst, .bool);
4571 try f.writeCValue(w, local, .Other);4615 try f.writeCValue(w, local, .Other);
4572 try w.writeAll(" = ");4616 try w.writeAll(" = ");
4573 try f.writeCValue(w, operand, .Other);4617 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();
4575 return local;4620 return local;
4576}4621}
45774622
...@@ -4592,7 +4637,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -4592,7 +4637,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
4592 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);4637 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
45934638
4594 const local = try f.allocLocal(inst, inst_ty);4639 const local = try f.allocLocal(inst, inst_ty);
4595 const w = f.object.writer();4640 const w = &f.object.code.writer;
4596 const v = try Vectorize.start(f, inst, w, inst_ty);4641 const v = try Vectorize.start(f, inst, w, inst_ty);
4597 const a = try Assignment.start(f, w, inst_scalar_ctype);4642 const a = try Assignment.start(f, w, inst_scalar_ctype);
4598 try f.writeCValue(w, local, .Other);4643 try f.writeCValue(w, local, .Other);
...@@ -4634,7 +4679,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -4634,7 +4679,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
4634 const rhs = try f.resolveInst(bin_op.rhs);4679 const rhs = try f.resolveInst(bin_op.rhs);
4635 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });4680 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
46364681
4637 const w = f.object.writer();4682 const w = &f.object.code.writer;
4638 const local = try f.allocLocal(inst, inst_ty);4683 const local = try f.allocLocal(inst, inst_ty);
4639 const v = try Vectorize.start(f, inst, w, inst_ty);4684 const v = try Vectorize.start(f, inst, w, inst_ty);
4640 try f.writeCValue(w, local, .Other);4685 try f.writeCValue(w, local, .Other);
...@@ -4654,7 +4699,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -4654,7 +4699,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
4654 try w.writeAll(" : ");4699 try w.writeAll(" : ");
4655 try f.writeCValue(w, rhs, .Other);4700 try f.writeCValue(w, rhs, .Other);
4656 try v.elem(f, w);4701 try v.elem(f, w);
4657 try w.writeAll(";\n");4702 try w.writeByte(';');
4703 try f.object.newline();
4658 try v.end(f, inst, w);4704 try v.end(f, inst, w);
46594705
4660 return local;4706 return local;
...@@ -4673,7 +4719,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4673,7 +4719,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4673 const inst_ty = f.typeOfIndex(inst);4719 const inst_ty = f.typeOfIndex(inst);
4674 const ptr_ty = inst_ty.slicePtrFieldType(zcu);4720 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
46754721
4676 const w = f.object.writer();4722 const w = &f.object.code.writer;
4677 const local = try f.allocLocal(inst, inst_ty);4723 const local = try f.allocLocal(inst, inst_ty);
4678 {4724 {
4679 const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));4725 const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
...@@ -4704,7 +4750,7 @@ fn airCall(...@@ -4704,7 +4750,7 @@ fn airCall(
4704 if (f.object.dg.is_naked_fn) return .none;4750 if (f.object.dg.is_naked_fn) return .none;
47054751
4706 const gpa = f.object.dg.gpa;4752 const gpa = f.object.dg.gpa;
4707 const w = f.object.writer();4753 const w = &f.object.code.writer;
47084754
4709 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4755 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4710 const extra = f.air.extraData(Air.Call, pl_op.payload);4756 const extra = f.air.extraData(Air.Call, pl_op.payload);
...@@ -4731,7 +4777,8 @@ fn airCall(...@@ -4731,7 +4777,8 @@ fn airCall(
4731 try f.writeCValue(w, resolved_arg.*, .FunctionArgument);4777 try f.writeCValue(w, resolved_arg.*, .FunctionArgument);
4732 try w.writeAll(", sizeof(");4778 try w.writeAll(", sizeof(");
4733 try f.renderCType(w, arg_ctype);4779 try f.renderCType(w, arg_ctype);
4734 try w.writeAll("));\n");4780 try w.writeAll("));");
4781 try f.object.newline();
4735 resolved_arg.* = array_local;4782 resolved_arg.* = array_local;
4736 }4783 }
4737 }4784 }
...@@ -4826,7 +4873,11 @@ fn airCall(...@@ -4826,7 +4873,11 @@ fn airCall(
4826 try f.writeCValue(w, resolved_arg, .FunctionArgument);4873 try f.writeCValue(w, resolved_arg, .FunctionArgument);
4827 try f.freeCValue(inst, resolved_arg);4874 try f.freeCValue(inst, resolved_arg);
4828 }4875 }
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
4831 const result = result: {4882 const result = result: {
4832 if (result_local == .none or !lowersToArray(ret_ty, pt))4883 if (result_local == .none or !lowersToArray(ret_ty, pt))
...@@ -4839,7 +4890,8 @@ fn airCall(...@@ -4839,7 +4890,8 @@ fn airCall(
4839 try f.writeCValueMember(w, result_local, .{ .identifier = "array" });4890 try f.writeCValueMember(w, result_local, .{ .identifier = "array" });
4840 try w.writeAll(", sizeof(");4891 try w.writeAll(", sizeof(");
4841 try f.renderType(w, ret_ty);4892 try f.renderType(w, ret_ty);
4842 try w.writeAll("));\n");4893 try w.writeAll("));");
4894 try f.object.newline();
4843 try freeLocal(f, inst, result_local.new_local, null);4895 try freeLocal(f, inst, result_local.new_local, null);
4844 break :result array_local;4896 break :result array_local;
4845 };4897 };
...@@ -4849,7 +4901,7 @@ fn airCall(...@@ -4849,7 +4901,7 @@ fn airCall(
48494901
4850fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {4902fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4851 const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;4903 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;
4853 // TODO re-evaluate whether to emit these or not. If we naively emit4905 // TODO re-evaluate whether to emit these or not. If we naively emit
4854 // these directives, the output file will report bogus line numbers because4906 // these directives, the output file will report bogus line numbers because
4855 // every newline after the #line directive adds one to the line.4907 // every newline after the #line directive adds one to the line.
...@@ -4857,13 +4909,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4857,13 +4909,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4857 // If we wanted to go this route, we would need to go all the way and not output4909 // If we wanted to go this route, we would need to go all the way and not output
4858 // newlines until the next dbg_stmt occurs.4910 // newlines until the next dbg_stmt occurs.
4859 // Perhaps an additional compilation option is in order?4911 // Perhaps an additional compilation option is in order?
4860 //try w.print("#line {d}\n", .{dbg_stmt.line + 1});4912 //try w.print("#line {d}", .{dbg_stmt.line + 1});
4861 try w.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 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();
4862 return .none;4916 return .none;
4863}4917}
48644918
4865fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {4919fn 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();
4867 return .none;4922 return .none;
4868}4923}
48694924
...@@ -4874,8 +4929,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4874,8 +4929,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4874 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4929 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4875 const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);4930 const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
4876 const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);4931 const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);
4877 const w = f.object.writer();4932 const w = &f.object.code.writer;
4878 try w.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)});4933 try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
4934 try f.object.newline();
4879 return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));4935 return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
4880}4936}
48814937
...@@ -4889,8 +4945,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4889,8 +4945,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4889 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);4945 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
48904946
4891 try reap(f, inst, &.{pl_op.operand});4947 try reap(f, inst, &.{pl_op.operand});
4892 const w = f.object.writer();4948 const w = &f.object.code.writer;
4893 try w.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });4949 try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) });
4950 try f.object.newline();
4894 return .none;4951 return .none;
4895}4952}
48964953
...@@ -4907,7 +4964,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)...@@ -4907,7 +4964,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
49074964
4908 const block_id = f.next_block_index;4965 const block_id = f.next_block_index;
4909 f.next_block_index += 1;4966 f.next_block_index += 1;
4910 const w = f.object.writer();4967 const w = &f.object.code.writer;
49114968
4912 const inst_ty = f.typeOfIndex(inst);4969 const inst_ty = f.typeOfIndex(inst);
4913 const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))4970 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)...@@ -4929,8 +4986,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
4929 try die(f, inst, death.toRef());4986 try die(f, inst, death.toRef());
4930 }4987 }
49314988
4932 try f.object.indent_writer.insertNewline();
4933
4934 // noreturn blocks have no `br` instructions reaching them, so we don't want a label4989 // noreturn blocks have no `br` instructions reaching them, so we don't want a label
4935 if (f.object.dg.is_naked_fn) {4990 if (f.object.dg.is_naked_fn) {
4936 if (f.object.dg.expected_block) |expected_block| {4991 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)...@@ -4940,7 +4995,8 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
4940 }4995 }
4941 } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {4996 } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
4942 // label must be followed by an expression, include an empty one.4997 // 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();
4944 }5000 }
49455001
4946 return result;5002 return result;
...@@ -4977,7 +5033,7 @@ fn lowerTry(...@@ -4977,7 +5033,7 @@ fn lowerTry(
4977 const err_union = try f.resolveInst(operand);5033 const err_union = try f.resolveInst(operand);
4978 const inst_ty = f.typeOfIndex(inst);5034 const inst_ty = f.typeOfIndex(inst);
4979 const liveness_condbr = f.liveness.getCondBr(inst);5035 const liveness_condbr = f.liveness.getCondBr(inst);
4980 const w = f.object.writer();5036 const w = &f.object.code.writer;
4981 const payload_ty = err_union_ty.errorUnionPayload(zcu);5037 const payload_ty = err_union_ty.errorUnionPayload(zcu);
4982 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);5038 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
49835039
...@@ -5001,7 +5057,7 @@ fn lowerTry(...@@ -5001,7 +5057,7 @@ fn lowerTry(
5001 try w.writeAll(") ");5057 try w.writeAll(") ");
50025058
5003 try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);5059 try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);
5004 try f.object.indent_writer.insertNewline();5060 try f.object.newline();
5005 if (f.object.dg.expected_block) |_|5061 if (f.object.dg.expected_block) |_|
5006 return f.fail("runtime code not allowed in naked function", .{});5062 return f.fail("runtime code not allowed in naked function", .{});
5007 }5063 }
...@@ -5039,7 +5095,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {...@@ -5039,7 +5095,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
5039 const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;5095 const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
5040 const block = f.blocks.get(branch.block_inst).?;5096 const block = f.blocks.get(branch.block_inst).?;
5041 const result = block.result;5097 const result = block.result;
5042 const w = f.object.writer();5098 const w = &f.object.code.writer;
50435099
5044 if (f.object.dg.is_naked_fn) {5100 if (f.object.dg.is_naked_fn) {
5045 if (result != .none) return f.fail("runtime code not allowed in naked function", .{});5101 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 {...@@ -5065,15 +5121,14 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
50655121
5066fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {5122fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {
5067 const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;5123 const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
5068 const w = f.object.writer();5124 try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
5069 try w.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
5070}5125}
50715126
5072fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {5127fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
5073 const pt = f.object.dg.pt;5128 const pt = f.object.dg.pt;
5074 const zcu = pt.zcu;5129 const zcu = pt.zcu;
5075 const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;5130 const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
5076 const w = f.object.writer();5131 const w = &f.object.code.writer;
50775132
5078 if (try f.air.value(br.operand, pt)) |cond_val| {5133 if (try f.air.value(br.operand, pt)) |cond_val| {
5079 // Comptime-known dispatch. Iterate the cases to find the correct5134 // Comptime-known dispatch. Iterate the cases to find the correct
...@@ -5105,8 +5160,9 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {...@@ -5105,8 +5160,9 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
5105 try f.writeCValue(w, .{ .local = cond_local }, .Other);5160 try f.writeCValue(w, .{ .local = cond_local }, .Other);
5106 try w.writeAll(" = ");5161 try w.writeAll(" = ");
5107 try f.writeCValue(w, cond, .Other);5162 try f.writeCValue(w, cond, .Other);
5108 try w.writeAll(";\n");5163 try w.writeByte(';');
5109 try w.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)});5164 try f.object.newline();
5165 try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
5110}5166}
51115167
5112fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {5168fn 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...@@ -5126,7 +5182,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5126 const zcu = pt.zcu;5182 const zcu = pt.zcu;
5127 const target = &f.object.dg.mod.resolved_target.result;5183 const target = &f.object.dg.mod.resolved_target.result;
5128 const ctype_pool = &f.object.dg.ctype_pool;5184 const ctype_pool = &f.object.dg.ctype_pool;
5129 const w = f.object.writer();5185 const w = &f.object.code.writer;
51305186
5131 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {5187 if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
5132 const src_info = dest_ty.intInfo(zcu);5188 const src_info = dest_ty.intInfo(zcu);
...@@ -5142,16 +5198,24 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5142,16 +5198,24 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5142 try f.renderType(w, dest_ty);5198 try f.renderType(w, dest_ty);
5143 try w.writeByte(')');5199 try w.writeByte(')');
5144 try f.writeCValue(w, operand, .Other);5200 try f.writeCValue(w, operand, .Other);
5145 try w.writeAll(";\n");5201 try w.writeByte(';');
5202 try f.object.newline();
5146 return local;5203 return local;
5147 }5204 }
51485205
5149 const operand_lval = if (operand == .constant) blk: {5206 const operand_lval = if (operand == .constant) blk: {
5150 const operand_local = try f.allocLocal(null, operand_ty);5207 const operand_local = try f.allocLocal(null, operand_ty);
5151 try f.writeCValue(w, operand_local, .Other);5208 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 }
5153 try f.writeCValue(w, operand, .Other);5216 try f.writeCValue(w, operand, .Other);
5154 try w.writeAll(";\n");5217 try w.writeByte(';');
5218 try f.object.newline();
5155 break :blk operand_local;5219 break :blk operand_local;
5156 } else operand;5220 } else operand;
51575221
...@@ -5165,7 +5229,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5165,7 +5229,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5165 w,5229 w,
5166 if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,5230 if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
5167 );5231 );
5168 try w.writeAll("));\n");5232 try w.writeAll("));");
5233 try f.object.newline();
51695234
5170 // Ensure padding bits have the expected value.5235 // Ensure padding bits have the expected value.
5171 if (dest_ty.isAbiInt(zcu)) {5236 if (dest_ty.isAbiInt(zcu)) {
...@@ -5221,7 +5286,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -5221,7 +5286,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
5221 if (need_bitcasts) try w.writeByte(')');5286 if (need_bitcasts) try w.writeByte(')');
5222 try f.object.dg.renderBuiltinInfo(w, info_ty, .bits);5287 try f.object.dg.renderBuiltinInfo(w, info_ty, .bits);
5223 if (need_bitcasts) try w.writeByte(')');5288 if (need_bitcasts) try w.writeByte(')');
5224 try w.writeAll(");\n");5289 try w.writeAll(");");
5290 try f.object.newline();
5225 }5291 }
52265292
5227 try f.freeCValue(null, operand_lval);5293 try f.freeCValue(null, operand_lval);
...@@ -5234,48 +5300,53 @@ fn airTrap(f: *Function, w: *Writer) !void {...@@ -5234,48 +5300,53 @@ fn airTrap(f: *Function, w: *Writer) !void {
5234 try w.writeAll("zig_trap();\n");5300 try w.writeAll("zig_trap();\n");
5235}5301}
52365302
5237fn airBreakpoint(w: *Writer) !CValue {5303fn airBreakpoint(f: *Function) !CValue {
5238 try w.writeAll("zig_breakpoint();\n");5304 const w = &f.object.code.writer;
5305 try w.writeAll("zig_breakpoint();");
5306 try f.object.newline();
5239 return .none;5307 return .none;
5240}5308}
52415309
5242fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {5310fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {
5243 const w = f.object.writer();5311 const w = &f.object.code.writer;
5244 const local = try f.allocLocal(inst, .usize);5312 const local = try f.allocLocal(inst, .usize);
5245 try f.writeCValue(w, local, .Other);5313 try f.writeCValue(w, local, .Other);
5246 try w.writeAll(" = (");5314 try w.writeAll(" = (");
5247 try f.renderType(w, .usize);5315 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();
5249 return local;5318 return local;
5250}5319}
52515320
5252fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {5321fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
5253 const w = f.object.writer();5322 const w = &f.object.code.writer;
5254 const local = try f.allocLocal(inst, .usize);5323 const local = try f.allocLocal(inst, .usize);
5255 try f.writeCValue(w, local, .Other);5324 try f.writeCValue(w, local, .Other);
5256 try w.writeAll(" = (");5325 try w.writeAll(" = (");
5257 try f.renderType(w, .usize);5326 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();
5259 return local;5329 return local;
5260}5330}
52615331
5262fn airUnreach(f: *Function) !void {5332fn airUnreach(o: *Object) !void {
5263 // Not even allowed to call unreachable in a naked function.5333 // Not even allowed to call unreachable in a naked function.
5264 if (f.object.dg.is_naked_fn) return;5334 if (o.dg.is_naked_fn) return;
5265 try f.object.writer().writeAll("zig_unreachable();\n");5335 try o.code.writer.writeAll("zig_unreachable();\n");
5266}5336}
52675337
5268fn airLoop(f: *Function, inst: Air.Inst.Index) !void {5338fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
5269 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5339 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5270 const loop = f.air.extraData(Air.Block, ty_pl.payload);5340 const loop = f.air.extraData(Air.Block, ty_pl.payload);
5271 const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);5341 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
5274 // `repeat` instructions matching this loop will branch to5344 // `repeat` instructions matching this loop will branch to
5275 // this label. Since we need a label for arbitrary `repeat`5345 // this label. Since we need a label for arbitrary `repeat`
5276 // anyway, there's actually no need to use a "real" looping5346 // anyway, there's actually no need to use a "real" looping
5277 // construct at all!5347 // 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();
5279 try genBodyInner(f, body); // no need to restore state, we're noreturn5350 try genBodyInner(f, body); // no need to restore state, we're noreturn
5280}5351}
52815352
...@@ -5287,14 +5358,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {...@@ -5287,14 +5358,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {
5287 const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);5358 const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);
5288 const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);5359 const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);
5289 const liveness_condbr = f.liveness.getCondBr(inst);5360 const liveness_condbr = f.liveness.getCondBr(inst);
5290 const w = f.object.writer();5361 const w = &f.object.code.writer;
52915362
5292 try w.writeAll("if (");5363 try w.writeAll("if (");
5293 try f.writeCValue(w, cond, .Other);5364 try f.writeCValue(w, cond, .Other);
5294 try w.writeAll(") ");5365 try w.writeAll(") ");
52955366
5296 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);5367 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
5297 try w.writeByte('\n');5368 try f.object.newline();
5298 if (else_body.len > 0) if (f.object.dg.expected_block) |_|5369 if (else_body.len > 0) if (f.object.dg.expected_block) |_|
5299 return f.fail("runtime code not allowed in naked function", .{});5370 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...@@ -5320,7 +5391,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5320 const init_condition = try f.resolveInst(switch_br.operand);5391 const init_condition = try f.resolveInst(switch_br.operand);
5321 try reap(f, inst, &.{switch_br.operand});5392 try reap(f, inst, &.{switch_br.operand});
5322 const condition_ty = f.typeOf(switch_br.operand);5393 const condition_ty = f.typeOf(switch_br.operand);
5323 const w = f.object.writer();5394 const w = &f.object.code.writer;
53245395
5325 // For dispatches, we will create a local alloc to contain the condition value.5396 // For dispatches, we will create a local alloc to contain the condition value.
5326 // This may not result in optimal codegen for switch loops, but it minimizes the5397 // 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...@@ -5328,7 +5399,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5328 const condition = if (is_dispatch_loop) cond: {5399 const condition = if (is_dispatch_loop) cond: {
5329 const new_local = try f.allocLocal(inst, condition_ty);5400 const new_local = try f.allocLocal(inst, condition_ty);
5330 try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition);5401 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();
5332 try f.loop_switch_conds.put(gpa, inst, new_local.new_local);5404 try f.loop_switch_conds.put(gpa, inst, new_local.new_local);
5333 break :cond new_local;5405 break :cond new_local;
5334 } else init_condition;5406 } else init_condition;
...@@ -5352,7 +5424,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5352,7 +5424,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5352 }5424 }
5353 try f.writeCValue(w, condition, .Other);5425 try f.writeCValue(w, condition, .Other);
5354 try w.writeAll(") {");5426 try w.writeAll(") {");
5355 f.object.indent_writer.pushIndent();5427 f.object.indent();
53565428
5357 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);5429 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);
5358 defer gpa.free(liveness.deaths);5430 defer gpa.free(liveness.deaths);
...@@ -5365,7 +5437,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5365,7 +5437,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5365 continue;5437 continue;
5366 }5438 }
5367 for (case.items) |item| {5439 for (case.items) |item| {
5368 try f.object.indent_writer.insertNewline();5440 try f.object.newline();
5369 try w.writeAll("case ");5441 try w.writeAll("case ");
5370 const item_value = try f.air.value(item, pt);5442 const item_value = try f.air.value(item, pt);
5371 // If `item_value` is a pointer with a known integer address, print the address5443 // 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...@@ -5386,13 +5458,15 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5386 }5458 }
5387 try w.writeByte(':');5459 try w.writeByte(':');
5388 }5460 }
5389 try w.writeAll(" {\n");5461 try w.writeAll(" {");
5390 f.object.indent_writer.pushIndent();5462 f.object.indent();
5463 try f.object.newline();
5391 if (is_dispatch_loop) {5464 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();
5393 }5467 }
5394 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);5468 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5395 f.object.indent_writer.popIndent();5469 try f.object.outdent();
5396 try w.writeByte('}');5470 try w.writeByte('}');
5397 if (f.object.dg.expected_block) |_|5471 if (f.object.dg.expected_block) |_|
5398 return f.fail("runtime code not allowed in naked function", .{});5472 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...@@ -5401,7 +5475,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5401 }5475 }
54025476
5403 const else_body = it.elseBody();5477 const else_body = it.elseBody();
5404 try f.object.indent_writer.insertNewline();5478 try f.object.newline();
54055479
5406 try w.writeAll("default: ");5480 try w.writeAll("default: ");
5407 if (any_range_cases) {5481 if (any_range_cases) {
...@@ -5431,13 +5505,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void...@@ -5431,13 +5505,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5431 try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other);5505 try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other);
5432 try w.writeByte(')');5506 try w.writeByte(')');
5433 }5507 }
5434 try w.writeAll(") {\n");5508 try w.writeAll(") {");
5435 f.object.indent_writer.pushIndent();5509 f.object.indent();
5510 try f.object.newline();
5436 if (is_dispatch_loop) {5511 if (is_dispatch_loop) {
5437 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });5512 try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
5438 }5513 }
5439 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);5514 try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
5440 f.object.indent_writer.popIndent();5515 try f.object.outdent();
5441 try w.writeByte('}');5516 try w.writeByte('}');
5442 if (f.object.dg.expected_block) |_|5517 if (f.object.dg.expected_block) |_|
5443 return f.fail("runtime code not allowed in naked function", .{});5518 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...@@ -5455,12 +5530,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
5455 try genBody(f, else_body);5530 try genBody(f, else_body);
5456 if (f.object.dg.expected_block) |_|5531 if (f.object.dg.expected_block) |_|
5457 return f.fail("runtime code not allowed in naked function", .{});5532 return f.fail("runtime code not allowed in naked function", .{});
5458 } else {5533 } else try airUnreach(&f.object);
5459 try w.writeAll("zig_unreachable();");5534 try f.object.newline();
5460 }5535 try f.object.outdent();
5461 try f.object.indent_writer.insertNewline();
5462
5463 f.object.indent_writer.popIndent();
5464 try w.writeAll("}\n");5536 try w.writeAll("}\n");
5465}5537}
54665538
...@@ -5499,7 +5571,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5499,7 +5571,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5499 extra_i += inputs.len;5571 extra_i += inputs.len;
55005572
5501 const result = result: {5573 const result = result: {
5502 const w = f.object.writer();5574 const w = &f.object.code.writer;
5503 const inst_ty = f.typeOfIndex(inst);5575 const inst_ty = f.typeOfIndex(inst);
5504 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {5576 const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
5505 const inst_local = try f.allocLocalValue(.{5577 const inst_local = try f.allocLocalValue(.{
...@@ -5510,7 +5582,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5510,7 +5582,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5510 try f.writeCValue(w, inst_local, .Other);5582 try f.writeCValue(w, inst_local, .Other);
5511 try w.writeAll(" = ");5583 try w.writeAll(" = ");
5512 try f.writeCValue(w, .{ .undef = inst_ty }, .Other);5584 try f.writeCValue(w, .{ .undef = inst_ty }, .Other);
5513 try w.writeAll(";\n");5585 try w.writeByte(';');
5586 try f.object.newline();
5514 }5587 }
5515 break :local inst_local;5588 break :local inst_local;
5516 } else .none;5589 } else .none;
...@@ -5548,7 +5621,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5548,7 +5621,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5548 try w.writeAll(" = ");5621 try w.writeAll(" = ");
5549 try f.writeCValue(w, .{ .undef = output_ty }, .Other);5622 try f.writeCValue(w, .{ .undef = output_ty }, .Other);
5550 }5623 }
5551 try w.writeAll(";\n");5624 try w.writeByte(';');
5625 try f.object.newline();
5552 }5626 }
5553 }5627 }
5554 for (inputs) |input| {5628 for (inputs) |input| {
...@@ -5583,7 +5657,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5583,7 +5657,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5583 }5657 }
5584 try w.writeAll(" = ");5658 try w.writeAll(" = ");
5585 try f.writeCValue(w, input_val, .Other);5659 try f.writeCValue(w, input_val, .Other);
5586 try w.writeAll(";\n");5660 try w.writeByte(';');
5661 try f.object.newline();
5587 }5662 }
5588 }5663 }
5589 for (0..clobbers_len) |_| {5664 for (0..clobbers_len) |_| {
...@@ -5709,7 +5784,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5709,7 +5784,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5709 if (clobber_i > 0) try w.writeByte(',');5784 if (clobber_i > 0) try w.writeByte(',');
5710 try w.print(" {f}", .{fmtStringLiteral(clobber, null)});5785 try w.print(" {f}", .{fmtStringLiteral(clobber, null)});
5711 }5786 }
5712 try w.writeAll(");\n");5787 try w.writeAll(");");
5788 try f.object.newline();
57135789
5714 extra_i = constraints_extra_begin;5790 extra_i = constraints_extra_begin;
5715 locals_index = locals_begin;5791 locals_index = locals_begin;
...@@ -5730,7 +5806,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5730,7 +5806,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5730 try w.writeAll(" = ");5806 try w.writeAll(" = ");
5731 try f.writeCValue(w, .{ .local = locals_index }, .Other);5807 try f.writeCValue(w, .{ .local = locals_index }, .Other);
5732 locals_index += 1;5808 locals_index += 1;
5733 try w.writeAll(";\n");5809 try w.writeByte(';');
5810 try f.object.newline();
5734 }5811 }
5735 }5812 }
57365813
...@@ -5760,7 +5837,7 @@ fn airIsNull(...@@ -5760,7 +5837,7 @@ fn airIsNull(
5760 const ctype_pool = &f.object.dg.ctype_pool;5837 const ctype_pool = &f.object.dg.ctype_pool;
5761 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5838 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;
5764 const operand = try f.resolveInst(un_op);5841 const operand = try f.resolveInst(un_op);
5765 try reap(f, inst, &.{un_op});5842 try reap(f, inst, &.{un_op});
57665843
...@@ -5828,7 +5905,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue...@@ -5828,7 +5905,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue
5828 .aligned, .array, .vector, .fwd_decl, .function => unreachable,5905 .aligned, .array, .vector, .fwd_decl, .function => unreachable,
5829 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {5906 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
5830 .is_null, .payload => {5907 .is_null, .payload => {
5831 const w = f.object.writer();5908 const w = &f.object.code.writer;
5832 const local = try f.allocLocal(inst, inst_ty);5909 const local = try f.allocLocal(inst, inst_ty);
5833 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));5910 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
5834 try f.writeCValue(w, local, .Other);5911 try f.writeCValue(w, local, .Other);
...@@ -5850,7 +5927,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5850,7 +5927,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5850 const pt = f.object.dg.pt;5927 const pt = f.object.dg.pt;
5851 const zcu = pt.zcu;5928 const zcu = pt.zcu;
5852 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5929 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;
5854 const operand = try f.resolveInst(ty_op.operand);5931 const operand = try f.resolveInst(ty_op.operand);
5855 try reap(f, inst, &.{ty_op.operand});5932 try reap(f, inst, &.{ty_op.operand});
5856 const operand_ty = f.typeOf(ty_op.operand);5933 const operand_ty = f.typeOf(ty_op.operand);
...@@ -6000,7 +6077,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6000,7 +6077,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6000 const field_ptr_val = try f.resolveInst(extra.field_ptr);6077 const field_ptr_val = try f.resolveInst(extra.field_ptr);
6001 try reap(f, inst, &.{extra.field_ptr});6078 try reap(f, inst, &.{extra.field_ptr});
60026079
6003 const w = f.object.writer();6080 const w = &f.object.code.writer;
6004 const local = try f.allocLocal(inst, container_ptr_ty);6081 const local = try f.allocLocal(inst, container_ptr_ty);
6005 try f.writeCValue(w, local, .Other);6082 try f.writeCValue(w, local, .Other);
6006 try w.writeAll(" = (");6083 try w.writeAll(" = (");
...@@ -6035,7 +6112,8 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6035,7 +6112,8 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6035 },6112 },
6036 }6113 }
60376114
6038 try w.writeAll(";\n");6115 try w.writeByte(';');
6116 try f.object.newline();
6039 return local;6117 return local;
6040}6118}
60416119
...@@ -6054,7 +6132,7 @@ fn fieldPtr(...@@ -6054,7 +6132,7 @@ fn fieldPtr(
6054 // Ensure complete type definition is visible before accessing fields.6132 // Ensure complete type definition is visible before accessing fields.
6055 _ = try f.ctypeFromType(container_ty, .complete);6133 _ = try f.ctypeFromType(container_ty, .complete);
60566134
6057 const w = f.object.writer();6135 const w = &f.object.code.writer;
6058 const local = try f.allocLocal(inst, field_ptr_ty);6136 const local = try f.allocLocal(inst, field_ptr_ty);
6059 try f.writeCValue(w, local, .Other);6137 try f.writeCValue(w, local, .Other);
6060 try w.writeAll(" = (");6138 try w.writeAll(" = (");
...@@ -6080,7 +6158,8 @@ fn fieldPtr(...@@ -6080,7 +6158,8 @@ fn fieldPtr(
6080 },6158 },
6081 }6159 }
60826160
6083 try w.writeAll(";\n");6161 try w.writeByte(';');
6162 try f.object.newline();
6084 return local;6163 return local;
6085}6164}
60866165
...@@ -6100,7 +6179,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6100,7 +6179,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6100 const struct_byval = try f.resolveInst(extra.struct_operand);6179 const struct_byval = try f.resolveInst(extra.struct_operand);
6101 try reap(f, inst, &.{extra.struct_operand});6180 try reap(f, inst, &.{extra.struct_operand});
6102 const struct_ty = f.typeOf(extra.struct_operand);6181 const struct_ty = f.typeOf(extra.struct_operand);
6103 const w = f.object.writer();6182 const w = &f.object.code.writer;
61046183
6105 // Ensure complete type definition is visible before accessing fields.6184 // Ensure complete type definition is visible before accessing fields.
6106 _ = try f.ctypeFromType(struct_ty, .complete);6185 _ = try f.ctypeFromType(struct_ty, .complete);
...@@ -6151,7 +6230,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6151,7 +6230,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6151 });6230 });
6152 if (cant_cast) try w.writeByte(')');6231 if (cant_cast) try w.writeByte(')');
6153 try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits);6232 try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits);
6154 try w.writeAll(");\n");6233 try w.writeAll(");");
6234 try f.object.newline();
6155 if (inst_ty.eql(field_int_ty, zcu)) return temp_local;6235 if (inst_ty.eql(field_int_ty, zcu)) return temp_local;
61566236
6157 const local = try f.allocLocal(inst, inst_ty);6237 const local = try f.allocLocal(inst, inst_ty);
...@@ -6162,7 +6242,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6162,7 +6242,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6162 try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument);6242 try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
6163 try w.writeAll(", sizeof(");6243 try w.writeAll(", sizeof(");
6164 try f.renderType(w, inst_ty);6244 try f.renderType(w, inst_ty);
6165 try w.writeAll("));\n");6245 try w.writeAll("));");
6246 try f.object.newline();
6166 }6247 }
6167 try freeLocal(f, inst, temp_local.new_local, null);6248 try freeLocal(f, inst, temp_local.new_local, null);
6168 return local;6249 return local;
...@@ -6186,7 +6267,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6186,7 +6267,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6186 try f.writeCValue(w, operand_local, .Other);6267 try f.writeCValue(w, operand_local, .Other);
6187 try w.writeAll(" = ");6268 try w.writeAll(" = ");
6188 try f.writeCValue(w, struct_byval, .Other);6269 try f.writeCValue(w, struct_byval, .Other);
6189 try w.writeAll(";\n");6270 try w.writeByte(';');
6271 try f.object.newline();
6190 break :blk operand_local;6272 break :blk operand_local;
6191 } else struct_byval;6273 } else struct_byval;
6192 const local = try f.allocLocal(inst, inst_ty);6274 const local = try f.allocLocal(inst, inst_ty);
...@@ -6203,7 +6285,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6203,7 +6285,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
6203 try f.writeCValue(w, operand_lval, .Other);6285 try f.writeCValue(w, operand_lval, .Other);
6204 try w.writeAll(", sizeof(");6286 try w.writeAll(", sizeof(");
6205 try f.renderType(w, inst_ty);6287 try f.renderType(w, inst_ty);
6206 try w.writeAll("));\n");6288 try w.writeAll("));");
6289 try f.object.newline();
6207 }6290 }
6208 try f.freeCValue(inst, operand_lval);6291 try f.freeCValue(inst, operand_lval);
6209 return local;6292 return local;
...@@ -6245,7 +6328,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6245,7 +6328,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6245 return local;6328 return local;
6246 }6329 }
62476330
6248 const w = f.object.writer();6331 const w = &f.object.code.writer;
6249 try f.writeCValue(w, local, .Other);6332 try f.writeCValue(w, local, .Other);
6250 try w.writeAll(" = ");6333 try w.writeAll(" = ");
62516334
...@@ -6259,7 +6342,8 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6259,7 +6342,8 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6259 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })6342 try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
6260 else6343 else
6261 try f.writeCValueMember(w, operand, .{ .identifier = "error" });6344 try f.writeCValueMember(w, operand, .{ .identifier = "error" });
6262 try w.writeAll(";\n");6345 try w.writeByte(';');
6346 try f.object.newline();
6263 return local;6347 return local;
6264}6348}
62656349
...@@ -6274,7 +6358,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -6274,7 +6358,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
6274 const operand_ty = f.typeOf(ty_op.operand);6358 const operand_ty = f.typeOf(ty_op.operand);
6275 const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;6359 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;
6278 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {6362 if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
6279 if (!is_ptr) return .none;6363 if (!is_ptr) return .none;
62806364
...@@ -6284,7 +6368,8 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -6284,7 +6368,8 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
6284 try f.renderType(w, inst_ty);6368 try f.renderType(w, inst_ty);
6285 try w.writeByte(')');6369 try w.writeByte(')');
6286 try f.writeCValue(w, operand, .Other);6370 try f.writeCValue(w, operand, .Other);
6287 try w.writeAll(";\n");6371 try w.writeByte(';');
6372 try f.object.newline();
6288 return local;6373 return local;
6289 }6374 }
62906375
...@@ -6315,7 +6400,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6315,7 +6400,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
6315 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {6400 .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
6316 .is_null, .payload => {6401 .is_null, .payload => {
6317 const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);6402 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;
6319 const local = try f.allocLocal(inst, inst_ty);6404 const local = try f.allocLocal(inst, inst_ty);
6320 {6405 {
6321 const a = try Assignment.start(f, w, .bool);6406 const a = try Assignment.start(f, w, .bool);
...@@ -6351,7 +6436,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6351,7 +6436,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6351 const err = try f.resolveInst(ty_op.operand);6436 const err = try f.resolveInst(ty_op.operand);
6352 try reap(f, inst, &.{ty_op.operand});6437 try reap(f, inst, &.{ty_op.operand});
63536438
6354 const w = f.object.writer();6439 const w = &f.object.code.writer;
6355 const local = try f.allocLocal(inst, inst_ty);6440 const local = try f.allocLocal(inst, inst_ty);
63566441
6357 if (repr_is_err and err == .local and err.local == local.new_local) {6442 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 {...@@ -6382,7 +6467,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
6382fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {6467fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
6383 const pt = f.object.dg.pt;6468 const pt = f.object.dg.pt;
6384 const zcu = pt.zcu;6469 const zcu = pt.zcu;
6385 const w = f.object.writer();6470 const w = &f.object.code.writer;
6386 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6471 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6387 const inst_ty = f.typeOfIndex(inst);6472 const inst_ty = f.typeOfIndex(inst);
6388 const operand = try f.resolveInst(ty_op.operand);6473 const operand = try f.resolveInst(ty_op.operand);
...@@ -6451,7 +6536,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6451,7 +6536,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
6451 const err_ty = inst_ty.errorUnionSet(zcu);6536 const err_ty = inst_ty.errorUnionSet(zcu);
6452 try reap(f, inst, &.{ty_op.operand});6537 try reap(f, inst, &.{ty_op.operand});
64536538
6454 const w = f.object.writer();6539 const w = &f.object.code.writer;
6455 const local = try f.allocLocal(inst, inst_ty);6540 const local = try f.allocLocal(inst, inst_ty);
6456 if (!repr_is_err) {6541 if (!repr_is_err) {
6457 const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));6542 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...@@ -6478,7 +6563,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
6478 const zcu = pt.zcu;6563 const zcu = pt.zcu;
6479 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;6564 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;
6482 const operand = try f.resolveInst(un_op);6567 const operand = try f.resolveInst(un_op);
6483 try reap(f, inst, &.{un_op});6568 try reap(f, inst, &.{un_op});
6484 const operand_ty = f.typeOf(un_op);6569 const operand_ty = f.typeOf(un_op);
...@@ -6519,7 +6604,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6519,7 +6604,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
6519 try reap(f, inst, &.{ty_op.operand});6604 try reap(f, inst, &.{ty_op.operand});
6520 const inst_ty = f.typeOfIndex(inst);6605 const inst_ty = f.typeOfIndex(inst);
6521 const ptr_ty = inst_ty.slicePtrFieldType(zcu);6606 const ptr_ty = inst_ty.slicePtrFieldType(zcu);
6522 const w = f.object.writer();6607 const w = &f.object.code.writer;
6523 const local = try f.allocLocal(inst, inst_ty);6608 const local = try f.allocLocal(inst, inst_ty);
6524 const operand_ty = f.typeOf(ty_op.operand);6609 const operand_ty = f.typeOf(ty_op.operand);
6525 const array_ty = operand_ty.childType(zcu);6610 const array_ty = operand_ty.childType(zcu);
...@@ -6584,7 +6669,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6584,7 +6669,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
6584 else6669 else
6585 unreachable;6670 unreachable;
65866671
6587 const w = f.object.writer();6672 const w = &f.object.code.writer;
6588 const local = try f.allocLocal(inst, inst_ty);6673 const local = try f.allocLocal(inst, inst_ty);
6589 const v = try Vectorize.start(f, inst, w, operand_ty);6674 const v = try Vectorize.start(f, inst, w, operand_ty);
6590 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));6675 const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
...@@ -6634,7 +6719,7 @@ fn airUnBuiltinCall(...@@ -6634,7 +6719,7 @@ fn airUnBuiltinCall(
6634 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6719 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6635 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6720 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;
6638 const local = try f.allocLocal(inst, inst_ty);6723 const local = try f.allocLocal(inst, inst_ty);
6639 const v = try Vectorize.start(f, inst, w, operand_ty);6724 const v = try Vectorize.start(f, inst, w, operand_ty);
6640 if (!ref_ret) {6725 if (!ref_ret) {
...@@ -6653,7 +6738,8 @@ fn airUnBuiltinCall(...@@ -6653,7 +6738,8 @@ fn airUnBuiltinCall(
6653 try f.writeCValue(w, operand, .FunctionArgument);6738 try f.writeCValue(w, operand, .FunctionArgument);
6654 try v.elem(f, w);6739 try v.elem(f, w);
6655 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);6740 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
6656 try w.writeAll(");\n");6741 try w.writeAll(");");
6742 try f.object.newline();
6657 try v.end(f, inst, w);6743 try v.end(f, inst, w);
66586744
6659 return local;6745 return local;
...@@ -6684,7 +6770,7 @@ fn airBinBuiltinCall(...@@ -6684,7 +6770,7 @@ fn airBinBuiltinCall(
6684 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6770 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6685 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6771 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;
6688 const local = try f.allocLocal(inst, inst_ty);6774 const local = try f.allocLocal(inst, inst_ty);
6689 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6775 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6690 const v = try Vectorize.start(f, inst, w, operand_ty);6776 const v = try Vectorize.start(f, inst, w, operand_ty);
...@@ -6735,7 +6821,7 @@ fn airCmpBuiltinCall(...@@ -6735,7 +6821,7 @@ fn airCmpBuiltinCall(
6735 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6821 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
6736 const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;6822 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;
6739 const local = try f.allocLocal(inst, inst_ty);6825 const local = try f.allocLocal(inst, inst_ty);
6740 const v = try Vectorize.start(f, inst, w, operand_ty);6826 const v = try Vectorize.start(f, inst, w, operand_ty);
6741 if (!ref_ret) {6827 if (!ref_ret) {
...@@ -6765,7 +6851,8 @@ fn airCmpBuiltinCall(...@@ -6765,7 +6851,8 @@ fn airCmpBuiltinCall(
6765 compareOperatorC(operator),6851 compareOperatorC(operator),
6766 try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)),6852 try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)),
6767 });6853 });
6768 try w.writeAll(";\n");6854 try w.writeByte(';');
6855 try f.object.newline();
6769 try v.end(f, inst, w);6856 try v.end(f, inst, w);
67706857
6771 return local;6858 return local;
...@@ -6784,7 +6871,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6784,7 +6871,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6784 const ty = ptr_ty.childType(zcu);6871 const ty = ptr_ty.childType(zcu);
6785 const ctype = try f.ctypeFromType(ty, .complete);6872 const ctype = try f.ctypeFromType(ty, .complete);
67866873
6787 const w = f.object.writer();6874 const w = &f.object.code.writer;
6788 const new_value_mat = try Materialize.start(f, inst, ty, new_value);6875 const new_value_mat = try Materialize.start(f, inst, ty, new_value);
6789 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });6876 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...@@ -6823,8 +6910,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6823 try w.writeAll(", ");6910 try w.writeAll(", ");
6824 try f.renderType(w, repr_ty);6911 try f.renderType(w, repr_ty);
6825 try w.writeByte(')');6912 try w.writeByte(')');
6826 try w.writeAll(") {\n");6913 try w.writeAll(") {");
6827 f.object.indent_writer.pushIndent();6914 f.object.indent();
6915 try f.object.newline();
6828 {6916 {
6829 const a = try Assignment.start(f, w, ctype);6917 const a = try Assignment.start(f, w, ctype);
6830 try f.writeCValue(w, local, .Other);6918 try f.writeCValue(w, local, .Other);
...@@ -6832,8 +6920,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6832,8 +6920,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6832 try w.writeAll("NULL");6920 try w.writeAll("NULL");
6833 try a.end(f, w);6921 try a.end(f, w);
6834 }6922 }
6835 f.object.indent_writer.popIndent();6923 try f.object.outdent();
6836 try w.writeAll("}\n");6924 try w.writeByte('}');
6925 try f.object.newline();
6837 } else {6926 } else {
6838 {6927 {
6839 const a = try Assignment.start(f, w, ctype);6928 const a = try Assignment.start(f, w, ctype);
...@@ -6889,7 +6978,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6889,7 +6978,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6889 const ptr = try f.resolveInst(pl_op.operand);6978 const ptr = try f.resolveInst(pl_op.operand);
6890 const operand = try f.resolveInst(extra.operand);6979 const operand = try f.resolveInst(extra.operand);
68916980
6892 const w = f.object.writer();6981 const w = &f.object.code.writer;
6893 const operand_mat = try Materialize.start(f, inst, ty, operand);6982 const operand_mat = try Materialize.start(f, inst, ty, operand);
6894 try reap(f, inst, &.{ pl_op.operand, extra.operand });6983 try reap(f, inst, &.{ pl_op.operand, extra.operand });
68956984
...@@ -6923,7 +7012,8 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6923,7 +7012,8 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6923 try f.object.dg.renderTypeForBuiltinFnName(w, ty);7012 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6924 try w.writeAll(", ");7013 try w.writeAll(", ");
6925 try f.renderType(w, repr_ty);7014 try f.renderType(w, repr_ty);
6926 try w.writeAll(");\n");7015 try w.writeAll(");");
7016 try f.object.newline();
6927 try operand_mat.end(f, inst);7017 try operand_mat.end(f, inst);
69287018
6929 if (f.liveness.isUnused(inst)) {7019 if (f.liveness.isUnused(inst)) {
...@@ -6949,7 +7039,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6949,7 +7039,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6949 ty;7039 ty;
69507040
6951 const inst_ty = f.typeOfIndex(inst);7041 const inst_ty = f.typeOfIndex(inst);
6952 const w = f.object.writer();7042 const w = &f.object.code.writer;
6953 const local = try f.allocLocal(inst, inst_ty);7043 const local = try f.allocLocal(inst, inst_ty);
69547044
6955 try w.writeAll("zig_atomic_load(");7045 try w.writeAll("zig_atomic_load(");
...@@ -6966,7 +7056,8 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6966,7 +7056,8 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6966 try f.object.dg.renderTypeForBuiltinFnName(w, ty);7056 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
6967 try w.writeAll(", ");7057 try w.writeAll(", ");
6968 try f.renderType(w, repr_ty);7058 try f.renderType(w, repr_ty);
6969 try w.writeAll(");\n");7059 try w.writeAll(");");
7060 try f.object.newline();
69707061
6971 return local;7062 return local;
6972}7063}
...@@ -6980,7 +7071,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -6980,7 +7071,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
6980 const ptr = try f.resolveInst(bin_op.lhs);7071 const ptr = try f.resolveInst(bin_op.lhs);
6981 const element = try f.resolveInst(bin_op.rhs);7072 const element = try f.resolveInst(bin_op.rhs);
69827073
6983 const w = f.object.writer();7074 const w = &f.object.code.writer;
6984 const element_mat = try Materialize.start(f, inst, ty, element);7075 const element_mat = try Materialize.start(f, inst, ty, element);
6985 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7076 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...@@ -7001,7 +7092,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
7001 try f.object.dg.renderTypeForBuiltinFnName(w, ty);7092 try f.object.dg.renderTypeForBuiltinFnName(w, ty);
7002 try w.writeAll(", ");7093 try w.writeAll(", ");
7003 try f.renderType(w, repr_ty);7094 try f.renderType(w, repr_ty);
7004 try w.writeAll(");\n");7095 try w.writeAll(");");
7096 try f.object.newline();
7005 try element_mat.end(f, inst);7097 try element_mat.end(f, inst);
70067098
7007 return .none;7099 return .none;
...@@ -7027,7 +7119,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7027,7 +7119,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
7027 const elem_ty = f.typeOf(bin_op.rhs);7119 const elem_ty = f.typeOf(bin_op.rhs);
7028 const elem_abi_size = elem_ty.abiSize(zcu);7120 const elem_abi_size = elem_ty.abiSize(zcu);
7029 const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(zcu) else false;7121 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
7032 if (val_is_undef) {7124 if (val_is_undef) {
7033 if (!safety) {7125 if (!safety) {
...@@ -7042,17 +7134,18 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7042,17 +7134,18 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
7042 try w.writeAll(", 0xaa, ");7134 try w.writeAll(", 0xaa, ");
7043 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });7135 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7044 if (elem_abi_size > 1) {7136 if (elem_abi_size > 1) {
7045 try w.print(" * {d});\n", .{elem_abi_size});7137 try w.print(" * {d}", .{elem_abi_size});
7046 } else {
7047 try w.writeAll(");\n");
7048 }7138 }
7139 try w.writeAll(");");
7140 try f.object.newline();
7049 },7141 },
7050 .one => {7142 .one => {
7051 const array_ty = dest_ty.childType(zcu);7143 const array_ty = dest_ty.childType(zcu);
7052 const len = array_ty.arrayLen(zcu) * elem_abi_size;7144 const len = array_ty.arrayLen(zcu) * elem_abi_size;
70537145
7054 try f.writeCValue(w, dest_slice, .FunctionArgument);7146 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();
7056 },7149 },
7057 .many, .c => unreachable,7150 .many, .c => unreachable,
7058 }7151 }
...@@ -7122,7 +7215,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7122,7 +7215,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
7122 try f.writeCValue(w, bitcasted, .FunctionArgument);7215 try f.writeCValue(w, bitcasted, .FunctionArgument);
7123 try w.writeAll(", ");7216 try w.writeAll(", ");
7124 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });7217 try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
7125 try w.writeAll(");\n");7218 try w.writeAll(");");
7219 try f.object.newline();
7126 },7220 },
7127 .one => {7221 .one => {
7128 const array_ty = dest_ty.childType(zcu);7222 const array_ty = dest_ty.childType(zcu);
...@@ -7131,7 +7225,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -7131,7 +7225,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
7131 try f.writeCValue(w, dest_slice, .FunctionArgument);7225 try f.writeCValue(w, dest_slice, .FunctionArgument);
7132 try w.writeAll(", ");7226 try w.writeAll(", ");
7133 try f.writeCValue(w, bitcasted, .FunctionArgument);7227 try f.writeCValue(w, bitcasted, .FunctionArgument);
7134 try w.print(", {d});\n", .{len});7228 try w.print(", {d});", .{len});
7229 try f.object.newline();
7135 },7230 },
7136 .many, .c => unreachable,7231 .many, .c => unreachable,
7137 }7232 }
...@@ -7148,11 +7243,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV...@@ -7148,11 +7243,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
7148 const src_ptr = try f.resolveInst(bin_op.rhs);7243 const src_ptr = try f.resolveInst(bin_op.rhs);
7149 const dest_ty = f.typeOf(bin_op.lhs);7244 const dest_ty = f.typeOf(bin_op.lhs);
7150 const src_ty = f.typeOf(bin_op.rhs);7245 const src_ty = f.typeOf(bin_op.rhs);
7151 const w = f.object.writer();7246 const w = &f.object.code.writer;
71527247
7153 if (dest_ty.ptrSize(zcu) != .one) {7248 if (dest_ty.ptrSize(zcu) != .one) {
7154 try w.writeAll("if (");7249 try w.writeAll("if (");
7155 try writeArrayLen(f, w, dest_ptr, dest_ty);7250 try writeArrayLen(f, dest_ptr, dest_ty);
7156 try w.writeAll(" != 0) ");7251 try w.writeAll(" != 0) ");
7157 }7252 }
7158 try w.writeAll(function_paren);7253 try w.writeAll(function_paren);
...@@ -7160,24 +7255,26 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV...@@ -7160,24 +7255,26 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
7160 try w.writeAll(", ");7255 try w.writeAll(", ");
7161 try writeSliceOrPtr(f, w, src_ptr, src_ty);7256 try writeSliceOrPtr(f, w, src_ptr, src_ty);
7162 try w.writeAll(", ");7257 try w.writeAll(", ");
7163 try writeArrayLen(f, w, dest_ptr, dest_ty);7258 try writeArrayLen(f, dest_ptr, dest_ty);
7164 try w.writeAll(" * sizeof(");7259 try w.writeAll(" * sizeof(");
7165 try f.renderType(w, dest_ty.elemType2(zcu));7260 try f.renderType(w, dest_ty.elemType2(zcu));
7166 try w.writeAll("));\n");7261 try w.writeAll("));");
7262 try f.object.newline();
71677263
7168 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });7264 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
7169 return .none;7265 return .none;
7170}7266}
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 {
7173 const pt = f.object.dg.pt;7269 const pt = f.object.dg.pt;
7174 const zcu = pt.zcu;7270 const zcu = pt.zcu;
7271 const w = &f.object.code.writer;
7175 switch (dest_ty.ptrSize(zcu)) {7272 switch (dest_ty.ptrSize(zcu)) {
7176 .one => try alw.print("{f}", .{7273 .one => try w.print("{f}", .{
7177 try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),7274 try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
7178 }),7275 }),
7179 .many, .c => unreachable,7276 .many, .c => unreachable,
7180 .slice => try f.writeCValueMember(alw, dest_ptr, .{ .identifier = "len" }),7277 .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }),
7181 }7278 }
7182}7279}
71837280
...@@ -7194,7 +7291,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7194,7 +7291,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
7194 if (layout.tag_size == 0) return .none;7291 if (layout.tag_size == 0) return .none;
7195 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;7292 const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
71967293
7197 const w = f.object.writer();7294 const w = &f.object.code.writer;
7198 const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));7295 const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
7199 try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" });7296 try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" });
7200 try a.assign(f, w);7297 try a.assign(f, w);
...@@ -7216,7 +7313,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7216,7 +7313,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
7216 if (layout.tag_size == 0) return .none;7313 if (layout.tag_size == 0) return .none;
72177314
7218 const inst_ty = f.typeOfIndex(inst);7315 const inst_ty = f.typeOfIndex(inst);
7219 const w = f.object.writer();7316 const w = &f.object.code.writer;
7220 const local = try f.allocLocal(inst, inst_ty);7317 const local = try f.allocLocal(inst, inst_ty);
7221 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));7318 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
7222 try f.writeCValue(w, local, .Other);7319 try f.writeCValue(w, local, .Other);
...@@ -7234,14 +7331,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7234,14 +7331,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
7234 const operand = try f.resolveInst(un_op);7331 const operand = try f.resolveInst(un_op);
7235 try reap(f, inst, &.{un_op});7332 try reap(f, inst, &.{un_op});
72367333
7237 const w = f.object.writer();7334 const w = &f.object.code.writer;
7238 const local = try f.allocLocal(inst, inst_ty);7335 const local = try f.allocLocal(inst, inst_ty);
7239 try f.writeCValue(w, local, .Other);7336 try f.writeCValue(w, local, .Other);
7240 try w.print(" = {s}(", .{7337 try w.print(" = {s}(", .{
7241 try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),7338 try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),
7242 });7339 });
7243 try f.writeCValue(w, operand, .Other);7340 try f.writeCValue(w, operand, .Other);
7244 try w.writeAll(");\n");7341 try w.writeAll(");");
7342 try f.object.newline();
72457343
7246 return local;7344 return local;
7247}7345}
...@@ -7249,7 +7347,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7249,7 +7347,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
7249fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {7347fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
7250 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;7348 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;
7253 const inst_ty = f.typeOfIndex(inst);7351 const inst_ty = f.typeOfIndex(inst);
7254 const operand = try f.resolveInst(un_op);7352 const operand = try f.resolveInst(un_op);
7255 try reap(f, inst, &.{un_op});7353 try reap(f, inst, &.{un_op});
...@@ -7258,7 +7356,8 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7258,7 +7356,8 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
72587356
7259 try w.writeAll(" = zig_errorName[");7357 try w.writeAll(" = zig_errorName[");
7260 try f.writeCValue(w, operand, .Other);7358 try f.writeCValue(w, operand, .Other);
7261 try w.writeAll(" - 1];\n");7359 try w.writeAll(" - 1];");
7360 try f.object.newline();
7262 return local;7361 return local;
7263}7362}
72647363
...@@ -7273,7 +7372,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7273,7 +7372,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
7273 const inst_ty = f.typeOfIndex(inst);7372 const inst_ty = f.typeOfIndex(inst);
7274 const inst_scalar_ty = inst_ty.scalarType(zcu);7373 const inst_scalar_ty = inst_ty.scalarType(zcu);
72757374
7276 const w = f.object.writer();7375 const w = &f.object.code.writer;
7277 const local = try f.allocLocal(inst, inst_ty);7376 const local = try f.allocLocal(inst, inst_ty);
7278 const v = try Vectorize.start(f, inst, w, inst_ty);7377 const v = try Vectorize.start(f, inst, w, inst_ty);
7279 const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));7378 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 {...@@ -7298,7 +7397,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
72987397
7299 const inst_ty = f.typeOfIndex(inst);7398 const inst_ty = f.typeOfIndex(inst);
73007399
7301 const w = f.object.writer();7400 const w = &f.object.code.writer;
7302 const local = try f.allocLocal(inst, inst_ty);7401 const local = try f.allocLocal(inst, inst_ty);
7303 const v = try Vectorize.start(f, inst, w, inst_ty);7402 const v = try Vectorize.start(f, inst, w, inst_ty);
7304 try f.writeCValue(w, local, .Other);7403 try f.writeCValue(w, local, .Other);
...@@ -7312,7 +7411,8 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7312,7 +7411,8 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
7312 try w.writeAll(" : ");7411 try w.writeAll(" : ");
7313 try f.writeCValue(w, rhs, .Other);7412 try f.writeCValue(w, rhs, .Other);
7314 try v.elem(f, w);7413 try v.elem(f, w);
7315 try w.writeAll(";\n");7414 try w.writeByte(';');
7415 try f.object.newline();
7316 try v.end(f, inst, w);7416 try v.end(f, inst, w);
73177417
7318 return local;7418 return local;
...@@ -7327,7 +7427,7 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7327,7 +7427,7 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
7327 const operand = try f.resolveInst(unwrapped.operand);7427 const operand = try f.resolveInst(unwrapped.operand);
7328 const inst_ty = unwrapped.result_ty;7428 const inst_ty = unwrapped.result_ty;
73297429
7330 const w = f.object.writer();7430 const w = &f.object.code.writer;
7331 const local = try f.allocLocal(inst, inst_ty);7431 const local = try f.allocLocal(inst, inst_ty);
7332 try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand7432 try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand
7333 for (mask, 0..) |mask_elem, out_idx| {7433 for (mask, 0..) |mask_elem, out_idx| {
...@@ -7361,7 +7461,7 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7361,7 +7461,7 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
7361 const inst_ty = unwrapped.result_ty;7461 const inst_ty = unwrapped.result_ty;
7362 const elem_ty = inst_ty.childType(zcu);7462 const elem_ty = inst_ty.childType(zcu);
73637463
7364 const w = f.object.writer();7464 const w = &f.object.code.writer;
7365 const local = try f.allocLocal(inst, inst_ty);7465 const local = try f.allocLocal(inst, inst_ty);
7366 try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands7466 try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands
7367 for (mask, 0..) |mask_elem, out_idx| {7467 for (mask, 0..) |mask_elem, out_idx| {
...@@ -7384,7 +7484,8 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7384,7 +7484,8 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
7384 },7484 },
7385 .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other),7485 .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other),
7386 }7486 }
7387 try w.writeAll(";\n");7487 try w.writeByte(';');
7488 try f.object.newline();
7388 }7489 }
73897490
7390 return local;7491 return local;
...@@ -7399,7 +7500,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7399,7 +7500,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7399 const operand = try f.resolveInst(reduce.operand);7500 const operand = try f.resolveInst(reduce.operand);
7400 try reap(f, inst, &.{reduce.operand});7501 try reap(f, inst, &.{reduce.operand});
7401 const operand_ty = f.typeOf(reduce.operand);7502 const operand_ty = f.typeOf(reduce.operand);
7402 const w = f.object.writer();7503 const w = &f.object.code.writer;
74037504
7404 const use_operator = scalar_ty.bitSize(zcu) <= 64;7505 const use_operator = scalar_ty.bitSize(zcu) <= 64;
7405 const op: union(enum) {7506 const op: union(enum) {
...@@ -7486,7 +7587,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7486,7 +7587,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7486 else => unreachable,7587 else => unreachable,
7487 },7588 },
7488 }, .Other);7589 }, .Other);
7489 try w.writeAll(";\n");7590 try w.writeByte(';');
7591 try f.object.newline();
74907592
7491 const v = try Vectorize.start(f, inst, w, operand_ty);7593 const v = try Vectorize.start(f, inst, w, operand_ty);
7492 try f.writeCValue(w, accum, .Other);7594 try f.writeCValue(w, accum, .Other);
...@@ -7520,7 +7622,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7520,7 +7622,8 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7520 try v.elem(f, w);7622 try v.elem(f, w);
7521 },7623 },
7522 }7624 }
7523 try w.writeAll(";\n");7625 try w.writeByte(';');
7626 try f.object.newline();
7524 try v.end(f, inst, w);7627 try v.end(f, inst, w);
75257628
7526 return accum;7629 return accum;
...@@ -7547,7 +7650,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7547,7 +7650,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7547 }7650 }
7548 }7651 }
75497652
7550 const w = f.object.writer();7653 const w = &f.object.code.writer;
7551 const local = try f.allocLocal(inst, inst_ty);7654 const local = try f.allocLocal(inst, inst_ty);
7552 switch (ip.indexToKey(inst_ty.toIntern())) {7655 switch (ip.indexToKey(inst_ty.toIntern())) {
7553 inline .array_type, .vector_type => |info, tag| {7656 inline .array_type, .vector_type => |info, tag| {
...@@ -7670,7 +7773,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7670,7 +7773,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7670 bit_offset += field_ty.bitSize(zcu);7773 bit_offset += field_ty.bitSize(zcu);
7671 empty = false;7774 empty = false;
7672 }7775 }
7673 try w.writeAll(";\n");7776 try w.writeByte(';');
7777 try f.object.newline();
7674 },7778 },
7675 }7779 }
7676 },7780 },
...@@ -7705,7 +7809,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7705,7 +7809,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
7705 const payload = try f.resolveInst(extra.init);7809 const payload = try f.resolveInst(extra.init);
7706 try reap(f, inst, &.{extra.init});7810 try reap(f, inst, &.{extra.init});
77077811
7708 const w = f.object.writer();7812 const w = &f.object.code.writer;
7709 const local = try f.allocLocal(inst, union_ty);7813 const local = try f.allocLocal(inst, union_ty);
7710 if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload);7814 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 {...@@ -7741,7 +7845,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7741 const ptr = try f.resolveInst(prefetch.ptr);7845 const ptr = try f.resolveInst(prefetch.ptr);
7742 try reap(f, inst, &.{prefetch.ptr});7846 try reap(f, inst, &.{prefetch.ptr});
77437847
7744 const w = f.object.writer();7848 const w = &f.object.code.writer;
7745 switch (prefetch.cache) {7849 switch (prefetch.cache) {
7746 .data => {7850 .data => {
7747 try w.writeAll("zig_prefetch(");7851 try w.writeAll("zig_prefetch(");
...@@ -7749,7 +7853,8 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7749,7 +7853,8 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7749 try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" })7853 try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" })
7750 else7854 else
7751 try f.writeCValue(w, ptr, .FunctionArgument);7855 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();
7753 },7858 },
7754 // The available prefetch intrinsics do not accept a cache argument; only7859 // The available prefetch intrinsics do not accept a cache argument; only
7755 // address, rw, and locality.7860 // address, rw, and locality.
...@@ -7762,13 +7867,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7762,13 +7867,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
7762fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {7867fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
7763 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7868 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;
7766 const inst_ty = f.typeOfIndex(inst);7871 const inst_ty = f.typeOfIndex(inst);
7767 const local = try f.allocLocal(inst, inst_ty);7872 const local = try f.allocLocal(inst, inst_ty);
7768 try f.writeCValue(w, local, .Other);7873 try f.writeCValue(w, local, .Other);
77697874
7770 try w.writeAll(" = ");7875 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
7773 return local;7879 return local;
7774}7880}
...@@ -7776,7 +7882,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7776,7 +7882,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
7776fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {7882fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
7777 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7883 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;
7780 const inst_ty = f.typeOfIndex(inst);7886 const inst_ty = f.typeOfIndex(inst);
7781 const operand = try f.resolveInst(pl_op.operand);7887 const operand = try f.resolveInst(pl_op.operand);
7782 try reap(f, inst, &.{pl_op.operand});7888 try reap(f, inst, &.{pl_op.operand});
...@@ -7786,7 +7892,8 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7786,7 +7892,8 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
7786 try w.writeAll(" = ");7892 try w.writeAll(" = ");
7787 try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});7893 try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
7788 try f.writeCValue(w, operand, .FunctionArgument);7894 try f.writeCValue(w, operand, .FunctionArgument);
7789 try w.writeAll(");\n");7895 try w.writeAll(");");
7896 try f.object.newline();
7790 return local;7897 return local;
7791}7898}
77927899
...@@ -7804,7 +7911,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7804,7 +7911,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7804 const inst_ty = f.typeOfIndex(inst);7911 const inst_ty = f.typeOfIndex(inst);
7805 const inst_scalar_ty = inst_ty.scalarType(zcu);7912 const inst_scalar_ty = inst_ty.scalarType(zcu);
78067913
7807 const w = f.object.writer();7914 const w = &f.object.code.writer;
7808 const local = try f.allocLocal(inst, inst_ty);7915 const local = try f.allocLocal(inst, inst_ty);
7809 const v = try Vectorize.start(f, inst, w, inst_ty);7916 const v = try Vectorize.start(f, inst, w, inst_ty);
7810 try f.writeCValue(w, local, .Other);7917 try f.writeCValue(w, local, .Other);
...@@ -7820,7 +7927,8 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7820,7 +7927,8 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7820 try w.writeAll(", ");7927 try w.writeAll(", ");
7821 try f.writeCValue(w, addend, .FunctionArgument);7928 try f.writeCValue(w, addend, .FunctionArgument);
7822 try v.elem(f, w);7929 try v.elem(f, w);
7823 try w.writeAll(");\n");7930 try w.writeAll(");");
7931 try f.object.newline();
7824 try v.end(f, inst, w);7932 try v.end(f, inst, w);
78257933
7826 return local;7934 return local;
...@@ -7828,12 +7936,13 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7828,12 +7936,13 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
78287936
7829fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {7937fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {
7830 const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;7938 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;
7832 const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));7940 const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));
7833 try f.writeCValue(w, local, .Other);7941 try f.writeCValue(w, local, .Other);
7834 try w.writeAll(" = ");7942 try w.writeAll(" = ");
7835 try f.object.dg.renderNav(w, ty_nav.nav, .Other);7943 try f.object.dg.renderNav(w, ty_nav.nav, .Other);
7836 try w.writeAll(";\n");7944 try w.writeByte(';');
7945 try f.object.newline();
7837 return local;7946 return local;
7838}7947}
78397948
...@@ -7845,7 +7954,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7845,7 +7954,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7845 const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;7954 const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;
7846 assert(function_info.varargs);7955 assert(function_info.varargs);
78477956
7848 const w = f.object.writer();7957 const w = &f.object.code.writer;
7849 const local = try f.allocLocal(inst, inst_ty);7958 const local = try f.allocLocal(inst, inst_ty);
7850 try w.writeAll("va_start(*(va_list *)&");7959 try w.writeAll("va_start(*(va_list *)&");
7851 try f.writeCValue(w, local, .Other);7960 try f.writeCValue(w, local, .Other);
...@@ -7853,7 +7962,8 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7853,7 +7962,8 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7853 try w.writeAll(", ");7962 try w.writeAll(", ");
7854 try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);7963 try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);
7855 }7964 }
7856 try w.writeAll(");\n");7965 try w.writeAll(");");
7966 try f.object.newline();
7857 return local;7967 return local;
7858}7968}
78597969
...@@ -7864,14 +7974,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7864,14 +7974,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
7864 const va_list = try f.resolveInst(ty_op.operand);7974 const va_list = try f.resolveInst(ty_op.operand);
7865 try reap(f, inst, &.{ty_op.operand});7975 try reap(f, inst, &.{ty_op.operand});
78667976
7867 const w = f.object.writer();7977 const w = &f.object.code.writer;
7868 const local = try f.allocLocal(inst, inst_ty);7978 const local = try f.allocLocal(inst, inst_ty);
7869 try f.writeCValue(w, local, .Other);7979 try f.writeCValue(w, local, .Other);
7870 try w.writeAll(" = va_arg(*(va_list *)");7980 try w.writeAll(" = va_arg(*(va_list *)");
7871 try f.writeCValue(w, va_list, .Other);7981 try f.writeCValue(w, va_list, .Other);
7872 try w.writeAll(", ");7982 try w.writeAll(", ");
7873 try f.renderType(w, ty_op.ty.toType());7983 try f.renderType(w, ty_op.ty.toType());
7874 try w.writeAll(");\n");7984 try w.writeAll(");");
7985 try f.object.newline();
7875 return local;7986 return local;
7876}7987}
78777988
...@@ -7881,10 +7992,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7881,10 +7992,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
7881 const va_list = try f.resolveInst(un_op);7992 const va_list = try f.resolveInst(un_op);
7882 try reap(f, inst, &.{un_op});7993 try reap(f, inst, &.{un_op});
78837994
7884 const w = f.object.writer();7995 const w = &f.object.code.writer;
7885 try w.writeAll("va_end(*(va_list *)");7996 try w.writeAll("va_end(*(va_list *)");
7886 try f.writeCValue(w, va_list, .Other);7997 try f.writeCValue(w, va_list, .Other);
7887 try w.writeAll(");\n");7998 try w.writeAll(");");
7999 try f.object.newline();
7888 return .none;8000 return .none;
7889}8001}
78908002
...@@ -7895,13 +8007,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7895,13 +8007,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
7895 const va_list = try f.resolveInst(ty_op.operand);8007 const va_list = try f.resolveInst(ty_op.operand);
7896 try reap(f, inst, &.{ty_op.operand});8008 try reap(f, inst, &.{ty_op.operand});
78978009
7898 const w = f.object.writer();8010 const w = &f.object.code.writer;
7899 const local = try f.allocLocal(inst, inst_ty);8011 const local = try f.allocLocal(inst, inst_ty);
7900 try w.writeAll("va_copy(*(va_list *)&");8012 try w.writeAll("va_copy(*(va_list *)&");
7901 try f.writeCValue(w, local, .Other);8013 try f.writeCValue(w, local, .Other);
7902 try w.writeAll(", *(va_list *)");8014 try w.writeAll(", *(va_list *)");
7903 try f.writeCValue(w, va_list, .Other);8015 try f.writeCValue(w, va_list, .Other);
7904 try w.writeAll(");\n");8016 try w.writeAll(");");
8017 try f.object.newline();
7905 return local;8018 return local;
7906}8019}
79078020
...@@ -8003,93 +8116,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {...@@ -8003,93 +8116,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {
8003 };8116 };
8004}8117}
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
8093fn toCIntBits(zig_bits: u32) ?u32 {8119fn toCIntBits(zig_bits: u32) ?u32 {
8094 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {8120 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {
8095 if (zig_bits <= c_bits) {8121 if (zig_bits <= c_bits) {
...@@ -8148,7 +8174,7 @@ const StringLiteral = struct {...@@ -8148,7 +8174,7 @@ const StringLiteral = struct {
8148 len: usize,8174 len: usize,
8149 cur_len: usize,8175 cur_len: usize,
8150 start_count: usize,8176 start_count: usize,
8151 writer: *std.io.Writer,8177 w: *Writer,
81528178
8153 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,8179 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
8154 // regardless of the length of the string literal initializing it. Array initializer syntax is8180 // regardless of the length of the string literal initializing it. Array initializer syntax is
...@@ -8161,63 +8187,63 @@ const StringLiteral = struct {...@@ -8161,63 +8187,63 @@ const StringLiteral = struct {
8161 const max_char_len = 4;8187 const max_char_len = 4;
8162 const max_literal_len = @min(16380 - max_char_len, 4095);8188 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 {
8165 return .{8191 return .{
8166 .cur_len = 0,8192 .cur_len = 0,
8167 .len = len,8193 .len = len,
8168 .start_count = w.count,8194 .start_count = w.count,
8169 .writer = w,8195 .w = w,
8170 };8196 };
8171 }8197 }
81728198
8173 pub fn start(sl: *StringLiteral) std.io.Writer.Error!void {8199 pub fn start(sl: *StringLiteral) Writer.Error!void {
8174 if (sl.len <= max_string_initializer_len) {8200 if (sl.len <= max_string_initializer_len) {
8175 try sl.writer.writeByte('\"');8201 try sl.w.writeByte('\"');
8176 } else {8202 } else {
8177 try sl.writer.writeByte('{');8203 try sl.w.writeByte('{');
8178 }8204 }
8179 }8205 }
81808206
8181 pub fn end(sl: *StringLiteral) std.io.Writer.Error!void {8207 pub fn end(sl: *StringLiteral) Writer.Error!void {
8182 if (sl.len <= max_string_initializer_len) {8208 if (sl.len <= max_string_initializer_len) {
8183 try sl.writer.writeByte('\"');8209 try sl.w.writeByte('\"');
8184 } else {8210 } else {
8185 try sl.writer.writeByte('}');8211 try sl.w.writeByte('}');
8186 }8212 }
8187 }8213 }
81888214
8189 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void {8215 fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!void {
8190 switch (c) {8216 switch (c) {
8191 7 => try sl.writer.writeAll("\\a"),8217 7 => try sl.w.writeAll("\\a"),
8192 8 => try sl.writer.writeAll("\\b"),8218 8 => try sl.w.writeAll("\\b"),
8193 '\t' => try sl.writer.writeAll("\\t"),8219 '\t' => try sl.w.writeAll("\\t"),
8194 '\n' => try sl.writer.writeAll("\\n"),8220 '\n' => try sl.w.writeAll("\\n"),
8195 11 => try sl.writer.writeAll("\\v"),8221 11 => try sl.w.writeAll("\\v"),
8196 12 => try sl.writer.writeAll("\\f"),8222 12 => try sl.w.writeAll("\\f"),
8197 '\r' => try sl.writer.writeAll("\\r"),8223 '\r' => try sl.w.writeAll("\\r"),
8198 '"', '\'', '?', '\\' => try sl.writer.print("\\{c}", .{c}),8224 '"', '\'', '?', '\\' => try sl.w.print("\\{c}", .{c}),
8199 else => switch (c) {8225 else => switch (c) {
8200 ' '...'~' => try sl.writer.writeByte(c),8226 ' '...'~' => try sl.w.writeByte(c),
8201 else => try sl.writer.print("\\{o:0>3}", .{c}),8227 else => try sl.w.print("\\{o:0>3}", .{c}),
8202 },8228 },
8203 }8229 }
8204 }8230 }
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 {
8207 if (sl.len <= max_string_initializer_len) {8233 if (sl.len <= max_string_initializer_len) {
8208 if (sl.cur_len == 0 and sl.writer.count - sl.start_count > 1)8234 if (sl.cur_len == 0 and sl.w.count - sl.start_count > 1)
8209 try sl.writer.writeAll("\"\"");8235 try sl.w.writeAll("\"\"");
82108236
8211 const count = sl.writer.count;8237 const count = sl.w.count;
8212 try sl.writeStringLiteralChar(c);8238 try sl.writeStringLiteralChar(c);
8213 const char_len = sl.writer.count - count;8239 const char_len = sl.w.count - count;
8214 assert(char_len <= max_char_len);8240 assert(char_len <= max_char_len);
8215 sl.cur_len += char_len;8241 sl.cur_len += char_len;
82168242
8217 if (sl.cur_len >= max_literal_len) sl.cur_len = 0;8243 if (sl.cur_len >= max_literal_len) sl.cur_len = 0;
8218 } else {8244 } else {
8219 if (sl.writer.count - sl.start_count > 1) try sl.writer.writeByte(',');8245 if (sl.w.count - sl.start_count > 1) try sl.w.writeByte(',');
8220 try sl.writer.print("'\\x{x}'", .{c});8246 try sl.w.print("'\\x{x}'", .{c});
8221 }8247 }
8222 }8248 }
8223};8249};
...@@ -8279,7 +8305,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri...@@ -8279,7 +8305,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
82798305
8280 var int_buf: Value.BigIntSpace = undefined;8306 var int_buf: Value.BigIntSpace = undefined;
8281 const int = if (data.val.isUndefDeep(zcu)) blk: {8307 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;
8283 @memset(undef_limbs, undefPattern(BigIntLimb));8309 @memset(undef_limbs, undefPattern(BigIntLimb));
82848310
8285 var undef_int = BigInt.Mutable{8311 var undef_int = BigInt.Mutable{
...@@ -8297,7 +8323,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri...@@ -8297,7 +8323,7 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
8297 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();8323 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
82988324
8299 var wrap = BigInt.Mutable{8325 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,
8301 .len = undefined,8327 .len = undefined,
8302 .positive = undefined,8328 .positive = undefined,
8303 };8329 };
...@@ -8351,7 +8377,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri...@@ -8351,7 +8377,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
8351 16 => try w.writeAll("0x"),8377 16 => try w.writeAll("0x"),
8352 else => unreachable,8378 else => unreachable,
8353 }8379 }
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;
8355 defer allocator.free(string);8382 defer allocator.free(string);
8356 try w.writeAll(string);8383 try w.writeAll(string);
8357 } else {8384 } else {
...@@ -8404,7 +8431,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri...@@ -8404,7 +8431,8 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Wri
8404 .int_info = c_limb_int_info,8431 .int_info = c_limb_int_info,
8405 .kind = data.kind,8432 .kind = data.kind,
8406 .ctype = c_limb_ctype,8433 .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,
8408 .base = data.base,8436 .base = data.base,
8409 .case = data.case,8437 .case = data.case,
8410 }, w);8438 }, w);
...@@ -8465,7 +8493,8 @@ const Assignment = struct {...@@ -8465,7 +8493,8 @@ const Assignment = struct {
8465 try w.writeAll("))");8493 try w.writeAll("))");
8466 },8494 },
8467 }8495 }
8468 try w.writeAll(";\n");8496 try w.writeByte(';');
8497 try f.object.newline();
8469 }8498 }
84708499
8471 fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {8500 fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {
...@@ -8492,7 +8521,8 @@ const Vectorize = struct {...@@ -8492,7 +8521,8 @@ const Vectorize = struct {
8492 try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))});8521 try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))});
8493 try f.writeCValue(w, local, .Other);8522 try f.writeCValue(w, local, .Other);
8494 try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)});8523 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
8497 break :index .{ .index = local };8527 break :index .{ .index = local };
8498 } else .{};8528 } else .{};
...@@ -8508,8 +8538,9 @@ const Vectorize = struct {...@@ -8508,8 +8538,9 @@ const Vectorize = struct {
85088538
8509 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void {8539 pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void {
8510 if (self.index != .none) {8540 if (self.index != .none) {
8511 f.object.indent_writer.popIndent();8541 try f.object.outdent();
8512 try w.writeAll("}\n");8542 try w.writeByte('}');
8543 try f.object.newline();
8513 try freeLocal(f, inst, self.index.new_local, null);8544 try freeLocal(f, inst, self.index.new_local, null);
8514 }8545 }
8515 }8546 }
...@@ -8617,9 +8648,3 @@ fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void {...@@ -8617,9 +8648,3 @@ fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void {
8617 }8648 }
8618 map.deinit(gpa);8649 map.deinit(gpa);
8619}8650}
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,...@@ -25,34 +25,34 @@ base: link.File,
25/// This linker backend does not try to incrementally link output C source code.25/// This linker backend does not try to incrementally link output C source code.
26/// Instead, it tracks all declarations in this table, and iterates over it26/// Instead, it tracks all declarations in this table, and iterates over it
27/// in the flush function, stitching pre-rendered pieces of C code together.27/// 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),
29/// All the string bytes of rendered C code, all squished into one array.29/// All the string bytes of rendered C code, all squished into one array.
30/// While in progress, a separate buffer is used, and then when finished, the30/// While in progress, a separate buffer is used, and then when finished, the
31/// buffer is copied into this one.31/// buffer is copied into this one.
32string_bytes: std.ArrayListUnmanaged(u8) = .empty,32string_bytes: std.ArrayListUnmanaged(u8),
33/// Tracks all the anonymous decls that are used by all the decls so they can33/// Tracks all the anonymous decls that are used by all the decls so they can
34/// be rendered during flush().34/// be rendered during flush().
35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock) = .empty,35uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock),
36/// Sparse set of uavs that are overaligned. Underaligned anon decls are36/// Sparse set of uavs that are overaligned. Underaligned anon decls are
37/// lowered the same as ABI-aligned anon decls. The keys here are a subset of37/// lowered the same as ABI-aligned anon decls. The keys here are a subset of
38/// the keys of `uavs`.38/// 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,41exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock),
42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .empty,42exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock),
4343
44/// Optimization, `updateDecl` reuses this buffer rather than creating a new44/// Optimization, `updateDecl` reuses this buffer rather than creating a new
45/// one with every call.45/// one with every call.
46fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,46fwd_decl_buf: []u8,
47/// Optimization, `updateDecl` reuses this buffer rather than creating a new47/// Optimization, `updateDecl` reuses this buffer rather than creating a new
48/// one with every call.48/// one with every call.
49code_buf: std.ArrayListUnmanaged(u8) = .empty,49code_header_buf: []u8,
50/// Optimization, `flush` reuses this buffer rather than creating a new50/// Optimization, `updateDecl` reuses this buffer rather than creating a new
51/// one with every call.51/// one with every call.
52lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .empty,52code_buf: []u8,
53/// Optimization, `flush` reuses this buffer rather than creating a new53/// Optimization, `flush` reuses this buffer rather than creating a new
54/// one with every call.54/// one with every call.
55lazy_code_buf: std.ArrayListUnmanaged(u8) = .empty,55scratch_buf: []u32,
5656
57/// A reference into `string_bytes`.57/// A reference into `string_bytes`.
58const String = extern struct {58const String = extern struct {
...@@ -67,11 +67,11 @@ const String = extern struct {...@@ -67,11 +67,11 @@ const String = extern struct {
6767
68/// Per-declaration data.68/// Per-declaration data.
69pub const AvBlock = struct {69pub const AvBlock = struct {
70 code: String = String.empty,70 fwd_decl: String = .empty,
71 fwd_decl: String = String.empty,71 code: String = .empty,
72 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate72 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
73 /// over each `Decl` and generate the definition for each used `CType` once.73 /// 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,
75 /// May contain string references to ctype_pool75 /// May contain string references to ctype_pool
76 lazy_fns: codegen.LazyFnMap = .{},76 lazy_fns: codegen.LazyFnMap = .{},
7777
...@@ -84,20 +84,21 @@ pub const AvBlock = struct {...@@ -84,20 +84,21 @@ pub const AvBlock = struct {
8484
85/// Per-exported-symbol data.85/// Per-exported-symbol data.
86pub const ExportedBlock = struct {86pub const ExportedBlock = struct {
87 fwd_decl: String = String.empty,87 fwd_decl: String = .empty,
88};88};
8989
90pub fn getString(this: C, s: String) []const u8 {90pub fn getString(this: C, s: String) []const u8 {
91 return this.string_bytes.items[s.start..][0..s.len];91 return this.string_bytes.items[s.start..][0..s.len];
92}92}
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 {
95 const comp = this.base.comp;95 const comp = this.base.comp;
96 const gpa = comp.gpa;96 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());
98 return .{99 return .{
99 .start = @intCast(this.string_bytes.items.len - s.len),100 .start = @intCast(start),
100 .len = @intCast(s.len),101 .len = @intCast(this.string_bytes.items.len - start),
101 };102 };
102}103}
103104
...@@ -147,6 +148,16 @@ pub fn createEmpty(...@@ -147,6 +148,16 @@ pub fn createEmpty(
147 .file = file,148 .file = file,
148 .build_id = options.build_id,149 .build_id = options.build_id,
149 },150 },
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 = &.{},
150 };161 };
151162
152 return c_file;163 return c_file;
...@@ -170,10 +181,10 @@ pub fn deinit(self: *C) void {...@@ -170,10 +181,10 @@ pub fn deinit(self: *C) void {
170 self.exported_uavs.deinit(gpa);181 self.exported_uavs.deinit(gpa);
171182
172 self.string_bytes.deinit(gpa);183 self.string_bytes.deinit(gpa);
173 self.fwd_decl_buf.deinit(gpa);184 gpa.free(self.fwd_decl_buf);
174 self.code_buf.deinit(gpa);185 gpa.free(self.code_header_buf);
175 self.lazy_fwd_decl_buf.deinit(gpa);186 gpa.free(self.code_buf);
176 self.lazy_code_buf.deinit(gpa);187 gpa.free(self.scratch_buf);
177}188}
178189
179pub fn updateFunc(190pub fn updateFunc(
...@@ -196,18 +207,14 @@ pub fn updateFunc(...@@ -196,18 +207,14 @@ pub fn updateFunc(
196 };207 };
197 gop.value_ptr.code = try self.addString(mir.c.code);208 gop.value_ptr.code = try self.addString(mir.c.code);
198 gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl);209 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);
199 try self.addUavsFromCodegen(&mir.c.uavs);211 try self.addUavsFromCodegen(&mir.c.uavs);
200}212}
201213
202fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {214fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void {
203 const gpa = self.base.comp.gpa;215 const gpa = self.base.comp.gpa;
204 const uav = self.uavs.keys()[i];216 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
211 var object: codegen.Object = .{218 var object: codegen.Object = .{
212 .dg = .{219 .dg = .{
213 .gpa = gpa,220 .gpa = gpa,
...@@ -217,21 +224,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {...@@ -217,21 +224,24 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
217 .pass = .{ .uav = uav },224 .pass = .{ .uav = uav },
218 .is_naked_fn = false,225 .is_naked_fn = false,
219 .expected_block = null,226 .expected_block = null,
220 .fwd_decl = fwd_decl.toManaged(gpa),227 .fwd_decl = undefined,
221 .ctype_pool = codegen.CType.Pool.empty,228 .ctype_pool = .empty,
222 .scratch = .{},229 .scratch = .initBuffer(self.scratch_buf),
223 .uavs = .empty,230 .uavs = .empty,
224 },231 },
225 .code = code.toManaged(gpa),232 .code_header = undefined,
226 .indent_writer = undefined, // set later so we can get a pointer to object.code233 .code = undefined,
234 .indent_counter = 0,
227 };235 };
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);
229 defer {238 defer {
230 object.dg.uavs.deinit(gpa);239 object.dg.uavs.deinit(gpa);
231 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
232 object.dg.ctype_pool.deinit(object.dg.gpa);240 object.dg.ctype_pool.deinit(object.dg.gpa);
233 object.dg.scratch.deinit(gpa);241
234 code.* = object.code.moveToUnmanaged();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();
235 }245 }
236 try object.dg.ctype_pool.init(gpa);246 try object.dg.ctype_pool.init(gpa);
237247
...@@ -243,15 +253,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {...@@ -243,15 +253,15 @@ fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) !void {
243 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);253 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
244 //return;254 //return;
245 },255 },
246 else => |e| return e,256 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
247 };257 };
248258
249 try self.addUavsFromCodegen(&object.dg.uavs);259 try self.addUavsFromCodegen(&object.dg.uavs);
250260
251 object.dg.ctype_pool.freeUnusedCapacity(gpa);261 object.dg.ctype_pool.freeUnusedCapacity(gpa);
252 self.uavs.values()[i] = .{262 self.uavs.values()[i] = .{
253 .code = try self.addString(object.code.items),263 .fwd_decl = try self.addString(&.{&object.dg.fwd_decl}),
254 .fwd_decl = try self.addString(object.dg.fwd_decl.items),264 .code = try self.addString(&.{&object.code}),
255 .ctype_pool = object.dg.ctype_pool.move(),265 .ctype_pool = object.dg.ctype_pool.move(),
256 };266 };
257}267}
...@@ -277,12 +287,8 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -277,12 +287,8 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
277 errdefer _ = self.navs.pop();287 errdefer _ = self.navs.pop();
278 if (!gop.found_existing) gop.value_ptr.* = .{};288 if (!gop.found_existing) gop.value_ptr.* = .{};
279 const ctype_pool = &gop.value_ptr.ctype_pool;289 const ctype_pool = &gop.value_ptr.ctype_pool;
280 const fwd_decl = &self.fwd_decl_buf;
281 const code = &self.code_buf;
282 try ctype_pool.init(gpa);290 try ctype_pool.init(gpa);
283 ctype_pool.clearRetainingCapacity();291 ctype_pool.clearRetainingCapacity();
284 fwd_decl.clearRetainingCapacity();
285 code.clearRetainingCapacity();
286292
287 var object: codegen.Object = .{293 var object: codegen.Object = .{
288 .dg = .{294 .dg = .{
...@@ -293,22 +299,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -293,22 +299,25 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
293 .pass = .{ .nav = nav_index },299 .pass = .{ .nav = nav_index },
294 .is_naked_fn = false,300 .is_naked_fn = false,
295 .expected_block = null,301 .expected_block = null,
296 .fwd_decl = fwd_decl.toManaged(gpa),302 .fwd_decl = undefined,
297 .ctype_pool = ctype_pool.*,303 .ctype_pool = ctype_pool.*,
298 .scratch = .{},304 .scratch = .initBuffer(self.scratch_buf),
299 .uavs = .empty,305 .uavs = .empty,
300 },306 },
301 .code = code.toManaged(gpa),307 .code_header = undefined,
302 .indent_writer = undefined, // set later so we can get a pointer to object.code308 .code = undefined,
309 .indent_counter = 0,
303 };310 };
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);
305 defer {313 defer {
306 object.dg.uavs.deinit(gpa);314 object.dg.uavs.deinit(gpa);
307 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
308 ctype_pool.* = object.dg.ctype_pool.move();315 ctype_pool.* = object.dg.ctype_pool.move();
309 ctype_pool.freeUnusedCapacity(gpa);316 ctype_pool.freeUnusedCapacity(gpa);
310 object.dg.scratch.deinit(gpa);317
311 code.* = object.code.moveToUnmanaged();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();
312 }321 }
313322
314 codegen.genDecl(&object) catch |err| switch (err) {323 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...@@ -316,10 +325,10 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
316 error.CodegenFail => return,325 error.CodegenFail => return,
317 error.OutOfMemory => |e| return e,326 error.OutOfMemory => |e| return e,
318 },327 },
319 else => |e| return e,328 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
320 };329 };
321 gop.value_ptr.code = try self.addString(object.code.items);330 gop.value_ptr.fwd_decl = try self.addString(&.{&object.dg.fwd_decl});
322 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);331 gop.value_ptr.code = try self.addString(&.{&object.code});
323 try self.addUavsFromCodegen(&object.dg.uavs);332 try self.addUavsFromCodegen(&object.dg.uavs);
324}333}
325334
...@@ -331,19 +340,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn...@@ -331,19 +340,14 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
331 _ = ti_id;340 _ = ti_id;
332}341}
333342
334fn abiDefines(self: *C, target: *const std.Target) !std.ArrayList(u8) {343fn abiDefines(w: *std.io.Writer, target: std.Target) !void {
335 const gpa = self.base.comp.gpa;
336 var defines = std.ArrayList(u8).init(gpa);
337 errdefer defines.deinit();
338 const writer = defines.writer();
339 switch (target.abi) {344 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"),
341 else => {},346 else => {},
342 }347 }
343 try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{348 try w.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{
344 target.cMaxIntAlignment(),349 target.cMaxIntAlignment(),
345 });350 });
346 return defines;
347}351}
348352
349pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {353pub 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...@@ -374,37 +378,47 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
374 // emit-h is in `flushEmitH` below.378 // emit-h is in `flushEmitH` below.
375379
376 var f: Flush = .{380 var f: Flush = .{
377 .ctype_pool = codegen.CType.Pool.empty,381 .ctype_pool = .empty,
378 .lazy_ctype_pool = codegen.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,
379 };392 };
380 defer f.deinit(gpa);393 defer f.deinit(gpa);
381394
382 const abi_defines = try self.abiDefines(zcu.getTarget());395 var abi_defines_aw: std.io.Writer.Allocating = .init(gpa);
383 defer abi_defines.deinit();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
385 // Covers defines, zig.h, ctypes, asm, lazy fwd.401 // Covers defines, zig.h, ctypes, asm, lazy fwd.
386 try f.all_buffers.ensureUnusedCapacity(gpa, 5);402 try f.all_buffers.ensureUnusedCapacity(gpa, 5);
387403
388 f.appendBufAssumeCapacity(abi_defines.items);404 f.appendBufAssumeCapacity(abi_defines_aw.getWritten());
389 f.appendBufAssumeCapacity(zig_h);405 f.appendBufAssumeCapacity(zig_h);
390406
391 const ctypes_index = f.all_buffers.items.len;407 const ctypes_index = f.all_buffers.items.len;
392 f.all_buffers.items.len += 1;408 f.all_buffers.items.len += 1;
393409
394 {410 var asm_aw: std.io.Writer.Allocating = .init(gpa);
395 var asm_buf = f.asm_buf.toManaged(gpa);411 defer asm_aw.deinit();
396 defer f.asm_buf = asm_buf.moveToUnmanaged();412 codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) {
397 try codegen.genGlobalAsm(zcu, asm_buf.writer());413 error.WriteFailed => return error.OutOfMemory,
398 f.appendBufAssumeCapacity(asm_buf.items);414 };
399 }415 f.appendBufAssumeCapacity(asm_aw.getWritten());
400416
401 const lazy_index = f.all_buffers.items.len;417 const lazy_index = f.all_buffers.items.len;
402 f.all_buffers.items.len += 1;418 f.all_buffers.items.len += 1;
403419
404 self.lazy_fwd_decl_buf.clearRetainingCapacity();
405 self.lazy_code_buf.clearRetainingCapacity();
406 try f.lazy_ctype_pool.init(gpa);420 try f.lazy_ctype_pool.init(gpa);
407 try self.flushErrDecls(pt, &f.lazy_ctype_pool);421 try self.flushErrDecls(pt, &f);
408422
409 // Unlike other backends, the .c code we are emitting has order-dependent decls.423 // Unlike other backends, the .c code we are emitting has order-dependent decls.
410 // `CType`s, forward decls, and non-functions first.424 // `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...@@ -462,22 +476,15 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
462 }476 }
463 }477 }
464478
465 f.all_buffers.items[ctypes_index] = .{479 f.all_buffers.items[ctypes_index] = f.ctypes.items;
466 .base = if (f.ctypes_buf.items.len > 0) f.ctypes_buf.items.ptr else "",480 f.file_size += f.ctypes.items.len;
467 .len = f.ctypes_buf.items.len,
468 };
469 f.file_size += f.ctypes_buf.items.len;
470481
471 const lazy_fwd_decl_len = self.lazy_fwd_decl_buf.items.len;482 f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items;
472 f.all_buffers.items[lazy_index] = .{483 f.file_size += f.lazy_fwd_decl.items.len;
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;
477484
478 // Now the code.485 // Now the code.
479 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2);486 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);
481 for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity(488 for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity(
482 if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) {489 if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) {
483 .@"extern" => .zig_extern,490 .@"extern" => .zig_extern,
...@@ -493,31 +500,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P...@@ -493,31 +500,35 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P
493500
494 const file = self.base.file.?;501 const file = self.base.file.?;
495 file.setEndPos(f.file_size) catch |err| return diags.fail("failed to allocate file: {s}", .{@errorName(err)});502 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}", .{503 var fw = file.writer(&.{});
497 self.base.emit, @errorName(err),504 var w = &fw.interface;
498 });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 };
499}510}
500511
501const Flush = struct {512const Flush = struct {
502 ctype_pool: codegen.CType.Pool,513 ctype_pool: codegen.CType.Pool,
503 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .empty,514 ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType),
504 ctypes_buf: std.ArrayListUnmanaged(u8) = .empty,515 ctypes: std.ArrayListUnmanaged(u8),
505516
506 lazy_ctype_pool: codegen.CType.Pool,517 lazy_ctype_pool: codegen.CType.Pool,
507 lazy_fns: LazyFns = .{},518 lazy_fns: LazyFns,
508519 lazy_fwd_decl: std.ArrayListUnmanaged(u8),
509 asm_buf: std.ArrayListUnmanaged(u8) = .empty,520 lazy_code: std.ArrayListUnmanaged(u8),
510521
511 /// We collect a list of buffers to write, and write them all at once with pwritev 😎522 /// 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),
513 /// Keeps track of the total bytes of `all_buffers`.524 /// Keeps track of the total bytes of `all_buffers`.
514 file_size: u64 = 0,525 file_size: u64,
515526
516 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);527 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);
517528
518 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {529 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
519 if (buf.len == 0) return;530 if (buf.len == 0) return;
520 f.all_buffers.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len });531 f.all_buffers.appendAssumeCapacity(buf);
521 f.file_size += buf.len;532 f.file_size += buf.len;
522 }533 }
523534
...@@ -532,14 +543,15 @@ const Flush = struct {...@@ -532,14 +543,15 @@ const Flush = struct {
532 }543 }
533544
534 fn deinit(f: *Flush, gpa: Allocator) void {545 fn deinit(f: *Flush, gpa: Allocator) void {
535 f.all_buffers.deinit(gpa);546 f.ctype_pool.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);
540 assert(f.ctype_global_from_decl_map.items.len == 0);547 assert(f.ctype_global_from_decl_map.items.len == 0);
541 f.ctype_global_from_decl_map.deinit(gpa);548 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);
543 }555 }
544};556};
545557
...@@ -562,9 +574,9 @@ fn flushCTypes(...@@ -562,9 +574,9 @@ fn flushCTypes(
562 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);574 try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len);
563 defer global_from_decl_map.clearRetainingCapacity();575 defer global_from_decl_map.clearRetainingCapacity();
564576
565 var ctypes_buf = f.ctypes_buf.toManaged(gpa);577 var ctypes_aw: std.io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes);
566 defer f.ctypes_buf = ctypes_buf.moveToUnmanaged();578 const ctypes_bw = &ctypes_aw.writer;
567 const writer = ctypes_buf.writer();579 defer f.ctypes = ctypes_aw.toArrayList();
568580
569 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {581 for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| {
570 const PoolAdapter = struct {582 const PoolAdapter = struct {
...@@ -591,26 +603,25 @@ fn flushCTypes(...@@ -591,26 +603,25 @@ fn flushCTypes(
591 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },603 PoolAdapter{ .global_from_decl_map = global_from_decl_map.items },
592 );604 );
593 global_from_decl_map.appendAssumeCapacity(global_ctype);605 global_from_decl_map.appendAssumeCapacity(global_ctype);
594 try codegen.genTypeDecl(606 codegen.genTypeDecl(
595 zcu,607 zcu,
596 writer,608 ctypes_bw,
597 global_ctype_pool,609 global_ctype_pool,
598 global_ctype,610 global_ctype,
599 pass,611 pass,
600 decl_ctype_pool,612 decl_ctype_pool,
601 decl_ctype,613 decl_ctype,
602 found_existing,614 found_existing,
603 );615 ) catch |err| switch (err) {
616 error.WriteFailed => return error.OutOfMemory,
617 };
604 }618 }
605}619}
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 {
608 const gpa = self.base.comp.gpa;622 const gpa = self.base.comp.gpa;
609623
610 const fwd_decl = &self.lazy_fwd_decl_buf;624 var object: codegen.Object = .{
611 const code = &self.lazy_code_buf;
612
613 var object = codegen.Object{
614 .dg = .{625 .dg = .{
615 .gpa = gpa,626 .gpa = gpa,
616 .pt = pt,627 .pt = pt,
...@@ -619,27 +630,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F...@@ -619,27 +630,30 @@ fn flushErrDecls(self: *C, pt: Zcu.PerThread, ctype_pool: *codegen.CType.Pool) F
619 .pass = .flush,630 .pass = .flush,
620 .is_naked_fn = false,631 .is_naked_fn = false,
621 .expected_block = null,632 .expected_block = null,
622 .fwd_decl = fwd_decl.toManaged(gpa),633 .fwd_decl = undefined,
623 .ctype_pool = ctype_pool.*,634 .ctype_pool = f.lazy_ctype_pool,
624 .scratch = .{},635 .scratch = .initBuffer(self.scratch_buf),
625 .uavs = .empty,636 .uavs = .empty,
626 },637 },
627 .code = code.toManaged(gpa),638 .code_header = undefined,
628 .indent_writer = undefined, // set later so we can get a pointer to object.code639 .code = undefined,
640 .indent_counter = 0,
629 };641 };
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);
631 defer {644 defer {
632 object.dg.uavs.deinit(gpa);645 object.dg.uavs.deinit(gpa);
633 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();646 f.lazy_ctype_pool = object.dg.ctype_pool.move();
634 ctype_pool.* = object.dg.ctype_pool.move();647 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
635 ctype_pool.freeUnusedCapacity(gpa);648
636 object.dg.scratch.deinit(gpa);649 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
637 code.* = object.code.moveToUnmanaged();650 f.lazy_code = object.code.toArrayList();
651 self.scratch_buf = object.dg.scratch.allocatedSlice();
638 }652 }
639653
640 codegen.genErrDecls(&object) catch |err| switch (err) {654 codegen.genErrDecls(&object) catch |err| switch (err) {
641 error.AnalysisFail => unreachable,655 error.AnalysisFail => unreachable,
642 else => |e| return e,656 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
643 };657 };
644658
645 try self.addUavsFromCodegen(&object.dg.uavs);659 try self.addUavsFromCodegen(&object.dg.uavs);
...@@ -649,16 +663,13 @@ fn flushLazyFn(...@@ -649,16 +663,13 @@ fn flushLazyFn(
649 self: *C,663 self: *C,
650 pt: Zcu.PerThread,664 pt: Zcu.PerThread,
651 mod: *Module,665 mod: *Module,
652 ctype_pool: *codegen.CType.Pool,666 f: *Flush,
653 lazy_ctype_pool: *const codegen.CType.Pool,667 lazy_ctype_pool: *const codegen.CType.Pool,
654 lazy_fn: codegen.LazyFnMap.Entry,668 lazy_fn: codegen.LazyFnMap.Entry,
655) FlushDeclError!void {669) FlushDeclError!void {
656 const gpa = self.base.comp.gpa;670 const gpa = self.base.comp.gpa;
657671
658 const fwd_decl = &self.lazy_fwd_decl_buf;672 var object: codegen.Object = .{
659 const code = &self.lazy_code_buf;
660
661 var object = codegen.Object{
662 .dg = .{673 .dg = .{
663 .gpa = gpa,674 .gpa = gpa,
664 .pt = pt,675 .pt = pt,
...@@ -667,29 +678,32 @@ fn flushLazyFn(...@@ -667,29 +678,32 @@ fn flushLazyFn(
667 .pass = .flush,678 .pass = .flush,
668 .is_naked_fn = false,679 .is_naked_fn = false,
669 .expected_block = null,680 .expected_block = null,
670 .fwd_decl = fwd_decl.toManaged(gpa),681 .fwd_decl = undefined,
671 .ctype_pool = ctype_pool.*,682 .ctype_pool = f.lazy_ctype_pool,
672 .scratch = .{},683 .scratch = .initBuffer(self.scratch_buf),
673 .uavs = .empty,684 .uavs = .empty,
674 },685 },
675 .code = code.toManaged(gpa),686 .code_header = undefined,
676 .indent_writer = undefined, // set later so we can get a pointer to object.code687 .code = undefined,
688 .indent_counter = 0,
677 };689 };
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);
679 defer {692 defer {
680 // If this assert trips just handle the anon_decl_deps the same as693 // If this assert trips just handle the anon_decl_deps the same as
681 // `updateFunc()` does.694 // `updateFunc()` does.
682 assert(object.dg.uavs.count() == 0);695 assert(object.dg.uavs.count() == 0);
683 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();696 f.lazy_ctype_pool = object.dg.ctype_pool.move();
684 ctype_pool.* = object.dg.ctype_pool.move();697 f.lazy_ctype_pool.freeUnusedCapacity(gpa);
685 ctype_pool.freeUnusedCapacity(gpa);698
686 object.dg.scratch.deinit(gpa);699 f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList();
687 code.* = object.code.moveToUnmanaged();700 f.lazy_code = object.code.toArrayList();
701 self.scratch_buf = object.dg.scratch.allocatedSlice();
688 }702 }
689703
690 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {704 codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) {
691 error.AnalysisFail => unreachable,705 error.AnalysisFail => unreachable,
692 else => |e| return e,706 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
693 };707 };
694}708}
695709
...@@ -709,7 +723,7 @@ fn flushLazyFns(...@@ -709,7 +723,7 @@ fn flushLazyFns(
709 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);723 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
710 if (gop.found_existing) continue;724 if (gop.found_existing) continue;
711 gop.value_ptr.* = {};725 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);
713 }727 }
714}728}
715729
...@@ -802,8 +816,6 @@ pub fn updateExports(...@@ -802,8 +816,6 @@ pub fn updateExports(
802 },816 },
803 };817 };
804 const ctype_pool = &decl_block.ctype_pool;818 const ctype_pool = &decl_block.ctype_pool;
805 const fwd_decl = &self.fwd_decl_buf;
806 fwd_decl.clearRetainingCapacity();
807 var dg: codegen.DeclGen = .{819 var dg: codegen.DeclGen = .{
808 .gpa = gpa,820 .gpa = gpa,
809 .pt = pt,821 .pt = pt,
...@@ -812,20 +824,24 @@ pub fn updateExports(...@@ -812,20 +824,24 @@ pub fn updateExports(
812 .pass = pass,824 .pass = pass,
813 .is_naked_fn = false,825 .is_naked_fn = false,
814 .expected_block = null,826 .expected_block = null,
815 .fwd_decl = fwd_decl.toManaged(gpa),827 .fwd_decl = undefined,
816 .ctype_pool = decl_block.ctype_pool,828 .ctype_pool = decl_block.ctype_pool,
817 .scratch = .{},829 .scratch = .initBuffer(self.scratch_buf),
818 .uavs = .empty,830 .uavs = .empty,
819 };831 };
832 dg.fwd_decl.initOwnedSlice(gpa, self.fwd_decl_buf);
820 defer {833 defer {
821 assert(dg.uavs.count() == 0);834 assert(dg.uavs.count() == 0);
822 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
823 ctype_pool.* = dg.ctype_pool.move();835 ctype_pool.* = dg.ctype_pool.move();
824 ctype_pool.freeUnusedCapacity(gpa);836 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();
826 }840 }
827 try codegen.genExports(&dg, exported, export_indices);841 codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) {
828 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) };842 error.WriteFailed, error.OutOfMemory => return error.OutOfMemory,
843 };
844 exported_block.* = .{ .fwd_decl = try self.addString(&.{&dg.fwd_decl}) };
829}845}
830846
831pub fn deleteExport(847pub fn deleteExport(