Commit 9eda6ccefc
Changed files (11)
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),
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);
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);
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 },
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),
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 = .{
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|
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,
} })));
},
}
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,
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| {
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;