| ... | @@ -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. |
| 694 | pub const Object = struct { | 694 | pub 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), | | |
| 701 | | 699 | |
| 702 | fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { | 700 | const indent_width = 1; |
| 703 | return o.indent_writer.writer(); | | |
| 704 | } | | |
| 705 | | 701 | |
| 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 | }; |
| 710 | | 714 | |
| ... | @@ -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 | }; |
| 736 | | 739 | |
| 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(); |
| 4220 | | 4219 | |
| 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); |
| 4224 | | 4223 | |
| ... | @@ -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 | } |
| 7138 | | 7137 | |
| 7139 | fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void { | 7138 | fn 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 | } |
| 7972 | | 7972 | |
| 7973 | const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error); | | |
| 7974 | | | |
| 7975 | fn 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 | | | |
| 7987 | fn 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. | | |
| 8052 | fn 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 | | | |
| 8060 | fn toCIntBits(zig_bits: u32) ?u32 { | 7973 | fn 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) { |