| ... | ... | @@ -693,18 +693,22 @@ pub const Function = struct { |
| 693 | 693 | /// It is not available when generating .h file. |
| 694 | 694 | pub const Object = struct { |
| 695 | 695 | dg: DeclGen, |
| 696 | | /// This is a borrowed reference from `link.C`. |
| 697 | | code: std.ArrayList(u8), |
| 698 | | /// Goes before code. Initialized and deinitialized in `genFunc`. |
| 699 | | code_header: std.ArrayList(u8) = undefined, |
| 700 | | indent_writer: IndentWriter(std.ArrayList(u8).Writer), |
| 696 | code_header: std.io.AllocatingWriter, |
| 697 | code: std.io.AllocatingWriter, |
| 698 | indent_counter: usize, |
| 701 | 699 | |
| 702 | | fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { |
| 703 | | return o.indent_writer.writer(); |
| 704 | | } |
| 700 | const indent_width = 1; |
| 705 | 701 | |
| 706 | | fn codeHeaderWriter(o: *Object) ArrayListWriter { |
| 707 | | return arrayListWriter(&o.code_header); |
| 702 | fn nl(o: *Object) anyerror!void { |
| 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 | 720 | pass: Pass, |
| 717 | 721 | is_naked_fn: bool, |
| 718 | 722 | expected_block: ?u32, |
| 719 | | /// This is a borrowed reference from `link.C`. |
| 720 | | fwd_decl: std.ArrayList(u8), |
| 723 | fwd_decl: std.io.AllocatingWriter, |
| 721 | 724 | error_msg: ?*Zcu.ErrorMsg, |
| 722 | 725 | ctype_pool: CType.Pool, |
| 723 | 726 | scratch: std.ArrayListUnmanaged(u32), |
| ... | ... | @@ -734,10 +737,6 @@ pub const DeclGen = struct { |
| 734 | 737 | flush, |
| 735 | 738 | }; |
| 736 | 739 | |
| 737 | | fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter { |
| 738 | | return arrayListWriter(&dg.fwd_decl); |
| 739 | | } |
| 740 | | |
| 741 | 740 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 742 | 741 | @branchHint(.cold); |
| 743 | 742 | const zcu = dg.pt.zcu; |
| ... | ... | @@ -4218,7 +4217,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4218 | 4217 | var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits)); |
| 4219 | 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 | 4221 | try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset); |
| 4223 | 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 | 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 | 7139 | const pt = f.object.dg.pt; |
| 7141 | 7140 | const zcu = pt.zcu; |
| 7141 | const writer = f.object.writer(); |
| 7142 | 7142 | switch (dest_ty.ptrSize(zcu)) { |
| 7143 | 7143 | .one => try writer.print("{}", .{ |
| 7144 | 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 | 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 | 7973 | fn toCIntBits(zig_bits: u32) ?u32 { |
| 8061 | 7974 | for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| { |
| 8062 | 7975 | if (zig_bits <= c_bits) { |