authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-29 07:30:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log4f70863a55e699c13731325f8c52870119479c02
treec3e45219ecaf9ae0fd2ffc7316a0063028d65fce
parent32692569656d9a178abb24f8fb7893395700cb62

InternPool: fix various pointer issues


4 files changed, 102 insertions(+), 80 deletions(-)

src/InternPool.zig+78-67
......@@ -1374,12 +1374,12 @@ pub const Index = enum(u32) {
13741374 undef: DataIsIndex,
13751375 runtime_value: DataIsIndex,
13761376 simple_value: struct { data: SimpleValue },
1377 ptr_mut_decl: struct { data: *PtrMutDecl },
13781377 ptr_decl: struct { data: *PtrDecl },
1379 ptr_int: struct { data: *PtrAddr },
1380 ptr_eu_payload: DataIsIndex,
1381 ptr_opt_payload: DataIsIndex,
1378 ptr_mut_decl: struct { data: *PtrMutDecl },
13821379 ptr_comptime_field: struct { data: *PtrComptimeField },
1380 ptr_int: struct { data: *PtrBase },
1381 ptr_eu_payload: struct { data: *PtrBase },
1382 ptr_opt_payload: struct { data: *PtrBase },
13831383 ptr_elem: struct { data: *PtrBaseIndex },
13841384 ptr_field: struct { data: *PtrBaseIndex },
13851385 ptr_slice: struct { data: *PtrSlice },
......@@ -1774,29 +1774,25 @@ pub const Tag = enum(u8) {
17741774 /// A value that can be represented with only an enum tag.
17751775 /// data is SimpleValue enum value.
17761776 simple_value,
1777 /// A pointer to a decl that can be mutated at comptime.
1778 /// data is extra index of PtrMutDecl, which contains the type and address.
1779 ptr_mut_decl,
17801777 /// A pointer to a decl.
1781 /// data is extra index of PtrDecl, which contains the type and address.
1778 /// data is extra index of `PtrDecl`, which contains the type and address.
17821779 ptr_decl,
1780 /// A pointer to a decl that can be mutated at comptime.
1781 /// data is extra index of `PtrMutDecl`, which contains the type and address.
1782 ptr_mut_decl,
1783 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
1784 ptr_comptime_field,
17831785 /// A pointer with an integer value.
1784 /// data is extra index of PtrAddr, which contains the type and address.
1786 /// data is extra index of `PtrBase`, which contains the type and address.
17851787 /// Only pointer types are allowed to have this encoding. Optional types must use
17861788 /// `opt_payload` or `opt_null`.
17871789 ptr_int,
17881790 /// A pointer to the payload of an error union.
1789 /// data is Index of a pointer value to the error union.
1790 /// In order to use this encoding, one must ensure that the `InternPool`
1791 /// already contains the payload pointer type corresponding to this payload.
1791 /// data is extra index of `PtrBase`, which contains the type and base pointer.
17921792 ptr_eu_payload,
17931793 /// A pointer to the payload of an optional.
1794 /// data is Index of a pointer value to the optional.
1795 /// In order to use this encoding, one must ensure that the `InternPool`
1796 /// already contains the payload pointer type corresponding to this payload.
1794 /// data is extra index of `PtrBase`, which contains the type and base pointer.
17971795 ptr_opt_payload,
1798 /// data is extra index of PtrComptimeField, which contains the pointer type and field value.
1799 ptr_comptime_field,
18001796 /// A pointer to an array element.
18011797 /// data is extra index of PtrBaseIndex, which contains the base array and element index.
18021798 /// In order to use this encoding, one must ensure that the `InternPool`
......@@ -2224,14 +2220,14 @@ pub const PtrMutDecl = struct {
22242220 runtime_index: RuntimeIndex,
22252221};
22262222
2227pub const PtrAddr = struct {
2223pub const PtrComptimeField = struct {
22282224 ty: Index,
2229 addr: Index,
2225 field_val: Index,
22302226};
22312227
2232pub const PtrComptimeField = struct {
2228pub const PtrBase = struct {
22332229 ty: Index,
2234 field_val: Index,
2230 base: Index,
22352231};
22362232
22372233pub const PtrBaseIndex = struct {
......@@ -2598,36 +2594,23 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
25982594 } },
25992595 } };
26002596 },
2601 .ptr_int => {
2602 const info = ip.extraData(PtrAddr, data);
2597 .ptr_comptime_field => {
2598 const info = ip.extraData(PtrComptimeField, data);
26032599 return .{ .ptr = .{
26042600 .ty = info.ty,
2605 .addr = .{ .int = info.addr },
2606 } };
2607 },
2608 .ptr_eu_payload => {
2609 const ptr_eu_index = @intToEnum(Index, data);
2610 var ptr_type = ip.indexToKey(ip.typeOf(ptr_eu_index)).ptr_type;
2611 ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).error_union_type.payload_type;
2612 return .{ .ptr = .{
2613 .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
2614 .addr = .{ .eu_payload = ptr_eu_index },
2601 .addr = .{ .comptime_field = info.field_val },
26152602 } };
26162603 },
2617 .ptr_opt_payload => {
2618 const ptr_opt_index = @intToEnum(Index, data);
2619 var ptr_type = ip.indexToKey(ip.typeOf(ptr_opt_index)).ptr_type;
2620 ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).opt_type;
2621 return .{ .ptr = .{
2622 .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
2623 .addr = .{ .opt_payload = ptr_opt_index },
2624 } };
2625 },
2626 .ptr_comptime_field => {
2627 const info = ip.extraData(PtrComptimeField, data);
2604 .ptr_int, .ptr_eu_payload, .ptr_opt_payload => {
2605 const info = ip.extraData(PtrBase, data);
26282606 return .{ .ptr = .{
26292607 .ty = info.ty,
2630 .addr = .{ .comptime_field = info.field_val },
2608 .addr = switch (item.tag) {
2609 .ptr_int => .{ .int = info.base },
2610 .ptr_eu_payload => .{ .eu_payload = info.base },
2611 .ptr_opt_payload => .{ .opt_payload = info.base },
2612 else => unreachable,
2613 },
26312614 } };
26322615 },
26332616 .ptr_elem => {
......@@ -3248,39 +3231,67 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
32483231 .runtime_index = mut_decl.runtime_index,
32493232 }),
32503233 }),
3251 .int => |int| {
3252 assert(ip.typeOf(int) == .usize_type);
3234 .comptime_field => |field_val| {
3235 assert(field_val != .none);
32533236 ip.items.appendAssumeCapacity(.{
3254 .tag = .ptr_int,
3255 .data = try ip.addExtra(gpa, PtrAddr{
3237 .tag = .ptr_comptime_field,
3238 .data = try ip.addExtra(gpa, PtrComptimeField{
32563239 .ty = ptr.ty,
3257 .addr = int,
3240 .field_val = field_val,
32583241 }),
32593242 });
32603243 },
3261 .eu_payload, .opt_payload => |data| {
3262 assert(data != .none);
3244 .int, .eu_payload, .opt_payload => |base| {
3245 switch (ptr.addr) {
3246 .int => assert(ip.typeOf(base) == .usize_type),
3247 .eu_payload => assert(ip.indexToKey(
3248 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3249 ) == .error_union_type),
3250 .opt_payload => assert(ip.indexToKey(
3251 ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
3252 ) == .opt_type),
3253 else => unreachable,
3254 }
32633255 ip.items.appendAssumeCapacity(.{
32643256 .tag = switch (ptr.addr) {
3257 .int => .ptr_int,
32653258 .eu_payload => .ptr_eu_payload,
32663259 .opt_payload => .ptr_opt_payload,
32673260 else => unreachable,
32683261 },
3269 .data = @enumToInt(data),
3270 });
3271 },
3272 .comptime_field => |field_val| {
3273 assert(field_val != .none);
3274 ip.items.appendAssumeCapacity(.{
3275 .tag = .ptr_comptime_field,
3276 .data = try ip.addExtra(gpa, PtrComptimeField{
3262 .data = try ip.addExtra(gpa, PtrBase{
32773263 .ty = ptr.ty,
3278 .field_val = field_val,
3264 .base = base,
32793265 }),
32803266 });
32813267 },
32823268 .elem, .field => |base_index| {
3283 assert(base_index.base != .none);
3269 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3270 switch (base_ptr_type.size) {
3271 .One => switch (ip.indexToKey(base_ptr_type.elem_type)) {
3272 .array_type, .vector_type => assert(ptr.addr == .elem),
3273 .anon_struct_type => |anon_struct_type| {
3274 assert(ptr.addr == .field);
3275 assert(base_index.index < anon_struct_type.types.len);
3276 },
3277 .struct_type => |struct_type| {
3278 assert(ptr.addr == .field);
3279 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3280 },
3281 .union_type => |union_type| {
3282 assert(ptr.addr == .field);
3283 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3284 },
3285 .ptr_type => |slice_type| {
3286 assert(ptr.addr == .field);
3287 assert(slice_type.size == .Slice);
3288 assert(base_index.index < 2);
3289 },
3290 else => unreachable,
3291 },
3292 .Many => assert(ptr.addr == .elem),
3293 .Slice, .C => unreachable,
3294 }
32843295 _ = ip.map.pop();
32853296 const index_index = try ip.get(gpa, .{ .int = .{
32863297 .ty = .usize_type,
......@@ -4750,10 +4761,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
47504761 .simple_value => 0,
47514762 .ptr_decl => @sizeOf(PtrDecl),
47524763 .ptr_mut_decl => @sizeOf(PtrMutDecl),
4753 .ptr_int => @sizeOf(PtrAddr),
4754 .ptr_eu_payload => 0,
4755 .ptr_opt_payload => 0,
47564764 .ptr_comptime_field => @sizeOf(PtrComptimeField),
4765 .ptr_int => @sizeOf(PtrBase),
4766 .ptr_eu_payload => @sizeOf(PtrBase),
4767 .ptr_opt_payload => @sizeOf(PtrBase),
47574768 .ptr_elem => @sizeOf(PtrBaseIndex),
47584769 .ptr_field => @sizeOf(PtrBaseIndex),
47594770 .ptr_slice => @sizeOf(PtrSlice),
......@@ -5281,12 +5292,12 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std
52815292 .undef,
52825293 .runtime_value,
52835294 .simple_value,
5284 .ptr_mut_decl,
52855295 .ptr_decl,
5296 .ptr_mut_decl,
5297 .ptr_comptime_field,
52865298 .ptr_int,
52875299 .ptr_eu_payload,
52885300 .ptr_opt_payload,
5289 .ptr_comptime_field,
52905301 .ptr_elem,
52915302 .ptr_field,
52925303 .ptr_slice,
src/Module.zig+4
......@@ -6716,6 +6716,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
67166716 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });
67176717}
67186718
6719pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6720 return ptrType(mod, .{ .elem_type = child_type.toIntern(), .size = .Many, .is_const = true });
6721}
6722
67196723pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
67206724 const info = Type.ptrInfoIp(mod.intern_pool, ptr_ty.toIntern());
67216725 return mod.ptrType(.{
src/Sema.zig+17-12
......@@ -25412,11 +25412,13 @@ fn elemVal(
2541225412 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
2541325413 const index_val = maybe_index_val orelse break :rs elem_index_src;
2541425414 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25415 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index);
25416 const elem_ptr_val = try indexable_val.elemPtr(elem_ptr_ty, index, mod);
25415 const elem_ty = indexable_ty.elemType2(mod);
25416 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
25417 const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);
25418 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
25419 const elem_ptr_val = try many_ptr_val.elemPtr(elem_ptr_ty, index, mod);
2541725420 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
25418 const result_ty = indexable_ty.elemType2(mod);
25419 return sema.addConstant(result_ty, try mod.getCoerced(elem_val, result_ty));
25421 return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
2542025422 }
2542125423 break :rs indexable_src;
2542225424 };
......@@ -29906,7 +29908,7 @@ fn analyzeSlice(
2990629908 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
2990729909 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {
2990829910 .Pointer => ptr_ptr_ty.childType(mod),
29909 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}),
29911 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(mod)}),
2991029912 };
2991129913
2991229914 var array_ty = ptr_ptr_child_ty;
......@@ -30111,7 +30113,10 @@ fn analyzeSlice(
3011130113 const end_int = end_val.getUnsignedInt(mod).?;
3011230114 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
3011330115
30114 const elem_ptr = try ptr_val.elemPtr(try sema.elemPtrType(new_ptr_ty, sentinel_index), sentinel_index, sema.mod);
30116 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
30117 const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);
30118 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
30119 const elem_ptr = try many_ptr_val.elemPtr(elem_ptr_ty, sentinel_index, mod);
3011530120 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty);
3011630121 const actual_sentinel = switch (res) {
3011730122 .runtime_load => break :sentinel_check,
......@@ -30120,23 +30125,23 @@ fn analyzeSlice(
3012030125 block,
3012130126 src,
3012230127 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
30123 .{ty.fmt(sema.mod)},
30128 .{ty.fmt(mod)},
3012430129 ),
3012530130 .out_of_bounds => |ty| return sema.fail(
3012630131 block,
3012730132 end_src,
3012830133 "slice end index {d} exceeds bounds of containing decl of type '{}'",
30129 .{ end_int, ty.fmt(sema.mod) },
30134 .{ end_int, ty.fmt(mod) },
3013030135 ),
3013130136 };
3013230137
30133 if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {
30138 if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) {
3013430139 const msg = msg: {
3013530140 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
3013630141 errdefer msg.destroy(sema.gpa);
3013730142 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
30138 expected_sentinel.fmtValue(elem_ty, sema.mod),
30139 actual_sentinel.fmtValue(elem_ty, sema.mod),
30143 expected_sentinel.fmtValue(elem_ty, mod),
30144 actual_sentinel.fmtValue(elem_ty, mod),
3014030145 });
3014130146
3014230147 break :msg msg;
......@@ -30310,7 +30315,7 @@ fn cmpNumeric(
3031030315
3031130316 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
3031230317 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
30313 const target = sema.mod.getTarget();
30318 const target = mod.getTarget();
3031430319
3031530320 // One exception to heterogeneous comparison: comptime_float needs to
3031630321 // coerce to fixed-width float.
src/value.zig+3-1
......@@ -1857,7 +1857,8 @@ pub const Value = struct {
18571857 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
18581858 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
18591859 .toValue().elemValue(mod, index),
1860 .int, .eu_payload, .opt_payload => unreachable,
1860 .int, .eu_payload => unreachable,
1861 .opt_payload => |base| base.toValue().elemValue(mod, index),
18611862 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
18621863 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
18631864 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
......@@ -1866,6 +1867,7 @@ pub const Value = struct {
18661867 return field_val.elemValue(mod, index);
18671868 } else unreachable,
18681869 },
1870 .opt => |opt| opt.val.toValue().elemValue(mod, index),
18691871 .aggregate => |aggregate| {
18701872 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
18711873 if (index < len) return switch (aggregate.storage) {