aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-07-10 12:04:27 +0200
committerGitHub <noreply@github.com>2025-07-10 12:04:27 +0200
commit1a998886c863a1829d649f196093f1058cd9cf13 (patch)
treedb1b3b0a043a113cfb6544e8103cb64f8e4e4d8f /src/codegen
parent5b4b033236a7bed19c90faf7fefbc1990911cfef (diff)
parent10d6db5d7d1fb62ee2915a7ad2c7feb771ea3bbb (diff)
downloadzig-1a998886c863a1829d649f196093f1058cd9cf13.tar.gz
zig-1a998886c863a1829d649f196093f1058cd9cf13.zip
Merge pull request #24329 from ziglang/writergate
Deprecates all existing std.io readers and writers in favor of the newly provided std.io.Reader and std.io.Writer which are non-generic and have the buffer above the vtable - in other words the buffer is in the interface, not the implementation. This means that although Reader and Writer are no longer generic, they are still transparent to optimization; all of the interface functions have a concrete hot path operating on the buffer, and only make vtable calls when the buffer is full.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig4379
-rw-r--r--src/codegen/c/Type.zig46
-rw-r--r--src/codegen/llvm.zig48
-rw-r--r--src/codegen/spirv.zig18
-rw-r--r--src/codegen/spirv/spec.zig10
5 files changed, 2278 insertions, 2223 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 7ee33577d8..61bd5259ae 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -4,6 +4,7 @@ const assert = std.debug.assert;
const mem = std.mem;
const log = std.log.scoped(.c);
const Allocator = mem.Allocator;
+const Writer = std.io.Writer;
const dev = @import("../dev.zig");
const link = @import("../link.zig");
@@ -55,6 +56,7 @@ pub const Mir = struct {
/// less than the natural alignment.
uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
// These remaining fields are essentially just an owned version of `link.C.AvBlock`.
+ code_header: []u8,
code: []u8,
fwd_decl: []u8,
ctype_pool: CType.Pool,
@@ -62,6 +64,7 @@ pub const Mir = struct {
pub fn deinit(mir: *Mir, gpa: Allocator) void {
mir.uavs.deinit(gpa);
+ gpa.free(mir.code_header);
gpa.free(mir.code);
gpa.free(mir.fwd_decl);
mir.ctype_pool.deinit(gpa);
@@ -69,6 +72,8 @@ pub const Mir = struct {
}
};
+pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail};
+
pub const CType = @import("c/Type.zig");
pub const CValue = union(enum) {
@@ -340,53 +345,61 @@ fn isReservedIdent(ident: []const u8) bool {
} else return reserved_idents.has(ident);
}
-fn formatIdent(
- ident: []const u8,
- comptime fmt_str: []const u8,
- _: std.fmt.FormatOptions,
- writer: anytype,
-) @TypeOf(writer).Error!void {
- const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident.
+fn formatIdentSolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
+ return formatIdentOptions(ident, w, true);
+}
+
+fn formatIdentUnsolo(ident: []const u8, w: *std.io.Writer) std.io.Writer.Error!void {
+ return formatIdentOptions(ident, w, false);
+}
+
+fn formatIdentOptions(ident: []const u8, w: *std.io.Writer, solo: bool) std.io.Writer.Error!void {
if (solo and isReservedIdent(ident)) {
- try writer.writeAll("zig_e_");
+ try w.writeAll("zig_e_");
}
for (ident, 0..) |c, i| {
switch (c) {
- 'a'...'z', 'A'...'Z', '_' => try writer.writeByte(c),
- '.' => try writer.writeByte('_'),
+ 'a'...'z', 'A'...'Z', '_' => try w.writeByte(c),
+ '.' => try w.writeByte('_'),
'0'...'9' => if (i == 0) {
- try writer.print("_{x:2}", .{c});
+ try w.print("_{x:2}", .{c});
} else {
- try writer.writeByte(c);
+ try w.writeByte(c);
},
- else => try writer.print("_{x:2}", .{c}),
+ else => try w.print("_{x:2}", .{c}),
}
}
}
-pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
+
+pub fn fmtIdentSolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentSolo) {
+ return .{ .data = ident };
+}
+
+pub fn fmtIdentUnsolo(ident: []const u8) std.fmt.Formatter([]const u8, formatIdentUnsolo) {
return .{ .data = ident };
}
const CTypePoolStringFormatData = struct {
ctype_pool_string: CType.Pool.String,
ctype_pool: *const CType.Pool,
+ solo: bool,
};
-fn formatCTypePoolString(
- data: CTypePoolStringFormatData,
- comptime fmt_str: []const u8,
- fmt_opts: std.fmt.FormatOptions,
- writer: anytype,
-) @TypeOf(writer).Error!void {
+fn formatCTypePoolString(data: CTypePoolStringFormatData, w: *std.io.Writer) std.io.Writer.Error!void {
if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice|
- try formatIdent(slice, fmt_str, fmt_opts, writer)
+ try formatIdentOptions(slice, w, data.solo)
else
- try writer.print("{}", .{data.ctype_pool_string.fmt(data.ctype_pool)});
+ try w.print("{f}", .{data.ctype_pool_string.fmt(data.ctype_pool)});
}
pub fn fmtCTypePoolString(
ctype_pool_string: CType.Pool.String,
ctype_pool: *const CType.Pool,
-) std.fmt.Formatter(formatCTypePoolString) {
- return .{ .data = .{ .ctype_pool_string = ctype_pool_string, .ctype_pool = ctype_pool } };
+ solo: bool,
+) std.fmt.Formatter(CTypePoolStringFormatData, formatCTypePoolString) {
+ return .{ .data = .{
+ .ctype_pool_string = ctype_pool_string,
+ .ctype_pool = ctype_pool,
+ .solo = solo,
+ } };
}
// Returns true if `formatIdent` would make any edits to ident.
@@ -440,18 +453,18 @@ pub const Function = struct {
const ty = f.typeOf(ref);
const result: CValue = if (lowersToArray(ty, pt)) result: {
- const writer = f.object.codeHeaderWriter();
+ const ch = &f.object.code_header.writer;
const decl_c_value = try f.allocLocalValue(.{
.ctype = try f.ctypeFromType(ty, .complete),
.alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),
});
const gpa = f.object.dg.gpa;
try f.allocs.put(gpa, decl_c_value.new_local, false);
- try writer.writeAll("static ");
- try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, .none, .complete);
- try writer.writeAll(" = ");
- try f.object.dg.renderValue(writer, val, .StaticInitializer);
- try writer.writeAll(";\n ");
+ try ch.writeAll("static ");
+ try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete);
+ try ch.writeAll(" = ");
+ try f.object.dg.renderValue(ch, val, .StaticInitializer);
+ try ch.writeAll(";\n ");
break :result .{ .local = decl_c_value.new_local };
} else .{ .constant = val };
@@ -504,7 +517,7 @@ pub const Function = struct {
return result;
}
- fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
+ fn writeCValue(f: *Function, w: *Writer, c_value: CValue, location: ValueRenderLocation) !void {
switch (c_value) {
.none => unreachable,
.new_local, .local => |i| try w.print("t{d}", .{i}),
@@ -517,7 +530,7 @@ pub const Function = struct {
}
}
- fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
+ fn writeCValueDeref(f: *Function, w: *Writer, c_value: CValue) !void {
switch (c_value) {
.none => unreachable,
.new_local, .local, .constant => {
@@ -538,41 +551,41 @@ pub const Function = struct {
fn writeCValueMember(
f: *Function,
- writer: anytype,
+ w: *Writer,
c_value: CValue,
member: CValue,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
switch (c_value) {
.new_local, .local, .local_ref, .constant, .arg, .arg_array => {
- try f.writeCValue(writer, c_value, .Other);
- try writer.writeByte('.');
- try f.writeCValue(writer, member, .Other);
+ try f.writeCValue(w, c_value, .Other);
+ try w.writeByte('.');
+ try f.writeCValue(w, member, .Other);
},
- else => return f.object.dg.writeCValueMember(writer, c_value, member),
+ else => return f.object.dg.writeCValueMember(w, c_value, member),
}
}
- fn writeCValueDerefMember(f: *Function, writer: anytype, c_value: CValue, member: CValue) !void {
+ fn writeCValueDerefMember(f: *Function, w: *Writer, c_value: CValue, member: CValue) !void {
switch (c_value) {
.new_local, .local, .arg, .arg_array => {
- try f.writeCValue(writer, c_value, .Other);
- try writer.writeAll("->");
+ try f.writeCValue(w, c_value, .Other);
+ try w.writeAll("->");
},
.constant => {
- try writer.writeByte('(');
- try f.writeCValue(writer, c_value, .Other);
- try writer.writeAll(")->");
+ try w.writeByte('(');
+ try f.writeCValue(w, c_value, .Other);
+ try w.writeAll(")->");
},
.local_ref => {
- try f.writeCValueDeref(writer, c_value);
- try writer.writeByte('.');
+ try f.writeCValueDeref(w, c_value);
+ try w.writeByte('.');
},
- else => return f.object.dg.writeCValueDerefMember(writer, c_value, member),
+ else => return f.object.dg.writeCValueDerefMember(w, c_value, member),
}
- try f.writeCValue(writer, member, .Other);
+ try f.writeCValue(w, member, .Other);
}
- fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
+ fn fail(f: *Function, comptime format: []const u8, args: anytype) Error {
return f.object.dg.fail(format, args);
}
@@ -584,20 +597,24 @@ pub const Function = struct {
return f.object.dg.byteSize(ctype);
}
- fn renderType(f: *Function, w: anytype, ctype: Type) !void {
+ fn renderType(f: *Function, w: *Writer, ctype: Type) !void {
return f.object.dg.renderType(w, ctype);
}
- fn renderCType(f: *Function, w: anytype, ctype: CType) !void {
+ fn renderCType(f: *Function, w: *Writer, ctype: CType) !void {
return f.object.dg.renderCType(w, ctype);
}
- fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
+ fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void {
return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
}
- fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) {
- return f.object.dg.fmtIntLiteral(val, .Other);
+ fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
+ return f.object.dg.fmtIntLiteralDec(val, .Other);
+ }
+
+ fn fmtIntLiteralHex(f: *Function, val: Value) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
+ return f.object.dg.fmtIntLiteralHex(val, .Other);
}
fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 {
@@ -614,16 +631,16 @@ pub const Function = struct {
gop.value_ptr.* = .{
.fn_name = switch (key) {
.tag_name,
- => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{
+ => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{
@tagName(key),
- fmtIdent(ip.loadEnumType(enum_ty).name.toSlice(ip)),
+ fmtIdentUnsolo(ip.loadEnumType(enum_ty).name.toSlice(ip)),
@intFromEnum(enum_ty),
}),
.never_tail,
.never_inline,
- => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{
+ => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{
@tagName(key),
- fmtIdent(ip.getNav(owner_nav).name.toSlice(ip)),
+ fmtIdentUnsolo(ip.getNav(owner_nav).name.toSlice(ip)),
@intFromEnum(owner_nav),
}),
},
@@ -659,12 +676,12 @@ pub const Function = struct {
},
else => {},
}
- const writer = f.object.writer();
- const a = try Assignment.start(f, writer, ctype);
- try f.writeCValue(writer, dst, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, src, .Other);
- try a.end(f, writer);
+ const w = &f.object.code.writer;
+ const a = try Assignment.start(f, w, ctype);
+ try f.writeCValue(w, dst, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, src, .Other);
+ try a.end(f, w);
}
fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue {
@@ -693,18 +710,32 @@ pub const Function = struct {
/// It is not available when generating .h file.
pub const Object = struct {
dg: DeclGen,
- /// This is a borrowed reference from `link.C`.
- code: std.ArrayList(u8),
- /// Goes before code. Initialized and deinitialized in `genFunc`.
- code_header: std.ArrayList(u8) = undefined,
- indent_writer: IndentWriter(std.ArrayList(u8).Writer),
-
- fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {
- return o.indent_writer.writer();
- }
-
- fn codeHeaderWriter(o: *Object) ArrayListWriter {
- return arrayListWriter(&o.code_header);
+ code_header: std.io.Writer.Allocating,
+ code: std.io.Writer.Allocating,
+ indent_counter: usize,
+
+ const indent_width = 1;
+ const indent_char = ' ';
+
+ fn newline(o: *Object) !void {
+ const w = &o.code.writer;
+ try w.writeByte('\n');
+ try w.splatByteAll(indent_char, o.indent_counter);
+ }
+ fn indent(o: *Object) void {
+ o.indent_counter += indent_width;
+ }
+ fn outdent(o: *Object) !void {
+ o.indent_counter -= indent_width;
+ const written = o.code.getWritten();
+ switch (written[written.len - 1]) {
+ indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width),
+ '\n' => try o.code.writer.splatByteAll(indent_char, o.indent_counter),
+ else => {
+ std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])});
+ unreachable;
+ },
+ }
}
};
@@ -716,8 +747,7 @@ pub const DeclGen = struct {
pass: Pass,
is_naked_fn: bool,
expected_block: ?u32,
- /// This is a borrowed reference from `link.C`.
- fwd_decl: std.ArrayList(u8),
+ fwd_decl: std.io.Writer.Allocating,
error_msg: ?*Zcu.ErrorMsg,
ctype_pool: CType.Pool,
scratch: std.ArrayListUnmanaged(u32),
@@ -734,11 +764,7 @@ pub const DeclGen = struct {
flush,
};
- fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter {
- return arrayListWriter(&dg.fwd_decl);
- }
-
- fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
+ fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
const zcu = dg.pt.zcu;
const src_loc = zcu.navSrcLoc(dg.pass.nav);
@@ -748,10 +774,10 @@ pub const DeclGen = struct {
fn renderUav(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
uav: InternPool.Key.Ptr.BaseAddr.Uav,
location: ValueRenderLocation,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -762,14 +788,14 @@ pub const DeclGen = struct {
// Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
const ptr_ty: Type = .fromInterned(uav.orig_ty);
if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(zcu)) {
- return dg.writeCValue(writer, .{ .undef = ptr_ty });
+ return dg.writeCValue(w, .{ .undef = ptr_ty });
}
// Chase function values in order to be able to reference the original function.
switch (ip.indexToKey(uav.val)) {
.variable => unreachable,
- .func => |func| return dg.renderNav(writer, func.owner_nav, location),
- .@"extern" => |@"extern"| return dg.renderNav(writer, @"extern".owner_nav, location),
+ .func => |func| return dg.renderNav(w, func.owner_nav, location),
+ .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location),
else => {},
}
@@ -783,13 +809,13 @@ pub const DeclGen = struct {
const need_cast = !elem_ctype.eql(uav_ctype) and
(elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function);
if (need_cast) {
- try writer.writeAll("((");
- try dg.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
+ try w.writeAll("((");
+ try dg.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('&');
- try renderUavName(writer, uav_val);
- if (need_cast) try writer.writeByte(')');
+ try w.writeByte('&');
+ try renderUavName(w, uav_val);
+ if (need_cast) try w.writeByte(')');
// Indicate that the anon decl should be rendered to the output so that
// our reference above is not undefined.
@@ -810,10 +836,10 @@ pub const DeclGen = struct {
fn renderNav(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
nav_index: InternPool.Nav.Index,
location: ValueRenderLocation,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
_ = location;
const pt = dg.pt;
const zcu = pt.zcu;
@@ -835,7 +861,7 @@ pub const DeclGen = struct {
const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip));
const ptr_ty = try pt.navPtrType(owner_nav);
if (!nav_ty.isFnOrHasRuntimeBits(zcu)) {
- return dg.writeCValue(writer, .{ .undef = ptr_ty });
+ return dg.writeCValue(w, .{ .undef = ptr_ty });
}
// We shouldn't cast C function pointers as this is UB (when you call
@@ -848,21 +874,21 @@ pub const DeclGen = struct {
const need_cast = !elem_ctype.eql(nav_ctype) and
(elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function);
if (need_cast) {
- try writer.writeAll("((");
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeAll("((");
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('&');
- try dg.renderNavName(writer, owner_nav);
- if (need_cast) try writer.writeByte(')');
+ try w.writeByte('&');
+ try dg.renderNavName(w, owner_nav);
+ if (need_cast) try w.writeByte(')');
}
fn renderPointer(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
derivation: Value.PointerDeriveStep,
location: ValueRenderLocation,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
switch (derivation) {
@@ -870,18 +896,18 @@ pub const DeclGen = struct {
.int => |int| {
const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete);
const addr_val = try pt.intValue(.usize, int.addr);
- try writer.writeByte('(');
- try dg.renderCType(writer, ptr_ctype);
- try writer.print("){x}", .{try dg.fmtIntLiteral(addr_val, .Other)});
+ try w.writeByte('(');
+ try dg.renderCType(w, ptr_ctype);
+ try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .Other)});
},
- .nav_ptr => |nav| try dg.renderNav(writer, nav, location),
- .uav_ptr => |uav| try dg.renderUav(writer, uav, location),
+ .nav_ptr => |nav| try dg.renderNav(w, nav, location),
+ .uav_ptr => |uav| try dg.renderUav(w, uav, location),
inline .eu_payload_ptr, .opt_payload_ptr => |info| {
- try writer.writeAll("&(");
- try dg.renderPointer(writer, info.parent.*, location);
- try writer.writeAll(")->payload");
+ try w.writeAll("&(");
+ try dg.renderPointer(w, info.parent.*, location);
+ try w.writeAll(")->payload");
},
.field_ptr => |field| {
@@ -893,26 +919,26 @@ pub const DeclGen = struct {
switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, pt)) {
.begin => {
const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);
- try writer.writeByte('(');
- try dg.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
- try dg.renderPointer(writer, field.parent.*, location);
+ try w.writeByte('(');
+ try dg.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
+ try dg.renderPointer(w, field.parent.*, location);
},
.field => |name| {
- try writer.writeAll("&(");
- try dg.renderPointer(writer, field.parent.*, location);
- try writer.writeAll(")->");
- try dg.writeCValue(writer, name);
+ try w.writeAll("&(");
+ try dg.renderPointer(w, field.parent.*, location);
+ try w.writeAll(")->");
+ try dg.writeCValue(w, name);
},
.byte_offset => |byte_offset| {
const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);
- try writer.writeByte('(');
- try dg.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
const offset_val = try pt.intValue(.usize, byte_offset);
- try writer.writeAll("((char *)");
- try dg.renderPointer(writer, field.parent.*, location);
- try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)});
+ try w.writeAll("((char *)");
+ try dg.renderPointer(w, field.parent.*, location);
+ try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)});
},
}
},
@@ -920,10 +946,10 @@ pub const DeclGen = struct {
.elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) {
// Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer.
const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete);
- try writer.writeByte('(');
- try dg.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
- try dg.renderPointer(writer, elem.parent.*, location);
+ try w.writeByte('(');
+ try dg.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
+ try dg.renderPointer(w, elem.parent.*, location);
} else {
const index_val = try pt.intValue(.usize, elem.elem_idx);
// We want to do pointer arithmetic on a pointer to the element type.
@@ -932,48 +958,47 @@ pub const DeclGen = struct {
const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete);
if (result_ctype.eql(parent_ctype)) {
// The pointer already has an appropriate type - just do the arithmetic.
- try writer.writeByte('(');
- try dg.renderPointer(writer, elem.parent.*, location);
- try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)});
+ try w.writeByte('(');
+ try dg.renderPointer(w, elem.parent.*, location);
+ try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)});
} else {
// We probably have an array pointer `T (*)[n]`. Cast to an element pointer,
// and *then* apply the index.
- try writer.writeAll("((");
- try dg.renderCType(writer, result_ctype);
- try writer.writeByte(')');
- try dg.renderPointer(writer, elem.parent.*, location);
- try writer.print(" + {})", .{try dg.fmtIntLiteral(index_val, .Other)});
+ try w.writeAll("((");
+ try dg.renderCType(w, result_ctype);
+ try w.writeByte(')');
+ try dg.renderPointer(w, elem.parent.*, location);
+ try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)});
}
},
.offset_and_cast => |oac| {
const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete);
- try writer.writeByte('(');
- try dg.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
if (oac.byte_offset == 0) {
- try dg.renderPointer(writer, oac.parent.*, location);
+ try dg.renderPointer(w, oac.parent.*, location);
} else {
const offset_val = try pt.intValue(.usize, oac.byte_offset);
- try writer.writeAll("((char *)");
- try dg.renderPointer(writer, oac.parent.*, location);
- try writer.print(" + {})", .{try dg.fmtIntLiteral(offset_val, .Other)});
+ try w.writeAll("((char *)");
+ try dg.renderPointer(w, oac.parent.*, location);
+ try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)});
}
},
}
}
- fn renderErrorName(dg: *DeclGen, writer: anytype, err_name: InternPool.NullTerminatedString) !void {
- const ip = &dg.pt.zcu.intern_pool;
- try writer.print("zig_error_{}", .{fmtIdent(err_name.toSlice(ip))});
+ fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void {
+ try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))});
}
fn renderValue(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
val: Value,
location: ValueRenderLocation,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -986,7 +1011,7 @@ pub const DeclGen = struct {
};
const ty = val.typeOf(zcu);
- if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location);
+ if (val.isUndefDeep(zcu)) return dg.renderUndefValue(w, ty, location);
const ctype = try dg.ctypeFromType(ty, location.toCTypeKind());
switch (ip.indexToKey(val.toIntern())) {
// types, not values
@@ -1019,8 +1044,8 @@ pub const DeclGen = struct {
.empty_tuple => unreachable,
.@"unreachable" => unreachable,
- .false => try writer.writeAll("false"),
- .true => try writer.writeAll("true"),
+ .false => try w.writeAll("false"),
+ .true => try w.writeAll("true"),
},
.variable,
.@"extern",
@@ -1029,45 +1054,45 @@ pub const DeclGen = struct {
.empty_enum_value,
=> unreachable, // non-runtime values
.int => |int| switch (int.storage) {
- .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}),
+ .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}),
.lazy_align, .lazy_size => {
- try writer.writeAll("((");
- try dg.renderCType(writer, ctype);
- try writer.print("){x})", .{try dg.fmtIntLiteral(
+ try w.writeAll("((");
+ try dg.renderCType(w, ctype);
+ try w.print("){f})", .{try dg.fmtIntLiteralHex(
try pt.intValue(.usize, val.toUnsignedInt(zcu)),
.Other,
)});
},
},
- .err => |err| try dg.renderErrorName(writer, err.name),
+ .err => |err| try dg.renderErrorName(w, err.name),
.error_union => |error_union| switch (ctype.info(ctype_pool)) {
.basic => switch (error_union.val) {
- .err_name => |err_name| try dg.renderErrorName(writer, err_name),
- .payload => try writer.writeAll("0"),
+ .err_name => |err_name| try dg.renderErrorName(w, err_name),
+ .payload => try w.writeByte('0'),
},
.pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => |aggregate| {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeByte(',');
+ if (field_index > 0) try w.writeByte(',');
switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
.@"error" => switch (error_union.val) {
- .err_name => |err_name| try dg.renderErrorName(writer, err_name),
- .payload => try writer.writeByte('0'),
+ .err_name => |err_name| try dg.renderErrorName(w, err_name),
+ .payload => try w.writeByte('0'),
},
.payload => switch (error_union.val) {
.err_name => try dg.renderUndefValue(
- writer,
+ w,
ty.errorUnionPayload(zcu),
initializer_type,
),
.payload => |payload| try dg.renderValue(
- writer,
+ w,
Value.fromInterned(payload),
initializer_type,
),
@@ -1075,10 +1100,10 @@ pub const DeclGen = struct {
else => unreachable,
}
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
},
- .enum_tag => |enum_tag| try dg.renderValue(writer, Value.fromInterned(enum_tag.int), location),
+ .enum_tag => |enum_tag| try dg.renderValue(w, Value.fromInterned(enum_tag.int), location),
.float => {
const bits = ty.floatBits(target);
const f128_val = val.toFloat(f128, zcu);
@@ -1105,18 +1130,18 @@ pub const DeclGen = struct {
var empty = true;
if (std.math.isFinite(f128_val)) {
- try writer.writeAll("zig_make_");
- try dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_make_");
+ try dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeByte('(');
switch (bits) {
- 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}),
- 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}),
- 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}),
- 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}),
- 128 => try writer.print("{x}", .{f128_val}),
+ 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}),
+ 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}),
+ 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}),
+ 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}),
+ 128 => try w.print("{x}", .{f128_val}),
else => unreachable,
}
- try writer.writeAll(", ");
+ try w.writeAll(", ");
empty = false;
} else {
// isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan
@@ -1140,45 +1165,45 @@ pub const DeclGen = struct {
// return dg.fail("Only quiet nans are supported in global variable initializers", .{});
}
- try writer.writeAll("zig_");
- try writer.writeAll(if (location == .StaticInitializer) "init" else "make");
- try writer.writeAll("_special_");
- try dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeByte('(');
- if (std.math.signbit(f128_val)) try writer.writeByte('-');
- try writer.writeAll(", ");
- try writer.writeAll(operation);
- try writer.writeAll(", ");
+ try w.writeAll("zig_");
+ try w.writeAll(if (location == .StaticInitializer) "init" else "make");
+ try w.writeAll("_special_");
+ try dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeByte('(');
+ if (std.math.signbit(f128_val)) try w.writeByte('-');
+ try w.writeAll(", ");
+ try w.writeAll(operation);
+ try w.writeAll(", ");
if (std.math.isNan(f128_val)) switch (bits) {
// We only actually need to pass the significand, but it will get
// properly masked anyway, so just pass the whole value.
- 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
- 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),
- 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
- 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
- 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
+ 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
+ 32 => try w.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),
+ 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
+ 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
+ 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
else => unreachable,
};
- try writer.writeAll(", ");
+ try w.writeAll(", ");
empty = false;
}
- try writer.print("{x}", .{try dg.fmtIntLiteral(
+ try w.print("{f}", .{try dg.fmtIntLiteralHex(
try pt.intValue_big(repr_ty, repr_val_big.toConst()),
location,
)});
- if (!empty) try writer.writeByte(')');
+ if (!empty) try w.writeByte(')');
},
.slice => |slice| {
const aggregate = ctype.info(ctype_pool).aggregate;
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeByte(',');
- try dg.renderValue(writer, Value.fromInterned(
+ if (field_index > 0) try w.writeByte(',');
+ try dg.renderValue(w, Value.fromInterned(
switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
.ptr => slice.ptr,
.len => slice.len,
@@ -1186,33 +1211,33 @@ pub const DeclGen = struct {
},
), initializer_type);
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
.ptr => {
var arena = std.heap.ArenaAllocator.init(zcu.gpa);
defer arena.deinit();
const derivation = try val.pointerDerivation(arena.allocator(), pt);
- try dg.renderPointer(writer, derivation, location);
+ try dg.renderPointer(w, derivation, location);
},
.opt => |opt| switch (ctype.info(ctype_pool)) {
- .basic => if (ctype.isBool()) try writer.writeAll(switch (opt.val) {
+ .basic => if (ctype.isBool()) try w.writeAll(switch (opt.val) {
.none => "true",
else => "false",
}) else switch (opt.val) {
- .none => try writer.writeAll("0"),
+ .none => try w.writeByte('0'),
else => |payload| switch (ip.indexToKey(payload)) {
.undef => |err_ty| try dg.renderUndefValue(
- writer,
+ w,
.fromInterned(err_ty),
location,
),
- .err => |err| try dg.renderErrorName(writer, err.name),
+ .err => |err| try dg.renderErrorName(w, err.name),
else => unreachable,
},
},
.pointer => switch (opt.val) {
- .none => try writer.writeAll("NULL"),
- else => |payload| try dg.renderValue(writer, Value.fromInterned(payload), location),
+ .none => try w.writeAll("NULL"),
+ else => |payload| try dg.renderValue(w, Value.fromInterned(payload), location),
},
.aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => |aggregate| {
@@ -1221,7 +1246,7 @@ pub const DeclGen = struct {
else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) {
.is_null, .payload => {},
.ptr, .len => return dg.renderValue(
- writer,
+ w,
Value.fromInterned(payload),
location,
),
@@ -1229,48 +1254,48 @@ pub const DeclGen = struct {
},
}
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeByte(',');
+ if (field_index > 0) try w.writeByte(',');
switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
- .is_null => try writer.writeAll(switch (opt.val) {
+ .is_null => try w.writeAll(switch (opt.val) {
.none => "true",
else => "false",
}),
.payload => switch (opt.val) {
.none => try dg.renderUndefValue(
- writer,
+ w,
ty.optionalChild(zcu),
initializer_type,
),
else => |payload| try dg.renderValue(
- writer,
+ w,
Value.fromInterned(payload),
initializer_type,
),
},
- .ptr => try writer.writeAll("NULL"),
- .len => try dg.renderUndefValue(writer, .usize, initializer_type),
+ .ptr => try w.writeAll("NULL"),
+ .len => try dg.renderUndefValue(w, .usize, initializer_type),
else => unreachable,
}
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
},
.aggregate => switch (ip.indexToKey(ty.toIntern())) {
.array_type, .vector_type => {
if (location == .FunctionArgument) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
const ai = ty.arrayInfo(zcu);
if (ai.elem_type.eql(.u8, zcu)) {
- var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu));
+ var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu)));
try literal.start();
var index: usize = 0;
while (index < ai.len) : (index += 1) {
@@ -1287,28 +1312,28 @@ pub const DeclGen = struct {
}
try literal.end();
} else {
- try writer.writeByte('{');
+ try w.writeByte('{');
var index: usize = 0;
while (index < ai.len) : (index += 1) {
- if (index != 0) try writer.writeByte(',');
+ if (index != 0) try w.writeByte(',');
const elem_val = try val.elemValue(pt, index);
- try dg.renderValue(writer, elem_val, initializer_type);
+ try dg.renderValue(w, elem_val, initializer_type);
}
if (ai.sentinel) |s| {
- if (index != 0) try writer.writeByte(',');
- try dg.renderValue(writer, s, initializer_type);
+ if (index != 0) try w.writeByte(',');
+ try dg.renderValue(w, s, initializer_type);
}
- try writer.writeByte('}');
+ try w.writeByte('}');
}
},
.tuple_type => |tuple| {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
var empty = true;
for (0..tuple.types.len) |field_index| {
const comptime_val = tuple.values.get(ip)[field_index];
@@ -1316,7 +1341,7 @@ pub const DeclGen = struct {
const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (!empty) try writer.writeByte(',');
+ if (!empty) try w.writeByte(',');
const field_val = Value.fromInterned(
switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
@@ -1328,30 +1353,30 @@ pub const DeclGen = struct {
.repeated_elem => |elem| elem,
},
);
- try dg.renderValue(writer, field_val, initializer_type);
+ try dg.renderValue(w, field_val, initializer_type);
empty = false;
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
.struct_type => {
const loaded_struct = ip.loadStructType(ty.toIntern());
switch (loaded_struct.layout) {
.auto, .@"extern" => {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
var field_it = loaded_struct.iterateRuntimeOrder(ip);
var need_comma = false;
while (field_it.next()) |field_index| {
const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (need_comma) try writer.writeByte(',');
+ if (need_comma) try w.writeByte(',');
need_comma = true;
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try pt.intern(.{ .int = .{
@@ -1361,9 +1386,9 @@ pub const DeclGen = struct {
.elems => |elems| elems[field_index],
.repeated_elem => |elem| elem,
};
- try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type);
+ try dg.renderValue(w, Value.fromInterned(field_val), initializer_type);
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
.@"packed" => {
const int_info = ty.intInfo(zcu);
@@ -1381,16 +1406,16 @@ pub const DeclGen = struct {
}
if (eff_num_fields == 0) {
- try writer.writeByte('(');
- try dg.renderUndefValue(writer, ty, location);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderUndefValue(w, ty, location);
+ try w.writeByte(')');
} else if (ty.bitSize(zcu) > 64) {
// zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
var num_or = eff_num_fields - 1;
while (num_or > 0) : (num_or -= 1) {
- try writer.writeAll("zig_or_");
- try dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_or_");
+ try dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeByte('(');
}
var eff_index: usize = 0;
@@ -1409,36 +1434,36 @@ pub const DeclGen = struct {
};
const cast_context = IntCastContext{ .value = .{ .value = Value.fromInterned(field_val) } };
if (bit_offset != 0) {
- try writer.writeAll("zig_shl_");
- try dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeByte('(');
- try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
- try writer.writeAll(", ");
- try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
- try writer.writeByte(')');
+ try w.writeAll("zig_shl_");
+ try dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeByte('(');
+ try dg.renderIntCast(w, ty, cast_context, field_ty, .FunctionArgument);
+ try w.writeAll(", ");
+ try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
+ try w.writeByte(')');
} else {
- try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
+ try dg.renderIntCast(w, ty, cast_context, field_ty, .FunctionArgument);
}
- if (needs_closing_paren) try writer.writeByte(')');
- if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
+ if (needs_closing_paren) try w.writeByte(')');
+ if (eff_index != eff_num_fields - 1) try w.writeAll(", ");
bit_offset += field_ty.bitSize(zcu);
needs_closing_paren = true;
eff_index += 1;
}
} else {
- try writer.writeByte('(');
+ try w.writeByte('(');
// a << a_off | b << b_off | c << c_off
var empty = true;
for (0..loaded_struct.field_types.len) |field_index| {
const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (!empty) try writer.writeAll(" | ");
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ if (!empty) try w.writeAll(" | ");
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
.bytes => |bytes| try pt.intern(.{ .int = .{
@@ -1455,24 +1480,24 @@ pub const DeclGen = struct {
.{ .signedness = .unsigned, .bits = undefined };
switch (field_int_info.signedness) {
.signed => {
- try writer.writeByte('(');
- try dg.renderValue(writer, Value.fromInterned(field_val), .Other);
- try writer.writeAll(" & ");
+ try w.writeByte('(');
+ try dg.renderValue(w, Value.fromInterned(field_val), .Other);
+ try w.writeAll(" & ");
const field_uint_ty = try pt.intType(.unsigned, field_int_info.bits);
- try dg.renderValue(writer, try field_uint_ty.maxIntScalar(pt, field_uint_ty), .Other);
- try writer.writeByte(')');
+ try dg.renderValue(w, try field_uint_ty.maxIntScalar(pt, field_uint_ty), .Other);
+ try w.writeByte(')');
},
- .unsigned => try dg.renderValue(writer, Value.fromInterned(field_val), .Other),
+ .unsigned => try dg.renderValue(w, Value.fromInterned(field_val), .Other),
}
if (bit_offset != 0) {
- try writer.writeAll(" << ");
- try dg.renderValue(writer, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
+ try w.writeAll(" << ");
+ try dg.renderValue(w, try pt.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
}
bit_offset += field_ty.bitSize(zcu);
empty = false;
}
- try writer.writeByte(')');
+ try w.writeByte(')');
}
},
}
@@ -1486,11 +1511,11 @@ pub const DeclGen = struct {
switch (loaded_union.flagsUnordered(ip).layout) {
.@"packed" => {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderType(writer, backing_ty);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderType(w, backing_ty);
+ try w.writeByte(')');
}
- try dg.renderValue(writer, Value.fromInterned(un.val), location);
+ try dg.renderValue(w, Value.fromInterned(un.val), location);
},
.@"extern" => {
if (location == .StaticInitializer) {
@@ -1498,21 +1523,21 @@ pub const DeclGen = struct {
}
const ptr_ty = try pt.singleConstPtrType(ty);
- try writer.writeAll("*((");
- try dg.renderType(writer, ptr_ty);
- try writer.writeAll(")(");
- try dg.renderType(writer, backing_ty);
- try writer.writeAll("){");
- try dg.renderValue(writer, Value.fromInterned(un.val), location);
- try writer.writeAll("})");
+ try w.writeAll("*((");
+ try dg.renderType(w, ptr_ty);
+ try w.writeAll(")(");
+ try dg.renderType(w, backing_ty);
+ try w.writeAll("){");
+ try dg.renderValue(w, Value.fromInterned(un.val), location);
+ try w.writeAll("})");
},
else => unreachable,
}
} else {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?;
@@ -1521,57 +1546,57 @@ pub const DeclGen = struct {
if (loaded_union.flagsUnordered(ip).layout == .@"packed") {
if (field_ty.hasRuntimeBits(zcu)) {
if (field_ty.isPtrAtRuntime(zcu)) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
} else if (field_ty.zigTypeTag(zcu) == .float) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try dg.renderValue(writer, Value.fromInterned(un.val), location);
- } else try writer.writeAll("0");
+ try dg.renderValue(w, Value.fromInterned(un.val), location);
+ } else try w.writeByte('0');
return;
}
const has_tag = loaded_union.hasTag(ip);
- if (has_tag) try writer.writeByte('{');
+ if (has_tag) try w.writeByte('{');
const aggregate = ctype.info(ctype_pool).aggregate;
for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
- if (outer_field_index > 0) try writer.writeByte(',');
+ if (outer_field_index > 0) try w.writeByte(',');
switch (if (has_tag)
aggregate.fields.at(outer_field_index, ctype_pool).name.index
else
.payload) {
.tag => try dg.renderValue(
- writer,
+ w,
Value.fromInterned(un.tag),
initializer_type,
),
.payload => {
- try writer.writeByte('{');
+ try w.writeByte('{');
if (field_ty.hasRuntimeBits(zcu)) {
- try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))});
+ try w.print(" .{f} = ", .{fmtIdentSolo(field_name.toSlice(ip))});
try dg.renderValue(
- writer,
+ w,
Value.fromInterned(un.val),
initializer_type,
);
- try writer.writeByte(' ');
+ try w.writeByte(' ');
} else for (0..loaded_union.field_types.len) |inner_field_index| {
const inner_field_ty: Type = .fromInterned(
loaded_union.field_types.get(ip)[inner_field_index],
);
if (!inner_field_ty.hasRuntimeBits(zcu)) continue;
- try dg.renderUndefValue(writer, inner_field_ty, initializer_type);
+ try dg.renderUndefValue(w, inner_field_ty, initializer_type);
break;
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
else => unreachable,
}
}
- if (has_tag) try writer.writeByte('}');
+ if (has_tag) try w.writeByte('}');
}
},
}
@@ -1579,10 +1604,10 @@ pub const DeclGen = struct {
fn renderUndefValue(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
ty: Type,
location: ValueRenderLocation,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -1612,57 +1637,57 @@ pub const DeclGen = struct {
// All unsigned ints matching float types are pre-allocated.
const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable;
- try writer.writeAll("zig_make_");
- try dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_make_");
+ try dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeByte('(');
switch (bits) {
- 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
- 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
- 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
- 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
- 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
+ 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
+ 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
+ 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
+ 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
+ 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
else => unreachable,
}
- try writer.writeAll(", ");
- try dg.renderUndefValue(writer, repr_ty, .FunctionArgument);
- return writer.writeByte(')');
+ try w.writeAll(", ");
+ try dg.renderUndefValue(w, repr_ty, .FunctionArgument);
+ return w.writeByte(')');
},
- .bool_type => try writer.writeAll(if (safety_on) "0xaa" else "false"),
+ .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"),
else => switch (ip.indexToKey(ty.toIntern())) {
.simple_type,
.int_type,
.enum_type,
.error_set_type,
.inferred_error_set_type,
- => return writer.print("{x}", .{
- try dg.fmtIntLiteral(try pt.undefValue(ty), location),
+ => return w.print("{f}", .{
+ try dg.fmtIntLiteralHex(try pt.undefValue(ty), location),
}),
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
.one, .many, .c => {
- try writer.writeAll("((");
- try dg.renderCType(writer, ctype);
- return writer.print("){x})", .{
- try dg.fmtIntLiteral(.undef_usize, .Other),
+ try w.writeAll("((");
+ try dg.renderCType(w, ctype);
+ return w.print("){f})", .{
+ try dg.fmtIntLiteralHex(.undef_usize, .Other),
});
},
.slice => {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeAll("{(");
+ try w.writeAll("{(");
const ptr_ty = ty.slicePtrFieldType(zcu);
- try dg.renderType(writer, ptr_ty);
- return writer.print("){x}, {0x}}}", .{
- try dg.fmtIntLiteral(.undef_usize, .Other),
+ try dg.renderType(w, ptr_ty);
+ return w.print("){f}, {0f}}}", .{
+ try dg.fmtIntLiteralHex(.undef_usize, .Other),
});
},
},
.opt_type => |child_type| switch (ctype.info(ctype_pool)) {
.basic, .pointer => try dg.renderUndefValue(
- writer,
+ w,
.fromInterned(if (ctype.isBool()) .bool_type else child_type),
location,
),
@@ -1671,21 +1696,21 @@ pub const DeclGen = struct {
switch (aggregate.fields.at(0, ctype_pool).name.index) {
.is_null, .payload => {},
.ptr, .len => return dg.renderUndefValue(
- writer,
+ w,
.fromInterned(child_type),
location,
),
else => unreachable,
}
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeByte(',');
- try dg.renderUndefValue(writer, .fromInterned(
+ if (field_index > 0) try w.writeByte(',');
+ try dg.renderUndefValue(w, .fromInterned(
switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
.is_null => .bool_type,
.payload => child_type,
@@ -1693,7 +1718,7 @@ pub const DeclGen = struct {
},
), initializer_type);
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
},
.struct_type => {
@@ -1701,117 +1726,117 @@ pub const DeclGen = struct {
switch (loaded_struct.layout) {
.auto, .@"extern" => {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
var field_it = loaded_struct.iterateRuntimeOrder(ip);
var need_comma = false;
while (field_it.next()) |field_index| {
const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (need_comma) try writer.writeByte(',');
+ if (need_comma) try w.writeByte(',');
need_comma = true;
- try dg.renderUndefValue(writer, field_ty, initializer_type);
+ try dg.renderUndefValue(w, field_ty, initializer_type);
}
- return writer.writeByte('}');
+ return w.writeByte('}');
},
- .@"packed" => return writer.print("{x}", .{
- try dg.fmtIntLiteral(try pt.undefValue(ty), .Other),
+ .@"packed" => return w.print("{f}", .{
+ try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other),
}),
}
},
.tuple_type => |tuple_info| {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
var need_comma = false;
for (0..tuple_info.types.len) |field_index| {
if (tuple_info.values.get(ip)[field_index] != .none) continue;
const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (need_comma) try writer.writeByte(',');
+ if (need_comma) try w.writeByte(',');
need_comma = true;
- try dg.renderUndefValue(writer, field_ty, initializer_type);
+ try dg.renderUndefValue(w, field_ty, initializer_type);
}
- return writer.writeByte('}');
+ return w.writeByte('}');
},
.union_type => {
const loaded_union = ip.loadUnionType(ty.toIntern());
switch (loaded_union.flagsUnordered(ip).layout) {
.auto, .@"extern" => {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
const has_tag = loaded_union.hasTag(ip);
- if (has_tag) try writer.writeByte('{');
+ if (has_tag) try w.writeByte('{');
const aggregate = ctype.info(ctype_pool).aggregate;
for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| {
- if (outer_field_index > 0) try writer.writeByte(',');
+ if (outer_field_index > 0) try w.writeByte(',');
switch (if (has_tag)
aggregate.fields.at(outer_field_index, ctype_pool).name.index
else
.payload) {
.tag => try dg.renderUndefValue(
- writer,
+ w,
.fromInterned(loaded_union.enum_tag_ty),
initializer_type,
),
.payload => {
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..loaded_union.field_types.len) |inner_field_index| {
const inner_field_ty: Type = .fromInterned(
loaded_union.field_types.get(ip)[inner_field_index],
);
if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue;
try dg.renderUndefValue(
- writer,
+ w,
inner_field_ty,
initializer_type,
);
break;
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
else => unreachable,
}
}
- if (has_tag) try writer.writeByte('}');
+ if (has_tag) try w.writeByte('}');
},
- .@"packed" => return writer.print("{x}", .{
- try dg.fmtIntLiteral(try pt.undefValue(ty), .Other),
+ .@"packed" => return w.print("{f}", .{
+ try dg.fmtIntLiteralHex(try pt.undefValue(ty), .Other),
}),
}
},
.error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) {
.basic => try dg.renderUndefValue(
- writer,
+ w,
.fromInterned(error_union_type.error_set_type),
location,
),
.pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => |aggregate| {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeByte(',');
+ if (field_index > 0) try w.writeByte(',');
try dg.renderUndefValue(
- writer,
+ w,
.fromInterned(
switch (aggregate.fields.at(field_index, ctype_pool).name.index) {
.@"error" => error_union_type.error_set_type,
@@ -1822,14 +1847,14 @@ pub const DeclGen = struct {
initializer_type,
);
}
- try writer.writeByte('}');
+ try w.writeByte('}');
},
},
.array_type, .vector_type => {
const ai = ty.arrayInfo(zcu);
if (ai.elem_type.eql(.u8, zcu)) {
const c_len = ty.arrayLenIncludingSentinel(zcu);
- var literal = stringLiteral(writer, c_len);
+ var literal: StringLiteral = .init(w, @intCast(c_len));
try literal.start();
var index: u64 = 0;
while (index < c_len) : (index += 1)
@@ -1837,19 +1862,19 @@ pub const DeclGen = struct {
return literal.end();
} else {
if (!location.isInitializer()) {
- try writer.writeByte('(');
- try dg.renderCType(writer, ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try dg.renderCType(w, ctype);
+ try w.writeByte(')');
}
- try writer.writeByte('{');
+ try w.writeByte('{');
const c_len = ty.arrayLenIncludingSentinel(zcu);
var index: u64 = 0;
while (index < c_len) : (index += 1) {
- if (index > 0) try writer.writeAll(", ");
- try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type);
+ if (index > 0) try w.writeAll(", ");
+ try dg.renderUndefValue(w, ty.childType(zcu), initializer_type);
}
- return writer.writeByte('}');
+ return w.writeByte('}');
}
},
.anyframe_type,
@@ -1882,13 +1907,13 @@ pub const DeclGen = struct {
fn renderFunctionSignature(
dg: *DeclGen,
- w: anytype,
+ w: *Writer,
fn_val: Value,
fn_align: InternPool.Alignment,
kind: CType.Kind,
name: union(enum) {
nav: InternPool.Nav.Index,
- fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),
+ fmt_ctype_pool_string: std.fmt.Formatter(CTypePoolStringFormatData, formatCTypePoolString),
@"export": struct {
main_name: InternPool.NullTerminatedString,
extern_name: InternPool.NullTerminatedString,
@@ -1925,15 +1950,15 @@ pub const DeclGen = struct {
var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});
if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
- try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
+ try w.print("{f}zig_callconv({s})", .{ trailing, call_conv });
trailing = .maybe_space;
}
- try w.print("{}", .{trailing});
+ try w.print("{f}", .{trailing});
switch (name) {
.nav => |nav| try dg.renderNavName(w, nav),
- .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}),
- .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}),
+ .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}),
+ .@"export" => |@"export"| try w.print("{f}", .{fmtIdentSolo(@"export".extern_name.toSlice(ip))}),
}
try renderTypeSuffix(
@@ -1960,17 +1985,17 @@ pub const DeclGen = struct {
const is_mangled = isMangledIdent(extern_name, true);
const is_export = @"export".extern_name != @"export".main_name;
if (is_mangled and is_export) {
- try w.print(" zig_mangled_export({ }, {s}, {s})", .{
- fmtIdent(extern_name),
+ try w.print(" zig_mangled_export({f}, {f}, {f})", .{
+ fmtIdentSolo(extern_name),
fmtStringLiteral(extern_name, null),
fmtStringLiteral(@"export".main_name.toSlice(ip), null),
});
} else if (is_mangled) {
- try w.print(" zig_mangled({ }, {s})", .{
- fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
+ try w.print(" zig_mangled({f}, {f})", .{
+ fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null),
});
} else if (is_export) {
- try w.print(" zig_export({s}, {s})", .{
+ try w.print(" zig_export({f}, {f})", .{
fmtStringLiteral(@"export".main_name.toSlice(ip), null),
fmtStringLiteral(extern_name, null),
});
@@ -2003,11 +2028,11 @@ pub const DeclGen = struct {
/// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
/// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
///
- fn renderType(dg: *DeclGen, w: anytype, t: Type) error{OutOfMemory}!void {
+ fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void {
try dg.renderCType(w, try dg.ctypeFromType(t, .complete));
}
- fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{OutOfMemory}!void {
+ fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void {
_ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{});
}
@@ -2022,7 +2047,7 @@ pub const DeclGen = struct {
value: Value,
},
- pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, location: ValueRenderLocation) !void {
+ pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void {
switch (self.*) {
.c_value => |v| {
try v.f.writeCValue(w, v.value, location);
@@ -2068,7 +2093,7 @@ pub const DeclGen = struct {
/// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
fn renderIntCast(
dg: *DeclGen,
- w: anytype,
+ w: *Writer,
dest_ty: Type,
context: IntCastContext,
src_ty: Type,
@@ -2118,7 +2143,7 @@ pub const DeclGen = struct {
} else if (dest_bits > 64 and src_bits <= 64) {
try w.writeAll("zig_make_");
try dg.renderTypeForBuiltinFnName(w, dest_ty);
- try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral?
+ try w.writeAll("(0, ");
if (src_is_ptr) {
try w.writeByte('(');
try dg.renderType(w, src_eff_ty);
@@ -2152,13 +2177,13 @@ pub const DeclGen = struct {
///
fn renderTypeAndName(
dg: *DeclGen,
- w: anytype,
+ w: *Writer,
ty: Type,
name: CValue,
qualifiers: CQualifiers,
alignment: Alignment,
kind: CType.Kind,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) !void {
try dg.renderCTypeAndName(
w,
try dg.ctypeFromType(ty, kind),
@@ -2173,12 +2198,12 @@ pub const DeclGen = struct {
fn renderCTypeAndName(
dg: *DeclGen,
- w: anytype,
+ w: *Writer,
ctype: CType,
name: CValue,
qualifiers: CQualifiers,
alignas: CType.AlignAs,
- ) error{ OutOfMemory, AnalysisFail }!void {
+ ) !void {
const zcu = dg.pt.zcu;
switch (alignas.abiOrder()) {
.lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
@@ -2186,24 +2211,24 @@ pub const DeclGen = struct {
.gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
}
- try w.print("{}", .{
+ try w.print("{f}", .{
try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers),
});
try dg.writeName(w, name);
try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{});
}
- fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {
+ fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
switch (c_value) {
.new_local, .local => |i| try w.print("t{d}", .{i}),
.constant => |uav| try renderUavName(w, uav),
.nav => |nav| try dg.renderNavName(w, nav),
- .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
+ .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}),
else => unreachable,
}
}
- fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
+ fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void {
switch (c_value) {
.none, .new_local, .local, .local_ref => unreachable,
.constant => |uav| try renderUavName(w, uav),
@@ -2215,18 +2240,18 @@ pub const DeclGen = struct {
try dg.renderNavName(w, nav);
},
.undef => |ty| try dg.renderUndefValue(w, ty, .Other),
- .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
- .payload_identifier => |ident| try w.print("{ }.{ }", .{
- fmtIdent("payload"),
- fmtIdent(ident),
+ .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}),
+ .payload_identifier => |ident| try w.print("{f}.{f}", .{
+ fmtIdentSolo("payload"),
+ fmtIdentSolo(ident),
}),
- .ctype_pool_string => |string| try w.print("{ }", .{
- fmtCTypePoolString(string, &dg.ctype_pool),
+ .ctype_pool_string => |string| try w.print("{f}", .{
+ fmtCTypePoolString(string, &dg.ctype_pool, true),
}),
}
}
- fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
+ fn writeCValueDeref(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
switch (c_value) {
.none,
.new_local,
@@ -2245,26 +2270,31 @@ pub const DeclGen = struct {
},
.nav_ref => |nav| try dg.renderNavName(w, nav),
.undef => unreachable,
- .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
- .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
- fmtIdent("payload"),
- fmtIdent(ident),
+ .identifier => |ident| try w.print("(*{f})", .{fmtIdentSolo(ident)}),
+ .payload_identifier => |ident| try w.print("(*{f}.{f})", .{
+ fmtIdentSolo("payload"),
+ fmtIdentSolo(ident),
}),
}
}
fn writeCValueMember(
dg: *DeclGen,
- writer: anytype,
+ w: *Writer,
c_value: CValue,
member: CValue,
- ) error{ OutOfMemory, AnalysisFail }!void {
- try dg.writeCValue(writer, c_value);
- try writer.writeByte('.');
- try dg.writeCValue(writer, member);
+ ) Error!void {
+ try dg.writeCValue(w, c_value);
+ try w.writeByte('.');
+ try dg.writeCValue(w, member);
}
- fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
+ fn writeCValueDerefMember(
+ dg: *DeclGen,
+ w: *Writer,
+ c_value: CValue,
+ member: CValue,
+ ) !void {
switch (c_value) {
.none,
.new_local,
@@ -2278,15 +2308,15 @@ pub const DeclGen = struct {
.ctype_pool_string,
=> unreachable,
.nav, .identifier, .payload_identifier => {
- try dg.writeCValue(writer, c_value);
- try writer.writeAll("->");
+ try dg.writeCValue(w, c_value);
+ try w.writeAll("->");
},
.nav_ref => {
- try dg.writeCValueDeref(writer, c_value);
- try writer.writeByte('.');
+ try dg.writeCValueDeref(w, c_value);
+ try w.writeByte('.');
},
}
- try dg.writeCValue(writer, member);
+ try dg.writeCValue(w, member);
}
fn renderFwdDecl(
@@ -2302,7 +2332,7 @@ pub const DeclGen = struct {
const zcu = dg.pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
- const fwd = dg.fwdDeclWriter();
+ const fwd = &dg.fwd_decl.writer;
try fwd.writeAll(switch (flags.linkage) {
.internal => "static ",
.strong, .weak, .link_once => "zig_extern ",
@@ -2328,36 +2358,36 @@ pub const DeclGen = struct {
try fwd.writeAll(";\n");
}
- fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void {
+ fn renderNavName(dg: *DeclGen, w: *Writer, nav_index: InternPool.Nav.Index) !void {
const zcu = dg.pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
if (nav.getExtern(ip)) |@"extern"| {
- try writer.print("{ }", .{
- fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),
+ try w.print("{f}", .{
+ fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),
});
} else {
// MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
// expand to 3x the length of its input, but let's cut it off at a much shorter limit.
const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
- try writer.print("{}__{d}", .{
- fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
+ try w.print("{f}__{d}", .{
+ fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]),
@intFromEnum(nav_index),
});
}
}
- fn renderUavName(writer: anytype, uav: Value) !void {
- try writer.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});
+ fn renderUavName(w: *Writer, uav: Value) !void {
+ try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())});
}
- fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void {
- try dg.renderCTypeForBuiltinFnName(writer, try dg.ctypeFromType(ty, .complete));
+ fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void {
+ try dg.renderCTypeForBuiltinFnName(w, try dg.ctypeFromType(ty, .complete));
}
- fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void {
+ fn renderCTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ctype: CType) !void {
switch (ctype.info(&dg.ctype_pool)) {
- else => |ctype_info| try writer.print("{c}{d}", .{
+ else => |ctype_info| try w.print("{c}{d}", .{
if (ctype.isBool())
signAbbrev(.unsigned)
else if (ctype.isInteger())
@@ -2370,11 +2400,11 @@ pub const DeclGen = struct {
return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}),
if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8,
}),
- .array => try writer.writeAll("big"),
+ .array => try w.writeAll("big"),
}
}
- fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
+ fn renderBuiltinInfo(dg: *DeclGen, w: *Writer, ty: Type, info: BuiltinInfo) !void {
const ctype = try dg.ctypeFromType(ty, .complete);
const is_big = ctype.info(&dg.ctype_pool) == .array;
switch (info) {
@@ -2389,8 +2419,8 @@ pub const DeclGen = struct {
.bits = @intCast(ty.bitSize(zcu)),
};
- if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
- try writer.print(", {}", .{try dg.fmtIntLiteral(
+ if (is_big) try w.print(", {}", .{int_info.signedness == .signed});
+ try w.print(", {f}", .{try dg.fmtIntLiteralDec(
try pt.intValue(if (is_big) .u16 else .u8, int_info.bits),
.FunctionArgument,
)});
@@ -2400,18 +2430,38 @@ pub const DeclGen = struct {
dg: *DeclGen,
val: Value,
loc: ValueRenderLocation,
- ) !std.fmt.Formatter(formatIntLiteral) {
+ base: u8,
+ case: std.fmt.Case,
+ ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
const zcu = dg.pt.zcu;
const kind = loc.toCTypeKind();
const ty = val.typeOf(zcu);
- return std.fmt.Formatter(formatIntLiteral){ .data = .{
+ return .{ .data = .{
.dg = dg,
.int_info = ty.intInfo(zcu),
.kind = kind,
.ctype = try dg.ctypeFromType(ty, kind),
.val = val,
+ .base = base,
+ .case = case,
} };
}
+
+ fn fmtIntLiteralDec(
+ dg: *DeclGen,
+ val: Value,
+ loc: ValueRenderLocation,
+ ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
+ return fmtIntLiteral(dg, val, loc, 10, .lower);
+ }
+
+ fn fmtIntLiteralHex(
+ dg: *DeclGen,
+ val: Value,
+ loc: ValueRenderLocation,
+ ) !std.fmt.Formatter(FormatIntLiteralContext, formatIntLiteral) {
+ return fmtIntLiteral(dg, val, loc, 16, .lower);
+ }
};
const CTypeFix = enum { prefix, suffix };
@@ -2421,28 +2471,19 @@ const RenderCTypeTrailing = enum {
no_space,
maybe_space,
- pub fn format(
- self: @This(),
- comptime fmt: []const u8,
- _: std.fmt.FormatOptions,
- w: anytype,
- ) @TypeOf(w).Error!void {
- if (fmt.len != 0)
- @compileError("invalid format string '" ++ fmt ++ "' for type '" ++
- @typeName(@This()) ++ "'");
- comptime assert(fmt.len == 0);
+ pub fn format(self: @This(), w: *Writer) Writer.Error!void {
switch (self) {
.no_space => {},
.maybe_space => try w.writeByte(' '),
}
}
};
-fn renderAlignedTypeName(w: anytype, ctype: CType) !void {
+fn renderAlignedTypeName(w: *Writer, ctype: CType) !void {
try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)});
}
fn renderFwdDeclTypeName(
zcu: *Zcu,
- w: anytype,
+ w: *Writer,
ctype: CType,
fwd_decl: CType.Info.FwdDecl,
attributes: []const u8,
@@ -2451,8 +2492,8 @@ fn renderFwdDeclTypeName(
try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes });
switch (fwd_decl.name) {
.anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}),
- .index => |index| try w.print("{}__{d}", .{
- fmtIdent(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),
+ .index => |index| try w.print("{f}__{d}", .{
+ fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)),
@intFromEnum(index),
}),
}
@@ -2461,17 +2502,17 @@ fn renderTypePrefix(
pass: DeclGen.Pass,
ctype_pool: *const CType.Pool,
zcu: *Zcu,
- w: anytype,
+ w: *Writer,
ctype: CType,
parent_fix: CTypeFix,
qualifiers: CQualifiers,
-) @TypeOf(w).Error!RenderCTypeTrailing {
+) Writer.Error!RenderCTypeTrailing {
var trailing = RenderCTypeTrailing.maybe_space;
switch (ctype.info(ctype_pool)) {
.basic => |basic_info| try w.writeAll(@tagName(basic_info)),
.pointer => |pointer_info| {
- try w.print("{}*", .{try renderTypePrefix(
+ try w.print("{f}*", .{try renderTypePrefix(
pass,
ctype_pool,
zcu,
@@ -2508,7 +2549,7 @@ fn renderTypePrefix(
);
switch (parent_fix) {
.prefix => {
- try w.print("{}(", .{child_trailing});
+ try w.print("{f}(", .{child_trailing});
return .no_space;
},
.suffix => return child_trailing,
@@ -2560,7 +2601,7 @@ fn renderTypePrefix(
);
switch (parent_fix) {
.prefix => {
- try w.print("{}(", .{child_trailing});
+ try w.print("{f}(", .{child_trailing});
return .no_space;
},
.suffix => return child_trailing,
@@ -2569,7 +2610,7 @@ fn renderTypePrefix(
}
var qualifier_it = qualifiers.iterator();
while (qualifier_it.next()) |qualifier| {
- try w.print("{}{s}", .{ trailing, @tagName(qualifier) });
+ try w.print("{f}{s}", .{ trailing, @tagName(qualifier) });
trailing = .maybe_space;
}
return trailing;
@@ -2578,11 +2619,11 @@ fn renderTypeSuffix(
pass: DeclGen.Pass,
ctype_pool: *const CType.Pool,
zcu: *Zcu,
- w: anytype,
+ w: *Writer,
ctype: CType,
parent_fix: CTypeFix,
qualifiers: CQualifiers,
-) @TypeOf(w).Error!void {
+) Writer.Error!void {
switch (ctype.info(ctype_pool)) {
.basic, .aligned, .fwd_decl, .aggregate => {},
.pointer => |pointer_info| try renderTypeSuffix(
@@ -2617,7 +2658,7 @@ fn renderTypeSuffix(
need_comma = true;
const trailing =
try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers);
- if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index });
+ if (qualifiers.contains(.@"const")) try w.print("{f}a{d}", .{ trailing, param_index });
try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{});
}
if (function_info.varargs) {
@@ -2634,49 +2675,49 @@ fn renderTypeSuffix(
}
fn renderFields(
zcu: *Zcu,
- writer: anytype,
+ w: *Writer,
ctype_pool: *const CType.Pool,
aggregate_info: CType.Info.Aggregate,
indent: usize,
) !void {
- try writer.writeAll("{\n");
+ try w.writeAll("{\n");
for (0..aggregate_info.fields.len) |field_index| {
const field_info = aggregate_info.fields.at(field_index, ctype_pool);
- try writer.writeByteNTimes(' ', indent + 1);
+ try w.splatByteAll(' ', indent + 1);
switch (field_info.alignas.abiOrder()) {
.lt => {
std.debug.assert(aggregate_info.@"packed");
- if (field_info.alignas.@"align" != .@"1") try writer.print("zig_under_align({}) ", .{
+ if (field_info.alignas.@"align" != .@"1") try w.print("zig_under_align({}) ", .{
field_info.alignas.toByteUnits(),
});
},
.eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1")
- try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}),
+ try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}),
.gt => {
std.debug.assert(field_info.alignas.@"align" != .@"1");
- try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()});
+ try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()});
},
}
const trailing = try renderTypePrefix(
.flush,
ctype_pool,
zcu,
- writer,
+ w,
field_info.ctype,
.suffix,
.{},
);
- try writer.print("{}{ }", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool) });
- try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{});
- try writer.writeAll(";\n");
+ try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });
+ try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});
+ try w.writeAll(";\n");
}
- try writer.writeByteNTimes(' ', indent);
- try writer.writeByte('}');
+ try w.splatByteAll(' ', indent);
+ try w.writeByte('}');
}
pub fn genTypeDecl(
zcu: *Zcu,
- writer: anytype,
+ w: *Writer,
global_ctype_pool: *const CType.Pool,
global_ctype: CType,
pass: DeclGen.Pass,
@@ -2689,27 +2730,27 @@ pub fn genTypeDecl(
.aligned => |aligned_info| {
if (!found_existing) {
std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
- try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
- try writer.print("{}", .{try renderTypePrefix(
+ try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
+ try w.print("{f}", .{try renderTypePrefix(
.flush,
global_ctype_pool,
zcu,
- writer,
+ w,
aligned_info.ctype,
.suffix,
.{},
)});
- try renderAlignedTypeName(writer, global_ctype);
- try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{});
- try writer.writeAll(";\n");
+ try renderAlignedTypeName(w, global_ctype);
+ try renderTypeSuffix(.flush, global_ctype_pool, zcu, w, aligned_info.ctype, .suffix, .{});
+ try w.writeAll(";\n");
}
switch (pass) {
.nav, .uav => {
- try writer.writeAll("typedef ");
- _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});
- try writer.writeByte(' ');
- _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{});
- try writer.writeAll(";\n");
+ try w.writeAll("typedef ");
+ _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
+ try w.writeByte(' ');
+ _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{});
+ try w.writeAll(";\n");
},
.flush => {},
}
@@ -2717,24 +2758,24 @@ pub fn genTypeDecl(
.fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {
.anon => switch (pass) {
.nav, .uav => {
- try writer.writeAll("typedef ");
- _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});
- try writer.writeByte(' ');
- _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{});
- try writer.writeAll(";\n");
+ try w.writeAll("typedef ");
+ _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
+ try w.writeByte(' ');
+ _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{});
+ try w.writeAll(";\n");
},
.flush => {},
},
.index => |index| if (!found_existing) {
const ip = &zcu.intern_pool;
const ty: Type = .fromInterned(index);
- _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});
- try writer.writeByte(';');
+ _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{});
+ try w.writeByte(';');
const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);
- if (!zcu.fileByIndex(file_scope).mod.?.strip) try writer.print(" /* {} */", .{
+ if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {f} */", .{
ty.containerTypeName(ip).fmt(ip),
});
- try writer.writeByte('\n');
+ try w.writeByte('\n');
},
},
.aggregate => |aggregate_info| switch (aggregate_info.name) {
@@ -2742,38 +2783,39 @@ pub fn genTypeDecl(
.fwd_decl => |fwd_decl| if (!found_existing) {
try renderFwdDeclTypeName(
zcu,
- writer,
+ w,
fwd_decl,
fwd_decl.info(global_ctype_pool).fwd_decl,
if (aggregate_info.@"packed") "zig_packed(" else "",
);
- try writer.writeByte(' ');
- try renderFields(zcu, writer, global_ctype_pool, aggregate_info, 0);
- if (aggregate_info.@"packed") try writer.writeByte(')');
- try writer.writeAll(";\n");
+ try w.writeByte(' ');
+ try renderFields(zcu, w, global_ctype_pool, aggregate_info, 0);
+ if (aggregate_info.@"packed") try w.writeByte(')');
+ try w.writeAll(";\n");
},
},
}
}
-pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void {
+pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
for (zcu.global_assembly.values()) |asm_source| {
- try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)});
+ try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)});
}
}
-pub fn genErrDecls(o: *Object) !void {
+pub fn genErrDecls(o: *Object) Error!void {
const pt = o.dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- const writer = o.writer();
+ const w = &o.code.writer;
var max_name_len: usize = 0;
// do not generate an invalid empty enum when the global error set is empty
const names = ip.global_error_set.getNamesFromMainThread();
if (names.len > 0) {
- try writer.writeAll("enum {\n");
- o.indent_writer.pushIndent();
+ try w.writeAll("enum {");
+ o.indent();
+ try o.newline();
for (names, 1..) |name_nts, value| {
const name = name_nts.toSlice(ip);
max_name_len = @max(name.len, max_name_len);
@@ -2781,11 +2823,13 @@ pub fn genErrDecls(o: *Object) !void {
.ty = .anyerror_type,
.name = name_nts,
} });
- try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other);
- try writer.print(" = {d}u,\n", .{value});
+ try o.dg.renderValue(w, Value.fromInterned(err_val), .Other);
+ try w.print(" = {d}u,", .{value});
+ try o.newline();
}
- o.indent_writer.popIndent();
- try writer.writeAll("};\n");
+ try o.outdent();
+ try w.writeAll("};");
+ try o.newline();
}
const array_identifier = "zig_errorName";
const name_prefix = array_identifier ++ "_";
@@ -2808,18 +2852,19 @@ pub fn genErrDecls(o: *Object) !void {
.storage = .{ .bytes = name.toString() },
} });
- try writer.writeAll("static ");
+ try w.writeAll("static ");
try o.dg.renderTypeAndName(
- writer,
+ w,
name_ty,
.{ .identifier = identifier },
Const,
.none,
.complete,
);
- try writer.writeAll(" = ");
- try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer);
- try writer.writeAll(";\n");
+ try w.writeAll(" = ");
+ try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
+ try w.writeByte(';');
+ try o.newline();
}
const name_array_ty = try pt.arrayType(.{
@@ -2827,33 +2872,34 @@ pub fn genErrDecls(o: *Object) !void {
.child = .slice_const_u8_sentinel_0_type,
});
- try writer.writeAll("static ");
+ try w.writeAll("static ");
try o.dg.renderTypeAndName(
- writer,
+ w,
name_array_ty,
.{ .identifier = array_identifier },
Const,
.none,
.complete,
);
- try writer.writeAll(" = {");
+ try w.writeAll(" = {");
for (names, 1..) |name_nts, val| {
const name = name_nts.toSlice(ip);
- if (val > 1) try writer.writeAll(", ");
- try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
- fmtIdent(name),
- try o.dg.fmtIntLiteral(try pt.intValue(.usize, name.len), .StaticInitializer),
+ if (val > 1) try w.writeAll(", ");
+ try w.print("{{" ++ name_prefix ++ "{f}, {f}}}", .{
+ fmtIdentUnsolo(name),
+ try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer),
});
}
- try writer.writeAll("};\n");
+ try w.writeAll("};");
+ try o.newline();
}
-pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
+pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void {
const pt = o.dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const ctype_pool = &o.dg.ctype_pool;
- const w = o.writer();
+ const w = &o.code.writer;
const key = lazy_fn.key_ptr.*;
const val = lazy_fn.value_ptr;
switch (key) {
@@ -2863,9 +2909,14 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
try w.writeAll("static ");
try o.dg.renderType(w, name_slice_ty);
- try w.print(" {}(", .{val.fn_name.fmt(lazy_ctype_pool)});
+ try w.print(" {f}(", .{val.fn_name.fmt(lazy_ctype_pool)});
try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
- try w.writeAll(") {\n switch (tag) {\n");
+ try w.writeAll(") {");
+ o.indent();
+ try o.newline();
+ try w.writeAll("switch (tag) {");
+ o.indent();
+ try o.newline();
const tag_names = enum_ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
const tag_name = tag_names.get(ip)[tag_index];
@@ -2882,34 +2933,43 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
.storage = .{ .bytes = tag_name.toString() },
} });
- try w.print(" case {}: {{\n static ", .{
- try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, pt), .Other),
+ try w.print("case {f}: {{", .{
+ try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other),
});
+ o.indent();
+ try o.newline();
+ try w.writeAll("static ");
try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
try w.writeAll(" = ");
try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer);
- try w.writeAll(";\n return (");
+ try w.writeByte(';');
+ try o.newline();
+ try w.writeAll("return (");
try o.dg.renderType(w, name_slice_ty);
- try w.print("){{{}, {}}};\n", .{
- fmtIdent("name"),
- try o.dg.fmtIntLiteral(try pt.intValue(.usize, tag_name_len), .Other),
+ try w.print("){{{f}, {f}}};", .{
+ fmtIdentUnsolo("name"),
+ try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other),
});
-
- try w.writeAll(" }\n");
+ try o.newline();
+ try o.outdent();
+ try w.writeByte('}');
+ try o.newline();
}
- try w.writeAll(" }\n while (");
- try o.dg.renderValue(w, Value.true, .Other);
- try w.writeAll(") ");
- _ = try airBreakpoint(w);
- try w.writeAll("}\n");
+ try o.outdent();
+ try w.writeByte('}');
+ try o.newline();
+ try airUnreach(o);
+ try o.outdent();
+ try w.writeByte('}');
+ try o.newline();
},
.never_tail, .never_inline => |fn_nav_index| {
const fn_val = zcu.navValue(fn_nav_index);
const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete);
const fn_info = fn_ctype.info(ctype_pool).function;
- const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);
+ const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true);
- const fwd = o.dg.fwdDeclWriter();
+ const fwd = &o.dg.fwd_decl.writer;
try fwd.print("static zig_{s} ", .{@tagName(key)});
try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
.fmt_ctype_pool_string = fn_name,
@@ -2920,14 +2980,21 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{
.fmt_ctype_pool_string = fn_name,
});
- try w.writeAll(" {\n return ");
+ try w.writeAll(" {");
+ o.indent();
+ try o.newline();
+ try w.writeAll("return ");
try o.dg.renderNavName(w, fn_nav_index);
try w.writeByte('(');
for (0..fn_info.param_ctypes.len) |arg| {
if (arg > 0) try w.writeAll(", ");
try w.print("a{d}", .{arg});
}
- try w.writeAll(");\n}\n");
+ try w.writeAll(");");
+ try o.newline();
+ try o.outdent();
+ try w.writeByte('}');
+ try o.newline();
},
}
}
@@ -2967,12 +3034,14 @@ pub fn generate(
.scratch = .empty,
.uavs = .empty,
},
+ .code_header = .init(gpa),
.code = .init(gpa),
- .indent_writer = undefined, // set later so we can get a pointer to object.code
+ .indent_counter = 0,
},
.lazy_fns = .empty,
};
defer {
+ function.object.code_header.deinit();
function.object.code.deinit();
function.object.dg.fwd_decl.deinit();
function.object.dg.ctype_pool.deinit(gpa);
@@ -2981,22 +3050,24 @@ pub fn generate(
function.deinit();
}
try function.object.dg.ctype_pool.init(gpa);
- function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
genFunc(&function) catch |err| switch (err) {
error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?),
- error.OutOfMemory => |e| return e,
+ error.OutOfMemory => return error.OutOfMemory,
+ error.WriteFailed => return error.OutOfMemory,
};
var mir: Mir = .{
.uavs = .empty,
.code = &.{},
+ .code_header = &.{},
.fwd_decl = &.{},
.ctype_pool = .empty,
.lazy_fns = .empty,
};
errdefer mir.deinit(gpa);
mir.uavs = function.object.dg.uavs.move();
+ mir.code_header = try function.object.code_header.toOwnedSlice();
mir.code = try function.object.code.toOwnedSlice();
mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice();
mir.ctype_pool = function.object.dg.ctype_pool.move();
@@ -3004,7 +3075,7 @@ pub fn generate(
return mir;
}
-fn genFunc(f: *Function) !void {
+pub fn genFunc(f: *Function) Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -3016,10 +3087,7 @@ fn genFunc(f: *Function) !void {
const nav_val = zcu.navValue(nav_index);
const nav = ip.getNav(nav_index);
- o.code_header = std.ArrayList(u8).init(gpa);
- defer o.code_header.deinit();
-
- const fwd = o.dg.fwdDeclWriter();
+ const fwd = &o.dg.fwd_decl.writer;
try fwd.writeAll("static ");
try o.dg.renderFunctionSignature(
fwd,
@@ -3030,29 +3098,26 @@ fn genFunc(f: *Function) !void {
);
try fwd.writeAll(";\n");
+ const ch = &o.code_header.writer;
if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|
- try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
+ try ch.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderFunctionSignature(
- o.writer(),
+ ch,
nav_val,
.none,
.complete,
.{ .nav = nav_index },
);
- try o.writer().writeByte(' ');
-
- // In case we need to use the header, populate it with a copy of the function
- // signature here. We anticipate a brace, newline, and space.
- try o.code_header.ensureUnusedCapacity(o.code.items.len + 3);
- o.code_header.appendSliceAssumeCapacity(o.code.items);
- o.code_header.appendSliceAssumeCapacity("{\n ");
- const empty_header_len = o.code_header.items.len;
+ try ch.writeAll(" {\n ");
f.free_locals_map.clearRetainingCapacity();
const main_body = f.air.getMainBody();
- try genBodyResolveState(f, undefined, &.{}, main_body, false);
- try o.indent_writer.insertNewline();
+ o.indent();
+ try genBodyResolveState(f, undefined, &.{}, main_body, true);
+ try o.outdent();
+ try o.code.writer.writeByte('}');
+ try o.newline();
if (o.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
@@ -3083,24 +3148,16 @@ fn genFunc(f: *Function) !void {
};
free_locals.sort(SortContext{ .keys = free_locals.keys() });
- const w = o.codeHeaderWriter();
for (free_locals.values()) |list| {
for (list.keys()) |local_index| {
const local = f.locals.items[local_index];
- try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
- try w.writeAll(";\n ");
+ try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas);
+ try ch.writeAll(";\n ");
}
}
-
- // If we have a header to insert, append the body to the header
- // and then return the result, freeing the body.
- if (o.code_header.items.len > empty_header_len) {
- try o.code_header.appendSlice(o.code.items[empty_header_len..]);
- mem.swap(std.ArrayList(u8), &o.code, &o.code_header);
- }
}
-pub fn genDecl(o: *Object) !void {
+pub fn genDecl(o: *Object) Error!void {
const tracy = trace(@src());
defer tracy.end();
@@ -3120,7 +3177,7 @@ pub fn genDecl(o: *Object) !void {
.visibility = @"extern".visibility,
});
- const fwd = o.dg.fwdDeclWriter();
+ const fwd = &o.dg.fwd_decl.writer;
try fwd.writeAll("zig_extern ");
try o.dg.renderFunctionSignature(
fwd,
@@ -3141,10 +3198,10 @@ pub fn genDecl(o: *Object) !void {
.linkage = .internal,
.visibility = .default,
});
- const w = o.writer();
+ const w = &o.code.writer;
if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
- try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
+ try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderTypeAndName(
w,
nav_ty,
@@ -3156,7 +3213,7 @@ pub fn genDecl(o: *Object) !void {
try w.writeAll(" = ");
try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);
try w.writeByte(';');
- try o.indent_writer.insertNewline();
+ try o.newline();
},
else => try genDeclValue(
o,
@@ -3174,28 +3231,29 @@ pub fn genDeclValue(
decl_c_value: CValue,
alignment: Alignment,
@"linksection": InternPool.OptionalNullTerminatedString,
-) !void {
+) Error!void {
const zcu = o.dg.pt.zcu;
const ty = val.typeOf(zcu);
- const fwd = o.dg.fwdDeclWriter();
+ const fwd = &o.dg.fwd_decl.writer;
try fwd.writeAll("static ");
try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
try fwd.writeAll(";\n");
- const w = o.writer();
+ const w = &o.code.writer;
if (@"linksection".toSlice(&zcu.intern_pool)) |s|
- try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
+ try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
try w.writeAll(" = ");
try o.dg.renderValue(w, val, .StaticInitializer);
- try w.writeAll(";\n");
+ try w.writeByte(';');
+ try o.newline();
}
pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {
const zcu = dg.pt.zcu;
const ip = &zcu.intern_pool;
- const fwd = dg.fwdDeclWriter();
+ const fwd = &dg.fwd_decl.writer;
const main_name = export_indices[0].ptr(zcu).opts.name;
try fwd.writeAll("#define ");
@@ -3204,7 +3262,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
.uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)),
}
try fwd.writeByte(' ');
- try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))});
+ try fwd.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))});
try fwd.writeByte('\n');
const exported_val = exported.getValue(zcu);
@@ -3234,7 +3292,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
const @"export" = export_index.ptr(zcu);
try fwd.writeAll("zig_extern ");
if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
- if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({s}) ", .{
+ if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({f}) ", .{
fmtStringLiteral(s, null),
});
const extern_name = @"export".opts.name.toSlice(ip);
@@ -3249,17 +3307,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
.complete,
);
if (is_mangled and is_export) {
- try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
- fmtIdent(extern_name),
+ try fwd.print(" zig_mangled_export({f}, {f}, {f})", .{
+ fmtIdentSolo(extern_name),
fmtStringLiteral(extern_name, null),
fmtStringLiteral(main_name.toSlice(ip), null),
});
} else if (is_mangled) {
- try fwd.print(" zig_mangled({ }, {s})", .{
- fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
+ try fwd.print(" zig_mangled({f}, {f})", .{
+ fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null),
});
} else if (is_export) {
- try fwd.print(" zig_export({s}, {s})", .{
+ try fwd.print(" zig_export({f}, {f})", .{
fmtStringLiteral(main_name.toSlice(ip), null),
fmtStringLiteral(extern_name, null),
});
@@ -3272,16 +3330,17 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
/// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not
/// have been added to `free_locals_map`. For a version of this function that restores this state,
/// see `genBodyResolveState`.
-fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
- const writer = f.object.writer();
+fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void {
+ const w = &f.object.code.writer;
if (body.len == 0) {
- try writer.writeAll("{}");
+ try w.writeAll("{}");
} else {
- try writer.writeAll("{\n");
- f.object.indent_writer.pushIndent();
+ try w.writeByte('{');
+ f.object.indent();
+ try f.object.newline();
try genBodyInner(f, body);
- f.object.indent_writer.popIndent();
- try writer.writeByte('}');
+ try f.object.outdent();
+ try w.writeByte('}');
}
}
@@ -3291,10 +3350,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
/// `leading_deaths` have their deaths processed before the body is generated.
/// A scope is introduced (using braces) only if `inner` is `false`.
/// If `leading_deaths` is empty, `inst` may be `undefined`.
-fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void {
+fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void {
if (body.len == 0) {
// Don't go to the expense of cloning everything!
- if (!inner) try f.object.writer().writeAll("{}");
+ if (!inner) try f.object.code.writer.writeAll("{}");
return;
}
@@ -3340,7 +3399,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
}
}
-fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
+fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void {
const zcu = f.object.dg.pt.zcu;
const ip = &zcu.intern_pool;
const air_tags = f.air.instructions.items(.tag);
@@ -3358,7 +3417,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
.arg => try airArg(f, inst),
- .breakpoint => try airBreakpoint(f.object.writer()),
+ .breakpoint => try airBreakpoint(f),
.ret_addr => try airRetAddr(f, inst),
.frame_addr => try airFrameAddress(f, inst),
@@ -3611,8 +3670,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
.ret => return airRet(f, inst, false),
.ret_safe => return airRet(f, inst, false), // TODO
.ret_load => return airRet(f, inst, true),
- .trap => return airTrap(f, f.object.writer()),
- .unreach => return airUnreach(f),
+ .trap => return airTrap(f, &f.object.code.writer),
+ .unreach => return airUnreach(&f.object),
// Instructions which may be `noreturn`.
.block => res: {
@@ -3655,16 +3714,16 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
const operand = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
if (is_ptr) {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });
- } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });
- try a.end(f, writer);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = field_name });
+ } else try f.writeCValueMember(w, operand, .{ .identifier = field_name });
+ try a.end(f, w);
return local;
}
@@ -3681,16 +3740,16 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeByte('[');
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
+ try a.end(f, w);
return local;
}
@@ -3708,25 +3767,25 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try writer.writeByte('(');
- try f.renderType(writer, inst_ty);
- try writer.writeByte(')');
- if (elem_has_bits) try writer.writeByte('&');
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try w.writeByte('(');
+ try f.renderType(w, inst_ty);
+ try w.writeByte(')');
+ if (elem_has_bits) try w.writeByte('&');
if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) {
// It's a pointer to an array, so we need to de-reference.
- try f.writeCValueDeref(writer, ptr);
- } else try f.writeCValue(writer, ptr, .Other);
+ try f.writeCValueDeref(w, ptr);
+ } else try f.writeCValue(w, ptr, .Other);
if (elem_has_bits) {
- try writer.writeByte('[');
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
}
- try a.end(f, writer);
+ try a.end(f, w);
return local;
}
@@ -3743,16 +3802,16 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });
- try writer.writeByte('[');
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValueMember(w, slice, .{ .identifier = "ptr" });
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
+ try a.end(f, w);
return local;
}
@@ -3771,19 +3830,19 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- if (elem_has_bits) try writer.writeByte('&');
- try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" });
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ if (elem_has_bits) try w.writeByte('&');
+ try f.writeCValueMember(w, slice, .{ .identifier = "ptr" });
if (elem_has_bits) {
- try writer.writeByte('[');
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
}
- try a.end(f, writer);
+ try a.end(f, w);
return local;
}
@@ -3800,16 +3859,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const index = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, array, .Other);
- try writer.writeByte('[');
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, array, .Other);
+ try w.writeByte('[');
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
+ try a.end(f, w);
return local;
}
@@ -3863,12 +3922,13 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
.{ .arg_array = i };
if (f.liveness.isUnused(inst)) {
- const writer = f.object.writer();
- try writer.writeByte('(');
- try f.renderType(writer, .void);
- try writer.writeByte(')');
- try f.writeCValue(writer, result, .Other);
- try writer.writeAll(";\n");
+ const w = &f.object.code.writer;
+ try w.writeByte('(');
+ try f.renderType(w, .void);
+ try w.writeByte(')');
+ try f.writeCValue(w, result, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
return .none;
}
@@ -3901,21 +3961,21 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
const is_array = lowersToArray(src_ty, pt);
const need_memcpy = !is_aligned or is_array;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, src_ty);
- const v = try Vectorize.start(f, inst, writer, ptr_ty);
+ const v = try Vectorize.start(f, inst, w, ptr_ty);
if (need_memcpy) {
- try writer.writeAll("memcpy(");
- if (!is_array) try writer.writeByte('&');
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(", (const char *)");
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, src_ty);
- try writer.writeAll("))");
+ try w.writeAll("memcpy(");
+ if (!is_array) try w.writeByte('&');
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(", (const char *)");
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, src_ty);
+ try w.writeAll("))");
} else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
const host_ty = try pt.intType(.unsigned, host_bits);
@@ -3925,40 +3985,41 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
const field_ty = try pt.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu))));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = (");
- try f.renderType(writer, src_ty);
- try writer.writeAll(")zig_wrap_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);
- try writer.writeAll("((");
- try f.renderType(writer, field_ty);
- try writer.writeByte(')');
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = (");
+ try f.renderType(w, src_ty);
+ try w.writeAll(")zig_wrap_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, field_ty);
+ try w.writeAll("((");
+ try f.renderType(w, field_ty);
+ try w.writeByte(')');
const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
if (cant_cast) {
if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
- try writer.writeAll("zig_lo_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_lo_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeByte('(');
}
- try writer.writeAll("zig_shr_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeByte('(');
- try f.writeCValueDeref(writer, operand);
- try v.elem(f, writer);
- try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)});
- if (cant_cast) try writer.writeByte(')');
- try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);
- try writer.writeByte(')');
+ try w.writeAll("zig_shr_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeByte('(');
+ try f.writeCValueDeref(w, operand);
+ try v.elem(f, w);
+ try w.print(", {f})", .{try f.fmtIntLiteralDec(bit_offset_val)});
+ if (cant_cast) try w.writeByte(')');
+ try f.object.dg.renderBuiltinInfo(w, field_ty, .bits);
+ try w.writeByte(')');
} else {
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
- try f.writeCValueDeref(writer, operand);
- try v.elem(f, writer);
- }
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
+ try f.writeCValueDeref(w, operand);
+ try v.elem(f, w);
+ }
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -3967,7 +4028,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const op_inst = un_op.toIndex();
const op_ty = f.typeOf(un_op);
const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;
@@ -3986,33 +4047,34 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
.ctype = ret_ctype,
.alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),
});
- try writer.writeAll("memcpy(");
- try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
- try writer.writeAll(", ");
+ try w.writeAll("memcpy(");
+ try f.writeCValueMember(w, array_local, .{ .identifier = "array" });
+ try w.writeAll(", ");
if (deref)
- try f.writeCValueDeref(writer, operand)
+ try f.writeCValueDeref(w, operand)
else
- try f.writeCValue(writer, operand, .FunctionArgument);
+ try f.writeCValue(w, operand, .FunctionArgument);
deref = false;
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, ret_ty);
- try writer.writeAll("));\n");
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, ret_ty);
+ try w.writeAll("));");
+ try f.object.newline();
break :ret_val array_local;
} else operand;
- try writer.writeAll("return ");
+ try w.writeAll("return ");
if (deref)
- try f.writeCValueDeref(writer, ret_val)
+ try f.writeCValueDeref(w, ret_val)
else
- try f.writeCValue(writer, ret_val, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, ret_val, .Other);
+ try w.writeAll(";\n");
if (is_array) {
try freeLocal(f, inst, ret_val.new_local, null);
}
} else {
try reap(f, inst, &.{un_op});
// Not even allowed to return void in a naked function.
- if (!f.object.dg.is_naked_fn) try writer.writeAll("return;\n");
+ if (!f.object.dg.is_naked_fn) try w.writeAll("return;\n");
}
}
@@ -4031,16 +4093,16 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
- try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other);
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
+ try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .Other);
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -4067,35 +4129,35 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits);
if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
if (need_cast) {
- try writer.writeByte('(');
- try f.renderType(writer, inst_scalar_ty);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, inst_scalar_ty);
+ try w.writeByte(')');
}
if (need_lo) {
- try writer.writeAll("zig_lo_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_lo_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
}
if (!need_mask) {
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
} else switch (dest_int_info.signedness) {
.unsigned => {
- try writer.writeAll("zig_and_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
- try f.writeCValue(writer, operand, .FunctionArgument);
- try v.elem(f, writer);
- try writer.print(", {x})", .{
- try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),
+ try w.writeAll("zig_and_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
+ try f.writeCValue(w, operand, .FunctionArgument);
+ try v.elem(f, w);
+ try w.print(", {f})", .{
+ try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)),
});
},
.signed => {
@@ -4103,30 +4165,30 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
const shift_val = try pt.intValue(.u8, c_bits - dest_bits);
- try writer.writeAll("zig_shr_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
+ try w.writeAll("zig_shr_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
if (c_bits == 128) {
- try writer.print("(zig_bitCast_i{d}(", .{c_bits});
+ try w.print("(zig_bitCast_i{d}(", .{c_bits});
} else {
- try writer.print("((int{d}_t)", .{c_bits});
+ try w.print("((int{d}_t)", .{c_bits});
}
- try writer.print("zig_shl_u{d}(", .{c_bits});
+ try w.print("zig_shl_u{d}(", .{c_bits});
if (c_bits == 128) {
- try writer.print("zig_bitCast_u{d}(", .{c_bits});
+ try w.print("zig_bitCast_u{d}(", .{c_bits});
} else {
- try writer.print("(uint{d}_t)", .{c_bits});
+ try w.print("(uint{d}_t)", .{c_bits});
}
- try f.writeCValue(writer, operand, .FunctionArgument);
- try v.elem(f, writer);
- if (c_bits == 128) try writer.writeByte(')');
- try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});
- if (c_bits == 128) try writer.writeByte(')');
- try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});
+ try f.writeCValue(w, operand, .FunctionArgument);
+ try v.elem(f, w);
+ if (c_bits == 128) try w.writeByte(')');
+ try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
+ if (c_bits == 128) try w.writeByte(')');
+ try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)});
},
}
- if (need_lo) try writer.writeByte(')');
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ if (need_lo) try w.writeByte(')');
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -4145,15 +4207,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndefDeep(zcu) else false;
+ const w = &f.object.code.writer;
if (val_is_undef) {
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
if (safety and ptr_info.packed_offset.host_size == 0) {
- const writer = f.object.writer();
- try writer.writeAll("memset(");
- try f.writeCValue(writer, ptr_val, .FunctionArgument);
- try writer.writeAll(", 0xaa, sizeof(");
- try f.renderType(writer, .fromInterned(ptr_info.child));
- try writer.writeAll("));\n");
+ try w.writeAll("memset(");
+ try f.writeCValue(w, ptr_val, .FunctionArgument);
+ try w.writeAll(", 0xaa, sizeof(");
+ try f.renderType(w, .fromInterned(ptr_info.child));
+ try w.writeAll("));");
+ try f.object.newline();
}
return .none;
}
@@ -4169,7 +4232,6 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete);
- const writer = f.object.writer();
if (need_memcpy) {
// For this memcpy to safely work we need the rhs to have the same
// underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
@@ -4180,28 +4242,30 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
// TODO this should be done by manually initializing elements of the dest array
const array_src = if (src_val == .constant) blk: {
const new_local = try f.allocLocal(inst, src_ty);
- try f.writeCValue(writer, new_local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, src_val, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, new_local, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, src_val, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
break :blk new_local;
} else src_val;
- const v = try Vectorize.start(f, inst, writer, ptr_ty);
- try writer.writeAll("memcpy((char *)");
- try f.writeCValue(writer, ptr_val, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- if (!is_array) try writer.writeByte('&');
- try f.writeCValue(writer, array_src, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, src_ty);
- try writer.writeAll("))");
+ const v = try Vectorize.start(f, inst, w, ptr_ty);
+ try w.writeAll("memcpy((char *)");
+ try f.writeCValue(w, ptr_val, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ if (!is_array) try w.writeByte('&');
+ try f.writeCValue(w, array_src, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, src_ty);
+ try w.writeAll("))");
try f.freeCValue(inst, array_src);
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
} else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
const host_bits = ptr_info.packed_offset.host_size * 8;
const host_ty = try pt.intType(.unsigned, host_bits);
@@ -4218,50 +4282,50 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
defer mask.deinit();
- try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits)));
+ try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits));
try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
try mask.bitNotWrap(&mask, .unsigned, host_bits);
const mask_val = try pt.intValue_big(host_ty, mask.toConst());
- const v = try Vectorize.start(f, inst, writer, ptr_ty);
- const a = try Assignment.start(f, writer, src_scalar_ctype);
- try f.writeCValueDeref(writer, ptr_val);
- try v.elem(f, writer);
- try a.assign(f, writer);
- try writer.writeAll("zig_or_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeAll("(zig_and_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeByte('(');
- try f.writeCValueDeref(writer, ptr_val);
- try v.elem(f, writer);
- try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)});
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeByte('(');
+ const v = try Vectorize.start(f, inst, w, ptr_ty);
+ const a = try Assignment.start(f, w, src_scalar_ctype);
+ try f.writeCValueDeref(w, ptr_val);
+ try v.elem(f, w);
+ try a.assign(f, w);
+ try w.writeAll("zig_or_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeAll("(zig_and_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeByte('(');
+ try f.writeCValueDeref(w, ptr_val);
+ try v.elem(f, w);
+ try w.print(", {f}), zig_shl_", .{try f.fmtIntLiteralHex(mask_val)});
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeByte('(');
const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
if (cant_cast) {
if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
- try writer.writeAll("zig_make_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
- try writer.writeAll("(0, ");
+ try w.writeAll("zig_make_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, host_ty);
+ try w.writeAll("(0, ");
} else {
- try writer.writeByte('(');
- try f.renderType(writer, host_ty);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, host_ty);
+ try w.writeByte(')');
}
if (src_ty.isPtrAtRuntime(zcu)) {
- try writer.writeByte('(');
- try f.renderType(writer, .usize);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, .usize);
+ try w.writeByte(')');
}
- try f.writeCValue(writer, src_val, .Other);
- try v.elem(f, writer);
- if (cant_cast) try writer.writeByte(')');
- try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)});
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ try f.writeCValue(w, src_val, .Other);
+ try v.elem(f, w);
+ if (cant_cast) try w.writeByte(')');
+ try w.print(", {f}))", .{try f.fmtIntLiteralDec(bit_offset_val)});
+ try a.end(f, w);
+ try v.end(f, inst, w);
} else {
switch (ptr_val) {
.local_ref => |ptr_local_index| switch (src_val) {
@@ -4271,15 +4335,15 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
},
else => {},
}
- const v = try Vectorize.start(f, inst, writer, ptr_ty);
- const a = try Assignment.start(f, writer, src_scalar_ctype);
- try f.writeCValueDeref(writer, ptr_val);
- try v.elem(f, writer);
- try a.assign(f, writer);
- try f.writeCValue(writer, src_val, .Other);
- try v.elem(f, writer);
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, ptr_ty);
+ const a = try Assignment.start(f, w, src_scalar_ctype);
+ try f.writeCValueDeref(w, ptr_val);
+ try v.elem(f, w);
+ try a.assign(f, w);
+ try f.writeCValue(w, src_val, .Other);
+ try v.elem(f, w);
+ try a.end(f, w);
+ try v.end(f, inst, w);
}
return .none;
}
@@ -4298,7 +4362,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
const operand_ty = f.typeOf(bin_op.lhs);
const scalar_ty = operand_ty.scalarType(zcu);
- const w = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
const v = try Vectorize.start(f, inst, w, operand_ty);
try f.writeCValueMember(w, local, .{ .field = 1 });
@@ -4317,7 +4381,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
try f.writeCValue(w, rhs, .FunctionArgument);
if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
- try w.writeAll(");\n");
+ try w.writeAll(");");
+ try f.object.newline();
try v.end(f, inst, w);
return local;
@@ -4336,17 +4401,18 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.typeOfIndex(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
- try writer.writeByte('!');
- try f.writeCValue(writer, op, .Other);
- try v.elem(f, writer);
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
+ try w.writeByte('!');
+ try f.writeCValue(w, op, .Other);
+ try v.elem(f, w);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -4372,21 +4438,22 @@ fn airBinOp(
const inst_ty = f.typeOfIndex(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeByte(' ');
- try writer.writeAll(operator);
- try writer.writeByte(' ');
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeByte(' ');
+ try w.writeAll(operator);
+ try w.writeByte(' ');
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -4422,27 +4489,27 @@ fn airCmpOp(
const rhs_ty = f.typeOf(data.rhs);
const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, lhs_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
- if (lhs != .undef and lhs.eql(rhs)) try writer.writeAll(switch (operator) {
+ const v = try Vectorize.start(f, inst, w, lhs_ty);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
+ if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) {
.lt, .neq, .gt => "false",
.lte, .eq, .gte => "true",
}) else {
- if (need_cast) try writer.writeAll("(void*)");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(compareOperatorC(operator));
- if (need_cast) try writer.writeAll("(void*)");
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- }
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ if (need_cast) try w.writeAll("(void*)");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll(compareOperatorC(operator));
+ if (need_cast) try w.writeAll("(void*)");
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ }
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -4475,41 +4542,41 @@ fn airEquality(
const rhs = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, .bool);
- const a = try Assignment.start(f, writer, .bool);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, .bool);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
- if (lhs != .undef and lhs.eql(rhs)) try writer.writeAll(switch (operator) {
+ if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) {
.lt, .lte, .gte, .gt => unreachable,
.neq => "false",
.eq => "true",
}) else switch (operand_ctype.info(ctype_pool)) {
.basic, .pointer => {
- try f.writeCValue(writer, lhs, .Other);
- try writer.writeAll(compareOperatorC(operator));
- try f.writeCValue(writer, rhs, .Other);
+ try f.writeCValue(w, lhs, .Other);
+ try w.writeAll(compareOperatorC(operator));
+ try f.writeCValue(w, rhs, .Other);
},
.aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => |aggregate| if (aggregate.fields.len == 2 and
(aggregate.fields.at(0, ctype_pool).name.index == .is_null or
aggregate.fields.at(1, ctype_pool).name.index == .is_null))
{
- try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
- try writer.writeAll(" || ");
- try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
- try writer.writeAll(" ? ");
- try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
- try writer.writeAll(compareOperatorC(operator));
- try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
- try writer.writeAll(" : ");
- try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" });
- try writer.writeAll(compareOperatorC(operator));
- try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" });
+ try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" });
+ try w.writeAll(" || ");
+ try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" });
+ try w.writeAll(" ? ");
+ try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" });
+ try w.writeAll(compareOperatorC(operator));
+ try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" });
+ try w.writeAll(" : ");
+ try f.writeCValueMember(w, lhs, .{ .identifier = "payload" });
+ try w.writeAll(compareOperatorC(operator));
+ try f.writeCValueMember(w, rhs, .{ .identifier = "payload" });
} else for (0..aggregate.fields.len) |field_index| {
- if (field_index > 0) try writer.writeAll(switch (operator) {
+ if (field_index > 0) try w.writeAll(switch (operator) {
.lt, .lte, .gte, .gt => unreachable,
.eq => " && ",
.neq => " || ",
@@ -4517,12 +4584,12 @@ fn airEquality(
const field_name: CValue = .{
.ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name,
};
- try f.writeCValueMember(writer, lhs, field_name);
- try writer.writeAll(compareOperatorC(operator));
- try f.writeCValueMember(writer, rhs, field_name);
+ try f.writeCValueMember(w, lhs, field_name);
+ try w.writeAll(compareOperatorC(operator));
+ try f.writeCValueMember(w, rhs, field_name);
},
}
- try a.end(f, writer);
+ try a.end(f, w);
return local;
}
@@ -4533,12 +4600,13 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, .bool);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, operand, .Other);
- try writer.print(" < sizeof({ }) / sizeof(*{0 });\n", .{fmtIdent("zig_errorName")});
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, operand, .Other);
+ try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")});
+ try f.object.newline();
return local;
}
@@ -4559,30 +4627,30 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
const local = try f.allocLocal(inst, inst_ty);
- const writer = f.object.writer();
- const v = try Vectorize.start(f, inst, writer, inst_ty);
- const a = try Assignment.start(f, writer, inst_scalar_ctype);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
+ const w = &f.object.code.writer;
+ const v = try Vectorize.start(f, inst, w, inst_ty);
+ const a = try Assignment.start(f, w, inst_scalar_ctype);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
// We must convert to and from integer types to prevent UB if the operation
// results in a NULL pointer, or if LHS is NULL. The operation is only UB
// if the result is NULL and then dereferenced.
- try writer.writeByte('(');
- try f.renderCType(writer, inst_scalar_ctype);
- try writer.writeAll(")(((uintptr_t)");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(") ");
- try writer.writeByte(operator);
- try writer.writeAll(" (");
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll("*sizeof(");
- try f.renderType(writer, elem_ty);
- try writer.writeAll(")))");
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ try w.writeByte('(');
+ try f.renderCType(w, inst_scalar_ctype);
+ try w.writeAll(")(((uintptr_t)");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll(") ");
+ try w.writeByte(operator);
+ try w.writeAll(" (");
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll("*sizeof(");
+ try f.renderType(w, elem_ty);
+ try w.writeAll(")))");
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -4601,28 +4669,29 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
const rhs = try f.resolveInst(bin_op.rhs);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
+ const v = try Vectorize.start(f, inst, w, inst_ty);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
// (lhs <> rhs) ? lhs : rhs
- try writer.writeAll(" = (");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeByte(' ');
- try writer.writeByte(operator);
- try writer.writeByte(' ');
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(") ? ");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" : ");
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ try w.writeAll(" = (");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeByte(' ');
+ try w.writeByte(operator);
+ try w.writeByte(' ');
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll(") ? ");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" : ");
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -4640,21 +4709,21 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.typeOfIndex(inst);
const ptr_ty = inst_ty.slicePtrFieldType(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
{
- const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
- try a.assign(f, writer);
- try f.writeCValue(writer, ptr, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .identifier = "ptr" });
+ try a.assign(f, w);
+ try f.writeCValue(w, ptr, .Other);
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, .usize);
- try f.writeCValueMember(writer, local, .{ .identifier = "len" });
- try a.assign(f, writer);
- try f.writeCValue(writer, len, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, .usize);
+ try f.writeCValueMember(w, local, .{ .identifier = "len" });
+ try a.assign(f, w);
+ try f.writeCValue(w, len, .Other);
+ try a.end(f, w);
}
return local;
}
@@ -4671,7 +4740,7 @@ fn airCall(
if (f.object.dg.is_naked_fn) return .none;
const gpa = f.object.dg.gpa;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
const extra = f.air.extraData(Air.Call, pl_op.payload);
@@ -4692,13 +4761,14 @@ fn airCall(
.ctype = arg_ctype,
.alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)),
});
- try writer.writeAll("memcpy(");
- try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
- try writer.writeAll(", ");
- try f.writeCValue(writer, resolved_arg.*, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderCType(writer, arg_ctype);
- try writer.writeAll("));\n");
+ try w.writeAll("memcpy(");
+ try f.writeCValueMember(w, array_local, .{ .identifier = "array" });
+ try w.writeAll(", ");
+ try f.writeCValue(w, resolved_arg.*, .FunctionArgument);
+ try w.writeAll(", sizeof(");
+ try f.renderCType(w, arg_ctype);
+ try w.writeAll("));");
+ try f.object.newline();
resolved_arg.* = array_local;
}
}
@@ -4726,22 +4796,22 @@ fn airCall(
const result_local = result: {
if (modifier == .always_tail) {
- try writer.writeAll("zig_always_tail return ");
+ try w.writeAll("zig_always_tail return ");
break :result .none;
} else if (ret_ctype.index == .void) {
break :result .none;
} else if (f.liveness.isUnused(inst)) {
- try writer.writeByte('(');
- try f.renderCType(writer, .void);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderCType(w, .void);
+ try w.writeByte(')');
break :result .none;
} else {
const local = try f.allocAlignedLocal(inst, .{
.ctype = ret_ctype,
.alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)),
});
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = ");
break :result local;
}
};
@@ -4761,17 +4831,17 @@ fn airCall(
else => break :known,
};
if (need_cast) {
- try writer.writeAll("((");
- try f.renderType(writer, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty));
- try writer.writeByte(')');
- if (!callee_is_ptr) try writer.writeByte('&');
+ try w.writeAll("((");
+ try f.renderType(w, if (callee_is_ptr) callee_ty else try pt.singleConstPtrType(callee_ty));
+ try w.writeByte(')');
+ if (!callee_is_ptr) try w.writeByte('&');
}
switch (modifier) {
- .auto, .always_tail => try f.object.dg.renderNavName(writer, fn_nav),
- inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))),
+ .auto, .always_tail => try f.object.dg.renderNavName(w, fn_nav),
+ inline .never_tail, .never_inline => |m| try w.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))),
else => unreachable,
}
- if (need_cast) try writer.writeByte(')');
+ if (need_cast) try w.writeByte(')');
break :callee;
}
switch (modifier) {
@@ -4781,32 +4851,37 @@ fn airCall(
else => unreachable,
}
// Fall back to function pointer call.
- try f.writeCValue(writer, callee, .Other);
+ try f.writeCValue(w, callee, .Other);
}
- try writer.writeByte('(');
+ try w.writeByte('(');
var need_comma = false;
for (resolved_args) |resolved_arg| {
if (resolved_arg == .none) continue;
- if (need_comma) try writer.writeAll(", ");
+ if (need_comma) try w.writeAll(", ");
need_comma = true;
- try f.writeCValue(writer, resolved_arg, .FunctionArgument);
+ try f.writeCValue(w, resolved_arg, .FunctionArgument);
try f.freeCValue(inst, resolved_arg);
}
- try writer.writeAll(");\n");
+ try w.writeAll(");");
+ switch (modifier) {
+ .always_tail => try w.writeByte('\n'),
+ else => try f.object.newline(),
+ }
const result = result: {
if (result_local == .none or !lowersToArray(ret_ty, pt))
break :result result_local;
const array_local = try f.allocLocal(inst, ret_ty);
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, array_local, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, ret_ty);
- try writer.writeAll("));\n");
+ try w.writeAll("memcpy(");
+ try f.writeCValue(w, array_local, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValueMember(w, result_local, .{ .identifier = "array" });
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, ret_ty);
+ try w.writeAll("));");
+ try f.object.newline();
try freeLocal(f, inst, result_local.new_local, null);
break :result array_local;
};
@@ -4816,7 +4891,7 @@ fn airCall(
fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
// TODO re-evaluate whether to emit these or not. If we naively emit
// these directives, the output file will report bogus line numbers because
// every newline after the #line directive adds one to the line.
@@ -4824,13 +4899,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
// If we wanted to go this route, we would need to go all the way and not output
// newlines until the next dbg_stmt occurs.
// Perhaps an additional compilation option is in order?
- //try writer.print("#line {d}\n", .{dbg_stmt.line + 1});
- try writer.print("/* file:{d}:{d} */\n", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
+ //try w.print("#line {d}", .{dbg_stmt.line + 1});
+ //try f.object.newline();
+ try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
+ try f.object.newline();
return .none;
}
fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {
- try f.object.writer().writeAll("(void)0;\n");
+ try f.object.code.writer.writeAll("(void)0;");
+ try f.object.newline();
return .none;
}
@@ -4841,8 +4919,9 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);
- const writer = f.object.writer();
- try writer.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
+ const w = &f.object.code.writer;
+ try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
+ try f.object.newline();
return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
}
@@ -4856,8 +4935,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
try reap(f, inst, &.{pl_op.operand});
- const writer = f.object.writer();
- try writer.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });
+ const w = &f.object.code.writer;
+ try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) });
+ try f.object.newline();
return .none;
}
@@ -4874,7 +4954,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
const block_id = f.next_block_index;
f.next_block_index += 1;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const inst_ty = f.typeOfIndex(inst);
const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))
@@ -4896,8 +4976,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
try die(f, inst, death.toRef());
}
- try f.object.indent_writer.insertNewline();
-
// noreturn blocks have no `br` instructions reaching them, so we don't want a label
if (f.object.dg.is_naked_fn) {
if (f.object.dg.expected_block) |expected_block| {
@@ -4907,7 +4985,8 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
}
} else if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
// label must be followed by an expression, include an empty one.
- try writer.print("zig_block_{d}:;\n", .{block_id});
+ try w.print("\nzig_block_{d}:;", .{block_id});
+ try f.object.newline();
}
return result;
@@ -4944,31 +5023,31 @@ fn lowerTry(
const err_union = try f.resolveInst(operand);
const inst_ty = f.typeOfIndex(inst);
const liveness_condbr = f.liveness.getCondBr(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const payload_ty = err_union_ty.errorUnionPayload(zcu);
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
- try writer.writeAll("if (");
+ try w.writeAll("if (");
if (!payload_has_bits) {
if (is_ptr)
- try f.writeCValueDeref(writer, err_union)
+ try f.writeCValueDeref(w, err_union)
else
- try f.writeCValue(writer, err_union, .Other);
+ try f.writeCValue(w, err_union, .Other);
} else {
// Reap the operand so that it can be reused inside genBody.
// Remember we must avoid calling reap() twice for the same operand
// in this function.
try reap(f, inst, &.{operand});
if (is_ptr)
- try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })
+ try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" })
else
- try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });
+ try f.writeCValueMember(w, err_union, .{ .identifier = "error" });
}
- try writer.writeAll(") ");
+ try w.writeAll(") ");
try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false);
- try f.object.indent_writer.insertNewline();
+ try f.object.newline();
if (f.object.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
}
@@ -4991,14 +5070,14 @@ fn lowerTry(
if (f.liveness.isUnused(inst)) return .none;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
if (is_ptr) {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
- } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
- try a.end(f, writer);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, err_union, .{ .identifier = "payload" });
+ } else try f.writeCValueMember(w, err_union, .{ .identifier = "payload" });
+ try a.end(f, w);
return local;
}
@@ -5006,7 +5085,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
const block = f.blocks.get(branch.block_inst).?;
const result = block.result;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (f.object.dg.is_naked_fn) {
if (result != .none) return f.fail("runtime code not allowed in naked function", .{});
@@ -5020,27 +5099,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void {
const operand = try f.resolveInst(branch.operand);
try reap(f, inst, &.{branch.operand});
- const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));
- try f.writeCValue(writer, result, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, operand, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete));
+ try f.writeCValue(w, result, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, operand, .Other);
+ try a.end(f, w);
}
- try writer.print("goto zig_block_{d};\n", .{block.block_id});
+ try w.print("goto zig_block_{d};\n", .{block.block_id});
}
fn airRepeat(f: *Function, inst: Air.Inst.Index) !void {
const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat;
- const writer = f.object.writer();
- try writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
+ try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)});
}
fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (try f.air.value(br.operand, pt)) |cond_val| {
// Comptime-known dispatch. Iterate the cases to find the correct
@@ -5062,18 +5140,19 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void {
}
}
} else switch_br.cases_len;
- try writer.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx });
+ try w.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx });
return;
}
// Runtime-known dispatch. Set the switch condition, and branch back.
const cond = try f.resolveInst(br.operand);
const cond_local = f.loop_switch_conds.get(br.block_inst).?;
- try f.writeCValue(writer, .{ .local = cond_local }, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, cond, .Other);
- try writer.writeAll(";\n");
- try writer.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)});
+ try f.writeCValue(w, .{ .local = cond_local }, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, cond, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
+ try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)});
}
fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
@@ -5093,7 +5172,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
const zcu = pt.zcu;
const target = &f.object.dg.mod.resolved_target.result;
const ctype_pool = &f.object.dg.ctype_pool;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
const src_info = dest_ty.intInfo(zcu);
@@ -5104,35 +5183,38 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) {
const local = try f.allocLocal(null, dest_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, dest_ty);
- try writer.writeByte(')');
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, dest_ty);
+ try w.writeByte(')');
+ try f.writeCValue(w, operand, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
const operand_lval = if (operand == .constant) blk: {
const operand_local = try f.allocLocal(null, operand_ty);
- try f.writeCValue(writer, operand_local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, operand_local, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, operand, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
break :blk operand_local;
} else operand;
const local = try f.allocLocal(null, dest_ty);
- try writer.writeAll("memcpy(&");
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(", &");
- try f.writeCValue(writer, operand_lval, .Other);
- try writer.writeAll(", sizeof(");
+ try w.writeAll("memcpy(&");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", &");
+ try f.writeCValue(w, operand_lval, .Other);
+ try w.writeAll(", sizeof(");
try f.renderType(
- writer,
+ w,
if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
);
- try writer.writeAll("));\n");
+ try w.writeAll("));");
+ try f.object.newline();
// Ensure padding bits have the expected value.
if (dest_ty.isAbiInt(zcu)) {
@@ -5142,11 +5224,11 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
var wrap_ctype: ?CType = null;
var need_bitcasts = false;
- try f.writeCValue(writer, local, .Other);
+ try f.writeCValue(w, local, .Other);
switch (dest_ctype.info(ctype_pool)) {
else => {},
.array => |array_info| {
- try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) {
+ try w.print("[{d}]", .{switch (target.cpu.arch.endian()) {
.little => array_info.len - 1,
.big => 0,
}});
@@ -5157,92 +5239,98 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
bits += 1;
},
}
- try writer.writeAll(" = ");
+ try w.writeAll(" = ");
if (need_bitcasts) {
- try writer.writeAll("zig_bitCast_");
- try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?.toUnsigned());
- try writer.writeByte('(');
+ try w.writeAll("zig_bitCast_");
+ try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?.toUnsigned());
+ try w.writeByte('(');
}
- try writer.writeAll("zig_wrap_");
+ try w.writeAll("zig_wrap_");
const info_ty = try pt.intType(dest_info.signedness, bits);
if (wrap_ctype) |ctype|
- try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype)
+ try f.object.dg.renderCTypeForBuiltinFnName(w, ctype)
else
- try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty);
- try writer.writeByte('(');
+ try f.object.dg.renderTypeForBuiltinFnName(w, info_ty);
+ try w.writeByte('(');
if (need_bitcasts) {
- try writer.writeAll("zig_bitCast_");
- try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?);
- try writer.writeByte('(');
+ try w.writeAll("zig_bitCast_");
+ try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?);
+ try w.writeByte('(');
}
- try f.writeCValue(writer, local, .Other);
+ try f.writeCValue(w, local, .Other);
switch (dest_ctype.info(ctype_pool)) {
else => {},
- .array => |array_info| try writer.print("[{d}]", .{
+ .array => |array_info| try w.print("[{d}]", .{
switch (target.cpu.arch.endian()) {
.little => array_info.len - 1,
.big => 0,
},
}),
}
- if (need_bitcasts) try writer.writeByte(')');
- try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits);
- if (need_bitcasts) try writer.writeByte(')');
- try writer.writeAll(");\n");
+ if (need_bitcasts) try w.writeByte(')');
+ try f.object.dg.renderBuiltinInfo(w, info_ty, .bits);
+ if (need_bitcasts) try w.writeByte(')');
+ try w.writeAll(");");
+ try f.object.newline();
}
try f.freeCValue(null, operand_lval);
return local;
}
-fn airTrap(f: *Function, writer: anytype) !void {
+fn airTrap(f: *Function, w: *Writer) !void {
// Not even allowed to call trap in a naked function.
if (f.object.dg.is_naked_fn) return;
- try writer.writeAll("zig_trap();\n");
+ try w.writeAll("zig_trap();\n");
}
-fn airBreakpoint(writer: anytype) !CValue {
- try writer.writeAll("zig_breakpoint();\n");
+fn airBreakpoint(f: *Function) !CValue {
+ const w = &f.object.code.writer;
+ try w.writeAll("zig_breakpoint();");
+ try f.object.newline();
return .none;
}
fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, .usize);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, .usize);
- try writer.writeAll(")zig_return_address();\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, .usize);
+ try w.writeAll(")zig_return_address();");
+ try f.object.newline();
return local;
}
fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, .usize);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, .usize);
- try writer.writeAll(")zig_frame_address();\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, .usize);
+ try w.writeAll(")zig_frame_address();");
+ try f.object.newline();
return local;
}
-fn airUnreach(f: *Function) !void {
+fn airUnreach(o: *Object) !void {
// Not even allowed to call unreachable in a naked function.
- if (f.object.dg.is_naked_fn) return;
- try f.object.writer().writeAll("zig_unreachable();\n");
+ if (o.dg.is_naked_fn) return;
+ try o.code.writer.writeAll("zig_unreachable();\n");
}
fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const loop = f.air.extraData(Air.Block, ty_pl.payload);
const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
// `repeat` instructions matching this loop will branch to
// this label. Since we need a label for arbitrary `repeat`
// anyway, there's actually no need to use a "real" looping
// construct at all!
- try writer.print("zig_loop_{d}:\n", .{@intFromEnum(inst)});
+ try w.print("zig_loop_{d}:", .{@intFromEnum(inst)});
+ try f.object.newline();
try genBodyInner(f, body); // no need to restore state, we're noreturn
}
@@ -5254,14 +5342,14 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {
const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);
const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);
const liveness_condbr = f.liveness.getCondBr(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
- try writer.writeAll("if (");
- try f.writeCValue(writer, cond, .Other);
- try writer.writeAll(") ");
+ try w.writeAll("if (");
+ try f.writeCValue(w, cond, .Other);
+ try w.writeAll(") ");
try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
- try writer.writeByte('\n');
+ try f.object.newline();
if (else_body.len > 0) if (f.object.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
@@ -5287,7 +5375,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
const init_condition = try f.resolveInst(switch_br.operand);
try reap(f, inst, &.{switch_br.operand});
const condition_ty = f.typeOf(switch_br.operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
// For dispatches, we will create a local alloc to contain the condition value.
// This may not result in optimal codegen for switch loops, but it minimizes the
@@ -5295,7 +5383,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
const condition = if (is_dispatch_loop) cond: {
const new_local = try f.allocLocal(inst, condition_ty);
try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition);
- try writer.print("zig_switch_{d}_loop:\n", .{@intFromEnum(inst)});
+ try w.print("zig_switch_{d}_loop:", .{@intFromEnum(inst)});
+ try f.object.newline();
try f.loop_switch_conds.put(gpa, inst, new_local.new_local);
break :cond new_local;
} else init_condition;
@@ -5304,7 +5393,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
assert(f.loop_switch_conds.remove(inst));
};
- try writer.writeAll("switch (");
+ try w.writeAll("switch (");
const lowered_condition_ty: Type = if (condition_ty.toIntern() == .bool_type)
.u1
@@ -5313,13 +5402,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
else
condition_ty;
if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) {
- try writer.writeByte('(');
- try f.renderType(writer, lowered_condition_ty);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, lowered_condition_ty);
+ try w.writeByte(')');
}
- try f.writeCValue(writer, condition, .Other);
- try writer.writeAll(") {");
- f.object.indent_writer.pushIndent();
+ try f.writeCValue(w, condition, .Other);
+ try w.writeAll(") {");
+ f.object.indent();
const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1);
defer gpa.free(liveness.deaths);
@@ -5332,35 +5421,37 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
continue;
}
for (case.items) |item| {
- try f.object.indent_writer.insertNewline();
- try writer.writeAll("case ");
+ try f.object.newline();
+ try w.writeAll("case ");
const item_value = try f.air.value(item, pt);
// If `item_value` is a pointer with a known integer address, print the address
// with no cast to avoid a warning.
write_val: {
if (condition_ty.isPtrAtRuntime(zcu)) {
if (item_value.?.getUnsignedInt(zcu)) |item_int| {
- try writer.print("{}", .{try f.fmtIntLiteral(try pt.intValue(lowered_condition_ty, item_int))});
+ try w.print("{f}", .{try f.fmtIntLiteralDec(try pt.intValue(lowered_condition_ty, item_int))});
break :write_val;
}
}
if (condition_ty.isPtrAtRuntime(zcu)) {
- try writer.writeByte('(');
- try f.renderType(writer, .usize);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, .usize);
+ try w.writeByte(')');
}
- try f.object.dg.renderValue(writer, (try f.air.value(item, pt)).?, .Other);
+ try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other);
}
- try writer.writeByte(':');
+ try w.writeByte(':');
}
- try writer.writeAll(" {\n");
- f.object.indent_writer.pushIndent();
+ try w.writeAll(" {");
+ f.object.indent();
+ try f.object.newline();
if (is_dispatch_loop) {
- try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
+ try w.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx });
+ try f.object.newline();
}
try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
- f.object.indent_writer.popIndent();
- try writer.writeByte('}');
+ try f.object.outdent();
+ try w.writeByte('}');
if (f.object.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
@@ -5368,9 +5459,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
}
const else_body = it.elseBody();
- try f.object.indent_writer.insertNewline();
+ try f.object.newline();
- try writer.writeAll("default: ");
+ try w.writeAll("default: ");
if (any_range_cases) {
// We will iterate the cases again to handle those with ranges, and generate
// code using conditions rather than switch cases for such cases.
@@ -5378,40 +5469,41 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
while (it.next()) |case| {
if (case.ranges.len == 0) continue; // handled above
- try writer.writeAll("if (");
+ try w.writeAll("if (");
for (case.items, 0..) |item, item_i| {
- if (item_i != 0) try writer.writeAll(" || ");
- try f.writeCValue(writer, condition, .Other);
- try writer.writeAll(" == ");
- try f.object.dg.renderValue(writer, (try f.air.value(item, pt)).?, .Other);
+ if (item_i != 0) try w.writeAll(" || ");
+ try f.writeCValue(w, condition, .Other);
+ try w.writeAll(" == ");
+ try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other);
}
for (case.ranges, 0..) |range, range_i| {
- if (case.items.len != 0 or range_i != 0) try writer.writeAll(" || ");
+ if (case.items.len != 0 or range_i != 0) try w.writeAll(" || ");
// "(x >= lower && x <= upper)"
- try writer.writeByte('(');
- try f.writeCValue(writer, condition, .Other);
- try writer.writeAll(" >= ");
- try f.object.dg.renderValue(writer, (try f.air.value(range[0], pt)).?, .Other);
- try writer.writeAll(" && ");
- try f.writeCValue(writer, condition, .Other);
- try writer.writeAll(" <= ");
- try f.object.dg.renderValue(writer, (try f.air.value(range[1], pt)).?, .Other);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.writeCValue(w, condition, .Other);
+ try w.writeAll(" >= ");
+ try f.object.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .Other);
+ try w.writeAll(" && ");
+ try f.writeCValue(w, condition, .Other);
+ try w.writeAll(" <= ");
+ try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other);
+ try w.writeByte(')');
}
- try writer.writeAll(") {\n");
- f.object.indent_writer.pushIndent();
+ try w.writeAll(") {");
+ f.object.indent();
+ try f.object.newline();
if (is_dispatch_loop) {
- try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
+ try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx });
}
try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true);
- f.object.indent_writer.popIndent();
- try writer.writeByte('}');
+ try f.object.outdent();
+ try w.writeByte('}');
if (f.object.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
}
}
if (is_dispatch_loop) {
- try writer.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), switch_br.cases_len });
+ try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), switch_br.cases_len });
}
if (else_body.len > 0) {
// Note that this must be the last case, so we do not need to use `genBodyResolveState` since
@@ -5422,13 +5514,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void
try genBody(f, else_body);
if (f.object.dg.expected_block) |_|
return f.fail("runtime code not allowed in naked function", .{});
- } else {
- try writer.writeAll("zig_unreachable();");
- }
- try f.object.indent_writer.insertNewline();
-
- f.object.indent_writer.popIndent();
- try writer.writeAll("}\n");
+ } else try airUnreach(&f.object);
+ try f.object.newline();
+ try f.object.outdent();
+ try w.writeAll("}\n");
}
fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
@@ -5466,7 +5555,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i += inputs.len;
const result = result: {
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const inst_ty = f.typeOfIndex(inst);
const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
const inst_local = try f.allocLocalValue(.{
@@ -5474,10 +5563,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
.alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)),
});
if (f.wantSafety()) {
- try f.writeCValue(writer, inst_local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, .{ .undef = inst_ty }, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, inst_local, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, .{ .undef = inst_ty }, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
}
break :local inst_local;
} else .none;
@@ -5501,21 +5591,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
const is_reg = constraint[1] == '{';
if (is_reg) {
const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu);
- try writer.writeAll("register ");
+ try w.writeAll("register ");
const output_local = try f.allocLocalValue(.{
.ctype = try f.ctypeFromType(output_ty, .complete),
.alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)),
});
try f.allocs.put(gpa, output_local.new_local, false);
- try f.object.dg.renderTypeAndName(writer, output_ty, output_local, .{}, .none, .complete);
- try writer.writeAll(" __asm(\"");
- try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
- try writer.writeAll("\")");
+ try f.object.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none, .complete);
+ try w.writeAll(" __asm(\"");
+ try w.writeAll(constraint["={".len .. constraint.len - "}".len]);
+ try w.writeAll("\")");
if (f.wantSafety()) {
- try writer.writeAll(" = ");
- try f.writeCValue(writer, .{ .undef = output_ty }, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, .{ .undef = output_ty }, .Other);
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
}
}
for (inputs) |input| {
@@ -5536,21 +5627,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
const input_val = try f.resolveInst(input);
if (asmInputNeedsLocal(f, constraint, input_val)) {
const input_ty = f.typeOf(input);
- if (is_reg) try writer.writeAll("register ");
+ if (is_reg) try w.writeAll("register ");
const input_local = try f.allocLocalValue(.{
.ctype = try f.ctypeFromType(input_ty, .complete),
.alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)),
});
try f.allocs.put(gpa, input_local.new_local, false);
- try f.object.dg.renderTypeAndName(writer, input_ty, input_local, Const, .none, .complete);
+ try f.object.dg.renderTypeAndName(w, input_ty, input_local, Const, .none, .complete);
if (is_reg) {
- try writer.writeAll(" __asm(\"");
- try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
- try writer.writeAll("\")");
+ try w.writeAll(" __asm(\"");
+ try w.writeAll(constraint["{".len .. constraint.len - "}".len]);
+ try w.writeAll("\")");
}
- try writer.writeAll(" = ");
- try f.writeCValue(writer, input_val, .Other);
- try writer.writeAll(";\n");
+ try w.writeAll(" = ");
+ try f.writeCValue(w, input_val, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
}
}
for (0..clobbers_len) |_| {
@@ -5610,14 +5702,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
}
- try writer.writeAll("__asm");
- if (is_volatile) try writer.writeAll(" volatile");
- try writer.print("({s}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)});
+ try w.writeAll("__asm");
+ if (is_volatile) try w.writeAll(" volatile");
+ try w.print("({f}", .{fmtStringLiteral(fixed_asm_source[0..dst_i], null)});
}
extra_i = constraints_extra_begin;
var locals_index = locals_begin;
- try writer.writeByte(':');
+ try w.writeByte(':');
for (outputs, 0..) |output, index| {
const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
@@ -5626,22 +5718,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
// for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
- if (index > 0) try writer.writeByte(',');
- try writer.writeByte(' ');
- if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
+ if (index > 0) try w.writeByte(',');
+ try w.writeByte(' ');
+ if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name});
const is_reg = constraint[1] == '{';
- try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)});
+ try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)});
if (is_reg) {
- try f.writeCValue(writer, .{ .local = locals_index }, .Other);
+ try f.writeCValue(w, .{ .local = locals_index }, .Other);
locals_index += 1;
} else if (output == .none) {
- try f.writeCValue(writer, inst_local, .FunctionArgument);
+ try f.writeCValue(w, inst_local, .FunctionArgument);
} else {
- try f.writeCValueDeref(writer, try f.resolveInst(output));
+ try f.writeCValueDeref(w, try f.resolveInst(output));
}
- try writer.writeByte(')');
+ try w.writeByte(')');
}
- try writer.writeByte(':');
+ try w.writeByte(':');
for (inputs, 0..) |input, index| {
const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
@@ -5650,21 +5742,21 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
// for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
- if (index > 0) try writer.writeByte(',');
- try writer.writeByte(' ');
- if (!mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
+ if (index > 0) try w.writeByte(',');
+ try w.writeByte(' ');
+ if (!mem.eql(u8, name, "_")) try w.print("[{s}]", .{name});
const is_reg = constraint[0] == '{';
const input_val = try f.resolveInst(input);
- try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});
- try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: {
+ try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});
+ try f.writeCValue(w, if (asmInputNeedsLocal(f, constraint, input_val)) local: {
const input_local_idx = locals_index;
locals_index += 1;
break :local .{ .local = input_local_idx };
} else input_val, .Other);
- try writer.writeByte(')');
+ try w.writeByte(')');
}
- try writer.writeByte(':');
+ try w.writeByte(':');
for (0..clobbers_len) |clobber_i| {
const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -5673,10 +5765,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
if (clobber.len == 0) continue;
- if (clobber_i > 0) try writer.writeByte(',');
- try writer.print(" {s}", .{fmtStringLiteral(clobber, null)});
+ if (clobber_i > 0) try w.writeByte(',');
+ try w.print(" {f}", .{fmtStringLiteral(clobber, null)});
}
- try writer.writeAll(");\n");
+ try w.writeAll(");");
+ try f.object.newline();
extra_i = constraints_extra_begin;
locals_index = locals_begin;
@@ -5690,14 +5783,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
const is_reg = constraint[1] == '{';
if (is_reg) {
- try f.writeCValueDeref(writer, if (output == .none)
+ try f.writeCValueDeref(w, if (output == .none)
.{ .local_ref = inst_local.new_local }
else
try f.resolveInst(output));
- try writer.writeAll(" = ");
- try f.writeCValue(writer, .{ .local = locals_index }, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, .{ .local = locals_index }, .Other);
locals_index += 1;
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
}
}
@@ -5727,14 +5821,14 @@ fn airIsNull(
const ctype_pool = &f.object.dg.ctype_pool;
const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
const local = try f.allocLocal(inst, .bool);
- const a = try Assignment.start(f, writer, .bool);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, .bool);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
const operand_ty = f.typeOf(un_op);
const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
@@ -5742,9 +5836,9 @@ fn airIsNull(
const rhs = switch (opt_ctype.info(ctype_pool)) {
.basic, .pointer => rhs: {
if (is_ptr)
- try f.writeCValueDeref(writer, operand)
+ try f.writeCValueDeref(w, operand)
else
- try f.writeCValue(writer, operand, .Other);
+ try f.writeCValue(w, operand, .Other);
break :rhs if (opt_ctype.isBool())
"true"
else if (opt_ctype.isInteger())
@@ -5756,24 +5850,24 @@ fn airIsNull(
.aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
.is_null, .payload => rhs: {
if (is_ptr)
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" })
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" })
else
- try f.writeCValueMember(writer, operand, .{ .identifier = "is_null" });
+ try f.writeCValueMember(w, operand, .{ .identifier = "is_null" });
break :rhs "true";
},
.ptr, .len => rhs: {
if (is_ptr)
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "ptr" })
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "ptr" })
else
- try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });
+ try f.writeCValueMember(w, operand, .{ .identifier = "ptr" });
break :rhs "NULL";
},
else => unreachable,
},
};
- try writer.writeAll(compareOperatorC(operator));
- try writer.writeAll(rhs);
- try a.end(f, writer);
+ try w.writeAll(compareOperatorC(operator));
+ try w.writeAll(rhs);
+ try a.end(f, w);
return local;
}
@@ -5795,16 +5889,16 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue
.aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
.is_null, .payload => {
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
if (is_ptr) {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
- } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
- try a.end(f, writer);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
+ } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" });
+ try a.end(f, w);
return local;
},
.ptr, .len => return f.moveCValue(inst, inst_ty, operand),
@@ -5817,7 +5911,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const operand = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
const operand_ty = f.typeOf(ty_op.operand);
@@ -5826,40 +5920,40 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete);
switch (opt_ctype.info(&f.object.dg.ctype_pool)) {
.basic => {
- const a = try Assignment.start(f, writer, opt_ctype);
- try f.writeCValueDeref(writer, operand);
- try a.assign(f, writer);
- try f.object.dg.renderValue(writer, Value.false, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, opt_ctype);
+ try f.writeCValueDeref(w, operand);
+ try a.assign(f, w);
+ try f.object.dg.renderValue(w, Value.false, .Other);
+ try a.end(f, w);
return .none;
},
.pointer => {
if (f.liveness.isUnused(inst)) return .none;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, opt_ctype);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, operand, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, opt_ctype);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, operand, .Other);
+ try a.end(f, w);
return local;
},
.aligned, .array, .vector, .fwd_decl, .function => unreachable,
.aggregate => {
{
- const a = try Assignment.start(f, writer, opt_ctype);
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" });
- try a.assign(f, writer);
- try f.object.dg.renderValue(writer, Value.false, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, opt_ctype);
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" });
+ try a.assign(f, w);
+ try f.object.dg.renderValue(w, Value.false, .Other);
+ try a.end(f, w);
}
if (f.liveness.isUnused(inst)) return .none;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, opt_ctype);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, opt_ctype);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
+ try a.end(f, w);
return local;
},
}
@@ -5967,42 +6061,43 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const field_ptr_val = try f.resolveInst(extra.field_ptr);
try reap(f, inst, &.{extra.field_ptr});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, container_ptr_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, container_ptr_ty);
- try writer.writeByte(')');
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, container_ptr_ty);
+ try w.writeByte(')');
switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, pt)) {
- .begin => try f.writeCValue(writer, field_ptr_val, .Other),
+ .begin => try f.writeCValue(w, field_ptr_val, .Other),
.field => |field| {
const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
- try writer.writeAll("((");
- try f.renderType(writer, u8_ptr_ty);
- try writer.writeByte(')');
- try f.writeCValue(writer, field_ptr_val, .Other);
- try writer.writeAll(" - offsetof(");
- try f.renderType(writer, container_ty);
- try writer.writeAll(", ");
- try f.writeCValue(writer, field, .Other);
- try writer.writeAll("))");
+ try w.writeAll("((");
+ try f.renderType(w, u8_ptr_ty);
+ try w.writeByte(')');
+ try f.writeCValue(w, field_ptr_val, .Other);
+ try w.writeAll(" - offsetof(");
+ try f.renderType(w, container_ty);
+ try w.writeAll(", ");
+ try f.writeCValue(w, field, .Other);
+ try w.writeAll("))");
},
.byte_offset => |byte_offset| {
const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
- try writer.writeAll("((");
- try f.renderType(writer, u8_ptr_ty);
- try writer.writeByte(')');
- try f.writeCValue(writer, field_ptr_val, .Other);
- try writer.print(" - {})", .{
- try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)),
+ try w.writeAll("((");
+ try f.renderType(w, u8_ptr_ty);
+ try w.writeByte(')');
+ try f.writeCValue(w, field_ptr_val, .Other);
+ try w.print(" - {f})", .{
+ try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)),
});
},
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
@@ -6021,33 +6116,34 @@ fn fieldPtr(
// Ensure complete type definition is visible before accessing fields.
_ = try f.ctypeFromType(container_ty, .complete);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, field_ptr_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, field_ptr_ty);
- try writer.writeByte(')');
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, field_ptr_ty);
+ try w.writeByte(')');
switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, pt)) {
- .begin => try f.writeCValue(writer, container_ptr_val, .Other),
+ .begin => try f.writeCValue(w, container_ptr_val, .Other),
.field => |field| {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, container_ptr_val, field);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, container_ptr_val, field);
},
.byte_offset => |byte_offset| {
const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
- try writer.writeAll("((");
- try f.renderType(writer, u8_ptr_ty);
- try writer.writeByte(')');
- try f.writeCValue(writer, container_ptr_val, .Other);
- try writer.print(" + {})", .{
- try f.fmtIntLiteral(try pt.intValue(.usize, byte_offset)),
+ try w.writeAll("((");
+ try f.renderType(w, u8_ptr_ty);
+ try w.writeByte(')');
+ try f.writeCValue(w, container_ptr_val, .Other);
+ try w.print(" + {f})", .{
+ try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)),
});
},
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
@@ -6067,7 +6163,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const struct_byval = try f.resolveInst(extra.struct_operand);
try reap(f, inst, &.{extra.struct_operand});
const struct_ty = f.typeOf(extra.struct_operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
// Ensure complete type definition is visible before accessing fields.
_ = try f.ctypeFromType(struct_ty, .complete);
@@ -6094,42 +6190,44 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
const field_int_ty = try pt.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu))));
const temp_local = try f.allocLocal(inst, field_int_ty);
- try f.writeCValue(writer, temp_local, .Other);
- try writer.writeAll(" = zig_wrap_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
- try writer.writeAll("((");
- try f.renderType(writer, field_int_ty);
- try writer.writeByte(')');
+ try f.writeCValue(w, temp_local, .Other);
+ try w.writeAll(" = zig_wrap_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, field_int_ty);
+ try w.writeAll("((");
+ try f.renderType(w, field_int_ty);
+ try w.writeByte(')');
const cant_cast = int_info.bits > 64;
if (cant_cast) {
if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
- try writer.writeAll("zig_lo_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_lo_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty);
+ try w.writeByte('(');
}
if (bit_offset > 0) {
- try writer.writeAll("zig_shr_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_shr_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, struct_ty);
+ try w.writeByte('(');
}
- try f.writeCValue(writer, struct_byval, .Other);
- if (bit_offset > 0) try writer.print(", {})", .{
- try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)),
+ try f.writeCValue(w, struct_byval, .Other);
+ if (bit_offset > 0) try w.print(", {f})", .{
+ try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)),
});
- if (cant_cast) try writer.writeByte(')');
- try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
- try writer.writeAll(");\n");
+ if (cant_cast) try w.writeByte(')');
+ try f.object.dg.renderBuiltinInfo(w, field_int_ty, .bits);
+ try w.writeAll(");");
+ try f.object.newline();
if (inst_ty.eql(field_int_ty, zcu)) return temp_local;
const local = try f.allocLocal(inst, inst_ty);
if (local.new_local != temp_local.new_local) {
- try writer.writeAll("memcpy(");
- try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("));\n");
+ try w.writeAll("memcpy(");
+ try f.writeCValue(w, .{ .local_ref = local.new_local }, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValue(w, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, inst_ty);
+ try w.writeAll("));");
+ try f.object.newline();
}
try freeLocal(f, inst, temp_local.new_local, null);
return local;
@@ -6150,10 +6248,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
.@"packed" => {
const operand_lval = if (struct_byval == .constant) blk: {
const operand_local = try f.allocLocal(inst, struct_ty);
- try f.writeCValue(writer, operand_local, .Other);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, struct_byval, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, operand_local, .Other);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, struct_byval, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
break :blk operand_local;
} else struct_byval;
const local = try f.allocLocal(inst, inst_ty);
@@ -6164,13 +6263,14 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
},
else => true,
}) {
- try writer.writeAll("memcpy(&");
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(", &");
- try f.writeCValue(writer, operand_lval, .Other);
- try writer.writeAll(", sizeof(");
- try f.renderType(writer, inst_ty);
- try writer.writeAll("));\n");
+ try w.writeAll("memcpy(&");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", &");
+ try f.writeCValue(w, operand_lval, .Other);
+ try w.writeAll(", sizeof(");
+ try f.renderType(w, inst_ty);
+ try w.writeAll("));");
+ try f.object.newline();
}
try f.freeCValue(inst, operand_lval);
return local;
@@ -6181,11 +6281,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
};
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValueMember(writer, struct_byval, field_name);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValueMember(w, struct_byval, field_name);
+ try a.end(f, w);
return local;
}
@@ -6212,21 +6312,22 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
- const writer = f.object.writer();
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
+ const w = &f.object.code.writer;
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = ");
if (!payload_ty.hasRuntimeBits(zcu))
- try f.writeCValue(writer, operand, .Other)
+ try f.writeCValue(w, operand, .Other)
else if (error_ty.errorSetIsEmpty(zcu))
- try writer.print("{}", .{
- try f.fmtIntLiteral(try pt.intValue(try pt.errorIntType(), 0)),
+ try w.print("{f}", .{
+ try f.fmtIntLiteralDec(try pt.intValue(try pt.errorIntType(), 0)),
})
else if (operand_is_ptr)
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
else
- try f.writeCValueMember(writer, operand, .{ .identifier = "error" });
- try writer.writeAll(";\n");
+ try f.writeCValueMember(w, operand, .{ .identifier = "error" });
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
@@ -6241,29 +6342,30 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
const operand_ty = f.typeOf(ty_op.operand);
const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
if (!is_ptr) return .none;
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = (");
- try f.renderType(writer, inst_ty);
- try writer.writeByte(')');
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = (");
+ try f.renderType(w, inst_ty);
+ try w.writeByte(')');
+ try f.writeCValue(w, operand, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
if (is_ptr) {
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
- } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
- try a.end(f, writer);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
+ } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" });
+ try a.end(f, w);
return local;
}
@@ -6282,21 +6384,21 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
.aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) {
.is_null, .payload => {
const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
{
- const a = try Assignment.start(f, writer, .bool);
- try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
- try a.assign(f, writer);
- try writer.writeAll("false");
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, .bool);
+ try f.writeCValueMember(w, local, .{ .identifier = "is_null" });
+ try a.assign(f, w);
+ try w.writeAll("false");
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, operand_ctype);
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try a.assign(f, writer);
- try f.writeCValue(writer, operand, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, operand_ctype);
+ try f.writeCValueMember(w, local, .{ .identifier = "payload" });
+ try a.assign(f, w);
+ try f.writeCValue(w, operand, .Other);
+ try a.end(f, w);
}
return local;
},
@@ -6318,7 +6420,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
const err = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
if (repr_is_err and err == .local and err.local == local.new_local) {
@@ -6327,21 +6429,21 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
}
if (!repr_is_err) {
- const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try a.assign(f, writer);
- try f.object.dg.renderUndefValue(writer, payload_ty, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .identifier = "payload" });
+ try a.assign(f, w);
+ try f.object.dg.renderUndefValue(w, payload_ty, .Other);
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));
+ const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete));
if (repr_is_err)
- try f.writeCValue(writer, local, .Other)
+ try f.writeCValue(w, local, .Other)
else
- try f.writeCValueMember(writer, local, .{ .identifier = "error" });
- try a.assign(f, writer);
- try f.writeCValue(writer, err, .Other);
- try a.end(f, writer);
+ try f.writeCValueMember(w, local, .{ .identifier = "error" });
+ try a.assign(f, w);
+ try f.writeCValue(w, err, .Other);
+ try a.end(f, w);
}
return local;
}
@@ -6349,7 +6451,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const inst_ty = f.typeOfIndex(inst);
const operand = try f.resolveInst(ty_op.operand);
@@ -6363,31 +6465,31 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
// First, set the non-error value.
if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
- const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete));
- try f.writeCValueDeref(writer, operand);
- try a.assign(f, writer);
- try writer.print("{}", .{try f.fmtIntLiteral(no_err)});
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete));
+ try f.writeCValueDeref(w, operand);
+ try a.assign(f, w);
+ try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)});
+ try a.end(f, w);
return .none;
}
{
- const a = try Assignment.start(f, writer, try f.ctypeFromType(err_int_ty, .complete));
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" });
- try a.assign(f, writer);
- try writer.print("{}", .{try f.fmtIntLiteral(no_err)});
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(err_int_ty, .complete));
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" });
+ try a.assign(f, w);
+ try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)});
+ try a.end(f, w);
}
// Then return the payload pointer (only if it is used)
if (f.liveness.isUnused(inst)) return .none;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try writer.writeByte('&');
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try w.writeByte('&');
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" });
+ try a.end(f, w);
return local;
}
@@ -6418,24 +6520,24 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
const err_ty = inst_ty.errorUnionSet(zcu);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
if (!repr_is_err) {
- const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try a.assign(f, writer);
- try f.writeCValue(writer, payload, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .identifier = "payload" });
+ try a.assign(f, w);
+ try f.writeCValue(w, payload, .Other);
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete));
+ const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete));
if (repr_is_err)
- try f.writeCValue(writer, local, .Other)
+ try f.writeCValue(w, local, .Other)
else
- try f.writeCValueMember(writer, local, .{ .identifier = "error" });
- try a.assign(f, writer);
- try f.object.dg.renderValue(writer, try pt.intValue(try pt.errorIntType(), 0), .Other);
- try a.end(f, writer);
+ try f.writeCValueMember(w, local, .{ .identifier = "error" });
+ try a.assign(f, w);
+ try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other);
+ try a.end(f, w);
}
return local;
}
@@ -6445,7 +6547,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
const zcu = pt.zcu;
const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
const operand_ty = f.typeOf(un_op);
@@ -6454,25 +6556,25 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
const payload_ty = err_union_ty.errorUnionPayload(zcu);
const error_ty = err_union_ty.errorUnionSet(zcu);
- const a = try Assignment.start(f, writer, .bool);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, .bool);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
const err_int_ty = try pt.errorIntType();
if (!error_ty.errorSetIsEmpty(zcu))
if (payload_ty.hasRuntimeBits(zcu))
if (is_ptr)
- try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
+ try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" })
else
- try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
+ try f.writeCValueMember(w, operand, .{ .identifier = "error" })
else
- try f.writeCValue(writer, operand, .Other)
+ try f.writeCValue(w, operand, .Other)
else
- try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other);
- try writer.writeByte(' ');
- try writer.writeAll(operator);
- try writer.writeByte(' ');
- try f.object.dg.renderValue(writer, try pt.intValue(err_int_ty, 0), .Other);
- try a.end(f, writer);
+ try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other);
+ try w.writeByte(' ');
+ try w.writeAll(operator);
+ try w.writeByte(' ');
+ try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other);
+ try a.end(f, w);
return local;
}
@@ -6486,45 +6588,45 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
try reap(f, inst, &.{ty_op.operand});
const inst_ty = f.typeOfIndex(inst);
const ptr_ty = inst_ty.slicePtrFieldType(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
const operand_ty = f.typeOf(ty_op.operand);
const array_ty = operand_ty.childType(zcu);
{
- const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
- try a.assign(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .identifier = "ptr" });
+ try a.assign(f, w);
if (operand == .undef) {
- try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other);
+ try f.writeCValue(w, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other);
} else {
const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete);
const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype;
const elem_ty = array_ty.childType(zcu);
const elem_ctype = try f.ctypeFromType(elem_ty, .complete);
if (!ptr_child_ctype.eql(elem_ctype)) {
- try writer.writeByte('(');
- try f.renderCType(writer, ptr_ctype);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderCType(w, ptr_ctype);
+ try w.writeByte(')');
}
const operand_ctype = try f.ctypeFromType(operand_ty, .complete);
const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype;
if (operand_child_ctype.info(ctype_pool) == .array) {
- try writer.writeByte('&');
- try f.writeCValueDeref(writer, operand);
- try writer.print("[{}]", .{try f.fmtIntLiteral(.zero_usize)});
- } else try f.writeCValue(writer, operand, .Other);
+ try w.writeByte('&');
+ try f.writeCValueDeref(w, operand);
+ try w.print("[{f}]", .{try f.fmtIntLiteralDec(.zero_usize)});
+ } else try f.writeCValue(w, operand, .Other);
}
- try a.end(f, writer);
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, .usize);
- try f.writeCValueMember(writer, local, .{ .identifier = "len" });
- try a.assign(f, writer);
- try writer.print("{}", .{
- try f.fmtIntLiteral(try pt.intValue(.usize, array_ty.arrayLen(zcu))),
+ const a = try Assignment.start(f, w, .usize);
+ try f.writeCValueMember(w, local, .{ .identifier = "len" });
+ try a.assign(f, w);
+ try w.print("{f}", .{
+ try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))),
});
- try a.end(f, writer);
+ try a.end(f, w);
}
return local;
@@ -6551,32 +6653,32 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
else
unreachable;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
- try writer.writeAll("zig_wrap_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
- try writer.writeByte('(');
- }
- try writer.writeAll("zig_");
- try writer.writeAll(operation);
- try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
- try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
- try writer.writeByte('(');
- try f.writeCValue(writer, operand, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeByte(')');
+ try w.writeAll("zig_wrap_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
+ try w.writeByte('(');
+ }
+ try w.writeAll("zig_");
+ try w.writeAll(operation);
+ try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target));
+ try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target));
+ try w.writeByte('(');
+ try f.writeCValue(w, operand, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeByte(')');
if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
- try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits);
- try writer.writeByte(')');
+ try f.object.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits);
+ try w.writeByte(')');
}
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -6601,27 +6703,28 @@ fn airUnBuiltinCall(
const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
if (!ref_ret) {
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
}
- try writer.print("zig_{s}_", .{operation});
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
+ try w.print("zig_{s}_", .{operation});
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
if (ref_ret) {
- try f.writeCValue(writer, local, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
+ try f.writeCValue(w, local, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
}
- try f.writeCValue(writer, operand, .FunctionArgument);
- try v.elem(f, writer);
- try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
- try writer.writeAll(");\n");
- try v.end(f, inst, writer);
+ try f.writeCValue(w, operand, .FunctionArgument);
+ try v.elem(f, w);
+ try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
+ try w.writeAll(");");
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -6651,31 +6754,31 @@ fn airBinBuiltinCall(
const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
- const v = try Vectorize.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
if (!ref_ret) {
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
}
- try writer.print("zig_{s}_", .{operation});
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
+ try w.print("zig_{s}_", .{operation});
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
if (ref_ret) {
- try f.writeCValue(writer, local, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- }
- try f.writeCValue(writer, lhs, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- try f.writeCValue(writer, rhs, .FunctionArgument);
- if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer);
- try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
- try writer.writeAll(");\n");
- try v.end(f, inst, writer);
+ try f.writeCValue(w, local, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ }
+ try f.writeCValue(w, lhs, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ try f.writeCValue(w, rhs, .FunctionArgument);
+ if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
+ try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
+ try w.writeAll(");\n");
+ try v.end(f, inst, w);
return local;
}
@@ -6702,38 +6805,39 @@ fn airCmpBuiltinCall(
const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, operand_ty);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
if (!ref_ret) {
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
}
- try writer.print("zig_{s}_", .{switch (operation) {
+ try w.print("zig_{s}_", .{switch (operation) {
else => @tagName(operation),
.operator => compareOperatorAbbrev(operator),
}});
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
if (ref_ret) {
- try f.writeCValue(writer, local, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- }
- try f.writeCValue(writer, lhs, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- try f.writeCValue(writer, rhs, .FunctionArgument);
- try v.elem(f, writer);
- try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
- try writer.writeByte(')');
- if (!ref_ret) try writer.print("{s}{}", .{
+ try f.writeCValue(w, local, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ }
+ try f.writeCValue(w, lhs, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ try f.writeCValue(w, rhs, .FunctionArgument);
+ try v.elem(f, w);
+ try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
+ try w.writeByte(')');
+ if (!ref_ret) try w.print("{s}{f}", .{
compareOperatorC(operator),
- try f.fmtIntLiteral(try pt.intValue(.i32, 0)),
+ try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)),
});
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -6751,7 +6855,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
const ty = ptr_ty.childType(zcu);
const ctype = try f.ctypeFromType(ty, .complete);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const new_value_mat = try Materialize.start(f, inst, ty, new_value);
try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
@@ -6763,76 +6867,78 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
const local = try f.allocLocal(inst, inst_ty);
if (inst_ty.isPtrLikeOptional(zcu)) {
{
- const a = try Assignment.start(f, writer, ctype);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValue(writer, expected_value, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, ctype);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValue(w, expected_value, .Other);
+ try a.end(f, w);
}
- try writer.writeAll("if (");
- try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
- try f.renderType(writer, ty);
- try writer.writeByte(')');
- if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
- try writer.writeAll(" *)");
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll(", ");
- try f.writeCValue(writer, local, .FunctionArgument);
- try writer.writeAll(", ");
- try new_value_mat.mat(f, writer);
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, extra.successOrder());
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, extra.failureOrder());
- try writer.writeAll(", ");
- try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeAll(", ");
- try f.renderType(writer, repr_ty);
- try writer.writeByte(')');
- try writer.writeAll(") {\n");
- f.object.indent_writer.pushIndent();
+ try w.writeAll("if (");
+ try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
+ try f.renderType(w, ty);
+ try w.writeByte(')');
+ if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
+ try w.writeAll(" *)");
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeAll(", ");
+ try f.writeCValue(w, local, .FunctionArgument);
+ try w.writeAll(", ");
+ try new_value_mat.mat(f, w);
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, extra.successOrder());
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, extra.failureOrder());
+ try w.writeAll(", ");
+ try f.object.dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeAll(", ");
+ try f.renderType(w, repr_ty);
+ try w.writeByte(')');
+ try w.writeAll(") {");
+ f.object.indent();
+ try f.object.newline();
{
- const a = try Assignment.start(f, writer, ctype);
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try writer.writeAll("NULL");
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, ctype);
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try w.writeAll("NULL");
+ try a.end(f, w);
}
- f.object.indent_writer.popIndent();
- try writer.writeAll("}\n");
+ try f.object.outdent();
+ try w.writeByte('}');
+ try f.object.newline();
} else {
{
- const a = try Assignment.start(f, writer, ctype);
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try a.assign(f, writer);
- try f.writeCValue(writer, expected_value, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, ctype);
+ try f.writeCValueMember(w, local, .{ .identifier = "payload" });
+ try a.assign(f, w);
+ try f.writeCValue(w, expected_value, .Other);
+ try a.end(f, w);
}
{
- const a = try Assignment.start(f, writer, .bool);
- try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
- try a.assign(f, writer);
- try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
- try f.renderType(writer, ty);
- try writer.writeByte(')');
- if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
- try writer.writeAll(" *)");
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll(", ");
- try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
- try writer.writeAll(", ");
- try new_value_mat.mat(f, writer);
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, extra.successOrder());
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, extra.failureOrder());
- try writer.writeAll(", ");
- try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeAll(", ");
- try f.renderType(writer, repr_ty);
- try writer.writeByte(')');
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, .bool);
+ try f.writeCValueMember(w, local, .{ .identifier = "is_null" });
+ try a.assign(f, w);
+ try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
+ try f.renderType(w, ty);
+ try w.writeByte(')');
+ if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
+ try w.writeAll(" *)");
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeAll(", ");
+ try f.writeCValueMember(w, local, .{ .identifier = "payload" });
+ try w.writeAll(", ");
+ try new_value_mat.mat(f, w);
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, extra.successOrder());
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, extra.failureOrder());
+ try w.writeAll(", ");
+ try f.object.dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeAll(", ");
+ try f.renderType(w, repr_ty);
+ try w.writeByte(')');
+ try a.end(f, w);
}
}
try new_value_mat.end(f, inst);
@@ -6856,7 +6962,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
const ptr = try f.resolveInst(pl_op.operand);
const operand = try f.resolveInst(extra.operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const operand_mat = try Materialize.start(f, inst, ty, operand);
try reap(f, inst, &.{ pl_op.operand, extra.operand });
@@ -6866,31 +6972,32 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
const repr_ty = if (is_float) pt.intType(.unsigned, repr_bits) catch unreachable else ty;
const local = try f.allocLocal(inst, inst_ty);
- try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
- if (is_float) try writer.writeAll("_float") else if (is_128) try writer.writeAll("_int128");
- try writer.writeByte('(');
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(", (");
+ try w.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
+ if (is_float) try w.writeAll("_float") else if (is_128) try w.writeAll("_int128");
+ try w.writeByte('(');
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", (");
const use_atomic = switch (extra.op()) {
else => true,
// These are missing from stdatomic.h, so no atomic types unless a fallback is used.
.Nand, .Min, .Max => is_float or is_128,
};
- if (use_atomic) try writer.writeAll("zig_atomic(");
- try f.renderType(writer, ty);
- if (use_atomic) try writer.writeByte(')');
- if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
- try writer.writeAll(" *)");
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll(", ");
- try operand_mat.mat(f, writer);
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, extra.ordering());
- try writer.writeAll(", ");
- try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeAll(", ");
- try f.renderType(writer, repr_ty);
- try writer.writeAll(");\n");
+ if (use_atomic) try w.writeAll("zig_atomic(");
+ try f.renderType(w, ty);
+ if (use_atomic) try w.writeByte(')');
+ if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
+ try w.writeAll(" *)");
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeAll(", ");
+ try operand_mat.mat(f, w);
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, extra.ordering());
+ try w.writeAll(", ");
+ try f.object.dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeAll(", ");
+ try f.renderType(w, repr_ty);
+ try w.writeAll(");");
+ try f.object.newline();
try operand_mat.end(f, inst);
if (f.liveness.isUnused(inst)) {
@@ -6916,24 +7023,25 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
ty;
const inst_ty = f.typeOfIndex(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- try writer.writeAll("zig_atomic_load(");
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(", (zig_atomic(");
- try f.renderType(writer, ty);
- try writer.writeByte(')');
- if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
- try writer.writeAll(" *)");
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll(", ");
- try writeMemoryOrder(writer, atomic_load.order);
- try writer.writeAll(", ");
- try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeAll(", ");
- try f.renderType(writer, repr_ty);
- try writer.writeAll(");\n");
+ try w.writeAll("zig_atomic_load(");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", (zig_atomic(");
+ try f.renderType(w, ty);
+ try w.writeByte(')');
+ if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
+ try w.writeAll(" *)");
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeAll(", ");
+ try writeMemoryOrder(w, atomic_load.order);
+ try w.writeAll(", ");
+ try f.object.dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeAll(", ");
+ try f.renderType(w, repr_ty);
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -6947,7 +7055,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
const ptr = try f.resolveInst(bin_op.lhs);
const element = try f.resolveInst(bin_op.rhs);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const element_mat = try Materialize.start(f, inst, ty, element);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
@@ -6956,31 +7064,32 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
else
ty;
- try writer.writeAll("zig_atomic_store((zig_atomic(");
- try f.renderType(writer, ty);
- try writer.writeByte(')');
- if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
- try writer.writeAll(" *)");
- try f.writeCValue(writer, ptr, .Other);
- try writer.writeAll(", ");
- try element_mat.mat(f, writer);
- try writer.print(", {s}, ", .{order});
- try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
- try writer.writeAll(", ");
- try f.renderType(writer, repr_ty);
- try writer.writeAll(");\n");
+ try w.writeAll("zig_atomic_store((zig_atomic(");
+ try f.renderType(w, ty);
+ try w.writeByte(')');
+ if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile");
+ try w.writeAll(" *)");
+ try f.writeCValue(w, ptr, .Other);
+ try w.writeAll(", ");
+ try element_mat.mat(f, w);
+ try w.print(", {s}, ", .{order});
+ try f.object.dg.renderTypeForBuiltinFnName(w, ty);
+ try w.writeAll(", ");
+ try f.renderType(w, repr_ty);
+ try w.writeAll(");");
+ try f.object.newline();
try element_mat.end(f, inst);
return .none;
}
-fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {
+fn writeSliceOrPtr(f: *Function, w: *Writer, ptr: CValue, ptr_ty: Type) !void {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
if (ptr_ty.isSlice(zcu)) {
- try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
+ try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" });
} else {
- try f.writeCValue(writer, ptr, .FunctionArgument);
+ try f.writeCValue(w, ptr, .FunctionArgument);
}
}
@@ -6994,7 +7103,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
const elem_ty = f.typeOf(bin_op.rhs);
const elem_abi_size = elem_ty.abiSize(zcu);
const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndefDeep(zcu) else false;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (val_is_undef) {
if (!safety) {
@@ -7002,24 +7111,25 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
return .none;
}
- try writer.writeAll("memset(");
+ try w.writeAll("memset(");
switch (dest_ty.ptrSize(zcu)) {
.slice => {
- try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
- try writer.writeAll(", 0xaa, ");
- try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
+ try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" });
+ try w.writeAll(", 0xaa, ");
+ try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
if (elem_abi_size > 1) {
- try writer.print(" * {d});\n", .{elem_abi_size});
- } else {
- try writer.writeAll(");\n");
+ try w.print(" * {d}", .{elem_abi_size});
}
+ try w.writeAll(");");
+ try f.object.newline();
},
.one => {
const array_ty = dest_ty.childType(zcu);
const len = array_ty.arrayLen(zcu) * elem_abi_size;
- try f.writeCValue(writer, dest_slice, .FunctionArgument);
- try writer.print(", 0xaa, {d});\n", .{len});
+ try f.writeCValue(w, dest_slice, .FunctionArgument);
+ try w.print(", 0xaa, {d});", .{len});
+ try f.object.newline();
},
.many, .c => unreachable,
}
@@ -7040,38 +7150,38 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
const index = try f.allocLocal(inst, .usize);
- try writer.writeAll("for (");
- try f.writeCValue(writer, index, .Other);
- try writer.writeAll(" = ");
- try f.object.dg.renderValue(writer, .zero_usize, .Other);
- try writer.writeAll("; ");
- try f.writeCValue(writer, index, .Other);
- try writer.writeAll(" != ");
+ try w.writeAll("for (");
+ try f.writeCValue(w, index, .Other);
+ try w.writeAll(" = ");
+ try f.object.dg.renderValue(w, .zero_usize, .Other);
+ try w.writeAll("; ");
+ try f.writeCValue(w, index, .Other);
+ try w.writeAll(" != ");
switch (dest_ty.ptrSize(zcu)) {
.slice => {
- try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
+ try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
},
.one => {
const array_ty = dest_ty.childType(zcu);
- try writer.print("{d}", .{array_ty.arrayLen(zcu)});
+ try w.print("{d}", .{array_ty.arrayLen(zcu)});
},
.many, .c => unreachable,
}
- try writer.writeAll("; ++");
- try f.writeCValue(writer, index, .Other);
- try writer.writeAll(") ");
-
- const a = try Assignment.start(f, writer, try f.ctypeFromType(elem_ty, .complete));
- try writer.writeAll("((");
- try f.renderType(writer, elem_ptr_ty);
- try writer.writeByte(')');
- try writeSliceOrPtr(f, writer, dest_slice, dest_ty);
- try writer.writeAll(")[");
- try f.writeCValue(writer, index, .Other);
- try writer.writeByte(']');
- try a.assign(f, writer);
- try f.writeCValue(writer, value, .Other);
- try a.end(f, writer);
+ try w.writeAll("; ++");
+ try f.writeCValue(w, index, .Other);
+ try w.writeAll(") ");
+
+ const a = try Assignment.start(f, w, try f.ctypeFromType(elem_ty, .complete));
+ try w.writeAll("((");
+ try f.renderType(w, elem_ptr_ty);
+ try w.writeByte(')');
+ try writeSliceOrPtr(f, w, dest_slice, dest_ty);
+ try w.writeAll(")[");
+ try f.writeCValue(w, index, .Other);
+ try w.writeByte(']');
+ try a.assign(f, w);
+ try f.writeCValue(w, value, .Other);
+ try a.end(f, w);
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
try freeLocal(f, inst, index.new_local, null);
@@ -7081,24 +7191,26 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
const bitcasted = try bitcast(f, .u8, value, elem_ty);
- try writer.writeAll("memset(");
+ try w.writeAll("memset(");
switch (dest_ty.ptrSize(zcu)) {
.slice => {
- try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
- try writer.writeAll(", ");
- try f.writeCValue(writer, bitcasted, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
- try writer.writeAll(");\n");
+ try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" });
+ try w.writeAll(", ");
+ try f.writeCValue(w, bitcasted, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" });
+ try w.writeAll(");");
+ try f.object.newline();
},
.one => {
const array_ty = dest_ty.childType(zcu);
const len = array_ty.arrayLen(zcu) * elem_abi_size;
- try f.writeCValue(writer, dest_slice, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValue(writer, bitcasted, .FunctionArgument);
- try writer.print(", {d});\n", .{len});
+ try f.writeCValue(w, dest_slice, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValue(w, bitcasted, .FunctionArgument);
+ try w.print(", {d});", .{len});
+ try f.object.newline();
},
.many, .c => unreachable,
}
@@ -7115,36 +7227,38 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
const src_ptr = try f.resolveInst(bin_op.rhs);
const dest_ty = f.typeOf(bin_op.lhs);
const src_ty = f.typeOf(bin_op.rhs);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
if (dest_ty.ptrSize(zcu) != .one) {
- try writer.writeAll("if (");
- try writeArrayLen(f, writer, dest_ptr, dest_ty);
- try writer.writeAll(" != 0) ");
- }
- try writer.writeAll(function_paren);
- try writeSliceOrPtr(f, writer, dest_ptr, dest_ty);
- try writer.writeAll(", ");
- try writeSliceOrPtr(f, writer, src_ptr, src_ty);
- try writer.writeAll(", ");
- try writeArrayLen(f, writer, dest_ptr, dest_ty);
- try writer.writeAll(" * sizeof(");
- try f.renderType(writer, dest_ty.elemType2(zcu));
- try writer.writeAll("));\n");
+ try w.writeAll("if (");
+ try writeArrayLen(f, dest_ptr, dest_ty);
+ try w.writeAll(" != 0) ");
+ }
+ try w.writeAll(function_paren);
+ try writeSliceOrPtr(f, w, dest_ptr, dest_ty);
+ try w.writeAll(", ");
+ try writeSliceOrPtr(f, w, src_ptr, src_ty);
+ try w.writeAll(", ");
+ try writeArrayLen(f, dest_ptr, dest_ty);
+ try w.writeAll(" * sizeof(");
+ try f.renderType(w, dest_ty.elemType2(zcu));
+ try w.writeAll("));");
+ try f.object.newline();
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
return .none;
}
-fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void {
+fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
+ const w = &f.object.code.writer;
switch (dest_ty.ptrSize(zcu)) {
- .one => try writer.print("{}", .{
- try f.fmtIntLiteral(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
+ .one => try w.print("{f}", .{
+ try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
}),
.many, .c => unreachable,
- .slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }),
+ .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }),
}
}
@@ -7161,12 +7275,12 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
if (layout.tag_size == 0) return .none;
const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
- const writer = f.object.writer();
- const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));
- try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" });
- try a.assign(f, writer);
- try f.writeCValue(writer, new_tag, .Other);
- try a.end(f, writer);
+ const w = &f.object.code.writer;
+ const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
+ try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" });
+ try a.assign(f, w);
+ try f.writeCValue(w, new_tag, .Other);
+ try a.end(f, w);
return .none;
}
@@ -7183,13 +7297,13 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
if (layout.tag_size == 0) return .none;
const inst_ty = f.typeOfIndex(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try a.assign(f, writer);
- try f.writeCValueMember(writer, operand, .{ .identifier = "tag" });
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try a.assign(f, w);
+ try f.writeCValueMember(w, operand, .{ .identifier = "tag" });
+ try a.end(f, w);
return local;
}
@@ -7201,14 +7315,15 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.print(" = {s}(", .{
+ try f.writeCValue(w, local, .Other);
+ try w.print(" = {s}(", .{
try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }),
});
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(");\n");
+ try f.writeCValue(w, operand, .Other);
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -7216,16 +7331,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const inst_ty = f.typeOfIndex(inst);
const operand = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
+ try f.writeCValue(w, local, .Other);
- try writer.writeAll(" = zig_errorName[");
- try f.writeCValue(writer, operand, .Other);
- try writer.writeAll(" - 1];\n");
+ try w.writeAll(" = zig_errorName[");
+ try f.writeCValue(w, operand, .Other);
+ try w.writeAll(" - 1];");
+ try f.object.newline();
return local;
}
@@ -7240,16 +7356,16 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.typeOfIndex(inst);
const inst_scalar_ty = inst_ty.scalarType(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, inst_ty);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete));
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try a.assign(f, writer);
- try f.writeCValue(writer, operand, .Other);
- try a.end(f, writer);
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, inst_ty);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete));
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try a.assign(f, w);
+ try f.writeCValue(w, operand, .Other);
+ try a.end(f, w);
+ try v.end(f, inst, w);
return local;
}
@@ -7265,22 +7381,23 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.typeOfIndex(inst);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = ");
- try f.writeCValue(writer, pred, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" ? ");
- try f.writeCValue(writer, lhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" : ");
- try f.writeCValue(writer, rhs, .Other);
- try v.elem(f, writer);
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, inst_ty);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, pred, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" ? ");
+ try f.writeCValue(w, lhs, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" : ");
+ try f.writeCValue(w, rhs, .Other);
+ try v.elem(f, w);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
@@ -7294,24 +7411,24 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(unwrapped.operand);
const inst_ty = unwrapped.result_ty;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand
for (mask, 0..) |mask_elem, out_idx| {
- try f.writeCValue(writer, local, .Other);
- try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);
- try writer.writeAll("] = ");
+ try f.writeCValue(w, local, .Other);
+ try w.writeByte('[');
+ try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other);
+ try w.writeAll("] = ");
switch (mask_elem.unwrap()) {
.elem => |src_idx| {
- try f.writeCValue(writer, operand, .Other);
- try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
- try writer.writeByte(']');
+ try f.writeCValue(w, operand, .Other);
+ try w.writeByte('[');
+ try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
+ try w.writeByte(']');
},
- .value => |val| try f.object.dg.renderValue(writer, .fromInterned(val), .Other),
+ .value => |val| try f.object.dg.renderValue(w, .fromInterned(val), .Other),
}
- try writer.writeAll(";\n");
+ try w.writeAll(";\n");
}
return local;
@@ -7328,30 +7445,31 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = unwrapped.result_ty;
const elem_ty = inst_ty.childType(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands
for (mask, 0..) |mask_elem, out_idx| {
- try f.writeCValue(writer, local, .Other);
- try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other);
- try writer.writeAll("] = ");
+ try f.writeCValue(w, local, .Other);
+ try w.writeByte('[');
+ try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other);
+ try w.writeAll("] = ");
switch (mask_elem.unwrap()) {
.a_elem => |src_idx| {
- try f.writeCValue(writer, operand_a, .Other);
- try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
- try writer.writeByte(']');
+ try f.writeCValue(w, operand_a, .Other);
+ try w.writeByte('[');
+ try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
+ try w.writeByte(']');
},
.b_elem => |src_idx| {
- try f.writeCValue(writer, operand_b, .Other);
- try writer.writeByte('[');
- try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other);
- try writer.writeByte(']');
+ try f.writeCValue(w, operand_b, .Other);
+ try w.writeByte('[');
+ try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other);
+ try w.writeByte(']');
},
- .undef => try f.object.dg.renderUndefValue(writer, elem_ty, .Other),
+ .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other),
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
}
return local;
@@ -7366,7 +7484,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(reduce.operand);
try reap(f, inst, &.{reduce.operand});
const operand_ty = f.typeOf(reduce.operand);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const use_operator = scalar_ty.bitSize(zcu) <= 64;
const op: union(enum) {
@@ -7413,10 +7531,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
// }
const accum = try f.allocLocal(inst, scalar_ty);
- try f.writeCValue(writer, accum, .Other);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, accum, .Other);
+ try w.writeAll(" = ");
- try f.object.dg.renderValue(writer, switch (reduce.operation) {
+ try f.object.dg.renderValue(w, switch (reduce.operation) {
.Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
.bool => Value.false,
.int => try pt.intValue(scalar_ty, 0),
@@ -7453,42 +7571,44 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
else => unreachable,
},
}, .Other);
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
- const v = try Vectorize.start(f, inst, writer, operand_ty);
- try f.writeCValue(writer, accum, .Other);
+ const v = try Vectorize.start(f, inst, w, operand_ty);
+ try f.writeCValue(w, accum, .Other);
switch (op) {
.builtin => |func| {
- try writer.print(" = zig_{s}_", .{func.operation});
- try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
- try writer.writeByte('(');
- try f.writeCValue(writer, accum, .FunctionArgument);
- try writer.writeAll(", ");
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
- try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info);
- try writer.writeByte(')');
+ try w.print(" = zig_{s}_", .{func.operation});
+ try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
+ try w.writeByte('(');
+ try f.writeCValue(w, accum, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
+ try f.object.dg.renderBuiltinInfo(w, scalar_ty, func.info);
+ try w.writeByte(')');
},
.infix => |ass| {
- try writer.writeAll(ass);
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
+ try w.writeAll(ass);
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
},
.ternary => |cmp| {
- try writer.writeAll(" = ");
- try f.writeCValue(writer, accum, .Other);
- try writer.writeAll(cmp);
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" ? ");
- try f.writeCValue(writer, accum, .Other);
- try writer.writeAll(" : ");
- try f.writeCValue(writer, operand, .Other);
- try v.elem(f, writer);
+ try w.writeAll(" = ");
+ try f.writeCValue(w, accum, .Other);
+ try w.writeAll(cmp);
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" ? ");
+ try f.writeCValue(w, accum, .Other);
+ try w.writeAll(" : ");
+ try f.writeCValue(w, operand, .Other);
+ try v.elem(f, w);
},
}
- try writer.writeAll(";\n");
- try v.end(f, inst, writer);
+ try w.writeByte(';');
+ try f.object.newline();
+ try v.end(f, inst, w);
return accum;
}
@@ -7514,7 +7634,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
}
}
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
switch (ip.indexToKey(inst_ty.toIntern())) {
inline .array_type, .vector_type => |info, tag| {
@@ -7522,20 +7642,20 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
.ctype = try f.ctypeFromType(.fromInterned(info.child), .complete),
};
for (resolved_elements, 0..) |element, i| {
- try a.restart(f, writer);
- try f.writeCValue(writer, local, .Other);
- try writer.print("[{d}]", .{i});
- try a.assign(f, writer);
- try f.writeCValue(writer, element, .Other);
- try a.end(f, writer);
+ try a.restart(f, w);
+ try f.writeCValue(w, local, .Other);
+ try w.print("[{d}]", .{i});
+ try a.assign(f, w);
+ try f.writeCValue(w, element, .Other);
+ try a.end(f, w);
}
if (tag == .array_type and info.sentinel != .none) {
- try a.restart(f, writer);
- try f.writeCValue(writer, local, .Other);
- try writer.print("[{d}]", .{info.len});
- try a.assign(f, writer);
- try f.object.dg.renderValue(writer, Value.fromInterned(info.sentinel), .Other);
- try a.end(f, writer);
+ try a.restart(f, w);
+ try f.writeCValue(w, local, .Other);
+ try w.print("[{d}]", .{info.len});
+ try a.assign(f, w);
+ try f.object.dg.renderValue(w, Value.fromInterned(info.sentinel), .Other);
+ try a.end(f, w);
}
},
.struct_type => {
@@ -7547,19 +7667,19 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));
- try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
+ const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete));
+ try f.writeCValueMember(w, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name|
.{ .identifier = field_name.toSlice(ip) }
else
.{ .field = field_index });
- try a.assign(f, writer);
- try f.writeCValue(writer, resolved_elements[field_index], .Other);
- try a.end(f, writer);
+ try a.assign(f, w);
+ try f.writeCValue(w, resolved_elements[field_index], .Other);
+ try a.end(f, w);
}
},
.@"packed" => {
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = ");
const backing_int_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip));
const int_info = backing_int_ty.intInfo(zcu);
@@ -7575,9 +7695,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
if (!empty) {
- try writer.writeAll("zig_or_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_or_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
+ try w.writeByte('(');
}
empty = false;
}
@@ -7587,57 +7707,58 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const field_ty = inst_ty.fieldType(field_index, zcu);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- if (!empty) try writer.writeAll(", ");
+ if (!empty) try w.writeAll(", ");
// TODO: Skip this entire shift if val is 0?
- try writer.writeAll("zig_shlw_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_shlw_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
+ try w.writeByte('(');
if (field_ty.isAbiInt(zcu)) {
- try writer.writeAll("zig_and_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
- try writer.writeByte('(');
+ try w.writeAll("zig_and_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, inst_ty);
+ try w.writeByte('(');
}
if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) {
- try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
+ try f.renderIntCast(w, inst_ty, element, .{}, field_ty, .FunctionArgument);
} else {
- try writer.writeByte('(');
- try f.renderType(writer, inst_ty);
- try writer.writeByte(')');
+ try w.writeByte('(');
+ try f.renderType(w, inst_ty);
+ try w.writeByte(')');
if (field_ty.isPtrAtRuntime(zcu)) {
- try writer.writeByte('(');
- try f.renderType(writer, switch (int_info.signedness) {
+ try w.writeByte('(');
+ try f.renderType(w, switch (int_info.signedness) {
.unsigned => .usize,
.signed => .isize,
});
- try writer.writeByte(')');
+ try w.writeByte(')');
}
- try f.writeCValue(writer, element, .Other);
+ try f.writeCValue(w, element, .Other);
}
if (field_ty.isAbiInt(zcu)) {
- try writer.writeAll(", ");
+ try w.writeAll(", ");
const field_int_info = field_ty.intInfo(zcu);
const field_mask = if (int_info.signedness == .signed and int_info.bits == field_int_info.bits)
try pt.intValue(backing_int_ty, -1)
else
try (try pt.intType(.unsigned, field_int_info.bits)).maxIntScalar(pt, backing_int_ty);
- try f.object.dg.renderValue(writer, field_mask, .FunctionArgument);
- try writer.writeByte(')');
+ try f.object.dg.renderValue(w, field_mask, .FunctionArgument);
+ try w.writeByte(')');
}
- try writer.print(", {}", .{
- try f.fmtIntLiteral(try pt.intValue(bit_offset_ty, bit_offset)),
+ try w.print(", {f}", .{
+ try f.fmtIntLiteralDec(try pt.intValue(bit_offset_ty, bit_offset)),
});
- try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
- try writer.writeByte(')');
- if (!empty) try writer.writeByte(')');
+ try f.object.dg.renderBuiltinInfo(w, inst_ty, .bits);
+ try w.writeByte(')');
+ if (!empty) try w.writeByte(')');
bit_offset += field_ty.bitSize(zcu);
empty = false;
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
},
}
},
@@ -7646,11 +7767,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
- const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .field = field_index });
- try a.assign(f, writer);
- try f.writeCValue(writer, resolved_elements[field_index], .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .field = field_index });
+ try a.assign(f, w);
+ try f.writeCValue(w, resolved_elements[field_index], .Other);
+ try a.end(f, w);
},
else => unreachable,
}
@@ -7672,7 +7793,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
const payload = try f.resolveInst(extra.init);
try reap(f, inst, &.{extra.init});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, union_ty);
if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload);
@@ -7682,20 +7803,20 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
- const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete));
- try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
- try a.assign(f, writer);
- try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, pt))});
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete));
+ try f.writeCValueMember(w, local, .{ .identifier = "tag" });
+ try a.assign(f, w);
+ try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))});
+ try a.end(f, w);
}
break :field .{ .payload_identifier = field_name.toSlice(ip) };
} else .{ .identifier = field_name.toSlice(ip) };
- const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete));
- try f.writeCValueMember(writer, local, field);
- try a.assign(f, writer);
- try f.writeCValue(writer, payload, .Other);
- try a.end(f, writer);
+ const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete));
+ try f.writeCValueMember(w, local, field);
+ try a.assign(f, w);
+ try f.writeCValue(w, payload, .Other);
+ try a.end(f, w);
return local;
}
@@ -7708,15 +7829,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
const ptr = try f.resolveInst(prefetch.ptr);
try reap(f, inst, &.{prefetch.ptr});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
switch (prefetch.cache) {
.data => {
- try writer.writeAll("zig_prefetch(");
+ try w.writeAll("zig_prefetch(");
if (ptr_ty.isSlice(zcu))
- try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" })
+ try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" })
else
- try f.writeCValue(writer, ptr, .FunctionArgument);
- try writer.print(", {d}, {d});\n", .{ @intFromEnum(prefetch.rw), prefetch.locality });
+ try f.writeCValue(w, ptr, .FunctionArgument);
+ try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality });
+ try f.object.newline();
},
// The available prefetch intrinsics do not accept a cache argument; only
// address, rw, and locality.
@@ -7729,13 +7851,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const inst_ty = f.typeOfIndex(inst);
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
+ try f.writeCValue(w, local, .Other);
- try writer.writeAll(" = ");
- try writer.print("zig_wasm_memory_size({d});\n", .{pl_op.payload});
+ try w.writeAll(" = ");
+ try w.print("zig_wasm_memory_size({d});", .{pl_op.payload});
+ try f.object.newline();
return local;
}
@@ -7743,17 +7866,18 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const inst_ty = f.typeOfIndex(inst);
const operand = try f.resolveInst(pl_op.operand);
try reap(f, inst, &.{pl_op.operand});
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
+ try f.writeCValue(w, local, .Other);
- try writer.writeAll(" = ");
- try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
- try f.writeCValue(writer, operand, .FunctionArgument);
- try writer.writeAll(");\n");
+ try w.writeAll(" = ");
+ try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
+ try f.writeCValue(w, operand, .FunctionArgument);
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -7771,36 +7895,38 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.typeOfIndex(inst);
const inst_scalar_ty = inst_ty.scalarType(zcu);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- const v = try Vectorize.start(f, inst, writer, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try v.elem(f, writer);
- try writer.writeAll(" = zig_fma_");
- try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
- try writer.writeByte('(');
- try f.writeCValue(writer, mulend1, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- try f.writeCValue(writer, mulend2, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(", ");
- try f.writeCValue(writer, addend, .FunctionArgument);
- try v.elem(f, writer);
- try writer.writeAll(");\n");
- try v.end(f, inst, writer);
+ const v = try Vectorize.start(f, inst, w, inst_ty);
+ try f.writeCValue(w, local, .Other);
+ try v.elem(f, w);
+ try w.writeAll(" = zig_fma_");
+ try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty);
+ try w.writeByte('(');
+ try f.writeCValue(w, mulend1, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ try f.writeCValue(w, mulend2, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(", ");
+ try f.writeCValue(w, addend, .FunctionArgument);
+ try v.elem(f, w);
+ try w.writeAll(");");
+ try f.object.newline();
+ try v.end(f, inst, w);
return local;
}
fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav;
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty));
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = ");
- try f.object.dg.renderNav(writer, ty_nav.nav, .Other);
- try writer.writeAll(";\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = ");
+ try f.object.dg.renderNav(w, ty_nav.nav, .Other);
+ try w.writeByte(';');
+ try f.object.newline();
return local;
}
@@ -7812,15 +7938,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function;
assert(function_info.varargs);
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- try writer.writeAll("va_start(*(va_list *)&");
- try f.writeCValue(writer, local, .Other);
+ try w.writeAll("va_start(*(va_list *)&");
+ try f.writeCValue(w, local, .Other);
if (function_info.param_ctypes.len > 0) {
- try writer.writeAll(", ");
- try f.writeCValue(writer, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);
+ try w.writeAll(", ");
+ try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument);
}
- try writer.writeAll(");\n");
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -7831,14 +7958,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
const va_list = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(" = va_arg(*(va_list *)");
- try f.writeCValue(writer, va_list, .Other);
- try writer.writeAll(", ");
- try f.renderType(writer, ty_op.ty.toType());
- try writer.writeAll(");\n");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(" = va_arg(*(va_list *)");
+ try f.writeCValue(w, va_list, .Other);
+ try w.writeAll(", ");
+ try f.renderType(w, ty_op.ty.toType());
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -7848,10 +7976,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
const va_list = try f.resolveInst(un_op);
try reap(f, inst, &.{un_op});
- const writer = f.object.writer();
- try writer.writeAll("va_end(*(va_list *)");
- try f.writeCValue(writer, va_list, .Other);
- try writer.writeAll(");\n");
+ const w = &f.object.code.writer;
+ try w.writeAll("va_end(*(va_list *)");
+ try f.writeCValue(w, va_list, .Other);
+ try w.writeAll(");");
+ try f.object.newline();
return .none;
}
@@ -7862,13 +7991,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
const va_list = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
- const writer = f.object.writer();
+ const w = &f.object.code.writer;
const local = try f.allocLocal(inst, inst_ty);
- try writer.writeAll("va_copy(*(va_list *)&");
- try f.writeCValue(writer, local, .Other);
- try writer.writeAll(", *(va_list *)");
- try f.writeCValue(writer, va_list, .Other);
- try writer.writeAll(");\n");
+ try w.writeAll("va_copy(*(va_list *)&");
+ try f.writeCValue(w, local, .Other);
+ try w.writeAll(", *(va_list *)");
+ try f.writeCValue(w, va_list, .Other);
+ try w.writeAll(");");
+ try f.object.newline();
return local;
}
@@ -7883,7 +8013,7 @@ fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
};
}
-fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void {
+fn writeMemoryOrder(w: *Writer, order: std.builtin.AtomicOrder) !void {
return w.writeAll(toMemoryOrder(order));
}
@@ -7970,93 +8100,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {
};
}
-const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error);
-
-fn arrayListWriter(list: *std.ArrayList(u8)) ArrayListWriter {
- return .{ .context = .{
- .context = list,
- .writeFn = struct {
- fn write(context: *const anyopaque, bytes: []const u8) anyerror!usize {
- const l: *std.ArrayList(u8) = @alignCast(@constCast(@ptrCast(context)));
- return l.writer().write(bytes);
- }
- }.write,
- } };
-}
-
-fn IndentWriter(comptime UnderlyingWriter: type) type {
- return struct {
- const Self = @This();
- pub const Error = UnderlyingWriter.Error;
- pub const Writer = ErrorOnlyGenericWriter(Error);
-
- pub const indent_delta = 1;
-
- underlying_writer: UnderlyingWriter,
- indent_count: usize = 0,
- current_line_empty: bool = true,
-
- pub fn writer(self: *Self) Writer {
- return .{ .context = .{
- .context = self,
- .writeFn = writeAny,
- } };
- }
-
- pub fn write(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0) return 0;
-
- const current_indent = self.indent_count * Self.indent_delta;
- if (self.current_line_empty and current_indent > 0) {
- try self.underlying_writer.writeByteNTimes(' ', current_indent);
- }
- self.current_line_empty = false;
-
- return self.writeNoIndent(bytes);
- }
-
- fn writeAny(context: *const anyopaque, bytes: []const u8) anyerror!usize {
- const self: *Self = @alignCast(@constCast(@ptrCast(context)));
- return self.write(bytes);
- }
-
- pub fn insertNewline(self: *Self) Error!void {
- _ = try self.writeNoIndent("\n");
- }
-
- pub fn pushIndent(self: *Self) void {
- self.indent_count += 1;
- }
-
- pub fn popIndent(self: *Self) void {
- assert(self.indent_count != 0);
- self.indent_count -= 1;
- }
-
- fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0) return 0;
-
- try self.underlying_writer.writeAll(bytes);
- if (bytes[bytes.len - 1] == '\n') {
- self.current_line_empty = true;
- }
- return bytes.len;
- }
- };
-}
-
-/// A wrapper around `std.io.AnyWriter` that maintains a generic error set while
-/// erasing the rest of the implementation. This is intended to avoid duplicate
-/// generic instantiations for writer types which share the same error set, while
-/// maintaining ease of error handling.
-fn ErrorOnlyGenericWriter(comptime Error: type) type {
- return std.io.GenericWriter(std.io.AnyWriter, Error, struct {
- fn write(context: std.io.AnyWriter, bytes: []const u8) Error!usize {
- return @errorCast(context.write(bytes));
- }
- }.write);
-}
-
fn toCIntBits(zig_bits: u32) ?u32 {
for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {
if (zig_bits <= c_bits) {
@@ -8111,7 +8154,12 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 {
};
}
-fn StringLiteral(comptime WriterType: type) type {
+const StringLiteral = struct {
+ len: usize,
+ cur_len: usize,
+ w: *Writer,
+ first: bool,
+
// MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal,
// regardless of the length of the string literal initializing it. Array initializer syntax is
// used instead.
@@ -8123,99 +8171,116 @@ fn StringLiteral(comptime WriterType: type) type {
const max_char_len = 4;
const max_literal_len = @min(16380 - max_char_len, 4095);
- return struct {
- len: u64,
- cur_len: u64 = 0,
- counting_writer: std.io.CountingWriter(WriterType),
-
- pub const Error = WriterType.Error;
-
- const Self = @This();
+ fn init(w: *Writer, len: usize) StringLiteral {
+ return .{
+ .cur_len = 0,
+ .len = len,
+ .w = w,
+ .first = true,
+ };
+ }
- pub fn start(self: *Self) Error!void {
- const writer = self.counting_writer.writer();
- if (self.len <= max_string_initializer_len) {
- try writer.writeByte('\"');
- } else {
- try writer.writeByte('{');
- }
+ pub fn start(sl: *StringLiteral) Writer.Error!void {
+ if (sl.len <= max_string_initializer_len) {
+ try sl.w.writeByte('\"');
+ } else {
+ try sl.w.writeByte('{');
}
+ }
- pub fn end(self: *Self) Error!void {
- const writer = self.counting_writer.writer();
- if (self.len <= max_string_initializer_len) {
- try writer.writeByte('\"');
- } else {
- try writer.writeByte('}');
- }
+ pub fn end(sl: *StringLiteral) Writer.Error!void {
+ if (sl.len <= max_string_initializer_len) {
+ try sl.w.writeByte('\"');
+ } else {
+ try sl.w.writeByte('}');
}
+ }
- fn writeStringLiteralChar(writer: anytype, c: u8) !void {
- switch (c) {
- 7 => try writer.writeAll("\\a"),
- 8 => try writer.writeAll("\\b"),
- '\t' => try writer.writeAll("\\t"),
- '\n' => try writer.writeAll("\\n"),
- 11 => try writer.writeAll("\\v"),
- 12 => try writer.writeAll("\\f"),
- '\r' => try writer.writeAll("\\r"),
- '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}),
- else => switch (c) {
- ' '...'~' => try writer.writeByte(c),
- else => try writer.print("\\{o:0>3}", .{c}),
- },
- }
+ fn writeStringLiteralChar(sl: *StringLiteral, c: u8) Writer.Error!usize {
+ const w = sl.w;
+ switch (c) {
+ 7 => {
+ try w.writeAll("\\a");
+ return 2;
+ },
+ 8 => {
+ try w.writeAll("\\b");
+ return 2;
+ },
+ '\t' => {
+ try w.writeAll("\\t");
+ return 2;
+ },
+ '\n' => {
+ try w.writeAll("\\n");
+ return 2;
+ },
+ 11 => {
+ try w.writeAll("\\v");
+ return 2;
+ },
+ 12 => {
+ try w.writeAll("\\f");
+ return 2;
+ },
+ '\r' => {
+ try w.writeAll("\\r");
+ return 2;
+ },
+ '"', '\'', '?', '\\' => {
+ try w.print("\\{c}", .{c});
+ return 2;
+ },
+ ' '...'!', '#'...'&', '('...'>', '@'...'[', ']'...'~' => {
+ try w.writeByte(c);
+ return 1;
+ },
+ else => {
+ var buf: [4]u8 = undefined;
+ const printed = std.fmt.bufPrint(&buf, "\\{o:0>3}", .{c}) catch unreachable;
+ try w.writeAll(printed);
+ return printed.len;
+ },
}
+ }
- pub fn writeChar(self: *Self, c: u8) Error!void {
- const writer = self.counting_writer.writer();
- if (self.len <= max_string_initializer_len) {
- if (self.cur_len == 0 and self.counting_writer.bytes_written > 1)
- try writer.writeAll("\"\"");
-
- const len = self.counting_writer.bytes_written;
- try writeStringLiteralChar(writer, c);
+ pub fn writeChar(sl: *StringLiteral, c: u8) Writer.Error!void {
+ if (sl.len <= max_string_initializer_len) {
+ if (sl.cur_len == 0 and !sl.first) try sl.w.writeAll("\"\"");
- const char_length = self.counting_writer.bytes_written - len;
- assert(char_length <= max_char_len);
- self.cur_len += char_length;
+ const char_len = try sl.writeStringLiteralChar(c);
+ assert(char_len <= max_char_len);
+ sl.cur_len += char_len;
- if (self.cur_len >= max_literal_len) self.cur_len = 0;
- } else {
- if (self.counting_writer.bytes_written > 1) try writer.writeByte(',');
- try writer.print("'\\x{x}'", .{c});
+ if (sl.cur_len >= max_literal_len) {
+ sl.cur_len = 0;
+ sl.first = false;
}
+ } else {
+ if (!sl.first) try sl.w.writeByte(',');
+ var buf: [6]u8 = undefined;
+ const printed = std.fmt.bufPrint(&buf, "'\\x{x}'", .{c}) catch unreachable;
+ try sl.w.writeAll(printed);
+ sl.cur_len += printed.len;
+ sl.first = false;
}
- };
-}
-
-fn stringLiteral(
- child_stream: anytype,
- len: u64,
-) StringLiteral(@TypeOf(child_stream)) {
- return .{
- .len = len,
- .counting_writer = std.io.countingWriter(child_stream),
- };
-}
+ }
+};
-const FormatStringContext = struct { str: []const u8, sentinel: ?u8 };
-fn formatStringLiteral(
- data: FormatStringContext,
- comptime fmt: []const u8,
- _: std.fmt.FormatOptions,
- writer: anytype,
-) @TypeOf(writer).Error!void {
- if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);
+const FormatStringContext = struct {
+ str: []const u8,
+ sentinel: ?u8,
+};
- var literal = stringLiteral(writer, data.str.len + @intFromBool(data.sentinel != null));
+fn formatStringLiteral(data: FormatStringContext, w: *std.io.Writer) std.io.Writer.Error!void {
+ var literal: StringLiteral = .init(w, data.str.len + @intFromBool(data.sentinel != null));
try literal.start();
for (data.str) |c| try literal.writeChar(c);
if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel);
try literal.end();
}
-fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(formatStringLiteral) {
+fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(FormatStringContext, formatStringLiteral) {
return .{ .data = .{ .str = str, .sentinel = sentinel } };
}
@@ -8231,13 +8296,10 @@ const FormatIntLiteralContext = struct {
kind: CType.Kind,
ctype: CType,
val: Value,
+ base: u8,
+ case: std.fmt.Case,
};
-fn formatIntLiteral(
- data: FormatIntLiteralContext,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- writer: anytype,
-) @TypeOf(writer).Error!void {
+fn formatIntLiteral(data: FormatIntLiteralContext, w: *std.io.Writer) std.io.Writer.Error!void {
const pt = data.dg.pt;
const zcu = pt.zcu;
const target = &data.dg.mod.resolved_target.result;
@@ -8262,7 +8324,7 @@ fn formatIntLiteral(
var int_buf: Value.BigIntSpace = undefined;
const int = if (data.val.isUndefDeep(zcu)) blk: {
- undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
+ undef_limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)) catch return error.WriteFailed;
@memset(undef_limbs, undefPattern(BigIntLimb));
var undef_int = BigInt.Mutable{
@@ -8280,7 +8342,7 @@ fn formatIntLiteral(
const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
var wrap = BigInt.Mutable{
- .limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)),
+ .limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)) catch return error.WriteFailed,
.len = undefined,
.positive = undefined,
};
@@ -8317,46 +8379,29 @@ fn formatIntLiteral(
if (c_limb_info.count == 1) {
if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or
data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits))
- return writer.print("{s}_{s}", .{
- data.ctype.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{
+ return w.print("{s}_{s}", .{
+ data.ctype.getStandardDefineAbbrev() orelse return w.print("zig_{s}Int_{c}{d}", .{
if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits,
}),
if (int.positive) "MAX" else "MIN",
});
- if (!int.positive) try writer.writeByte('-');
- try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool);
+ if (!int.positive) try w.writeByte('-');
+ try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool);
- const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) {
- 0 => .{ .base = 10 },
- 1 => switch (fmt[0]) {
- 'b' => style: {
- try writer.writeAll("0b");
- break :style .{ .base = 2 };
- },
- 'o' => style: {
- try writer.writeByte('0');
- break :style .{ .base = 8 };
- },
- 'd' => .{ .base = 10 },
- 'x', 'X' => |base| style: {
- try writer.writeAll("0x");
- break :style .{ .base = 16, .case = switch (base) {
- 'x' => .lower,
- 'X' => .upper,
- else => unreachable,
- } };
- },
- else => @compileError("Invalid fmt: " ++ fmt),
- },
- else => @compileError("Invalid fmt: " ++ fmt),
- };
-
- const string = try int.abs().toStringAlloc(allocator, style.base, style.case);
+ switch (data.base) {
+ 2 => try w.writeAll("0b"),
+ 8 => try w.writeByte('0'),
+ 10 => {},
+ 16 => try w.writeAll("0x"),
+ else => unreachable,
+ }
+ const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch
+ return error.WriteFailed;
defer allocator.free(string);
- try writer.writeAll(string);
+ try w.writeAll(string);
} else {
- try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool);
+ try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool);
wrap.truncate(int, .unsigned, c_bits);
@memset(wrap.limbs[wrap.len..], 0);
wrap.len = wrap.limbs.len;
@@ -8399,17 +8444,20 @@ fn formatIntLiteral(
c_limb_ctype = c_limb_info.ctype;
}
- if (limb_offset > 0) try writer.writeAll(", ");
+ if (limb_offset > 0) try w.writeAll(", ");
try formatIntLiteral(.{
.dg = data.dg,
.int_info = c_limb_int_info,
.kind = data.kind,
.ctype = c_limb_ctype,
- .val = try pt.intValue_big(.comptime_int, c_limb_mut.toConst()),
- }, fmt, options, writer);
+ .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch
+ return error.WriteFailed,
+ .base = data.base,
+ .case = data.case,
+ }, w);
}
}
- try data.ctype.renderLiteralSuffix(writer, ctype_pool);
+ try data.ctype.renderLiteralSuffix(w, ctype_pool);
}
const Materialize = struct {
@@ -8423,8 +8471,8 @@ const Materialize = struct {
} };
}
- pub fn mat(self: Materialize, f: *Function, writer: anytype) !void {
- try f.writeCValue(writer, self.local, .Other);
+ pub fn mat(self: Materialize, f: *Function, w: *Writer) !void {
+ try f.writeCValue(w, self.local, .Other);
}
pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void {
@@ -8435,36 +8483,37 @@ const Materialize = struct {
const Assignment = struct {
ctype: CType,
- pub fn start(f: *Function, writer: anytype, ctype: CType) !Assignment {
+ pub fn start(f: *Function, w: *Writer, ctype: CType) !Assignment {
const self: Assignment = .{ .ctype = ctype };
- try self.restart(f, writer);
+ try self.restart(f, w);
return self;
}
- pub fn restart(self: Assignment, f: *Function, writer: anytype) !void {
+ pub fn restart(self: Assignment, f: *Function, w: *Writer) !void {
switch (self.strategy(f)) {
.assign => {},
- .memcpy => try writer.writeAll("memcpy("),
+ .memcpy => try w.writeAll("memcpy("),
}
}
- pub fn assign(self: Assignment, f: *Function, writer: anytype) !void {
+ pub fn assign(self: Assignment, f: *Function, w: *Writer) !void {
switch (self.strategy(f)) {
- .assign => try writer.writeAll(" = "),
- .memcpy => try writer.writeAll(", "),
+ .assign => try w.writeAll(" = "),
+ .memcpy => try w.writeAll(", "),
}
}
- pub fn end(self: Assignment, f: *Function, writer: anytype) !void {
+ pub fn end(self: Assignment, f: *Function, w: *Writer) !void {
switch (self.strategy(f)) {
.assign => {},
.memcpy => {
- try writer.writeAll(", sizeof(");
- try f.renderCType(writer, self.ctype);
- try writer.writeAll("))");
+ try w.writeAll(", sizeof(");
+ try f.renderCType(w, self.ctype);
+ try w.writeAll("))");
},
}
- try writer.writeAll(";\n");
+ try w.writeByte(';');
+ try f.object.newline();
}
fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } {
@@ -8478,37 +8527,39 @@ const Assignment = struct {
const Vectorize = struct {
index: CValue = .none,
- pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
+ pub fn start(f: *Function, inst: Air.Inst.Index, w: *Writer, ty: Type) !Vectorize {
const pt = f.object.dg.pt;
const zcu = pt.zcu;
return if (ty.zigTypeTag(zcu) == .vector) index: {
const local = try f.allocLocal(inst, .usize);
- try writer.writeAll("for (");
- try f.writeCValue(writer, local, .Other);
- try writer.print(" = {d}; ", .{try f.fmtIntLiteral(.zero_usize)});
- try f.writeCValue(writer, local, .Other);
- try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, ty.vectorLen(zcu)))});
- try f.writeCValue(writer, local, .Other);
- try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(.one_usize)});
- f.object.indent_writer.pushIndent();
+ try w.writeAll("for (");
+ try f.writeCValue(w, local, .Other);
+ try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)});
+ try f.writeCValue(w, local, .Other);
+ try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))});
+ try f.writeCValue(w, local, .Other);
+ try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)});
+ f.object.indent();
+ try f.object.newline();
break :index .{ .index = local };
} else .{};
}
- pub fn elem(self: Vectorize, f: *Function, writer: anytype) !void {
+ pub fn elem(self: Vectorize, f: *Function, w: *Writer) !void {
if (self.index != .none) {
- try writer.writeByte('[');
- try f.writeCValue(writer, self.index, .Other);
- try writer.writeByte(']');
+ try w.writeByte('[');
+ try f.writeCValue(w, self.index, .Other);
+ try w.writeByte(']');
}
}
- pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, writer: anytype) !void {
+ pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void {
if (self.index != .none) {
- f.object.indent_writer.popIndent();
- try writer.writeAll("}\n");
+ try f.object.outdent();
+ try w.writeByte('}');
+ try f.object.newline();
try freeLocal(f, inst, self.index.new_local, null);
}
}
diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig
index 044d947702..77555d773c 100644
--- a/src/codegen/c/Type.zig
+++ b/src/codegen/c/Type.zig
@@ -209,7 +209,7 @@ pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {
};
}
-pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *const Pool) @TypeOf(writer).Error!void {
+pub fn renderLiteralPrefix(ctype: CType, w: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void {
switch (ctype.info(pool)) {
.basic => |basic_info| switch (basic_info) {
.void => unreachable,
@@ -224,7 +224,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
.uintptr_t,
.intptr_t,
=> switch (kind) {
- else => try writer.print("({s})", .{@tagName(basic_info)}),
+ else => try w.print("({s})", .{@tagName(basic_info)}),
.global => {},
},
.int,
@@ -246,7 +246,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
.int32_t,
.uint64_t,
.int64_t,
- => try writer.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}),
+ => try w.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}),
.zig_u128,
.zig_i128,
.zig_f16,
@@ -255,7 +255,7 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
.zig_f80,
.zig_f128,
.zig_c_longdouble,
- => try writer.print("zig_{s}_{s}(", .{
+ => try w.print("zig_{s}_{s}(", .{
switch (kind) {
else => "make",
.global => "init",
@@ -265,12 +265,12 @@ pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *con
.va_list => unreachable,
_ => unreachable,
},
- .array, .vector => try writer.writeByte('{'),
+ .array, .vector => try w.writeByte('{'),
else => unreachable,
}
}
-pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @TypeOf(writer).Error!void {
+pub fn renderLiteralSuffix(ctype: CType, w: *Writer, pool: *const Pool) Writer.Error!void {
switch (ctype.info(pool)) {
.basic => |basic_info| switch (basic_info) {
.void => unreachable,
@@ -280,20 +280,20 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty
.short,
.int,
=> {},
- .long => try writer.writeByte('l'),
- .@"long long" => try writer.writeAll("ll"),
+ .long => try w.writeByte('l'),
+ .@"long long" => try w.writeAll("ll"),
.@"unsigned char",
.@"unsigned short",
.@"unsigned int",
- => try writer.writeByte('u'),
+ => try w.writeByte('u'),
.@"unsigned long",
.size_t,
.uintptr_t,
- => try writer.writeAll("ul"),
- .@"unsigned long long" => try writer.writeAll("ull"),
- .float => try writer.writeByte('f'),
+ => try w.writeAll("ul"),
+ .@"unsigned long long" => try w.writeAll("ull"),
+ .float => try w.writeByte('f'),
.double => {},
- .@"long double" => try writer.writeByte('l'),
+ .@"long double" => try w.writeByte('l'),
.bool,
.ptrdiff_t,
.intptr_t,
@@ -314,11 +314,11 @@ pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @Ty
.zig_f80,
.zig_f128,
.zig_c_longdouble,
- => try writer.writeByte(')'),
+ => try w.writeByte(')'),
.va_list => unreachable,
_ => unreachable,
},
- .array, .vector => try writer.writeByte('}'),
+ .array, .vector => try w.writeByte('}'),
else => unreachable,
}
}
@@ -938,19 +938,13 @@ pub const Pool = struct {
index: String.Index,
const FormatData = struct { string: String, pool: *const Pool };
- fn format(
- data: FormatData,
- comptime fmt_str: []const u8,
- _: std.fmt.FormatOptions,
- writer: anytype,
- ) @TypeOf(writer).Error!void {
- if (fmt_str.len > 0) @compileError("invalid format string '" ++ fmt_str ++ "'");
+ fn format(data: FormatData, writer: *Writer) Writer.Error!void {
if (data.string.toSlice(data.pool)) |slice|
try writer.writeAll(slice)
else
try writer.print("f{d}", .{@intFromEnum(data.string.index)});
}
- pub fn fmt(str: String, pool: *const Pool) std.fmt.Formatter(format) {
+ pub fn fmt(str: String, pool: *const Pool) std.fmt.Formatter(FormatData, format) {
return .{ .data = .{ .string = str, .pool = pool } };
}
@@ -2890,7 +2884,7 @@ pub const Pool = struct {
comptime fmt_str: []const u8,
fmt_args: anytype,
) !String {
- try pool.string_bytes.writer(allocator).print(fmt_str, fmt_args);
+ try pool.string_bytes.print(allocator, fmt_str, fmt_args);
return pool.trailingString(allocator);
}
@@ -3281,10 +3275,12 @@ pub const AlignAs = packed struct {
}
};
+const std = @import("std");
const assert = std.debug.assert;
+const Writer = std.io.Writer;
+
const CType = @This();
const InternPool = @import("../../InternPool.zig");
const Module = @import("../../Package/Module.zig");
-const std = @import("std");
const Type = @import("../../Type.zig");
const Zcu = @import("../../Zcu.zig");
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 5135095f69..3d670dce83 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -239,12 +239,12 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
.none,
.windows,
=> {},
- .semver => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
+ .semver => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
ver.min.major,
ver.min.minor,
ver.min.patch,
}),
- inline .linux, .hurd => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
+ inline .linux, .hurd => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
ver.range.min.major,
ver.range.min.minor,
ver.range.min.patch,
@@ -295,13 +295,13 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8
.windows,
=> {},
inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
- try llvm_triple.writer().print("{d}.{d}.{d}", .{
+ try llvm_triple.print("{d}.{d}.{d}", .{
ver.glibc.major,
ver.glibc.minor,
ver.glibc.patch,
});
} else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
- try llvm_triple.writer().print("{d}", .{ver.android});
+ try llvm_triple.print("{d}", .{ver.android});
},
}
@@ -746,12 +746,18 @@ pub const Object = struct {
try wip.finish();
}
- fn genModuleLevelAssembly(object: *Object) !void {
- const writer = object.builder.setModuleAsm();
+ fn genModuleLevelAssembly(object: *Object) Allocator.Error!void {
+ const b = &object.builder;
+ const gpa = b.gpa;
+ b.module_asm.clearRetainingCapacity();
for (object.pt.zcu.global_assembly.values()) |assembly| {
- try writer.print("{s}\n", .{assembly});
+ try b.module_asm.ensureUnusedCapacity(gpa, assembly.len + 1);
+ b.module_asm.appendSliceAssumeCapacity(assembly);
+ b.module_asm.appendAssumeCapacity('\n');
+ }
+ if (b.module_asm.getLastOrNull()) |last| {
+ if (last != '\n') try b.module_asm.append(gpa, '\n');
}
- try object.builder.finishModuleAsm();
}
pub const EmitOptions = struct {
@@ -939,7 +945,9 @@ pub const Object = struct {
if (std.mem.eql(u8, path, "-")) {
o.builder.dump();
} else {
- _ = try o.builder.printToFile(path);
+ o.builder.printToFilePath(std.fs.cwd(), path) catch |err| {
+ log.err("failed printing LLVM module to \"{s}\": {s}", .{ path, @errorName(err) });
+ };
}
}
@@ -2486,7 +2494,7 @@ pub const Object = struct {
var union_name_buf: ?[:0]const u8 = null;
defer if (union_name_buf) |buf| gpa.free(buf);
const union_name = if (layout.tag_size == 0) name else name: {
- union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name});
+ union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0);
break :name union_name_buf.?;
};
@@ -2680,10 +2688,12 @@ pub const Object = struct {
}
fn allocTypeName(o: *Object, ty: Type) Allocator.Error![:0]const u8 {
- var buffer = std.ArrayList(u8).init(o.gpa);
- errdefer buffer.deinit();
- try ty.print(buffer.writer(), o.pt);
- return buffer.toOwnedSliceSentinel(0);
+ var aw: std.io.Writer.Allocating = .init(o.gpa);
+ defer aw.deinit();
+ ty.print(&aw.writer, o.pt) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return aw.toOwnedSliceSentinel(0);
}
/// If the llvm function does not exist, create it.
@@ -4482,7 +4492,7 @@ pub const Object = struct {
const target = &zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
- try o.builder.strtabStringFmt("__zig_tag_name_{}", .{enum_type.name.fmt(ip)}),
+ try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);
@@ -4633,7 +4643,7 @@ pub const NavGen = struct {
if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") {
if (lib_name.toSlice(ip)) |lib_name_slice| {
if (!std.mem.eql(u8, lib_name_slice, "c")) {
- break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice });
+ break :decl_name try o.builder.strtabStringFmt("{f}|{s}", .{ nav.name.fmt(ip), lib_name_slice });
}
}
}
@@ -7472,7 +7482,7 @@ pub const FuncGen = struct {
llvm_param_types[llvm_param_i] = llvm_elem_ty;
}
- try llvm_constraints.writer(self.gpa).print(",{d}", .{output_index});
+ try llvm_constraints.print(self.gpa, ",{d}", .{output_index});
// In the case of indirect inputs, LLVM requires the callsite to have
// an elementtype(<ty>) attribute.
@@ -7573,7 +7583,7 @@ pub const FuncGen = struct {
// we should validate the assembly in Sema; by now it is too late
return self.todo("unknown input or output name: '{s}'", .{name});
};
- try rendered_template.writer().print("{d}", .{index});
+ try rendered_template.print("{d}", .{index});
if (byte == ':') {
try rendered_template.append(':');
modifier_start = i + 1;
@@ -10370,7 +10380,7 @@ pub const FuncGen = struct {
const target = &zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
- try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{enum_type.name.fmt(ip)}),
+ try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 8a782c54aa..f263e567e8 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -817,7 +817,7 @@ const NavGen = struct {
const result_ty_id = try self.resolveType(ty, repr);
const ip = &zcu.intern_pool;
- log.debug("lowering constant: ty = {}, val = {}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
+ log.debug("lowering constant: ty = {f}, val = {f}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
if (val.isUndefDeep(zcu)) {
return self.spv.constUndef(result_ty_id);
}
@@ -1147,7 +1147,7 @@ const NavGen = struct {
return result_ptr_id;
}
- return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
+ return self.fail("cannot perform pointer cast: '{f}' to '{f}'", .{
parent_ptr_ty.fmt(pt),
oac.new_ptr_ty.fmt(pt),
});
@@ -1260,10 +1260,12 @@ const NavGen = struct {
// Turn a Zig type's name into a cache reference.
fn resolveTypeName(self: *NavGen, ty: Type) ![]const u8 {
- var name = std.ArrayList(u8).init(self.gpa);
- defer name.deinit();
- try ty.print(name.writer(), self.pt);
- return try name.toOwnedSlice();
+ var aw: std.io.Writer.Allocating = .init(self.gpa);
+ defer aw.deinit();
+ ty.print(&aw.writer, self.pt) catch |err| switch (err) {
+ error.WriteFailed => return error.OutOfMemory,
+ };
+ return try aw.toOwnedSlice();
}
/// Create an integer type suitable for storing at least 'bits' bits.
@@ -1462,7 +1464,7 @@ const NavGen = struct {
const pt = self.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- log.debug("resolveType: ty = {}", .{ty.fmt(pt)});
+ log.debug("resolveType: ty = {f}", .{ty.fmt(pt)});
const target = self.spv.target;
const section = &self.spv.sections.types_globals_constants;
@@ -3068,7 +3070,7 @@ const NavGen = struct {
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
try self.spv.addFunction(spv_decl_index, self.func);
- try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{nav.fqn.fmt(ip)});
+ try self.spv.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
.id_result_type = ptr_ty_id,
diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig
index 970f5bfe7f..82ec05ebba 100644
--- a/src/codegen/spirv/spec.zig
+++ b/src/codegen/spirv/spec.zig
@@ -1,6 +1,7 @@
//! This file is auto-generated by tools/gen_spirv_spec.zig.
const std = @import("std");
+const assert = std.debug.assert;
pub const Version = packed struct(Word) {
padding: u8 = 0,
@@ -18,15 +19,10 @@ pub const IdResult = enum(Word) {
none,
_,
- pub fn format(
- self: IdResult,
- comptime _: []const u8,
- _: std.fmt.FormatOptions,
- writer: anytype,
- ) @TypeOf(writer).Error!void {
+ pub fn format(self: IdResult, writer: *std.io.Writer) std.io.Writer.Error!void {
switch (self) {
.none => try writer.writeAll("(none)"),
- else => try writer.print("%{}", .{@intFromEnum(self)}),
+ else => try writer.print("%{d}", .{@intFromEnum(self)}),
}
}
};