diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-02-01 16:58:52 +0000 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2024-02-02 11:02:03 +0000 |
| commit | 9eda6ccefce370c76209ea50dd57fe65bfe25536 (patch) | |
| tree | d5b4af496b8a6d1811788557d85e340ce26ef2bc /src | |
| parent | 5a3ae38f3b79a69cb6f4ad28934a51165cae2ef1 (diff) | |
| download | zig-9eda6ccefce370c76209ea50dd57fe65bfe25536.tar.gz zig-9eda6ccefce370c76209ea50dd57fe65bfe25536.zip | |
InternPool: use separate key for slices
This change eliminates some problematic recursive logic in InternPool,
and provides a safer API.
Diffstat (limited to 'src')
| -rw-r--r-- | src/InternPool.zig | 400 | ||||
| -rw-r--r-- | src/Module.zig | 35 | ||||
| -rw-r--r-- | src/Sema.zig | 289 | ||||
| -rw-r--r-- | src/TypedValue.zig | 88 | ||||
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 15 | ||||
| -rw-r--r-- | src/codegen.zig | 31 | ||||
| -rw-r--r-- | src/codegen/c.zig | 71 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 39 | ||||
| -rw-r--r-- | src/codegen/spirv.zig | 18 | ||||
| -rw-r--r-- | src/type.zig | 9 | ||||
| -rw-r--r-- | src/value.zig | 84 |
11 files changed, 533 insertions, 546 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index 88bd24ec93..01cd41942d 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -326,6 +326,7 @@ pub const Key = union(enum) { empty_enum_value: Index, float: Float, ptr: Ptr, + slice: Slice, opt: Opt, /// An instance of a struct, array, or vector. /// Each element/field stored as an `Index`. @@ -493,7 +494,7 @@ pub const Key = union(enum) { start: u32, len: u32, - pub fn get(slice: Slice, ip: *const InternPool) []RuntimeOrder { + pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder { return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); } }; @@ -1197,8 +1198,6 @@ pub const Key = union(enum) { ty: Index, /// The value of the address that the pointer points to. addr: Addr, - /// This could be `none` if size is not a slice. - len: Index = .none, pub const Addr = union(enum) { const Tag = @typeInfo(Addr).Union.tag_type.?; @@ -1232,6 +1231,15 @@ pub const Key = union(enum) { }; }; + pub const Slice = struct { + /// This is the slice type, not the element type. + ty: Index, + /// The slice's `ptr` field. Must be a many-ptr with the same properties as `ty`. + ptr: Index, + /// The slice's `len` field. Must be a `usize`. + len: Index, + }; + /// `null` is represented by the `val` field being `none`. pub const Opt = extern struct { /// This is the optional type; not the payload type. @@ -1354,12 +1362,14 @@ pub const Key = union(enum) { return hasher.final(); }, + .slice => |slice| Hash.hash(seed, asBytes(&slice.ty) ++ asBytes(&slice.ptr) ++ asBytes(&slice.len)), + .ptr => |ptr| { // Int-to-ptr pointers are hashed separately than decl-referencing pointers. // This is sound due to pointer provenance rules. const addr: @typeInfo(Key.Ptr.Addr).Union.tag_type.? = ptr.addr; const seed2 = seed + @intFromEnum(addr); - const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len); + const common = asBytes(&ptr.ty); return switch (ptr.addr) { .decl => |x| Hash.hash(seed2, common ++ asBytes(&x)), @@ -1624,9 +1634,17 @@ pub const Key = union(enum) { return a_ty_info.eql(b_ty_info, ip); }, + .slice => |a_info| { + const b_info = b.slice; + if (a_info.ty != b_info.ty) return false; + if (a_info.ptr != b_info.ptr) return false; + if (a_info.len != b_info.len) return false; + return true; + }, + .ptr => |a_info| { const b_info = b.ptr; - if (a_info.ty != b_info.ty or a_info.len != b_info.len) return false; + if (a_info.ty != b_info.ty) return false; const AddrTag = @typeInfo(Key.Ptr.Addr).Union.tag_type.?; if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false; @@ -1829,6 +1847,7 @@ pub const Key = union(enum) { => .type_type, inline .ptr, + .slice, .int, .float, .opt, @@ -3983,77 +4002,11 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .ptr_slice => { const info = ip.extraData(PtrSlice, data); - const ptr_item = ip.items.get(@intFromEnum(info.ptr)); - return .{ - .ptr = .{ - .ty = info.ty, - .addr = switch (ptr_item.tag) { - .ptr_decl => .{ - .decl = ip.extraData(PtrDecl, ptr_item.data).decl, - }, - .ptr_mut_decl => b: { - const sub_info = ip.extraData(PtrMutDecl, ptr_item.data); - break :b .{ .mut_decl = .{ - .decl = sub_info.decl, - .runtime_index = sub_info.runtime_index, - } }; - }, - .ptr_anon_decl => .{ - .anon_decl = .{ - .val = ip.extraData(PtrAnonDecl, ptr_item.data).val, - .orig_ty = info.ty, - }, - }, - .ptr_anon_decl_aligned => b: { - const sub_info = ip.extraData(PtrAnonDeclAligned, ptr_item.data); - break :b .{ .anon_decl = .{ - .val = sub_info.val, - .orig_ty = sub_info.orig_ty, - } }; - }, - .ptr_comptime_field => .{ - .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val, - }, - .ptr_int => .{ - .int = ip.extraData(PtrBase, ptr_item.data).base, - }, - .ptr_eu_payload => .{ - .eu_payload = ip.extraData(PtrBase, ptr_item.data).base, - }, - .ptr_opt_payload => .{ - .opt_payload = ip.extraData(PtrBase, ptr_item.data).base, - }, - .ptr_elem => b: { - // Avoid `indexToKey` recursion by asserting the tag encoding. - const sub_info = ip.extraData(PtrBaseIndex, ptr_item.data); - const index_item = ip.items.get(@intFromEnum(sub_info.index)); - break :b switch (index_item.tag) { - .int_usize => .{ .elem = .{ - .base = sub_info.base, - .index = index_item.data, - } }, - .int_positive => @panic("TODO"), // implement along with behavior test coverage - else => unreachable, - }; - }, - .ptr_field => b: { - // Avoid `indexToKey` recursion by asserting the tag encoding. - const sub_info = ip.extraData(PtrBaseIndex, ptr_item.data); - const index_item = ip.items.get(@intFromEnum(sub_info.index)); - break :b switch (index_item.tag) { - .int_usize => .{ .field = .{ - .base = sub_info.base, - .index = index_item.data, - } }, - .int_positive => @panic("TODO"), // implement along with behavior test coverage - else => unreachable, - }; - }, - else => unreachable, - }, - .len = info.len, - }, - }; + return .{ .slice = .{ + .ty = info.ty, + .ptr = info.ptr, + .len = info.len, + } }; }, .int_u8 => .{ .int = .{ .ty = .u8_type, @@ -4735,153 +4688,139 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }); }, + .slice => |slice| { + assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .Slice); + assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .Many); + ip.items.appendAssumeCapacity(.{ + .tag = .ptr_slice, + .data = try ip.addExtra(gpa, PtrSlice{ + .ty = slice.ty, + .ptr = slice.ptr, + .len = slice.len, + }), + }); + }, + .ptr => |ptr| { const ptr_type = ip.indexToKey(ptr.ty).ptr_type; - switch (ptr.len) { - .none => { - assert(ptr_type.flags.size != .Slice); - switch (ptr.addr) { - .decl => |decl| ip.items.appendAssumeCapacity(.{ - .tag = .ptr_decl, - .data = try ip.addExtra(gpa, PtrDecl{ - .ty = ptr.ty, - .decl = decl, - }), + assert(ptr_type.flags.size != .Slice); + switch (ptr.addr) { + .decl => |decl| ip.items.appendAssumeCapacity(.{ + .tag = .ptr_decl, + .data = try ip.addExtra(gpa, PtrDecl{ + .ty = ptr.ty, + .decl = decl, + }), + }), + .mut_decl => |mut_decl| ip.items.appendAssumeCapacity(.{ + .tag = .ptr_mut_decl, + .data = try ip.addExtra(gpa, PtrMutDecl{ + .ty = ptr.ty, + .decl = mut_decl.decl, + .runtime_index = mut_decl.runtime_index, + }), + }), + .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( + if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ + .tag = .ptr_anon_decl, + .data = try ip.addExtra(gpa, PtrAnonDecl{ + .ty = ptr.ty, + .val = anon_decl.val, }), - .mut_decl => |mut_decl| ip.items.appendAssumeCapacity(.{ - .tag = .ptr_mut_decl, - .data = try ip.addExtra(gpa, PtrMutDecl{ - .ty = ptr.ty, - .decl = mut_decl.decl, - .runtime_index = mut_decl.runtime_index, - }), + } else .{ + .tag = .ptr_anon_decl_aligned, + .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ + .ty = ptr.ty, + .val = anon_decl.val, + .orig_ty = anon_decl.orig_ty, }), - .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( - if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ - .tag = .ptr_anon_decl, - .data = try ip.addExtra(gpa, PtrAnonDecl{ - .ty = ptr.ty, - .val = anon_decl.val, - }), - } else .{ - .tag = .ptr_anon_decl_aligned, - .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ - .ty = ptr.ty, - .val = anon_decl.val, - .orig_ty = anon_decl.orig_ty, - }), - }, - ), - .comptime_field => |field_val| { - assert(field_val != .none); - ip.items.appendAssumeCapacity(.{ - .tag = .ptr_comptime_field, - .data = try ip.addExtra(gpa, PtrComptimeField{ - .ty = ptr.ty, - .field_val = field_val, - }), - }); + }, + ), + .comptime_field => |field_val| { + assert(field_val != .none); + ip.items.appendAssumeCapacity(.{ + .tag = .ptr_comptime_field, + .data = try ip.addExtra(gpa, PtrComptimeField{ + .ty = ptr.ty, + .field_val = field_val, + }), + }); + }, + .int, .eu_payload, .opt_payload => |base| { + switch (ptr.addr) { + .int => assert(ip.typeOf(base) == .usize_type), + .eu_payload => assert(ip.indexToKey( + ip.indexToKey(ip.typeOf(base)).ptr_type.child, + ) == .error_union_type), + .opt_payload => assert(ip.indexToKey( + ip.indexToKey(ip.typeOf(base)).ptr_type.child, + ) == .opt_type), + else => unreachable, + } + ip.items.appendAssumeCapacity(.{ + .tag = switch (ptr.addr) { + .int => .ptr_int, + .eu_payload => .ptr_eu_payload, + .opt_payload => .ptr_opt_payload, + else => unreachable, }, - .int, .eu_payload, .opt_payload => |base| { - switch (ptr.addr) { - .int => assert(ip.typeOf(base) == .usize_type), - .eu_payload => assert(ip.indexToKey( - ip.indexToKey(ip.typeOf(base)).ptr_type.child, - ) == .error_union_type), - .opt_payload => assert(ip.indexToKey( - ip.indexToKey(ip.typeOf(base)).ptr_type.child, - ) == .opt_type), - else => unreachable, - } - ip.items.appendAssumeCapacity(.{ - .tag = switch (ptr.addr) { - .int => .ptr_int, - .eu_payload => .ptr_eu_payload, - .opt_payload => .ptr_opt_payload, - else => unreachable, + .data = try ip.addExtra(gpa, PtrBase{ + .ty = ptr.ty, + .base = base, + }), + }); + }, + .elem, .field => |base_index| { + const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; + switch (ptr.addr) { + .elem => assert(base_ptr_type.flags.size == .Many), + .field => { + assert(base_ptr_type.flags.size == .One); + switch (ip.indexToKey(base_ptr_type.child)) { + .anon_struct_type => |anon_struct_type| { + assert(ptr.addr == .field); + assert(base_index.index < anon_struct_type.types.len); }, - .data = try ip.addExtra(gpa, PtrBase{ - .ty = ptr.ty, - .base = base, - }), - }); - }, - .elem, .field => |base_index| { - const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; - switch (ptr.addr) { - .elem => assert(base_ptr_type.flags.size == .Many), - .field => { - assert(base_ptr_type.flags.size == .One); - switch (ip.indexToKey(base_ptr_type.child)) { - .anon_struct_type => |anon_struct_type| { - assert(ptr.addr == .field); - assert(base_index.index < anon_struct_type.types.len); - }, - .struct_type => |struct_type| { - assert(ptr.addr == .field); - assert(base_index.index < struct_type.field_types.len); - }, - .union_type => |union_key| { - const union_type = ip.loadUnionType(union_key); - assert(ptr.addr == .field); - assert(base_index.index < union_type.field_names.len); - }, - .ptr_type => |slice_type| { - assert(ptr.addr == .field); - assert(slice_type.flags.size == .Slice); - assert(base_index.index < 2); - }, - else => unreachable, - } + .struct_type => |struct_type| { + assert(ptr.addr == .field); + assert(base_index.index < struct_type.field_types.len); + }, + .union_type => |union_key| { + const union_type = ip.loadUnionType(union_key); + assert(ptr.addr == .field); + assert(base_index.index < union_type.field_names.len); + }, + .ptr_type => |slice_type| { + assert(ptr.addr == .field); + assert(slice_type.flags.size == .Slice); + assert(base_index.index < 2); }, else => unreachable, } - _ = ip.map.pop(); - const index_index = try ip.get(gpa, .{ .int = .{ - .ty = .usize_type, - .storage = .{ .u64 = base_index.index }, - } }); - assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); - try ip.items.ensureUnusedCapacity(gpa, 1); - ip.items.appendAssumeCapacity(.{ - .tag = switch (ptr.addr) { - .elem => .ptr_elem, - .field => .ptr_field, - else => unreachable, - }, - .data = try ip.addExtra(gpa, PtrBaseIndex{ - .ty = ptr.ty, - .base = base_index.base, - .index = index_index, - }), - }); }, + else => unreachable, } - }, - else => { - // TODO: change Key.Ptr for slices to reference the manyptr value - // rather than having an addr field directly. Then we can avoid - // these problematic calls to pop(), get(), and getOrPutAdapted(). - assert(ptr_type.flags.size == .Slice); _ = ip.map.pop(); - var new_key = key; - new_key.ptr.ty = ip.slicePtrType(ptr.ty); - new_key.ptr.len = .none; - assert(ip.indexToKey(new_key.ptr.ty).ptr_type.flags.size == .Many); - const ptr_index = try ip.get(gpa, new_key); + const index_index = try ip.get(gpa, .{ .int = .{ + .ty = .usize_type, + .storage = .{ .u64 = base_index.index }, + } }); assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); try ip.items.ensureUnusedCapacity(gpa, 1); ip.items.appendAssumeCapacity(.{ - .tag = .ptr_slice, - .data = try ip.addExtra(gpa, PtrSlice{ + .tag = switch (ptr.addr) { + .elem => .ptr_elem, + .field => .ptr_field, + else => unreachable, + }, + .data = try ip.addExtra(gpa, PtrBaseIndex{ .ty = ptr.ty, - .ptr = ptr_index, - .len = ptr.len, + .base = base_index.base, + .index = index_index, }), }); }, } - assert(ptr.ty == ip.indexToKey(@as(Index, @enumFromInt(ip.items.len - 1))).ptr.ty); }, .opt => |opt| { @@ -6844,14 +6783,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al .val = .none, } }); - if (ip.isPointerType(new_ty)) return ip.get(gpa, .{ .ptr = .{ - .ty = new_ty, - .addr = .{ .int = .zero_usize }, - .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) { - .One, .Many, .C => .none, - .Slice => try ip.get(gpa, .{ .undef = .usize_type }), - }, - } }); + if (ip.isPointerType(new_ty)) switch (ip.indexToKey(new_ty).ptr_type.flags.size) { + .One, .Many, .C => return ip.get(gpa, .{ .ptr = .{ + .ty = new_ty, + .addr = .{ .int = .zero_usize }, + } }), + .Slice => return ip.get(gpa, .{ .slice = .{ + .ty = new_ty, + .ptr = try ip.get(gpa, .{ .ptr = .{ + .ty = ip.slicePtrType(new_ty), + .addr = .{ .int = .zero_usize }, + } }), + .len = try ip.get(gpa, .{ .undef = .usize_type }), + } }), + }; }, else => switch (tags[@intFromEnum(val)]) { .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty), @@ -6929,11 +6874,18 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al }, else => {}, }, - .ptr => |ptr| if (ip.isPointerType(new_ty)) + .slice => |slice| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size == .Slice) + return ip.get(gpa, .{ .slice = .{ + .ty = new_ty, + .ptr = try ip.getCoerced(gpa, slice.ptr, ip.slicePtrType(new_ty)), + .len = slice.len, + } }) + else if (ip.isIntegerType(new_ty)) + return ip.getCoerced(gpa, slice.ptr, new_ty), + .ptr => |ptr| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size != .Slice) return ip.get(gpa, .{ .ptr = .{ .ty = new_ty, .addr = ptr.addr, - .len = ptr.len, } }) else if (ip.isIntegerType(new_ty)) switch (ptr.addr) { @@ -6942,14 +6894,20 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al }, .opt => |opt| switch (ip.indexToKey(new_ty)) { .ptr_type => |ptr_type| return switch (opt.val) { - .none => try ip.get(gpa, .{ .ptr = .{ - .ty = new_ty, - .addr = .{ .int = .zero_usize }, - .len = switch (ptr_type.flags.size) { - .One, .Many, .C => .none, - .Slice => try ip.get(gpa, .{ .undef = .usize_type }), - }, - } }), + .none => switch (ptr_type.flags.size) { + .One, .Many, .C => try ip.get(gpa, .{ .ptr = .{ + .ty = new_ty, + .addr = .{ .int = .zero_usize }, + } }), + .Slice => try ip.get(gpa, .{ .slice = .{ + .ty = new_ty, + .ptr = try ip.get(gpa, .{ .ptr = .{ + .ty = ip.slicePtrType(new_ty), + .addr = .{ .int = .zero_usize }, + } }), + .len = try ip.get(gpa, .{ .undef = .usize_type }), + } }), + }, else => |payload| try ip.getCoerced(gpa, payload, new_ty), }, .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{ diff --git a/src/Module.zig b/src/Module.zig index 499eb02f1e..1b3342f775 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5278,9 +5278,12 @@ pub fn populateTestFunctions( const test_fn_fields = .{ // name - try mod.intern(.{ .ptr = .{ + try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_type, - .addr = .{ .decl = test_name_decl_index }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_type, + .addr = .{ .decl = test_name_decl_index }, + } }), .len = try mod.intern(.{ .int = .{ .ty = .usize_type, .storage = .{ .u64 = test_decl_name.len }, @@ -5331,9 +5334,12 @@ pub fn populateTestFunctions( }, }); const new_val = decl.val; - const new_init = try mod.intern(.{ .ptr = .{ + const new_init = try mod.intern(.{ .slice = .{ .ty = new_ty.toIntern(), - .addr = .{ .decl = array_decl_index }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = new_ty.slicePtrFieldType(mod).toIntern(), + .addr = .{ .decl = array_decl_index }, + } }), .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(), } }); ip.mutateVarInit(decl.val.toIntern(), new_init); @@ -5423,16 +5429,17 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void { .err_name => {}, .payload => |payload| try mod.markReferencedDeclsAlive(Value.fromInterned(payload)), }, - .ptr => |ptr| { - switch (ptr.addr) { - .decl => |decl| try mod.markDeclIndexAlive(decl), - .anon_decl => {}, - .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl), - .int, .comptime_field => {}, - .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(Value.fromInterned(parent)), - .elem, .field => |base_index| try mod.markReferencedDeclsAlive(Value.fromInterned(base_index.base)), - } - if (ptr.len != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(ptr.len)); + .slice => |slice| { + try mod.markReferencedDeclsAlive(Value.fromInterned(slice.ptr)); + try mod.markReferencedDeclsAlive(Value.fromInterned(slice.len)); + }, + .ptr => |ptr| switch (ptr.addr) { + .decl => |decl| try mod.markDeclIndexAlive(decl), + .anon_decl => {}, + .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl), + .int, .comptime_field => {}, + .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(Value.fromInterned(parent)), + .elem, .field => |base_index| try mod.markReferencedDeclsAlive(Value.fromInterned(base_index.base)), }, .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(opt.val)), .aggregate => |aggregate| for (aggregate.storage.values()) |elem| diff --git a/src/Sema.zig b/src/Sema.zig index f852710b95..8a30d2bb33 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -17375,16 +17375,19 @@ fn zirBuiltinSrc( .sentinel = .zero_u8, .child = .u8_type, } }); - break :v try ip.get(gpa, .{ .ptr = .{ + break :v try ip.get(gpa, .{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, + .ptr = try ip.get(gpa, .{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .orig_ty = .slice_const_u8_sentinel_0_type, + .val = try ip.get(gpa, .{ .aggregate = .{ + .ty = array_ty, + .storage = .{ .bytes = bytes }, + } }), + } }, + } }), .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), - .addr = .{ .anon_decl = .{ - .orig_ty = .slice_const_u8_sentinel_0_type, - .val = try ip.get(gpa, .{ .aggregate = .{ - .ty = array_ty, - .storage = .{ .bytes = bytes }, - } }), - } }, } }); }; @@ -17396,16 +17399,19 @@ fn zirBuiltinSrc( .sentinel = .zero_u8, .child = .u8_type, } }); - break :v try ip.get(gpa, .{ .ptr = .{ + break :v try ip.get(gpa, .{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, + .ptr = try ip.get(gpa, .{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .orig_ty = .slice_const_u8_sentinel_0_type, + .val = try ip.get(gpa, .{ .aggregate = .{ + .ty = array_ty, + .storage = .{ .bytes = bytes }, + } }), + } }, + } }), .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), - .addr = .{ .anon_decl = .{ - .orig_ty = .slice_const_u8_sentinel_0_type, - .val = try ip.get(gpa, .{ .aggregate = .{ - .ty = array_ty, - .storage = .{ .bytes = bytes }, - } }), - } }, } }); }; @@ -17517,12 +17523,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .is_const = true, }, })).toIntern(); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = ptr_ty, - .addr = .{ .anon_decl = .{ - .orig_ty = ptr_ty, - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .orig_ty = ptr_ty, + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, param_vals.len)).toIntern(), } }); }; @@ -17796,12 +17805,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = name }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = .slice_const_u8_sentinel_0_type, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = .slice_const_u8_sentinel_0_type, + } }, + } }), .len = (try mod.intValue(Type.usize, name.len)).toIntern(), } }); }; @@ -17838,12 +17850,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = array_errors_ty.toIntern(), .storage = .{ .elems = vals }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = slice_errors_ty.toIntern(), - .addr = .{ .anon_decl = .{ - .orig_ty = slice_errors_ty.toIntern(), - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = slice_errors_ty.slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .orig_ty = slice_errors_ty.toIntern(), + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, vals.len)).toIntern(), } }); } else .none; @@ -17925,12 +17940,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = name }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = .slice_const_u8_sentinel_0_type, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = .slice_const_u8_sentinel_0_type, + } }, + } }), .len = (try mod.intValue(Type.usize, name.len)).toIntern(), } }); }; @@ -17963,12 +17981,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .is_const = true, }, })).toIntern(); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = ptr_ty, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = ptr_ty, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = ptr_ty, + } }, + } }), .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(), } }); }; @@ -18051,12 +18072,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = name }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = .slice_const_u8_sentinel_0_type, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = .slice_const_u8_sentinel_0_type, + } }, + } }), .len = (try mod.intValue(Type.usize, name.len)).toIntern(), } }); }; @@ -18097,12 +18121,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .is_const = true, }, })).toIntern(); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = ptr_ty, - .addr = .{ .anon_decl = .{ - .orig_ty = ptr_ty, - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .orig_ty = ptr_ty, + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, union_field_vals.len)).toIntern(), } }); }; @@ -18199,12 +18226,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = bytes }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = .slice_const_u8_sentinel_0_type, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = .slice_const_u8_sentinel_0_type, + } }, + } }), .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), } }); }; @@ -18259,12 +18289,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = name }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .val = new_decl_val, - .orig_ty = .slice_const_u8_sentinel_0_type, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .val = new_decl_val, + .orig_ty = .slice_const_u8_sentinel_0_type, + } }, + } }), .len = (try mod.intValue(Type.usize, name.len)).toIntern(), } }); }; @@ -18315,12 +18348,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .is_const = true, }, })).toIntern(); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = ptr_ty, - .addr = .{ .anon_decl = .{ - .orig_ty = ptr_ty, - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .orig_ty = ptr_ty, + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(), } }); }; @@ -18453,12 +18489,15 @@ fn typeInfoDecls( .is_const = true, }, })).toIntern(); - return try mod.intern(.{ .ptr = .{ + return try mod.intern(.{ .slice = .{ .ty = ptr_ty, - .addr = .{ .anon_decl = .{ - .orig_ty = ptr_ty, - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(), + .addr = .{ .anon_decl = .{ + .orig_ty = ptr_ty, + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, decl_vals.items.len)).toIntern(), } }); } @@ -18498,12 +18537,15 @@ fn typeInfoNamespaceDecls( .ty = new_decl_ty.toIntern(), .storage = .{ .bytes = name }, } }); - break :v try mod.intern(.{ .ptr = .{ + break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, - .addr = .{ .anon_decl = .{ - .orig_ty = .slice_const_u8_sentinel_0_type, - .val = new_decl_val, - } }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .addr = .{ .anon_decl = .{ + .orig_ty = .slice_const_u8_sentinel_0_type, + .val = new_decl_val, + } }, + } }), .len = (try mod.intValue(Type.usize, name.len)).toIntern(), } }); }; @@ -22738,9 +22780,12 @@ fn ptrCastFull( if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) { if (ptr_val.isUndef(mod)) return mod.undefRef(dest_ty); const arr_len = try mod.intValue(Type.usize, Type.fromInterned(src_info.child).arrayLen(mod)); - return Air.internedToRef((try mod.intern(.{ .ptr = .{ + return Air.internedToRef((try mod.intern(.{ .slice = .{ .ty = dest_ty.toIntern(), - .addr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = dest_ty.slicePtrFieldType(mod).toIntern(), + .addr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr, + } }), .len = arr_len.toIntern(), } }))); } else { @@ -28765,21 +28810,24 @@ fn coerceExtra( if (inst_child_ty.structFieldCount(mod) == 0) { // Optional slice is represented with a null pointer so // we use a dummy pointer value with the required alignment. - return Air.internedToRef((try mod.intern(.{ .ptr = .{ + return Air.internedToRef((try mod.intern(.{ .slice = .{ .ty = dest_ty.toIntern(), - .addr = .{ .int = if (dest_info.flags.alignment != .none) - (try mod.intValue( - Type.usize, - dest_info.flags.alignment.toByteUnitsOptional().?, - )).toIntern() - else - try mod.intern_pool.getCoercedInts( - mod.gpa, - mod.intern_pool.indexToKey( - (try Type.fromInterned(dest_info.child).lazyAbiAlignment(mod)).toIntern(), - ).int, - .usize_type, - ) }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = dest_ty.slicePtrFieldType(mod).toIntern(), + .addr = .{ .int = if (dest_info.flags.alignment != .none) + (try mod.intValue( + Type.usize, + dest_info.flags.alignment.toByteUnitsOptional().?, + )).toIntern() + else + try mod.intern_pool.getCoercedInts( + mod.gpa, + mod.intern_pool.indexToKey( + (try Type.fromInterned(dest_info.child).lazyAbiAlignment(mod)).toIntern(), + ).int, + .usize_type, + ) }, + } }), .len = (try mod.intValue(Type.usize, 0)).toIntern(), } }))); } @@ -31276,7 +31324,7 @@ fn beginComptimePtrLoad( }, Value.slice_len_index => TypedValue{ .ty = Type.usize, - .val = Value.fromInterned(ip.indexToKey(try tv.val.intern(tv.ty, mod)).ptr.len), + .val = Value.fromInterned(ip.indexToKey(try tv.val.intern(tv.ty, mod)).slice.len), }, else => unreachable, }; @@ -31445,13 +31493,16 @@ fn coerceArrayPtrToSlice( if (try sema.resolveValue(inst)) |val| { const ptr_array_ty = sema.typeOf(inst); const array_ty = ptr_array_ty.childType(mod); - const slice_val = try mod.intern(.{ .ptr = .{ + const slice_val = try mod.intern(.{ .slice = .{ .ty = dest_ty.toIntern(), - .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) { - .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) }, - .ptr => |ptr| ptr.addr, - else => unreachable, - }, + .ptr = try mod.intern(.{ .ptr = .{ + .ty = dest_ty.slicePtrFieldType(mod).toIntern(), + .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) { + .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) }, + .ptr => |ptr| ptr.addr, + else => unreachable, + }, + } }), .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(), } }); return Air.internedToRef(slice_val); @@ -35211,51 +35262,43 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { (try val.getUnsignedIntAdvanced(mod, sema)).?, ), }, + .slice => |slice| { + const ptr = try sema.resolveLazyValue(Value.fromInterned(slice.ptr)); + const len = try sema.resolveLazyValue(Value.fromInterned(slice.len)); + if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val; + return Value.fromInterned(try mod.intern(.{ .slice = .{ + .ty = slice.ty, + .ptr = ptr.toIntern(), + .len = len.toIntern(), + } })); + }, .ptr => |ptr| { - const resolved_len = switch (ptr.len) { - .none => .none, - else => (try sema.resolveLazyValue(Value.fromInterned(ptr.len))).toIntern(), - }; switch (ptr.addr) { - .decl, .mut_decl, .anon_decl => return if (resolved_len == ptr.len) - val - else - Value.fromInterned((try mod.intern(.{ .ptr = .{ - .ty = ptr.ty, - .addr = switch (ptr.addr) { - .decl => |decl| .{ .decl = decl }, - .mut_decl => |mut_decl| .{ .mut_decl = mut_decl }, - .anon_decl => |anon_decl| .{ .anon_decl = anon_decl }, - else => unreachable, - }, - .len = resolved_len, - } }))), + .decl, .mut_decl, .anon_decl => return val, .comptime_field => |field_val| { const resolved_field_val = (try sema.resolveLazyValue(Value.fromInterned(field_val))).toIntern(); - return if (resolved_field_val == field_val and resolved_len == ptr.len) + return if (resolved_field_val == field_val) val else Value.fromInterned((try mod.intern(.{ .ptr = .{ .ty = ptr.ty, .addr = .{ .comptime_field = resolved_field_val }, - .len = resolved_len, } }))); }, .int => |int| { const resolved_int = (try sema.resolveLazyValue(Value.fromInterned(int))).toIntern(); - return if (resolved_int == int and resolved_len == ptr.len) + return if (resolved_int == int) val else Value.fromInterned((try mod.intern(.{ .ptr = .{ .ty = ptr.ty, .addr = .{ .int = resolved_int }, - .len = resolved_len, } }))); }, .eu_payload, .opt_payload => |base| { const resolved_base = (try sema.resolveLazyValue(Value.fromInterned(base))).toIntern(); - return if (resolved_base == base and resolved_len == ptr.len) + return if (resolved_base == base) val else Value.fromInterned((try mod.intern(.{ .ptr = .{ @@ -35265,12 +35308,11 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { .opt_payload => .{ .opt_payload = resolved_base }, else => unreachable, }, - .len = ptr.len, } }))); }, .elem, .field => |base_index| { const resolved_base = (try sema.resolveLazyValue(Value.fromInterned(base_index.base))).toIntern(); - return if (resolved_base == base_index.base and resolved_len == ptr.len) + return if (resolved_base == base_index.base) val else Value.fromInterned((try mod.intern(.{ .ptr = .{ @@ -35286,7 +35328,6 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { } }, else => unreachable, }, - .len = ptr.len, } }))); }, } diff --git a/src/TypedValue.zig b/src/TypedValue.zig index df4baf1008..ab2412ccf7 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -264,52 +264,56 @@ pub fn print( .float => |float| switch (float.storage) { inline else => |x| return writer.print("{d}", .{@as(f64, @floatCast(x))}), }, - .ptr => |ptr| { - if (ptr.addr == .int) { - switch (ip.indexToKey(ptr.addr.int)) { - .int => |i| switch (i.storage) { - inline else => |addr| return writer.print("{x:0>8}", .{addr}), - }, - .undef => return writer.writeAll("undefined"), - else => unreachable, - } + .slice => |slice| { + const ptr_ty = switch (ip.indexToKey(slice.ptr)) { + .ptr => |ptr| ty: { + if (ptr.addr == .int) return print(.{ + .ty = Type.fromInterned(ptr.ty), + .val = Value.fromInterned(slice.ptr), + }, writer, level - 1, mod); + break :ty ip.indexToKey(ptr.ty).ptr_type; + }, + .undef => |ptr_ty| ip.indexToKey(ptr_ty).ptr_type, + else => unreachable, + }; + if (level == 0) { + return writer.writeAll(".{ ... }"); } - - const ptr_ty = ip.indexToKey(ty.toIntern()).ptr_type; - if (ptr_ty.flags.size == .Slice) { - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - const elem_ty = Type.fromInterned(ptr_ty.child); - const len = Value.fromInterned(ptr.len).toUnsignedInt(mod); - if (elem_ty.eql(Type.u8, mod)) str: { - const max_len = @min(len, max_string_len); - var buf: [max_string_len]u8 = undefined; - for (buf[0..max_len], 0..) |*c, i| { - const maybe_elem = try val.maybeElemValue(mod, i); - const elem = maybe_elem orelse return writer.writeAll(".{ (reinterpreted data) }"); - if (elem.isUndef(mod)) break :str; - c.* = @as(u8, @intCast(elem.toUnsignedInt(mod))); - } - const truncated = if (len > max_string_len) " (truncated)" else ""; - return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); - } - try writer.writeAll(".{ "); - const max_len = @min(len, max_aggregate_items); - for (0..max_len) |i| { - if (i != 0) try writer.writeAll(", "); + const elem_ty = Type.fromInterned(ptr_ty.child); + const len = Value.fromInterned(slice.len).toUnsignedInt(mod); + if (elem_ty.eql(Type.u8, mod)) str: { + const max_len = @min(len, max_string_len); + var buf: [max_string_len]u8 = undefined; + for (buf[0..max_len], 0..) |*c, i| { const maybe_elem = try val.maybeElemValue(mod, i); - const elem = maybe_elem orelse return writer.writeAll("(reinterpreted data) }"); - try print(.{ - .ty = elem_ty, - .val = elem, - }, writer, level - 1, mod); - } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); + const elem = maybe_elem orelse return writer.writeAll(".{ (reinterpreted data) }"); + if (elem.isUndef(mod)) break :str; + c.* = @as(u8, @intCast(elem.toUnsignedInt(mod))); } - return writer.writeAll(" }"); + const truncated = if (len > max_string_len) " (truncated)" else ""; + return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); + } + try writer.writeAll(".{ "); + const max_len = @min(len, max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + const maybe_elem = try val.maybeElemValue(mod, i); + const elem = maybe_elem orelse return writer.writeAll("(reinterpreted data) }"); + try print(.{ + .ty = elem_ty, + .val = elem, + }, writer, level - 1, mod); } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + }, + .ptr => |ptr| { + if (ptr.addr == .int) {} + + const ptr_ty = ip.indexToKey(ty.toIntern()).ptr_type; + if (ptr_ty.flags.size == .Slice) {} switch (ptr.addr) { .decl => |decl_index| { diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 7005b07caa..6237a8af23 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -3179,9 +3179,6 @@ fn lowerAnonDeclRef( fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { const mod = func.bin_file.base.comp.module.?; - if (tv.ty.isSlice(mod)) { - return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) }; - } const decl = mod.declPtr(decl_index); // check if decl is an alias to a function, in which case we @@ -3335,6 +3332,18 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { .f64 => |f64_val| return WValue{ .float64 = f64_val }, else => unreachable, }, + .slice => |slice| { + var ptr = ip.indexToKey(slice.ptr).ptr; + const owner_decl = while (true) switch (ptr.addr) { + .decl => |decl| break decl, + .mut_decl => |mut_decl| break mut_decl.decl, + .int, .anon_decl => return func.fail("Wasm TODO: lower slice where ptr is not owned by decl", .{}), + .opt_payload, .eu_payload => |base| ptr = ip.indexToKey(base).ptr, + .elem, .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr, + .comptime_field => unreachable, + }; + return .{ .memory = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, owner_decl) }; + }, .ptr => |ptr| switch (ptr.addr) { .decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0), .mut_decl => |mut_decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, mut_decl.decl, 0), diff --git a/src/codegen.zig b/src/codegen.zig index e9509c4efd..dd851eeb03 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -322,24 +322,24 @@ pub fn generateSymbol( }, .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)), }, - .ptr => |ptr| { - // generate ptr - switch (try lowerParentPtr(bin_file, src_loc, switch (ptr.len) { - .none => typed_value.val, - else => typed_value.val.slicePtr(mod), - }.toIntern(), code, debug_output, reloc_info)) { + .ptr => switch (try lowerParentPtr(bin_file, src_loc, typed_value.val.toIntern(), code, debug_output, reloc_info)) { + .ok => {}, + .fail => |em| return .{ .fail = em }, + }, + .slice => |slice| { + switch (try generateSymbol(bin_file, src_loc, .{ + .ty = typed_value.ty.slicePtrFieldType(mod), + .val = Value.fromInterned(slice.ptr), + }, code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } - if (ptr.len != .none) { - // generate len - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.usize, - .val = Value.fromInterned(ptr.len), - }, code, debug_output, reloc_info)) { - .ok => {}, - .fail => |em| return Result{ .fail = em }, - } + switch (try generateSymbol(bin_file, src_loc, .{ + .ty = Type.usize, + .val = Value.fromInterned(slice.len), + }, code, debug_output, reloc_info)) { + .ok => {}, + .fail => |em| return .{ .fail = em }, } }, .opt => { @@ -676,7 +676,6 @@ fn lowerParentPtr( ) CodeGenError!Result { const mod = bin_file.comp.module.?; const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr; - assert(ptr.len == .none); return switch (ptr.addr) { .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info), .mut_decl => |md| try lowerDeclRef(bin_file, src_loc, md.decl, code, debug_output, reloc_info), diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 4d0566c9d8..9907a95fef 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1207,50 +1207,35 @@ pub const DeclGen = struct { try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)}); if (!empty) try writer.writeByte(')'); }, - .ptr => |ptr| { - if (ptr.len != .none) { - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - try writer.writeByte('{'); - } - const ptr_location = switch (ptr.len) { - .none => location, - else => initializer_type, - }; - const ptr_ty = switch (ptr.len) { - .none => ty, - else => ty.slicePtrFieldType(mod), - }; - const ptr_val = switch (ptr.len) { - .none => val, - else => val.slicePtr(mod), - }; - switch (ptr.addr) { - .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val, d, ptr_location), - .mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val, md.decl, ptr_location), - .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val, decl_val, ptr_location), - .int => |int| { - try writer.writeAll("(("); - try dg.renderType(writer, ptr_ty); - try writer.print("){x})", .{ - try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), ptr_location), - }); - }, - .eu_payload, - .opt_payload, - .elem, - .field, - => try dg.renderParentPtr(writer, ptr_val.ip_index, ptr_location), - .comptime_field => unreachable, - } - if (ptr.len != .none) { - try writer.writeAll(", "); - try dg.renderValue(writer, Type.usize, Value.fromInterned(ptr.len), initializer_type); - try writer.writeByte('}'); + .slice => |slice| { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); } + try writer.writeByte('{'); + try dg.renderValue(writer, ty.slicePtrFieldType(mod), Value.fromInterned(slice.ptr), initializer_type); + try writer.writeAll(", "); + try dg.renderValue(writer, Type.usize, Value.fromInterned(slice.len), initializer_type); + try writer.writeByte('}'); + }, + .ptr => |ptr| switch (ptr.addr) { + .decl => |d| try dg.renderDeclValue(writer, ty, val, d, location), + .mut_decl => |md| try dg.renderDeclValue(writer, ty, val, md.decl, location), + .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ty, val, decl_val, location), + .int => |int| { + try writer.writeAll("(("); + try dg.renderType(writer, ty); + try writer.print("){x})", .{ + try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), location), + }); + }, + .eu_payload, + .opt_payload, + .elem, + .field, + => try dg.renderParentPtr(writer, val.ip_index, location), + .comptime_field => unreachable, }, .opt => |opt| { const payload_ty = ty.optionalChild(mod); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a425511e51..1e63361048 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3644,6 +3644,7 @@ pub const Object = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -3872,30 +3873,22 @@ pub const Object = struct { 128 => try o.builder.fp128Const(val.toFloat(f128, mod)), else => unreachable, }, - .ptr => |ptr| { - const ptr_ty = switch (ptr.len) { - .none => ty, - else => ty.slicePtrFieldType(mod), - }; - const ptr_val = switch (ptr.addr) { - .decl => |decl| try o.lowerDeclRefValue(ptr_ty, decl), - .mut_decl => |mut_decl| try o.lowerDeclRefValue(ptr_ty, mut_decl.decl), - .anon_decl => |anon_decl| try o.lowerAnonDeclRef(ptr_ty, anon_decl), - .int => |int| try o.lowerIntAsPtr(int), - .eu_payload, - .opt_payload, - .elem, - .field, - => try o.lowerParentPtr(val), - .comptime_field => unreachable, - }; - switch (ptr.len) { - .none => return ptr_val, - else => return o.builder.structConst(try o.lowerType(ty), &.{ - ptr_val, try o.lowerValue(ptr.len), - }), - } + .ptr => |ptr| return switch (ptr.addr) { + .decl => |decl| try o.lowerDeclRefValue(ty, decl), + .mut_decl => |mut_decl| try o.lowerDeclRefValue(ty, mut_decl.decl), + .anon_decl => |anon_decl| try o.lowerAnonDeclRef(ty, anon_decl), + .int => |int| try o.lowerIntAsPtr(int), + .eu_payload, + .opt_payload, + .elem, + .field, + => try o.lowerParentPtr(val), + .comptime_field => unreachable, }, + .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{ + try o.lowerValue(slice.ptr), + try o.lowerValue(slice.len), + }), .opt => |opt| { comptime assert(optional_layout_version == 3); const payload_ty = ty.optionalChild(mod); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index fd7d2ed8d3..6c058308df 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -855,18 +855,12 @@ const DeclGen = struct { const int_ty = ty.intTagType(mod); return try self.constant(int_ty, int_val, repr); }, - .ptr => |ptr| { - const ptr_ty = switch (ptr.len) { - .none => ty, - else => ty.slicePtrFieldType(mod), - }; - const ptr_id = try self.constantPtr(ptr_ty, val); - if (ptr.len == .none) { - return ptr_id; - } - - const len_id = try self.constant(Type.usize, Value.fromInterned(ptr.len), .indirect); - return try self.constructStruct( + .ptr => return self.constantPtr(ty, val), + .slice => |slice| { + const ptr_ty = ty.slicePtrFieldType(mod); + const ptr_id = try self.constantPtr(ptr_ty, Value.fromInterned(slice.ptr)); + const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect); + return self.constructStruct( ty, &.{ ptr_ty, Type.usize }, &.{ ptr_id, len_id }, diff --git a/src/type.zig b/src/type.zig index 067deecfea..9ca2822204 100644 --- a/src/type.zig +++ b/src/type.zig @@ -426,6 +426,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -651,6 +652,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -758,6 +760,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -1073,6 +1076,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -1434,6 +1438,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -1660,6 +1665,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -2195,6 +2201,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -2538,6 +2545,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, @@ -2731,6 +2739,7 @@ pub const Type = struct { .empty_enum_value, .float, .ptr, + .slice, .opt, .aggregate, .un, diff --git a/src/value.zig b/src/value.zig index 9bcfad18e1..4276b09c68 100644 --- a/src/value.zig +++ b/src/value.zig @@ -194,10 +194,7 @@ pub const Value = struct { const ip = &mod.intern_pool; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .enum_literal => |enum_literal| enum_literal, - .ptr => |ptr| switch (ptr.len) { - .none => unreachable, - else => try arrayToIpString(val, Value.fromInterned(ptr.len).toUnsignedInt(mod), mod), - }, + .slice => |slice| try arrayToIpString(val, Value.fromInterned(slice.len).toUnsignedInt(mod), mod), .aggregate => |aggregate| switch (aggregate.storage) { .bytes => |bytes| try ip.getOrPutString(mod.gpa, bytes), .elems => try arrayToIpString(val, ty.arrayLen(mod), mod), @@ -217,10 +214,7 @@ pub const Value = struct { pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 { return switch (mod.intern_pool.indexToKey(val.toIntern())) { .enum_literal => |enum_literal| allocator.dupe(u8, mod.intern_pool.stringToSlice(enum_literal)), - .ptr => |ptr| switch (ptr.len) { - .none => unreachable, - else => try arrayToAllocatedBytes(val, Value.fromInterned(ptr.len).toUnsignedInt(mod), allocator, mod), - }, + .slice => |slice| try arrayToAllocatedBytes(val, Value.fromInterned(slice.len).toUnsignedInt(mod), allocator, mod), .aggregate => |aggregate| switch (aggregate.storage) { .bytes => |bytes| try allocator.dupe(u8, bytes), .elems => try arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod), @@ -286,12 +280,11 @@ pub const Value = struct { }, .slice => { const pl = val.castTag(.slice).?.data; - const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod); - var ptr_key = ip.indexToKey(ptr).ptr; - assert(ptr_key.len == .none); - ptr_key.ty = ty.toIntern(); - ptr_key.len = try pl.len.intern(Type.usize, mod); - return mod.intern(.{ .ptr = ptr_key }); + return mod.intern(.{ .slice = .{ + .ty = ty.toIntern(), + .len = try pl.len.intern(Type.usize, mod), + .ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod), + } }); }, .bytes => { const pl = val.castTag(.bytes).?.data; @@ -374,6 +367,7 @@ pub const Value = struct { .enum_tag, .empty_enum_value, .float, + .ptr, => val, .error_union => |error_union| switch (error_union.val) { @@ -381,13 +375,10 @@ pub const Value = struct { .payload => |payload| Tag.eu_payload.create(arena, Value.fromInterned(payload)), }, - .ptr => |ptr| switch (ptr.len) { - .none => val, - else => |len| Tag.slice.create(arena, .{ - .ptr = val.slicePtr(mod), - .len = Value.fromInterned(len), - }), - }, + .slice => |slice| Tag.slice.create(arena, .{ + .ptr = Value.fromInterned(slice.ptr), + .len = Value.fromInterned(slice.len), + }), .opt => |opt| switch (opt.val) { .none => val, @@ -1538,6 +1529,7 @@ pub const Value = struct { pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool { return switch (mod.intern_pool.indexToKey(val.toIntern())) { + .slice => |slice| return Value.fromInterned(slice.ptr).isComptimeMutablePtr(mod), .ptr => |ptr| switch (ptr.addr) { .mut_decl, .comptime_field => true, .eu_payload, .opt_payload => |base_ptr| Value.fromInterned(base_ptr).isComptimeMutablePtr(mod), @@ -1600,9 +1592,8 @@ pub const Value = struct { pub fn sliceLen(val: Value, mod: *Module) u64 { const ip = &mod.intern_pool; - const ptr = ip.indexToKey(val.toIntern()).ptr; - return switch (ptr.len) { - .none => switch (ip.indexToKey(switch (ptr.addr) { + return switch (ip.indexToKey(val.toIntern())) { + .ptr => |ptr| switch (ip.indexToKey(switch (ptr.addr) { .decl => |decl| mod.declPtr(decl).ty.toIntern(), .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(), .anon_decl => |anon_decl| ip.typeOf(anon_decl.val), @@ -1612,7 +1603,8 @@ pub const Value = struct { .array_type => |array_type| array_type.len, else => 1, }, - else => Value.fromInterned(ptr.len).toUnsignedInt(mod), + .slice => |slice| Value.fromInterned(slice.len).toUnsignedInt(mod), + else => unreachable, }; } @@ -1636,6 +1628,7 @@ pub const Value = struct { .undef => |ty| Value.fromInterned((try mod.intern(.{ .undef = Type.fromInterned(ty).elemType2(mod).toIntern(), }))), + .slice => |slice| return Value.fromInterned(slice.ptr).maybeElemValue(mod, index), .ptr => |ptr| switch (ptr.addr) { .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValue(mod, index), @@ -1800,25 +1793,23 @@ pub const Value = struct { ) Allocator.Error!Value { const elem_ty = elem_ptr_ty.childType(mod); const ptr_val = switch (mod.intern_pool.indexToKey(val.toIntern())) { - .ptr => |ptr| ptr: { - switch (ptr.addr) { - .elem => |elem| if (Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).eql(elem_ty, mod)) - return Value.fromInterned((try mod.intern(.{ .ptr = .{ - .ty = elem_ptr_ty.toIntern(), - .addr = .{ .elem = .{ - .base = elem.base, - .index = elem.index + index, - } }, - } }))), - else => {}, - } - break :ptr switch (ptr.len) { - .none => val, - else => val.slicePtr(mod), - }; - }, + .slice => |slice| Value.fromInterned(slice.ptr), else => val, }; + switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { + .ptr => |ptr| switch (ptr.addr) { + .elem => |elem| if (Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).eql(elem_ty, mod)) + return Value.fromInterned((try mod.intern(.{ .ptr = .{ + .ty = elem_ptr_ty.toIntern(), + .addr = .{ .elem = .{ + .base = elem.base, + .index = elem.index + index, + } }, + } }))), + else => {}, + }, + else => {}, + } var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type; assert(ptr_ty_key.flags.size != .Slice); ptr_ty_key.flags.size = .Many; @@ -1850,12 +1841,9 @@ pub const Value = struct { else => switch (mod.intern_pool.indexToKey(val.toIntern())) { .undef => true, .simple_value => |v| v == .undefined, - .ptr => |ptr| switch (ptr.len) { - .none => false, - else => for (0..@as(usize, @intCast(Value.fromInterned(ptr.len).toUnsignedInt(mod)))) |index| { - if (try (try val.elemValue(mod, index)).anyUndef(mod)) break true; - } else false, - }, + .slice => |slice| for (0..@intCast(Value.fromInterned(slice.len).toUnsignedInt(mod))) |idx| { + if (try (try val.elemValue(mod, idx)).anyUndef(mod)) break true; + } else false, .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i]; if (try anyUndef(Value.fromInterned(elem), mod)) break true; |
