authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-17 12:33:57-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:27-07:00
logb76b4c9c36d5cdbbaa9da8f49bcd0b83304a3875
tree5113a67e17ec22c761722c5a4ec7dd414aad5524
parentffb0e283d7aaaa896cd3db32ca11460ea63c8855

cbe: start porting to new `std.io.BufferedWriter` API

WIP while rebasing this commit, I gave up on the conflicts and copied src/link/C.zig from origin/master which was 710632b45cd7a7081af82af418eb3e405f7aa35e at the time.

1 files changed, 18 insertions(+), 105 deletions(-)

src/codegen/c.zig+18-105
...@@ -693,18 +693,22 @@ pub const Function = struct {...@@ -693,18 +693,22 @@ pub const Function = struct {
693/// It is not available when generating .h file.693/// It is not available when generating .h file.
694pub const Object = struct {694pub const Object = struct {
695 dg: DeclGen,695 dg: DeclGen,
696 /// This is a borrowed reference from `link.C`.696 code_header: std.io.AllocatingWriter,
697 code: std.ArrayList(u8),697 code: std.io.AllocatingWriter,
698 /// Goes before code. Initialized and deinitialized in `genFunc`.698 indent_counter: usize,
699 code_header: std.ArrayList(u8) = undefined,
700 indent_writer: IndentWriter(std.ArrayList(u8).Writer),
701699
702 fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {700 const indent_width = 1;
703 return o.indent_writer.writer();
704 }
705701
706 fn codeHeaderWriter(o: *Object) ArrayListWriter {702 fn nl(o: *Object) anyerror!void {
707 return arrayListWriter(&o.code_header);703 const bw = &o.code.buffered_writer;
704 try bw.writeByte('\n');
705 try bw.splatByteAll(' ', o.indent_counter);
706 }
707 fn indent(o: *Object) void {
708 o.indent_counter += indent_width;
709 }
710 fn outdent(o: *Object) void {
711 o.indent_counter -= indent_width;
708 }712 }
709};713};
710714
...@@ -716,8 +720,7 @@ pub const DeclGen = struct {...@@ -716,8 +720,7 @@ pub const DeclGen = struct {
716 pass: Pass,720 pass: Pass,
717 is_naked_fn: bool,721 is_naked_fn: bool,
718 expected_block: ?u32,722 expected_block: ?u32,
719 /// This is a borrowed reference from `link.C`.723 fwd_decl: std.io.AllocatingWriter,
720 fwd_decl: std.ArrayList(u8),
721 error_msg: ?*Zcu.ErrorMsg,724 error_msg: ?*Zcu.ErrorMsg,
722 ctype_pool: CType.Pool,725 ctype_pool: CType.Pool,
723 scratch: std.ArrayListUnmanaged(u32),726 scratch: std.ArrayListUnmanaged(u32),
...@@ -734,10 +737,6 @@ pub const DeclGen = struct {...@@ -734,10 +737,6 @@ pub const DeclGen = struct {
734 flush,737 flush,
735 };738 };
736739
737 fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter {
738 return arrayListWriter(&dg.fwd_decl);
739 }
740
741 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {740 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
742 @branchHint(.cold);741 @branchHint(.cold);
743 const zcu = dg.pt.zcu;742 const zcu = dg.pt.zcu;
...@@ -4218,7 +4217,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4218,7 +4217,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4218 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));4217 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
4219 defer mask.deinit();4218 defer mask.deinit();
42204219
4221 try mask.setTwosCompIntLimit(.max, .unsigned, @as(usize, @intCast(src_bits)));4220 try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(src_bits));
4222 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);4221 try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
4223 try mask.bitNotWrap(&mask, .unsigned, host_bits);4222 try mask.bitNotWrap(&mask, .unsigned, host_bits);
42244223
...@@ -7136,9 +7135,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV...@@ -7136,9 +7135,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
7136 return .none;7135 return .none;
7137}7136}
71387137
7139fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void {7138fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void {
7140 const pt = f.object.dg.pt;7139 const pt = f.object.dg.pt;
7141 const zcu = pt.zcu;7140 const zcu = pt.zcu;
7141 const writer = f.object.writer();
7142 switch (dest_ty.ptrSize(zcu)) {7142 switch (dest_ty.ptrSize(zcu)) {
7143 .one => try writer.print("{}", .{7143 .one => try writer.print("{}", .{
7144 try f.fmtIntLiteral(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),7144 try f.fmtIntLiteral(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))),
...@@ -7970,93 +7970,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {...@@ -7970,93 +7970,6 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 {
7970 };7970 };
7971}7971}
79727972
7973const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error);
7974
7975fn arrayListWriter(list: *std.ArrayList(u8)) ArrayListWriter {
7976 return .{ .context = .{
7977 .context = list,
7978 .writeFn = struct {
7979 fn write(context: *const anyopaque, bytes: []const u8) anyerror!usize {
7980 const l: *std.ArrayList(u8) = @alignCast(@constCast(@ptrCast(context)));
7981 return l.writer().write(bytes);
7982 }
7983 }.write,
7984 } };
7985}
7986
7987fn IndentWriter(comptime UnderlyingWriter: type) type {
7988 return struct {
7989 const Self = @This();
7990 pub const Error = UnderlyingWriter.Error;
7991 pub const Writer = ErrorOnlyGenericWriter(Error);
7992
7993 pub const indent_delta = 1;
7994
7995 underlying_writer: UnderlyingWriter,
7996 indent_count: usize = 0,
7997 current_line_empty: bool = true,
7998
7999 pub fn writer(self: *Self) Writer {
8000 return .{ .context = .{
8001 .context = self,
8002 .writeFn = writeAny,
8003 } };
8004 }
8005
8006 pub fn write(self: *Self, bytes: []const u8) Error!usize {
8007 if (bytes.len == 0) return 0;
8008
8009 const current_indent = self.indent_count * Self.indent_delta;
8010 if (self.current_line_empty and current_indent > 0) {
8011 try self.underlying_writer.writeByteNTimes(' ', current_indent);
8012 }
8013 self.current_line_empty = false;
8014
8015 return self.writeNoIndent(bytes);
8016 }
8017
8018 fn writeAny(context: *const anyopaque, bytes: []const u8) anyerror!usize {
8019 const self: *Self = @alignCast(@constCast(@ptrCast(context)));
8020 return self.write(bytes);
8021 }
8022
8023 pub fn insertNewline(self: *Self) Error!void {
8024 _ = try self.writeNoIndent("\n");
8025 }
8026
8027 pub fn pushIndent(self: *Self) void {
8028 self.indent_count += 1;
8029 }
8030
8031 pub fn popIndent(self: *Self) void {
8032 assert(self.indent_count != 0);
8033 self.indent_count -= 1;
8034 }
8035
8036 fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
8037 if (bytes.len == 0) return 0;
8038
8039 try self.underlying_writer.writeAll(bytes);
8040 if (bytes[bytes.len - 1] == '\n') {
8041 self.current_line_empty = true;
8042 }
8043 return bytes.len;
8044 }
8045 };
8046}
8047
8048/// A wrapper around `std.io.AnyWriter` that maintains a generic error set while
8049/// erasing the rest of the implementation. This is intended to avoid duplicate
8050/// generic instantiations for writer types which share the same error set, while
8051/// maintaining ease of error handling.
8052fn ErrorOnlyGenericWriter(comptime Error: type) type {
8053 return std.io.GenericWriter(std.io.AnyWriter, Error, struct {
8054 fn write(context: std.io.AnyWriter, bytes: []const u8) Error!usize {
8055 return @errorCast(context.write(bytes));
8056 }
8057 }.write);
8058}
8059
8060fn toCIntBits(zig_bits: u32) ?u32 {7973fn toCIntBits(zig_bits: u32) ?u32 {
8061 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {7974 for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| {
8062 if (zig_bits <= c_bits) {7975 if (zig_bits <= c_bits) {