Commit 4f70863a55
Changed files (4)
src/InternPool.zig
@@ -1374,12 +1374,12 @@ pub const Index = enum(u32) {
undef: DataIsIndex,
runtime_value: DataIsIndex,
simple_value: struct { data: SimpleValue },
- ptr_mut_decl: struct { data: *PtrMutDecl },
ptr_decl: struct { data: *PtrDecl },
- ptr_int: struct { data: *PtrAddr },
- ptr_eu_payload: DataIsIndex,
- ptr_opt_payload: DataIsIndex,
+ ptr_mut_decl: struct { data: *PtrMutDecl },
ptr_comptime_field: struct { data: *PtrComptimeField },
+ ptr_int: struct { data: *PtrBase },
+ ptr_eu_payload: struct { data: *PtrBase },
+ ptr_opt_payload: struct { data: *PtrBase },
ptr_elem: struct { data: *PtrBaseIndex },
ptr_field: struct { data: *PtrBaseIndex },
ptr_slice: struct { data: *PtrSlice },
@@ -1774,29 +1774,25 @@ pub const Tag = enum(u8) {
/// A value that can be represented with only an enum tag.
/// data is SimpleValue enum value.
simple_value,
- /// A pointer to a decl that can be mutated at comptime.
- /// data is extra index of PtrMutDecl, which contains the type and address.
- ptr_mut_decl,
/// A pointer to a decl.
- /// data is extra index of PtrDecl, which contains the type and address.
+ /// data is extra index of `PtrDecl`, which contains the type and address.
ptr_decl,
+ /// A pointer to a decl that can be mutated at comptime.
+ /// data is extra index of `PtrMutDecl`, which contains the type and address.
+ ptr_mut_decl,
+ /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
+ ptr_comptime_field,
/// A pointer with an integer value.
- /// data is extra index of PtrAddr, which contains the type and address.
+ /// data is extra index of `PtrBase`, which contains the type and address.
/// Only pointer types are allowed to have this encoding. Optional types must use
/// `opt_payload` or `opt_null`.
ptr_int,
/// A pointer to the payload of an error union.
- /// data is Index of a pointer value to the error union.
- /// In order to use this encoding, one must ensure that the `InternPool`
- /// already contains the payload pointer type corresponding to this payload.
+ /// data is extra index of `PtrBase`, which contains the type and base pointer.
ptr_eu_payload,
/// A pointer to the payload of an optional.
- /// data is Index of a pointer value to the optional.
- /// In order to use this encoding, one must ensure that the `InternPool`
- /// already contains the payload pointer type corresponding to this payload.
+ /// data is extra index of `PtrBase`, which contains the type and base pointer.
ptr_opt_payload,
- /// data is extra index of PtrComptimeField, which contains the pointer type and field value.
- ptr_comptime_field,
/// A pointer to an array element.
/// data is extra index of PtrBaseIndex, which contains the base array and element index.
/// In order to use this encoding, one must ensure that the `InternPool`
@@ -2224,14 +2220,14 @@ pub const PtrMutDecl = struct {
runtime_index: RuntimeIndex,
};
-pub const PtrAddr = struct {
+pub const PtrComptimeField = struct {
ty: Index,
- addr: Index,
+ field_val: Index,
};
-pub const PtrComptimeField = struct {
+pub const PtrBase = struct {
ty: Index,
- field_val: Index,
+ base: Index,
};
pub const PtrBaseIndex = struct {
@@ -2598,36 +2594,23 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
} },
} };
},
- .ptr_int => {
- const info = ip.extraData(PtrAddr, data);
+ .ptr_comptime_field => {
+ const info = ip.extraData(PtrComptimeField, data);
return .{ .ptr = .{
.ty = info.ty,
- .addr = .{ .int = info.addr },
- } };
- },
- .ptr_eu_payload => {
- const ptr_eu_index = @intToEnum(Index, data);
- var ptr_type = ip.indexToKey(ip.typeOf(ptr_eu_index)).ptr_type;
- ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).error_union_type.payload_type;
- return .{ .ptr = .{
- .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
- .addr = .{ .eu_payload = ptr_eu_index },
+ .addr = .{ .comptime_field = info.field_val },
} };
},
- .ptr_opt_payload => {
- const ptr_opt_index = @intToEnum(Index, data);
- var ptr_type = ip.indexToKey(ip.typeOf(ptr_opt_index)).ptr_type;
- ptr_type.elem_type = ip.indexToKey(ptr_type.elem_type).opt_type;
- return .{ .ptr = .{
- .ty = ip.getAssumeExists(.{ .ptr_type = ptr_type }),
- .addr = .{ .opt_payload = ptr_opt_index },
- } };
- },
- .ptr_comptime_field => {
- const info = ip.extraData(PtrComptimeField, data);
+ .ptr_int, .ptr_eu_payload, .ptr_opt_payload => {
+ const info = ip.extraData(PtrBase, data);
return .{ .ptr = .{
.ty = info.ty,
- .addr = .{ .comptime_field = info.field_val },
+ .addr = switch (item.tag) {
+ .ptr_int => .{ .int = info.base },
+ .ptr_eu_payload => .{ .eu_payload = info.base },
+ .ptr_opt_payload => .{ .opt_payload = info.base },
+ else => unreachable,
+ },
} };
},
.ptr_elem => {
@@ -3248,39 +3231,67 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.runtime_index = mut_decl.runtime_index,
}),
}),
- .int => |int| {
- assert(ip.typeOf(int) == .usize_type);
+ .comptime_field => |field_val| {
+ assert(field_val != .none);
ip.items.appendAssumeCapacity(.{
- .tag = .ptr_int,
- .data = try ip.addExtra(gpa, PtrAddr{
+ .tag = .ptr_comptime_field,
+ .data = try ip.addExtra(gpa, PtrComptimeField{
.ty = ptr.ty,
- .addr = int,
+ .field_val = field_val,
}),
});
},
- .eu_payload, .opt_payload => |data| {
- assert(data != .none);
+ .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.elem_type,
+ ) == .error_union_type),
+ .opt_payload => assert(ip.indexToKey(
+ ip.indexToKey(ip.typeOf(base)).ptr_type.elem_type,
+ ) == .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 = @enumToInt(data),
- });
- },
- .comptime_field => |field_val| {
- assert(field_val != .none);
- ip.items.appendAssumeCapacity(.{
- .tag = .ptr_comptime_field,
- .data = try ip.addExtra(gpa, PtrComptimeField{
+ .data = try ip.addExtra(gpa, PtrBase{
.ty = ptr.ty,
- .field_val = field_val,
+ .base = base,
}),
});
},
.elem, .field => |base_index| {
- assert(base_index.base != .none);
+ const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
+ switch (base_ptr_type.size) {
+ .One => switch (ip.indexToKey(base_ptr_type.elem_type)) {
+ .array_type, .vector_type => assert(ptr.addr == .elem),
+ .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 < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
+ },
+ .union_type => |union_type| {
+ assert(ptr.addr == .field);
+ assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
+ },
+ .ptr_type => |slice_type| {
+ assert(ptr.addr == .field);
+ assert(slice_type.size == .Slice);
+ assert(base_index.index < 2);
+ },
+ else => unreachable,
+ },
+ .Many => assert(ptr.addr == .elem),
+ .Slice, .C => unreachable,
+ }
_ = ip.map.pop();
const index_index = try ip.get(gpa, .{ .int = .{
.ty = .usize_type,
@@ -4750,10 +4761,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
.simple_value => 0,
.ptr_decl => @sizeOf(PtrDecl),
.ptr_mut_decl => @sizeOf(PtrMutDecl),
- .ptr_int => @sizeOf(PtrAddr),
- .ptr_eu_payload => 0,
- .ptr_opt_payload => 0,
.ptr_comptime_field => @sizeOf(PtrComptimeField),
+ .ptr_int => @sizeOf(PtrBase),
+ .ptr_eu_payload => @sizeOf(PtrBase),
+ .ptr_opt_payload => @sizeOf(PtrBase),
.ptr_elem => @sizeOf(PtrBaseIndex),
.ptr_field => @sizeOf(PtrBaseIndex),
.ptr_slice => @sizeOf(PtrSlice),
@@ -5281,12 +5292,12 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std
.undef,
.runtime_value,
.simple_value,
- .ptr_mut_decl,
.ptr_decl,
+ .ptr_mut_decl,
+ .ptr_comptime_field,
.ptr_int,
.ptr_eu_payload,
.ptr_opt_payload,
- .ptr_comptime_field,
.ptr_elem,
.ptr_field,
.ptr_slice,
src/Module.zig
@@ -6716,6 +6716,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
return ptrType(mod, .{ .elem_type = child_type.toIntern(), .is_const = true });
}
+pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
+ return ptrType(mod, .{ .elem_type = child_type.toIntern(), .size = .Many, .is_const = true });
+}
+
pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
const info = Type.ptrInfoIp(mod.intern_pool, ptr_ty.toIntern());
return mod.ptrType(.{
src/Sema.zig
@@ -25412,11 +25412,13 @@ fn elemVal(
const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt(mod));
- const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index);
- const elem_ptr_val = try indexable_val.elemPtr(elem_ptr_ty, index, mod);
+ const elem_ty = indexable_ty.elemType2(mod);
+ const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
+ const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);
+ const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
+ const elem_ptr_val = try many_ptr_val.elemPtr(elem_ptr_ty, index, mod);
if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
- const result_ty = indexable_ty.elemType2(mod);
- return sema.addConstant(result_ty, try mod.getCoerced(elem_val, result_ty));
+ return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
}
break :rs indexable_src;
};
@@ -29906,7 +29908,7 @@ fn analyzeSlice(
const ptr_ptr_ty = sema.typeOf(ptr_ptr);
const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {
.Pointer => ptr_ptr_ty.childType(mod),
- else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}),
+ else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(mod)}),
};
var array_ty = ptr_ptr_child_ty;
@@ -30111,7 +30113,10 @@ fn analyzeSlice(
const end_int = end_val.getUnsignedInt(mod).?;
const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
- const elem_ptr = try ptr_val.elemPtr(try sema.elemPtrType(new_ptr_ty, sentinel_index), sentinel_index, sema.mod);
+ const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
+ const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);
+ const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
+ const elem_ptr = try many_ptr_val.elemPtr(elem_ptr_ty, sentinel_index, mod);
const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty);
const actual_sentinel = switch (res) {
.runtime_load => break :sentinel_check,
@@ -30120,23 +30125,23 @@ fn analyzeSlice(
block,
src,
"comptime dereference requires '{}' to have a well-defined layout, but it does not.",
- .{ty.fmt(sema.mod)},
+ .{ty.fmt(mod)},
),
.out_of_bounds => |ty| return sema.fail(
block,
end_src,
"slice end index {d} exceeds bounds of containing decl of type '{}'",
- .{ end_int, ty.fmt(sema.mod) },
+ .{ end_int, ty.fmt(mod) },
),
};
- if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {
+ if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
errdefer msg.destroy(sema.gpa);
try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
- expected_sentinel.fmtValue(elem_ty, sema.mod),
- actual_sentinel.fmtValue(elem_ty, sema.mod),
+ expected_sentinel.fmtValue(elem_ty, mod),
+ actual_sentinel.fmtValue(elem_ty, mod),
});
break :msg msg;
@@ -30310,7 +30315,7 @@ fn cmpNumeric(
const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
- const target = sema.mod.getTarget();
+ const target = mod.getTarget();
// One exception to heterogeneous comparison: comptime_float needs to
// coerce to fixed-width float.
src/value.zig
@@ -1857,7 +1857,8 @@ pub const Value = struct {
.decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
.mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
.toValue().elemValue(mod, index),
- .int, .eu_payload, .opt_payload => unreachable,
+ .int, .eu_payload => unreachable,
+ .opt_payload => |base| base.toValue().elemValue(mod, index),
.comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
.elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
.field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
@@ -1866,6 +1867,7 @@ pub const Value = struct {
return field_val.elemValue(mod, index);
} else unreachable,
},
+ .opt => |opt| opt.val.toValue().elemValue(mod, index),
.aggregate => |aggregate| {
const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
if (index < len) return switch (aggregate.storage) {