authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-21 03:57:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:54-07:00
logbe1b23120648dff5e23d67b089c10b479564bffd
tree79e455747856a29c096ee4f5e5ef61e7186b57c2
parent9584feae5f27a8b987975d8fe8242e2169098a75

InternPool: add missing logic


3 files changed, 84 insertions(+), 30 deletions(-)

src/InternPool.zig+41-4
...@@ -1517,6 +1517,8 @@ pub const Tag = enum(u8) {...@@ -1517,6 +1517,8 @@ pub const Tag = enum(u8) {
1517/// 0. name: NullTerminatedString for each names_len1517/// 0. name: NullTerminatedString for each names_len
1518pub const ErrorSet = struct {1518pub const ErrorSet = struct {
1519 names_len: u32,1519 names_len: u32,
1520 /// Maps error names to declaration index.
1521 names_map: MapIndex,
1520};1522};
15211523
1522/// Trailing:1524/// Trailing:
...@@ -2024,6 +2026,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -2024,6 +2026,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
2024 const names = ip.extra.items[error_set.end..][0..names_len];2026 const names = ip.extra.items[error_set.end..][0..names_len];
2025 return .{ .error_set_type = .{2027 return .{ .error_set_type = .{
2026 .names = @ptrCast([]const NullTerminatedString, names),2028 .names = @ptrCast([]const NullTerminatedString, names),
2029 .names_map = error_set.data.names_map.toOptional(),
2027 } };2030 } };
2028 },2031 },
2029 .type_inferred_error_set => .{2032 .type_inferred_error_set => .{
...@@ -2518,6 +2521,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2518,6 +2521,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2518 .tag = .type_error_set,2521 .tag = .type_error_set,
2519 .data = ip.addExtraAssumeCapacity(ErrorSet{2522 .data = ip.addExtraAssumeCapacity(ErrorSet{
2520 .names_len = names_len,2523 .names_len = names_len,
2524 .names_map = names_map,
2521 }),2525 }),
2522 });2526 });
2523 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));2527 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));
...@@ -3605,15 +3609,34 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {...@@ -3605,15 +3609,34 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
3605/// * int <=> int3609/// * int <=> int
3606/// * int <=> enum3610/// * int <=> enum
3607/// * ptr <=> ptr3611/// * ptr <=> ptr
3612/// * null_value => opt
3613/// * payload => opt
3608pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {3614pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
3609 if (ip.typeOf(val) == new_ty) return val;3615 const old_ty = ip.typeOf(val);
3616 if (old_ty == new_ty) return val;
3610 switch (ip.indexToKey(val)) {3617 switch (ip.indexToKey(val)) {
3611 .int => |int| switch (ip.indexToKey(new_ty)) {3618 .int => |int| switch (ip.indexToKey(new_ty)) {
3619 .simple_type => |simple_type| switch (simple_type) {
3620 .usize,
3621 .isize,
3622 .c_char,
3623 .c_short,
3624 .c_ushort,
3625 .c_int,
3626 .c_uint,
3627 .c_long,
3628 .c_ulong,
3629 .c_longlong,
3630 .c_ulonglong,
3631 => return getCoercedInts(ip, gpa, int, new_ty),
3632 else => {},
3633 },
3634 .int_type => return getCoercedInts(ip, gpa, int, new_ty),
3612 .enum_type => return ip.get(gpa, .{ .enum_tag = .{3635 .enum_type => return ip.get(gpa, .{ .enum_tag = .{
3613 .ty = new_ty,3636 .ty = new_ty,
3614 .int = val,3637 .int = val,
3615 } }),3638 } }),
3616 else => return getCoercedInts(ip, gpa, int, new_ty),3639 else => {},
3617 },3640 },
3618 .enum_tag => |enum_tag| {3641 .enum_tag => |enum_tag| {
3619 // Assume new_ty is an integer type.3642 // Assume new_ty is an integer type.
...@@ -3624,10 +3647,24 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -3624,10 +3647,24 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
3624 .ty = new_ty,3647 .ty = new_ty,
3625 .addr = ptr.addr,3648 .addr = ptr.addr,
3626 } }),3649 } }),
3627 else => unreachable,3650 else => {},
3628 },3651 },
3629 else => unreachable,3652 else => {},
3653 }
3654 switch (ip.indexToKey(new_ty)) {
3655 .opt_type => |child_ty| switch (val) {
3656 .null_value => return ip.get(gpa, .{ .opt = .{
3657 .ty = new_ty,
3658 .val = .none,
3659 } }),
3660 else => return ip.get(gpa, .{ .opt = .{
3661 .ty = new_ty,
3662 .val = try ip.getCoerced(gpa, val, child_ty),
3663 } }),
3664 },
3665 else => {},
3630 }3666 }
3667 unreachable;
3631}3668}
36323669
3633/// Asserts `val` has an integer type.3670/// Asserts `val` has an integer type.
src/Sema.zig+10-9
...@@ -8480,13 +8480,10 @@ fn zirOptionalPayload(...@@ -8480,13 +8480,10 @@ fn zirOptionalPayload(
8480 };8480 };
84818481
8482 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8482 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8483 if (val.isNull(mod)) {8483 return if (val.optionalValue(mod)) |payload|
8484 return sema.fail(block, src, "unable to unwrap null", .{});8484 sema.addConstant(result_ty, payload)
8485 }8485 else
8486 if (val.castTag(.opt_payload)) |payload| {8486 sema.fail(block, src, "unable to unwrap null", .{});
8487 return sema.addConstant(result_ty, payload.data);
8488 }
8489 return sema.addConstant(result_ty, val);
8490 }8487 }
84918488
8492 try sema.requireRuntimeBlock(block, src, null);8489 try sema.requireRuntimeBlock(block, src, null);
...@@ -18929,7 +18926,7 @@ fn zirReify(...@@ -18929,7 +18926,7 @@ fn zirReify(
18929 if (ptr_size == .One or ptr_size == .C) {18926 if (ptr_size == .One or ptr_size == .C) {
18930 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});18927 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
18931 }18928 }
18932 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;18929 const sentinel_ptr_val = sentinel_val.optionalValue(mod).?;
18933 const ptr_ty = try Type.ptr(sema.arena, mod, .{18930 const ptr_ty = try Type.ptr(sema.arena, mod, .{
18934 .@"addrspace" = .generic,18931 .@"addrspace" = .generic,
18935 .pointee_type = elem_ty,18932 .pointee_type = elem_ty,
...@@ -28807,7 +28804,11 @@ fn coerceCompatiblePtrs(...@@ -28807,7 +28804,11 @@ fn coerceCompatiblePtrs(
28807 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});28804 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
28808 }28805 }
28809 // The comptime Value representation is compatible with both types.28806 // The comptime Value representation is compatible with both types.
28810 return sema.addConstant(dest_ty, val);28807 return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(
28808 mod.gpa,
28809 try val.intern(inst_ty, mod),
28810 dest_ty.ip_index,
28811 )).toValue());
28811 }28812 }
28812 try sema.requireRuntimeBlock(block, inst_src, null);28813 try sema.requireRuntimeBlock(block, inst_src, null);
28813 const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod);28814 const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod);
src/value.zig+33-17
...@@ -718,18 +718,25 @@ pub const Value = struct {...@@ -718,18 +718,25 @@ pub const Value = struct {
718 },718 },
719 else => unreachable,719 else => unreachable,
720 };720 };
721 const enum_type = ip.indexToKey(ty.ip_index).enum_type;721 return switch (ip.indexToKey(ty.ip_index)) {
722 if (enum_type.values.len != 0) {722 // Assume it is already an integer and return it directly.
723 return enum_type.values[field_index].toValue();723 .simple_type, .int_type => val,
724 } else {724 .enum_type => |enum_type| if (enum_type.values.len != 0)
725 // Field index and integer values are the same.725 enum_type.values[field_index].toValue()
726 return mod.intValue(enum_type.tag_ty.toType(), field_index);726 else // Field index and integer values are the same.
727 }727 mod.intValue(enum_type.tag_ty.toType(), field_index),
728 else => unreachable,
729 };
728 },730 },
729 else => {731 else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) {
730 const enum_type = ip.indexToKey(ip.typeOf(val.ip_index)).enum_type;732 // Assume it is already an integer and return it directly.
731 const int = try ip.getCoerced(mod.gpa, val.ip_index, enum_type.tag_ty);733 .simple_type, .int_type => val,
732 return int.toValue();734 .enum_type => |enum_type| (try ip.getCoerced(
735 mod.gpa,
736 val.ip_index,
737 enum_type.tag_ty,
738 )).toValue(),
739 else => unreachable,
733 },740 },
734 }741 }
735 }742 }
...@@ -2906,7 +2913,7 @@ pub const Value = struct {...@@ -2906,7 +2913,7 @@ pub const Value = struct {
2906 inline .u64, .i64 => |x| x == 0,2913 inline .u64, .i64 => |x| x == 0,
2907 },2914 },
2908 .opt => |opt| opt.val == .none,2915 .opt => |opt| opt.val == .none,
2909 else => unreachable,2916 else => false,
2910 },2917 },
2911 };2918 };
2912 }2919 }
...@@ -2949,11 +2956,20 @@ pub const Value = struct {...@@ -2949,11 +2956,20 @@ pub const Value = struct {
29492956
2950 /// Value of the optional, null if optional has no payload.2957 /// Value of the optional, null if optional has no payload.
2951 pub fn optionalValue(val: Value, mod: *const Module) ?Value {2958 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2952 if (val.isNull(mod)) return null;2959 return switch (val.ip_index) {
29532960 .none => if (val.isNull(mod)) null
2954 // Valid for optional representation to be the direct value2961 // Valid for optional representation to be the direct value
2955 // and not use opt_payload.2962 // and not use opt_payload.
2956 return if (val.castTag(.opt_payload)) |p| p.data else val;2963 else if (val.castTag(.opt_payload)) |p| p.data else val,
2964 .null_value => null,
2965 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2966 .opt => |opt| switch (opt.val) {
2967 .none => null,
2968 else => opt.val.toValue(),
2969 },
2970 else => unreachable,
2971 },
2972 };
2957 }2973 }
29582974
2959 /// Valid for all types. Asserts the value is not undefined.2975 /// Valid for all types. Asserts the value is not undefined.