| ... | ... | @@ -965,9 +965,9 @@ pub const DeclGen = struct { |
| 965 | 965 | .Array, .Vector => { |
| 966 | 966 | const ai = ty.arrayInfo(mod); |
| 967 | 967 | if (ai.elem_type.eql(Type.u8, mod)) { |
| 968 | | var literal = stringLiteral(writer); |
| 969 | | try literal.start(); |
| 970 | 968 | const c_len = ty.arrayLenIncludingSentinel(mod); |
| 969 | var literal = stringLiteral(writer, c_len); |
| 970 | try literal.start(); |
| 971 | 971 | var index: u64 = 0; |
| 972 | 972 | while (index < c_len) : (index += 1) |
| 973 | 973 | try literal.writeChar(0xaa); |
| ... | ... | @@ -1290,46 +1290,24 @@ pub const DeclGen = struct { |
| 1290 | 1290 | } |
| 1291 | 1291 | // Fall back to generic implementation. |
| 1292 | 1292 | |
| 1293 | | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal |
| 1294 | | const max_string_initializer_len = 65535; |
| 1295 | | |
| 1296 | 1293 | const ai = ty.arrayInfo(mod); |
| 1297 | 1294 | if (ai.elem_type.eql(Type.u8, mod)) { |
| 1298 | | if (ai.len <= max_string_initializer_len) { |
| 1299 | | var literal = stringLiteral(writer); |
| 1300 | | try literal.start(); |
| 1301 | | var index: usize = 0; |
| 1302 | | while (index < ai.len) : (index += 1) { |
| 1303 | | const elem_val = try val.elemValue(mod, index); |
| 1304 | | const elem_val_u8: u8 = if (elem_val.isUndef(mod)) |
| 1305 | | undefPattern(u8) |
| 1306 | | else |
| 1307 | | @intCast(elem_val.toUnsignedInt(mod)); |
| 1308 | | try literal.writeChar(elem_val_u8); |
| 1309 | | } |
| 1310 | | if (ai.sentinel) |s| { |
| 1311 | | const s_u8: u8 = @intCast(s.toUnsignedInt(mod)); |
| 1312 | | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1313 | | } |
| 1314 | | try literal.end(); |
| 1315 | | } else { |
| 1316 | | try writer.writeByte('{'); |
| 1317 | | var index: usize = 0; |
| 1318 | | while (index < ai.len) : (index += 1) { |
| 1319 | | if (index != 0) try writer.writeByte(','); |
| 1320 | | const elem_val = try val.elemValue(mod, index); |
| 1321 | | const elem_val_u8: u8 = if (elem_val.isUndef(mod)) |
| 1322 | | undefPattern(u8) |
| 1323 | | else |
| 1324 | | @intCast(elem_val.toUnsignedInt(mod)); |
| 1325 | | try writer.print("'\\x{x}'", .{elem_val_u8}); |
| 1326 | | } |
| 1327 | | if (ai.sentinel) |s| { |
| 1328 | | if (index != 0) try writer.writeByte(','); |
| 1329 | | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1330 | | } |
| 1331 | | try writer.writeByte('}'); |
| 1295 | var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(mod)); |
| 1296 | try literal.start(); |
| 1297 | var index: usize = 0; |
| 1298 | while (index < ai.len) : (index += 1) { |
| 1299 | const elem_val = try val.elemValue(mod, index); |
| 1300 | const elem_val_u8: u8 = if (elem_val.isUndef(mod)) |
| 1301 | undefPattern(u8) |
| 1302 | else |
| 1303 | @intCast(elem_val.toUnsignedInt(mod)); |
| 1304 | try literal.writeChar(elem_val_u8); |
| 1332 | 1305 | } |
| 1306 | if (ai.sentinel) |s| { |
| 1307 | const s_u8: u8 = @intCast(s.toUnsignedInt(mod)); |
| 1308 | if (s_u8 != 0) try literal.writeChar(s_u8); |
| 1309 | } |
| 1310 | try literal.end(); |
| 1333 | 1311 | } else { |
| 1334 | 1312 | try writer.writeByte('{'); |
| 1335 | 1313 | var index: usize = 0; |
| ... | ... | @@ -7660,11 +7638,17 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 { |
| 7660 | 7638 | } |
| 7661 | 7639 | |
| 7662 | 7640 | fn StringLiteral(comptime WriterType: type) type { |
| 7641 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal, |
| 7642 | // regardless of the length of the string literal initializing it. Array initializer syntax is |
| 7643 | // used instead. |
| 7644 | const max_string_initializer_len = 65535; |
| 7645 | |
| 7663 | 7646 | // MSVC has a length limit of 16380 per string literal (before concatenation) |
| 7664 | 7647 | const max_char_len = 4; |
| 7665 | | const max_len = 16380 - max_char_len; |
| 7648 | const max_literal_len = 16380 - max_char_len; |
| 7666 | 7649 | |
| 7667 | 7650 | return struct { |
| 7651 | len: u64, |
| 7668 | 7652 | cur_len: u64 = 0, |
| 7669 | 7653 | counting_writer: std.io.CountingWriter(WriterType), |
| 7670 | 7654 | |
| ... | ... | @@ -7674,12 +7658,20 @@ fn StringLiteral(comptime WriterType: type) type { |
| 7674 | 7658 | |
| 7675 | 7659 | pub fn start(self: *Self) Error!void { |
| 7676 | 7660 | const writer = self.counting_writer.writer(); |
| 7677 | | try writer.writeByte('\"'); |
| 7661 | if (self.len <= max_string_initializer_len) { |
| 7662 | try writer.writeByte('\"'); |
| 7663 | } else { |
| 7664 | try writer.writeByte('{'); |
| 7665 | } |
| 7678 | 7666 | } |
| 7679 | 7667 | |
| 7680 | 7668 | pub fn end(self: *Self) Error!void { |
| 7681 | 7669 | const writer = self.counting_writer.writer(); |
| 7682 | | try writer.writeByte('\"'); |
| 7670 | if (self.len <= max_string_initializer_len) { |
| 7671 | try writer.writeByte('\"'); |
| 7672 | } else { |
| 7673 | try writer.writeByte('}'); |
| 7674 | } |
| 7683 | 7675 | } |
| 7684 | 7676 | |
| 7685 | 7677 | fn writeStringLiteralChar(writer: anytype, c: u8) !void { |
| ... | ... | @@ -7701,24 +7693,34 @@ fn StringLiteral(comptime WriterType: type) type { |
| 7701 | 7693 | |
| 7702 | 7694 | pub fn writeChar(self: *Self, c: u8) Error!void { |
| 7703 | 7695 | const writer = self.counting_writer.writer(); |
| 7696 | if (self.len <= max_string_initializer_len) { |
| 7697 | if (self.cur_len == 0 and self.counting_writer.bytes_written > 1) |
| 7698 | try writer.writeAll("\"\""); |
| 7704 | 7699 | |
| 7705 | | if (self.cur_len == 0 and self.counting_writer.bytes_written > 1) |
| 7706 | | try writer.writeAll("\"\""); |
| 7700 | const len = self.counting_writer.bytes_written; |
| 7701 | try writeStringLiteralChar(writer, c); |
| 7707 | 7702 | |
| 7708 | | const len = self.counting_writer.bytes_written; |
| 7709 | | try writeStringLiteralChar(writer, c); |
| 7703 | const char_length = self.counting_writer.bytes_written - len; |
| 7704 | assert(char_length <= max_char_len); |
| 7705 | self.cur_len += char_length; |
| 7710 | 7706 | |
| 7711 | | const char_length = self.counting_writer.bytes_written - len; |
| 7712 | | assert(char_length <= max_char_len); |
| 7713 | | self.cur_len += char_length; |
| 7714 | | |
| 7715 | | if (self.cur_len >= max_len) self.cur_len = 0; |
| 7707 | if (self.cur_len >= max_literal_len) self.cur_len = 0; |
| 7708 | } else { |
| 7709 | if (self.counting_writer.bytes_written > 1) try writer.writeByte(','); |
| 7710 | try writer.print("'\\x{x}'", .{c}); |
| 7711 | } |
| 7716 | 7712 | } |
| 7717 | 7713 | }; |
| 7718 | 7714 | } |
| 7719 | 7715 | |
| 7720 | | fn stringLiteral(child_stream: anytype) StringLiteral(@TypeOf(child_stream)) { |
| 7721 | | return .{ .counting_writer = std.io.countingWriter(child_stream) }; |
| 7716 | fn stringLiteral( |
| 7717 | child_stream: anytype, |
| 7718 | len: u64, |
| 7719 | ) StringLiteral(@TypeOf(child_stream)) { |
| 7720 | return .{ |
| 7721 | .len = len, |
| 7722 | .counting_writer = std.io.countingWriter(child_stream), |
| 7723 | }; |
| 7722 | 7724 | } |
| 7723 | 7725 | |
| 7724 | 7726 | const FormatStringContext = struct { str: []const u8, sentinel: ?u8 }; |
| ... | ... | @@ -7730,7 +7732,7 @@ fn formatStringLiteral( |
| 7730 | 7732 | ) @TypeOf(writer).Error!void { |
| 7731 | 7733 | if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt); |
| 7732 | 7734 | |
| 7733 | | var literal = stringLiteral(writer); |
| 7735 | var literal = stringLiteral(writer, data.str.len + @intFromBool(data.sentinel != null)); |
| 7734 | 7736 | try literal.start(); |
| 7735 | 7737 | for (data.str) |c| try literal.writeChar(c); |
| 7736 | 7738 | if (data.sentinel) |sentinel| if (sentinel != 0) try literal.writeChar(sentinel); |