authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-08-09 02:15:05-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-11 11:30:51-07:00
log38dfa6537ee4a2042e3a80d2e3020c9059ca16cc
tree9c4c002c3717ca6864b3cfa074c8be3103a88763
parent0b3c3c02e30f61da44d6368cb89e1ecb1afb1399

cbe: emit `nonstring` attribute

Closes #24545

4 files changed, 182 insertions(+), 49 deletions(-)

lib/zig.h+6
...@@ -253,6 +253,12 @@...@@ -253,6 +253,12 @@
253#define zig_align_fn zig_align_fn_unavailable253#define zig_align_fn zig_align_fn_unavailable
254#endif254#endif
255255
256#if zig_has_attribute(nonstring)
257#define zig_nonstring __attribute__((nonstring))
258#else
259#define zig_nonstring
260#endif
261
256#if zig_has_attribute(packed) || defined(zig_tinyc)262#if zig_has_attribute(packed) || defined(zig_tinyc)
257#define zig_packed(definition) __attribute__((packed)) definition263#define zig_packed(definition) __attribute__((packed)) definition
258#elif defined(zig_msvc)264#elif defined(zig_msvc)
src/codegen/c.zig+15-8
...@@ -1316,12 +1316,12 @@ pub const DeclGen = struct {...@@ -1316,12 +1316,12 @@ pub const DeclGen = struct {
1316 try w.writeByte('{');1316 try w.writeByte('{');
1317 var index: usize = 0;1317 var index: usize = 0;
1318 while (index < ai.len) : (index += 1) {1318 while (index < ai.len) : (index += 1) {
1319 if (index != 0) try w.writeByte(',');1319 if (index > 0) try w.writeByte(',');
1320 const elem_val = try val.elemValue(pt, index);1320 const elem_val = try val.elemValue(pt, index);
1321 try dg.renderValue(w, elem_val, initializer_type);1321 try dg.renderValue(w, elem_val, initializer_type);
1322 }1322 }
1323 if (ai.sentinel) |s| {1323 if (ai.sentinel) |s| {
1324 if (index != 0) try w.writeByte(',');1324 if (index > 0) try w.writeByte(',');
1325 try dg.renderValue(w, s, initializer_type);1325 try dg.renderValue(w, s, initializer_type);
1326 }1326 }
1327 try w.writeByte('}');1327 try w.writeByte('}');
...@@ -1854,12 +1854,14 @@ pub const DeclGen = struct {...@@ -1854,12 +1854,14 @@ pub const DeclGen = struct {
1854 .array_type, .vector_type => {1854 .array_type, .vector_type => {
1855 const ai = ty.arrayInfo(zcu);1855 const ai = ty.arrayInfo(zcu);
1856 if (ai.elem_type.eql(.u8, zcu)) {1856 if (ai.elem_type.eql(.u8, zcu)) {
1857 const c_len = ty.arrayLenIncludingSentinel(zcu);1857 var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu)));
1858 var literal: StringLiteral = .init(w, @intCast(c_len));
1859 try literal.start();1858 try literal.start();
1860 var index: u64 = 0;1859 var index: u64 = 0;
1861 while (index < c_len) : (index += 1)1860 while (index < ai.len) : (index += 1) try literal.writeChar(0xaa);
1862 try literal.writeChar(0xaa);1861 if (ai.sentinel) |s| {
1862 const s_u8: u8 = @intCast(s.toUnsignedInt(zcu));
1863 if (s_u8 != 0) try literal.writeChar(s_u8);
1864 }
1863 return literal.end();1865 return literal.end();
1864 } else {1866 } else {
1865 if (!location.isInitializer()) {1867 if (!location.isInitializer()) {
...@@ -1869,12 +1871,15 @@ pub const DeclGen = struct {...@@ -1869,12 +1871,15 @@ pub const DeclGen = struct {
1869 }1871 }
18701872
1871 try w.writeByte('{');1873 try w.writeByte('{');
1872 const c_len = ty.arrayLenIncludingSentinel(zcu);
1873 var index: u64 = 0;1874 var index: u64 = 0;
1874 while (index < c_len) : (index += 1) {1875 while (index < ai.len) : (index += 1) {
1875 if (index > 0) try w.writeAll(", ");1876 if (index > 0) try w.writeAll(", ");
1876 try dg.renderUndefValue(w, ty.childType(zcu), initializer_type);1877 try dg.renderUndefValue(w, ty.childType(zcu), initializer_type);
1877 }1878 }
1879 if (ai.sentinel) |s| {
1880 if (index > 0) try w.writeAll(", ");
1881 try dg.renderValue(w, s, location);
1882 }
1878 return w.writeByte('}');1883 return w.writeByte('}');
1879 }1884 }
1880 },1885 },
...@@ -2217,6 +2222,7 @@ pub const DeclGen = struct {...@@ -2217,6 +2222,7 @@ pub const DeclGen = struct {
2217 });2222 });
2218 try dg.writeName(w, name);2223 try dg.writeName(w, name);
2219 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{});2224 try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{});
2225 if (ctype.isNonString(&dg.ctype_pool)) try w.writeAll(" zig_nonstring");
2220 }2226 }
22212227
2222 fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void {2228 fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void {
...@@ -2713,6 +2719,7 @@ fn renderFields(...@@ -2713,6 +2719,7 @@ fn renderFields(
2713 );2719 );
2714 try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });2720 try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) });
2715 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});2721 try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{});
2722 if (field_info.ctype.isNonString(ctype_pool)) try w.writeAll(" zig_nonstring");
2716 try w.writeAll(";\n");2723 try w.writeAll(";\n");
2717 }2724 }
2718 try w.splatByteAll(' ', indent);2725 try w.splatByteAll(' ', indent);
src/codegen/c/Type.zig+160-40
...@@ -177,6 +177,35 @@ pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType {...@@ -177,6 +177,35 @@ pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType {
177 };177 };
178}178}
179179
180pub fn isAnyChar(ctype: CType) bool {
181 return switch (ctype.index) {
182 else => false,
183 .char, .@"signed char", .@"unsigned char", .uint8_t, .int8_t => true,
184 };
185}
186
187pub fn isString(ctype: CType, pool: *const Pool) bool {
188 return info: switch (ctype.info(pool)) {
189 .basic, .fwd_decl, .aggregate, .function => false,
190 .pointer => |pointer_info| pointer_info.elem_ctype.isAnyChar(),
191 .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool),
192 .array, .vector => |sequence_info| sequence_info.elem_type.isAnyChar(),
193 };
194}
195
196pub fn isNonString(ctype: CType, pool: *const Pool) bool {
197 var allow_pointer = true;
198 return info: switch (ctype.info(pool)) {
199 .basic, .fwd_decl, .aggregate, .function => false,
200 .pointer => |pointer_info| allow_pointer and pointer_info.nonstring,
201 .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool),
202 .array, .vector => |sequence_info| sequence_info.nonstring or {
203 allow_pointer = false;
204 continue :info sequence_info.elem_ctype.info(pool);
205 },
206 };
207}
208
180pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {209pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 {
181 return switch (ctype.index) {210 return switch (ctype.index) {
182 .char => "CHAR",211 .char => "CHAR",
...@@ -427,6 +456,15 @@ pub fn info(ctype: CType, pool: *const Pool) Info {...@@ -427,6 +456,15 @@ pub fn info(ctype: CType, pool: *const Pool) Info {
427 .len = extra.len,456 .len = extra.len,
428 } };457 } };
429 },458 },
459 .nonstring => {
460 var child_info = info(.{ .index = @enumFromInt(item.data) }, pool);
461 switch (child_info) {
462 else => unreachable,
463 .pointer => |*pointer_info| pointer_info.nonstring = true,
464 .array, .vector => |*sequence_info| sequence_info.nonstring = true,
465 }
466 return child_info;
467 },
430 .fwd_decl_struct_anon => {468 .fwd_decl_struct_anon => {
431 const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data);469 const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data);
432 return .{ .fwd_decl = .{470 return .{ .fwd_decl = .{
...@@ -601,10 +639,12 @@ fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType {...@@ -601,10 +639,12 @@ fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType {
601 .array => |array_info| pool.getArray(allocator, .{639 .array => |array_info| pool.getArray(allocator, .{
602 .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator),640 .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator),
603 .len = array_info.len,641 .len = array_info.len,
642 .nonstring = array_info.nonstring,
604 }),643 }),
605 .vector => |vector_info| pool.getVector(allocator, .{644 .vector => |vector_info| pool.getVector(allocator, .{
606 .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator),645 .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator),
607 .len = vector_info.len,646 .len = vector_info.len,
647 .nonstring = vector_info.nonstring,
608 }),648 }),
609 .aggregate => |aggregate_info| switch (aggregate_info.name) {649 .aggregate => |aggregate_info| switch (aggregate_info.name) {
610 .anon => ctype,650 .anon => ctype,
...@@ -754,6 +794,7 @@ pub const Info = union(enum) {...@@ -754,6 +794,7 @@ pub const Info = union(enum) {
754 elem_ctype: CType,794 elem_ctype: CType,
755 @"const": bool = false,795 @"const": bool = false,
756 @"volatile": bool = false,796 @"volatile": bool = false,
797 nonstring: bool = false,
757798
758 fn tag(pointer_info: Pointer) Pool.Tag {799 fn tag(pointer_info: Pointer) Pool.Tag {
759 return @enumFromInt(@intFromEnum(Pool.Tag.pointer) +800 return @enumFromInt(@intFromEnum(Pool.Tag.pointer) +
...@@ -775,6 +816,7 @@ pub const Info = union(enum) {...@@ -775,6 +816,7 @@ pub const Info = union(enum) {
775 pub const Sequence = struct {816 pub const Sequence = struct {
776 elem_ctype: CType,817 elem_ctype: CType,
777 len: u64,818 len: u64,
819 nonstring: bool = false,
778 };820 };
779821
780 pub const AggregateTag = enum { @"enum", @"struct", @"union" };822 pub const AggregateTag = enum { @"enum", @"struct", @"union" };
...@@ -878,12 +920,15 @@ pub const Info = union(enum) {...@@ -878,12 +920,15 @@ pub const Info = union(enum) {
878 .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic,920 .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic,
879 .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and921 .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and
880 lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and922 lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and
923 lhs_pointer_info.nonstring == rhs_info.pointer.nonstring and
881 pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype),924 pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype),
882 .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and925 .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and
883 pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype),926 pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype),
884 .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and927 .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and
928 lhs_array_info.nonstring == rhs_info.array.nonstring and
885 pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype),929 pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype),
886 .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and930 .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and
931 lhs_vector_info.nonstring == rhs_info.vector.nonstring and
887 pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype),932 pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype),
888 .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and933 .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and
889 switch (lhs_fwd_decl_info.name) {934 switch (lhs_fwd_decl_info.name) {
...@@ -1063,12 +1108,12 @@ pub const Pool = struct {...@@ -1063,12 +1108,12 @@ pub const Pool = struct {
1063 pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType {1108 pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType {
1064 var hasher = Hasher.init;1109 var hasher = Hasher.init;
1065 hasher.update(pointer_info.elem_ctype.hash(pool));1110 hasher.update(pointer_info.elem_ctype.hash(pool));
1066 return pool.tagData(1111 return pool.getNonString(allocator, try pool.tagData(
1067 allocator,1112 allocator,
1068 hasher,1113 hasher,
1069 pointer_info.tag(),1114 pointer_info.tag(),
1070 @intFromEnum(pointer_info.elem_ctype.index),1115 @intFromEnum(pointer_info.elem_ctype.index),
1071 );1116 ), pointer_info.nonstring);
1072 }1117 }
10731118
1074 pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType {1119 pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType {
...@@ -1079,24 +1124,36 @@ pub const Pool = struct {...@@ -1079,24 +1124,36 @@ pub const Pool = struct {
1079 }1124 }
10801125
1081 pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType {1126 pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType {
1082 return if (std.math.cast(u32, array_info.len)) |small_len|1127 return pool.getNonString(allocator, if (std.math.cast(u32, array_info.len)) |small_len|
1083 pool.tagExtra(allocator, .array_small, SequenceSmall, .{1128 try pool.tagExtra(allocator, .array_small, SequenceSmall, .{
1084 .elem_ctype = array_info.elem_ctype.index,1129 .elem_ctype = array_info.elem_ctype.index,
1085 .len = small_len,1130 .len = small_len,
1086 })1131 })
1087 else1132 else
1088 pool.tagExtra(allocator, .array_large, SequenceLarge, .{1133 try pool.tagExtra(allocator, .array_large, SequenceLarge, .{
1089 .elem_ctype = array_info.elem_ctype.index,1134 .elem_ctype = array_info.elem_ctype.index,
1090 .len_lo = @truncate(array_info.len >> 0),1135 .len_lo = @truncate(array_info.len >> 0),
1091 .len_hi = @truncate(array_info.len >> 32),1136 .len_hi = @truncate(array_info.len >> 32),
1092 });1137 }), array_info.nonstring);
1093 }1138 }
10941139
1095 pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType {1140 pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType {
1096 return pool.tagExtra(allocator, .vector, SequenceSmall, .{1141 return pool.getNonString(allocator, try pool.tagExtra(allocator, .vector, SequenceSmall, .{
1097 .elem_ctype = vector_info.elem_ctype.index,1142 .elem_ctype = vector_info.elem_ctype.index,
1098 .len = @intCast(vector_info.len),1143 .len = @intCast(vector_info.len),
1099 });1144 }), vector_info.nonstring);
1145 }
1146
1147 pub fn getNonString(
1148 pool: *Pool,
1149 allocator: std.mem.Allocator,
1150 child_ctype: CType,
1151 nonstring: bool,
1152 ) !CType {
1153 if (!nonstring) return child_ctype;
1154 var hasher = Hasher.init;
1155 hasher.update(child_ctype.hash(pool));
1156 return pool.tagData(allocator, hasher, .nonstring, @intFromEnum(child_ctype.index));
1100 }1157 }
11011158
1102 pub fn getFwdDecl(1159 pub fn getFwdDecl(
...@@ -1314,12 +1371,14 @@ pub const Pool = struct {...@@ -1314,12 +1371,14 @@ pub const Pool = struct {
1314 else => {1371 else => {
1315 const target = &mod.resolved_target.result;1372 const target = &mod.resolved_target.result;
1316 const abi_align_bytes = std.zig.target.intAlignment(target, int_info.bits);1373 const abi_align_bytes = std.zig.target.intAlignment(target, int_info.bits);
1374 const limb_ctype = try pool.fromIntInfo(allocator, .{
1375 .signedness = .unsigned,
1376 .bits = @intCast(abi_align_bytes * 8),
1377 }, mod, kind.noParameter());
1317 const array_ctype = try pool.getArray(allocator, .{1378 const array_ctype = try pool.getArray(allocator, .{
1318 .len = @divExact(std.zig.target.intByteSize(target, int_info.bits), abi_align_bytes),1379 .len = @divExact(std.zig.target.intByteSize(target, int_info.bits), abi_align_bytes),
1319 .elem_ctype = try pool.fromIntInfo(allocator, .{1380 .elem_ctype = limb_ctype,
1320 .signedness = .unsigned,1381 .nonstring = limb_ctype.isAnyChar(),
1321 .bits = @intCast(abi_align_bytes * 8),
1322 }, mod, kind.noParameter()),
1323 });1382 });
1324 if (!kind.isParameter()) return array_ctype;1383 if (!kind.isParameter()) return array_ctype;
1325 var fields = [_]Info.Field{1384 var fields = [_]Info.Field{
...@@ -1402,28 +1461,49 @@ pub const Pool = struct {...@@ -1402,28 +1461,49 @@ pub const Pool = struct {
1402 .bits = pt.zcu.errorSetBits(),1461 .bits = pt.zcu.errorSetBits(),
1403 }, mod, kind),1462 }, mod, kind),
14041463
1405 .ptr_usize_type,1464 .ptr_usize_type => return pool.getPointer(allocator, .{
1406 => return pool.getPointer(allocator, .{
1407 .elem_ctype = .usize,1465 .elem_ctype = .usize,
1408 }),1466 }),
1409 .ptr_const_comptime_int_type,1467 .ptr_const_comptime_int_type => return pool.getPointer(allocator, .{
1410 => return pool.getPointer(allocator, .{
1411 .elem_ctype = .void,1468 .elem_ctype = .void,
1412 .@"const" = true,1469 .@"const" = true,
1413 }),1470 }),
1414 .manyptr_u8_type,1471 .manyptr_u8_type => return pool.getPointer(allocator, .{
1415 => return pool.getPointer(allocator, .{
1416 .elem_ctype = .u8,1472 .elem_ctype = .u8,
1473 .nonstring = true,
1417 }),1474 }),
1418 .manyptr_const_u8_type,1475 .manyptr_const_u8_type => return pool.getPointer(allocator, .{
1419 .manyptr_const_u8_sentinel_0_type,
1420 => return pool.getPointer(allocator, .{
1421 .elem_ctype = .u8,1476 .elem_ctype = .u8,
1422 .@"const" = true,1477 .@"const" = true,
1478 .nonstring = true,
1423 }),1479 }),
1424 .slice_const_u8_type,1480 .manyptr_const_u8_sentinel_0_type => return pool.getPointer(allocator, .{
1425 .slice_const_u8_sentinel_0_type,1481 .elem_ctype = .u8,
1426 => {1482 .@"const" = true,
1483 }),
1484 .slice_const_u8_type => {
1485 const target = &mod.resolved_target.result;
1486 var fields = [_]Info.Field{
1487 .{
1488 .name = .{ .index = .ptr },
1489 .ctype = try pool.getPointer(allocator, .{
1490 .elem_ctype = .u8,
1491 .@"const" = true,
1492 .nonstring = true,
1493 }),
1494 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1495 },
1496 .{
1497 .name = .{ .index = .len },
1498 .ctype = .usize,
1499 .alignas = AlignAs.fromAbiAlignment(
1500 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1501 ),
1502 },
1503 };
1504 return pool.fromFields(allocator, .@"struct", &fields, kind);
1505 },
1506 .slice_const_u8_sentinel_0_type => {
1427 const target = &mod.resolved_target.result;1507 const target = &mod.resolved_target.result;
1428 var fields = [_]Info.Field{1508 var fields = [_]Info.Field{
1429 .{1509 .{
...@@ -1449,6 +1529,7 @@ pub const Pool = struct {...@@ -1449,6 +1529,7 @@ pub const Pool = struct {
1449 const vector_ctype = try pool.getVector(allocator, .{1529 const vector_ctype = try pool.getVector(allocator, .{
1450 .elem_ctype = .i8,1530 .elem_ctype = .i8,
1451 .len = 8,1531 .len = 8,
1532 .nonstring = true,
1452 });1533 });
1453 if (!kind.isParameter()) return vector_ctype;1534 if (!kind.isParameter()) return vector_ctype;
1454 var fields = [_]Info.Field{1535 var fields = [_]Info.Field{
...@@ -1464,6 +1545,7 @@ pub const Pool = struct {...@@ -1464,6 +1545,7 @@ pub const Pool = struct {
1464 const vector_ctype = try pool.getVector(allocator, .{1545 const vector_ctype = try pool.getVector(allocator, .{
1465 .elem_ctype = .i8,1546 .elem_ctype = .i8,
1466 .len = 16,1547 .len = 16,
1548 .nonstring = true,
1467 });1549 });
1468 if (!kind.isParameter()) return vector_ctype;1550 if (!kind.isParameter()) return vector_ctype;
1469 var fields = [_]Info.Field{1551 var fields = [_]Info.Field{
...@@ -1479,6 +1561,7 @@ pub const Pool = struct {...@@ -1479,6 +1561,7 @@ pub const Pool = struct {
1479 const vector_ctype = try pool.getVector(allocator, .{1561 const vector_ctype = try pool.getVector(allocator, .{
1480 .elem_ctype = .i8,1562 .elem_ctype = .i8,
1481 .len = 32,1563 .len = 32,
1564 .nonstring = true,
1482 });1565 });
1483 if (!kind.isParameter()) return vector_ctype;1566 if (!kind.isParameter()) return vector_ctype;
1484 var fields = [_]Info.Field{1567 var fields = [_]Info.Field{
...@@ -1494,6 +1577,7 @@ pub const Pool = struct {...@@ -1494,6 +1577,7 @@ pub const Pool = struct {
1494 const vector_ctype = try pool.getVector(allocator, .{1577 const vector_ctype = try pool.getVector(allocator, .{
1495 .elem_ctype = .i8,1578 .elem_ctype = .i8,
1496 .len = 64,1579 .len = 64,
1580 .nonstring = true,
1497 });1581 });
1498 if (!kind.isParameter()) return vector_ctype;1582 if (!kind.isParameter()) return vector_ctype;
1499 var fields = [_]Info.Field{1583 var fields = [_]Info.Field{
...@@ -1509,6 +1593,7 @@ pub const Pool = struct {...@@ -1509,6 +1593,7 @@ pub const Pool = struct {
1509 const vector_ctype = try pool.getVector(allocator, .{1593 const vector_ctype = try pool.getVector(allocator, .{
1510 .elem_ctype = .u8,1594 .elem_ctype = .u8,
1511 .len = 1,1595 .len = 1,
1596 .nonstring = true,
1512 });1597 });
1513 if (!kind.isParameter()) return vector_ctype;1598 if (!kind.isParameter()) return vector_ctype;
1514 var fields = [_]Info.Field{1599 var fields = [_]Info.Field{
...@@ -1524,6 +1609,7 @@ pub const Pool = struct {...@@ -1524,6 +1609,7 @@ pub const Pool = struct {
1524 const vector_ctype = try pool.getVector(allocator, .{1609 const vector_ctype = try pool.getVector(allocator, .{
1525 .elem_ctype = .u8,1610 .elem_ctype = .u8,
1526 .len = 2,1611 .len = 2,
1612 .nonstring = true,
1527 });1613 });
1528 if (!kind.isParameter()) return vector_ctype;1614 if (!kind.isParameter()) return vector_ctype;
1529 var fields = [_]Info.Field{1615 var fields = [_]Info.Field{
...@@ -1539,6 +1625,7 @@ pub const Pool = struct {...@@ -1539,6 +1625,7 @@ pub const Pool = struct {
1539 const vector_ctype = try pool.getVector(allocator, .{1625 const vector_ctype = try pool.getVector(allocator, .{
1540 .elem_ctype = .u8,1626 .elem_ctype = .u8,
1541 .len = 4,1627 .len = 4,
1628 .nonstring = true,
1542 });1629 });
1543 if (!kind.isParameter()) return vector_ctype;1630 if (!kind.isParameter()) return vector_ctype;
1544 var fields = [_]Info.Field{1631 var fields = [_]Info.Field{
...@@ -1554,6 +1641,7 @@ pub const Pool = struct {...@@ -1554,6 +1641,7 @@ pub const Pool = struct {
1554 const vector_ctype = try pool.getVector(allocator, .{1641 const vector_ctype = try pool.getVector(allocator, .{
1555 .elem_ctype = .u8,1642 .elem_ctype = .u8,
1556 .len = 8,1643 .len = 8,
1644 .nonstring = true,
1557 });1645 });
1558 if (!kind.isParameter()) return vector_ctype;1646 if (!kind.isParameter()) return vector_ctype;
1559 var fields = [_]Info.Field{1647 var fields = [_]Info.Field{
...@@ -1569,6 +1657,7 @@ pub const Pool = struct {...@@ -1569,6 +1657,7 @@ pub const Pool = struct {
1569 const vector_ctype = try pool.getVector(allocator, .{1657 const vector_ctype = try pool.getVector(allocator, .{
1570 .elem_ctype = .u8,1658 .elem_ctype = .u8,
1571 .len = 16,1659 .len = 16,
1660 .nonstring = true,
1572 });1661 });
1573 if (!kind.isParameter()) return vector_ctype;1662 if (!kind.isParameter()) return vector_ctype;
1574 var fields = [_]Info.Field{1663 var fields = [_]Info.Field{
...@@ -1584,6 +1673,7 @@ pub const Pool = struct {...@@ -1584,6 +1673,7 @@ pub const Pool = struct {
1584 const vector_ctype = try pool.getVector(allocator, .{1673 const vector_ctype = try pool.getVector(allocator, .{
1585 .elem_ctype = .u8,1674 .elem_ctype = .u8,
1586 .len = 32,1675 .len = 32,
1676 .nonstring = true,
1587 });1677 });
1588 if (!kind.isParameter()) return vector_ctype;1678 if (!kind.isParameter()) return vector_ctype;
1589 var fields = [_]Info.Field{1679 var fields = [_]Info.Field{
...@@ -1599,6 +1689,7 @@ pub const Pool = struct {...@@ -1599,6 +1689,7 @@ pub const Pool = struct {
1599 const vector_ctype = try pool.getVector(allocator, .{1689 const vector_ctype = try pool.getVector(allocator, .{
1600 .elem_ctype = .u8,1690 .elem_ctype = .u8,
1601 .len = 64,1691 .len = 64,
1692 .nonstring = true,
1602 });1693 });
1603 if (!kind.isParameter()) return vector_ctype;1694 if (!kind.isParameter()) return vector_ctype;
1604 var fields = [_]Info.Field{1695 var fields = [_]Info.Field{
...@@ -2225,6 +2316,11 @@ pub const Pool = struct {...@@ -2225,6 +2316,11 @@ pub const Pool = struct {
2225 .function => false,2316 .function => false,
2226 },2317 },
2227 .@"volatile" = ptr_info.flags.is_volatile,2318 .@"volatile" = ptr_info.flags.is_volatile,
2319 .nonstring = elem_ctype.isAnyChar() and switch (ptr_info.sentinel) {
2320 .none => true,
2321 .zero_u8 => false,
2322 else => |sentinel| Value.fromInterned(sentinel).orderAgainstZero(zcu).compare(.neq),
2323 },
2228 });2324 });
2229 },2325 },
2230 .slice => {2326 .slice => {
...@@ -2269,6 +2365,11 @@ pub const Pool = struct {...@@ -2269,6 +2365,11 @@ pub const Pool = struct {
2269 const array_ctype = try pool.getArray(allocator, .{2365 const array_ctype = try pool.getArray(allocator, .{
2270 .elem_ctype = elem_ctype,2366 .elem_ctype = elem_ctype,
2271 .len = len,2367 .len = len,
2368 .nonstring = elem_ctype.isAnyChar() and switch (array_info.sentinel) {
2369 .none => true,
2370 .zero_u8 => false,
2371 else => |sentinel| Value.fromInterned(sentinel).orderAgainstZero(zcu).compare(.neq),
2372 },
2272 });2373 });
2273 if (!kind.isParameter()) return array_ctype;2374 if (!kind.isParameter()) return array_ctype;
2274 var fields = [_]Info.Field{2375 var fields = [_]Info.Field{
...@@ -2295,6 +2396,7 @@ pub const Pool = struct {...@@ -2295,6 +2396,7 @@ pub const Pool = struct {
2295 const vector_ctype = try pool.getVector(allocator, .{2396 const vector_ctype = try pool.getVector(allocator, .{
2296 .elem_ctype = elem_ctype,2397 .elem_ctype = elem_ctype,
2297 .len = vector_info.len,2398 .len = vector_info.len,
2399 .nonstring = elem_ctype.isAnyChar(),
2298 });2400 });
2299 if (!kind.isParameter()) return vector_ctype;2401 if (!kind.isParameter()) return vector_ctype;
2300 var fields = [_]Info.Field{2402 var fields = [_]Info.Field{
...@@ -2773,9 +2875,17 @@ pub const Pool = struct {...@@ -2773,9 +2875,17 @@ pub const Pool = struct {
2773 const ctype: CType = .fromPoolIndex(gop.index);2875 const ctype: CType = .fromPoolIndex(gop.index);
2774 if (!gop.found_existing) switch (source_info) {2876 if (!gop.found_existing) switch (source_info) {
2775 .basic => unreachable,2877 .basic => unreachable,
2776 .pointer => |pointer_info| pool.items.appendAssumeCapacity(.{2878 .pointer => |pointer_info| pool.items.appendAssumeCapacity(switch (pointer_info.nonstring) {
2777 .tag = tag,2879 false => .{
2778 .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index),2880 .tag = tag,
2881 .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index),
2882 },
2883 true => .{
2884 .tag = .nonstring,
2885 .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt(
2886 source_pool.items.items(.data)[source_ctype.toPoolIndex().?],
2887 ) }).index),
2888 },
2779 }),2889 }),
2780 .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{2890 .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{
2781 .tag = tag,2891 .tag = tag,
...@@ -2784,19 +2894,27 @@ pub const Pool = struct {...@@ -2784,19 +2894,27 @@ pub const Pool = struct {
2784 .flags = .{ .alignas = aligned_info.alignas },2894 .flags = .{ .alignas = aligned_info.alignas },
2785 }, 0),2895 }, 0),
2786 }),2896 }),
2787 .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(.{2897 .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(switch (sequence_info.nonstring) {
2788 .tag = tag,2898 false => .{
2789 .data = switch (tag) {2899 .tag = tag,
2790 .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{2900 .data = switch (tag) {
2791 .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index,2901 .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{
2792 .len = @intCast(sequence_info.len),2902 .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index,
2793 }, 0),2903 .len = @intCast(sequence_info.len),
2794 .array_large => try pool.addExtra(allocator, SequenceLarge, .{2904 }, 0),
2795 .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index,2905 .array_large => try pool.addExtra(allocator, SequenceLarge, .{
2796 .len_lo = @truncate(sequence_info.len >> 0),2906 .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index,
2797 .len_hi = @truncate(sequence_info.len >> 32),2907 .len_lo = @truncate(sequence_info.len >> 0),
2798 }, 0),2908 .len_hi = @truncate(sequence_info.len >> 32),
2799 else => unreachable,2909 }, 0),
2910 else => unreachable,
2911 },
2912 },
2913 true => .{
2914 .tag = .nonstring,
2915 .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt(
2916 source_pool.items.items(.data)[source_ctype.toPoolIndex().?],
2917 ) }).index),
2800 },2918 },
2801 }),2919 }),
2802 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {2920 .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) {
...@@ -3068,6 +3186,7 @@ pub const Pool = struct {...@@ -3068,6 +3186,7 @@ pub const Pool = struct {
3068 array_small,3186 array_small,
3069 array_large,3187 array_large,
3070 vector,3188 vector,
3189 nonstring,
3071 fwd_decl_struct_anon,3190 fwd_decl_struct_anon,
3072 fwd_decl_union_anon,3191 fwd_decl_union_anon,
3073 fwd_decl_struct,3192 fwd_decl_struct,
...@@ -3283,4 +3402,5 @@ const CType = @This();...@@ -3283,4 +3402,5 @@ const CType = @This();
3283const InternPool = @import("../../InternPool.zig");3402const InternPool = @import("../../InternPool.zig");
3284const Module = @import("../../Package/Module.zig");3403const Module = @import("../../Package/Module.zig");
3285const Type = @import("../../Type.zig");3404const Type = @import("../../Type.zig");
3405const Value = @import("../../Value.zig");
3286const Zcu = @import("../../Zcu.zig");3406const Zcu = @import("../../Zcu.zig");
test/behavior/x86_64/binary.zig+1-1
...@@ -1912,7 +1912,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela...@@ -1912,7 +1912,7 @@ fn binary(comptime op: anytype, comptime opts: struct { compare: Compare = .rela
1912 -0x1,1912 -0x1,
1913 });1913 });
1914 try testArgs(@Vector(2, i1), .{1914 try testArgs(@Vector(2, i1), .{
1915 0x0, 0x00,1915 0x0, 0x0,
1916 }, .{1916 }, .{
1917 -0x1, -0x1,1917 -0x1, -0x1,
1918 });1918 });