| ... | ... | @@ -848,12 +848,13 @@ pub const DeclGen = struct { |
| 848 | 848 | |
| 849 | 849 | const ai = ty.arrayInfo(); |
| 850 | 850 | if (ai.elem_type.eql(Type.u8, dg.module)) { |
| 851 | | try writer.writeByte('"'); |
| 851 | var literal = stringLiteral(writer); |
| 852 | try literal.start(); |
| 852 | 853 | const c_len = ty.arrayLenIncludingSentinel(); |
| 853 | 854 | var index: usize = 0; |
| 854 | 855 | while (index < c_len) : (index += 1) |
| 855 | | try writeStringLiteralChar(writer, 0xaa); |
| 856 | | return writer.writeByte('"'); |
| 856 | try literal.writeChar(0xaa); |
| 857 | return literal.end(); |
| 857 | 858 | } else { |
| 858 | 859 | try writer.writeByte('{'); |
| 859 | 860 | const c_len = ty.arrayLenIncludingSentinel(); |
| ... | ... | @@ -1060,23 +1061,40 @@ pub const DeclGen = struct { |
| 1060 | 1061 | defer arena.deinit(); |
| 1061 | 1062 | const arena_allocator = arena.allocator(); |
| 1062 | 1063 | |
| 1064 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal |
| 1065 | const max_string_initializer_len = 65535; |
| 1066 | |
| 1063 | 1067 | const ai = ty.arrayInfo(); |
| 1064 | 1068 | if (ai.elem_type.eql(Type.u8, dg.module)) { |
| 1065 | | try writer.writeByte('"'); |
| 1066 | | var index: usize = 0; |
| 1067 | | while (index < ai.len) : (index += 1) { |
| 1068 | | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1069 | | const elem_val_u8 = if (elem_val.isUndef()) |
| 1070 | | undefPattern(u8) |
| 1071 | | else |
| 1072 | | @intCast(u8, elem_val.toUnsignedInt(target)); |
| 1073 | | try writeStringLiteralChar(writer, elem_val_u8); |
| 1074 | | } |
| 1075 | | if (ai.sentinel) |s| { |
| 1076 | | const s_u8 = @intCast(u8, s.toUnsignedInt(target)); |
| 1077 | | try writeStringLiteralChar(writer, s_u8); |
| 1069 | if (ai.len <= max_string_initializer_len) { |
| 1070 | var literal = stringLiteral(writer); |
| 1071 | try literal.start(); |
| 1072 | var index: usize = 0; |
| 1073 | while (index < ai.len) : (index += 1) { |
| 1074 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1075 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target)); |
| 1076 | try literal.writeChar(elem_val_u8); |
| 1077 | } |
| 1078 | if (ai.sentinel) |s| { |
| 1079 | const s_u8 = @intCast(u8, s.toUnsignedInt(target)); |
| 1080 | try literal.writeChar(s_u8); |
| 1081 | } |
| 1082 | try literal.end(); |
| 1083 | } else { |
| 1084 | try writer.writeByte('{'); |
| 1085 | var index: usize = 0; |
| 1086 | while (index < ai.len) : (index += 1) { |
| 1087 | if (index != 0) try writer.writeByte(','); |
| 1088 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1089 | const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target)); |
| 1090 | try writer.print("'\\x{x}'", .{ elem_val_u8 }); |
| 1091 | } |
| 1092 | if (ai.sentinel) |s| { |
| 1093 | if (index != 0) try writer.writeByte(','); |
| 1094 | try dg.renderValue(writer, ai.elem_type, s, .Initializer); |
| 1095 | } |
| 1096 | try writer.writeByte('}'); |
| 1078 | 1097 | } |
| 1079 | | try writer.writeByte('"'); |
| 1080 | 1098 | } else { |
| 1081 | 1099 | try writer.writeByte('{'); |
| 1082 | 1100 | var index: usize = 0; |
| ... | ... | @@ -2134,7 +2152,7 @@ pub const DeclGen = struct { |
| 2134 | 2152 | const c_len_val = Value.initPayload(&c_len_pl.base); |
| 2135 | 2153 | |
| 2136 | 2154 | try suffix_writer.writeByte('['); |
| 2137 | | if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("static const "); |
| 2155 | if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("zig_const_arr "); |
| 2138 | 2156 | try suffix.writer().print("{}]", .{try dg.fmtIntLiteral(Type.usize, c_len_val)}); |
| 2139 | 2157 | render_ty = array_info.elem_type; |
| 2140 | 2158 | depth += 1; |
| ... | ... | @@ -6793,6 +6811,68 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { |
| 6793 | 6811 | } else unreachable; |
| 6794 | 6812 | } |
| 6795 | 6813 | |
| 6814 | fn StringLiteral(comptime WriterType: type) type { |
| 6815 | // msvc has a length limit of 16380 per string literal (before concatenation) |
| 6816 | const max_char_len = 4; |
| 6817 | const max_len = 16380 - max_char_len; |
| 6818 | |
| 6819 | return struct { |
| 6820 | cur_len: usize = 0, |
| 6821 | counting_writer: std.io.CountingWriter(WriterType), |
| 6822 | |
| 6823 | pub const Error = WriterType.Error; |
| 6824 | |
| 6825 | const Self = @This(); |
| 6826 | |
| 6827 | pub fn start(self: *Self) Error!void { |
| 6828 | const writer = self.counting_writer.writer(); |
| 6829 | try writer.writeByte('\"'); |
| 6830 | } |
| 6831 | |
| 6832 | pub fn end(self: *Self) Error!void { |
| 6833 | const writer = self.counting_writer.writer(); |
| 6834 | try writer.writeByte('\"'); |
| 6835 | } |
| 6836 | |
| 6837 | fn writeStringLiteralChar(writer: anytype, c: u8) !void { |
| 6838 | switch (c) { |
| 6839 | 7 => try writer.writeAll("\\a"), |
| 6840 | 8 => try writer.writeAll("\\b"), |
| 6841 | '\t' => try writer.writeAll("\\t"), |
| 6842 | '\n' => try writer.writeAll("\\n"), |
| 6843 | 11 => try writer.writeAll("\\v"), |
| 6844 | 12 => try writer.writeAll("\\f"), |
| 6845 | '\r' => try writer.writeAll("\\r"), |
| 6846 | '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}), |
| 6847 | else => switch (c) { |
| 6848 | ' '...'~' => try writer.writeByte(c), |
| 6849 | else => try writer.print("\\{o:0>3}", .{c}), |
| 6850 | }, |
| 6851 | } |
| 6852 | } |
| 6853 | |
| 6854 | pub fn writeChar(self: *Self, c: u8) Error!void { |
| 6855 | const writer = self.counting_writer.writer(); |
| 6856 | |
| 6857 | if (self.cur_len == 0 and self.counting_writer.bytes_written > 1) |
| 6858 | try writer.writeAll("\"\""); |
| 6859 | |
| 6860 | const len = self.counting_writer.bytes_written; |
| 6861 | try writeStringLiteralChar(writer, c); |
| 6862 | |
| 6863 | const char_length = self.counting_writer.bytes_written - len; |
| 6864 | assert(char_length <= max_char_len); |
| 6865 | self.cur_len += char_length; |
| 6866 | |
| 6867 | if (self.cur_len >= max_len) self.cur_len = 0; |
| 6868 | } |
| 6869 | }; |
| 6870 | } |
| 6871 | |
| 6872 | fn stringLiteral(child_stream: anytype) StringLiteral(@TypeOf(child_stream)) { |
| 6873 | return .{ .counting_writer = std.io.countingWriter(child_stream) }; |
| 6874 | } |
| 6875 | |
| 6796 | 6876 | fn formatStringLiteral( |
| 6797 | 6877 | str: []const u8, |
| 6798 | 6878 | comptime fmt: []const u8, |
| ... | ... | @@ -6800,33 +6880,18 @@ fn formatStringLiteral( |
| 6800 | 6880 | writer: anytype, |
| 6801 | 6881 | ) @TypeOf(writer).Error!void { |
| 6802 | 6882 | if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt); |
| 6803 | | try writer.writeByte('\"'); |
| 6883 | |
| 6884 | var literal = stringLiteral(writer); |
| 6885 | try literal.start(); |
| 6804 | 6886 | for (str) |c| |
| 6805 | | try writeStringLiteralChar(writer, c); |
| 6806 | | try writer.writeByte('\"'); |
| 6887 | try literal.writeChar(c); |
| 6888 | try literal.end(); |
| 6807 | 6889 | } |
| 6808 | 6890 | |
| 6809 | 6891 | fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) { |
| 6810 | 6892 | return .{ .data = str }; |
| 6811 | 6893 | } |
| 6812 | 6894 | |
| 6813 | | fn writeStringLiteralChar(writer: anytype, c: u8) !void { |
| 6814 | | switch (c) { |
| 6815 | | 7 => try writer.writeAll("\\a"), |
| 6816 | | 8 => try writer.writeAll("\\b"), |
| 6817 | | '\t' => try writer.writeAll("\\t"), |
| 6818 | | '\n' => try writer.writeAll("\\n"), |
| 6819 | | 11 => try writer.writeAll("\\v"), |
| 6820 | | 12 => try writer.writeAll("\\f"), |
| 6821 | | '\r' => try writer.writeAll("\\r"), |
| 6822 | | '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}), |
| 6823 | | else => switch (c) { |
| 6824 | | ' '...'~' => try writer.writeByte(c), |
| 6825 | | else => try writer.print("\\{o:0>3}", .{c}), |
| 6826 | | }, |
| 6827 | | } |
| 6828 | | } |
| 6829 | | |
| 6830 | 6895 | fn undefPattern(comptime IntType: type) IntType { |
| 6831 | 6896 | const int_info = @typeInfo(IntType).Int; |
| 6832 | 6897 | const UnsignedType = std.meta.Int(.unsigned, int_info.bits); |
| ... | ... | @@ -6905,7 +6970,15 @@ fn formatIntLiteral( |
| 6905 | 6970 | return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" }); |
| 6906 | 6971 | } |
| 6907 | 6972 | |
| 6908 | | if (!int.positive) try writer.writeByte('-'); |
| 6973 | // TODO: If > 64 bit, need to use a subtract from zero fn here instead of negate |
| 6974 | if (!int.positive) { |
| 6975 | if (c_bits > 64) { |
| 6976 | try writer.print("zig_sub_{c}{d}(zig_as_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits }); |
| 6977 | } else { |
| 6978 | try writer.writeByte('-'); |
| 6979 | } |
| 6980 | } |
| 6981 | |
| 6909 | 6982 | switch (data.ty.tag()) { |
| 6910 | 6983 | .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {}, |
| 6911 | 6984 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), |
| ... | ... | @@ -6976,6 +7049,7 @@ fn formatIntLiteral( |
| 6976 | 7049 | .mod = data.mod, |
| 6977 | 7050 | }, fmt, options, writer); |
| 6978 | 7051 | |
| 7052 | if (!int.positive and c_bits > 64) try writer.writeByte(')'); |
| 6979 | 7053 | return writer.writeByte(')'); |
| 6980 | 7054 | } |
| 6981 | 7055 | |