authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-26 21:22:34-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log2d5bc0146941f4cc207c4fd23058e25a16fd40a7
tree64087a3ecf4d63d9e53a5f04156dff508d58bd26
parentc8b0d4d149c891ed83db57fe6986d10c5dd654af

behavior: get more test cases passing with llvm


10 files changed, 749 insertions(+), 799 deletions(-)

src/InternPool.zig+254-155
...@@ -621,8 +621,7 @@ pub const Key = union(enum) {...@@ -621,8 +621,7 @@ pub const Key = union(enum) {
621621
622 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash, ip: *const InternPool) void {622 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash, ip: *const InternPool) void {
623 const KeyTag = @typeInfo(Key).Union.tag_type.?;623 const KeyTag = @typeInfo(Key).Union.tag_type.?;
624 const key_tag: KeyTag = key;624 std.hash.autoHash(hasher, @as(KeyTag, key));
625 std.hash.autoHash(hasher, key_tag);
626 switch (key) {625 switch (key) {
627 inline .int_type,626 inline .int_type,
628 .ptr_type,627 .ptr_type,
...@@ -710,39 +709,58 @@ pub const Key = union(enum) {...@@ -710,39 +709,58 @@ pub const Key = union(enum) {
710709
711 .aggregate => |aggregate| {710 .aggregate => |aggregate| {
712 std.hash.autoHash(hasher, aggregate.ty);711 std.hash.autoHash(hasher, aggregate.ty);
713 switch (ip.indexToKey(aggregate.ty)) {712 const len = ip.aggregateTypeLen(aggregate.ty);
714 .array_type => |array_type| if (array_type.child == .u8_type) {713 const child = switch (ip.indexToKey(aggregate.ty)) {
715 switch (aggregate.storage) {714 .array_type => |array_type| array_type.child,
716 .bytes => |bytes| for (bytes) |byte| std.hash.autoHash(hasher, byte),715 .vector_type => |vector_type| vector_type.child,
717 .elems => |elems| {716 .anon_struct_type, .struct_type => .none,
718 var buffer: Key.Int.Storage.BigIntSpace = undefined;717 else => unreachable,
719 for (elems) |elem| std.hash.autoHash(718 };
719
720 if (child == .u8_type) {
721 switch (aggregate.storage) {
722 .bytes => |bytes| for (bytes[0..@intCast(usize, len)]) |byte| {
723 std.hash.autoHash(hasher, KeyTag.int);
724 std.hash.autoHash(hasher, byte);
725 },
726 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem| {
727 const elem_key = ip.indexToKey(elem);
728 std.hash.autoHash(hasher, @as(KeyTag, elem_key));
729 switch (elem_key) {
730 .undef => {},
731 .int => |int| std.hash.autoHash(
720 hasher,732 hasher,
721 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch733 @intCast(u8, int.storage.u64),
722 unreachable,734 ),
723 );735 else => unreachable,
724 },736 }
725 .repeated_elem => |elem| {737 },
726 const len = ip.aggregateTypeLen(aggregate.ty);738 .repeated_elem => |elem| {
727 var buffer: Key.Int.Storage.BigIntSpace = undefined;739 const elem_key = ip.indexToKey(elem);
728 const byte = ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch740 var remaining = len;
729 unreachable;741 while (remaining > 0) : (remaining -= 1) {
730 var i: u64 = 0;742 std.hash.autoHash(hasher, @as(KeyTag, elem_key));
731 while (i < len) : (i += 1) std.hash.autoHash(hasher, byte);743 switch (elem_key) {
732 },744 .undef => {},
733 }745 .int => |int| std.hash.autoHash(
734 return;746 hasher,
735 },747 @intCast(u8, int.storage.u64),
736 else => {},748 ),
749 else => unreachable,
750 }
751 }
752 },
753 }
754 return;
737 }755 }
738756
739 switch (aggregate.storage) {757 switch (aggregate.storage) {
740 .bytes => unreachable,758 .bytes => unreachable,
741 .elems => |elems| for (elems) |elem| std.hash.autoHash(hasher, elem),759 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem|
760 std.hash.autoHash(hasher, elem),
742 .repeated_elem => |elem| {761 .repeated_elem => |elem| {
743 const len = ip.aggregateTypeLen(aggregate.ty);762 var remaining = len;
744 var i: u64 = 0;763 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(hasher, elem);
745 while (i < len) : (i += 1) std.hash.autoHash(hasher, elem);
746 },764 },
747 }765 }
748 },766 },
...@@ -960,9 +978,10 @@ pub const Key = union(enum) {...@@ -960,9 +978,10 @@ pub const Key = union(enum) {
960 const b_info = b.aggregate;978 const b_info = b.aggregate;
961 if (a_info.ty != b_info.ty) return false;979 if (a_info.ty != b_info.ty) return false;
962980
981 const len = ip.aggregateTypeLen(a_info.ty);
963 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;982 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;
964 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) {983 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) {
965 for (0..@intCast(usize, ip.aggregateTypeLen(a_info.ty))) |elem_index| {984 for (0..@intCast(usize, len)) |elem_index| {
966 const a_elem = switch (a_info.storage) {985 const a_elem = switch (a_info.storage) {
967 .bytes => |bytes| ip.getIfExists(.{ .int = .{986 .bytes => |bytes| ip.getIfExists(.{ .int = .{
968 .ty = .u8_type,987 .ty = .u8_type,
...@@ -987,11 +1006,19 @@ pub const Key = union(enum) {...@@ -987,11 +1006,19 @@ pub const Key = union(enum) {
987 switch (a_info.storage) {1006 switch (a_info.storage) {
988 .bytes => |a_bytes| {1007 .bytes => |a_bytes| {
989 const b_bytes = b_info.storage.bytes;1008 const b_bytes = b_info.storage.bytes;
990 return std.mem.eql(u8, a_bytes, b_bytes);1009 return std.mem.eql(
1010 u8,
1011 a_bytes[0..@intCast(usize, len)],
1012 b_bytes[0..@intCast(usize, len)],
1013 );
991 },1014 },
992 .elems => |a_elems| {1015 .elems => |a_elems| {
993 const b_elems = b_info.storage.elems;1016 const b_elems = b_info.storage.elems;
994 return std.mem.eql(Index, a_elems, b_elems);1017 return std.mem.eql(
1018 Index,
1019 a_elems[0..@intCast(usize, len)],
1020 b_elems[0..@intCast(usize, len)],
1021 );
995 },1022 },
996 .repeated_elem => |a_elem| {1023 .repeated_elem => |a_elem| {
997 const b_elem = b_info.storage.repeated_elem;1024 const b_elem = b_info.storage.repeated_elem;
...@@ -2691,7 +2718,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2691,7 +2718,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2691 },2718 },
2692 .bytes => {2719 .bytes => {
2693 const extra = ip.extraData(Bytes, data);2720 const extra = ip.extraData(Bytes, data);
2694 const len = @intCast(u32, ip.aggregateTypeLen(extra.ty));2721 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(extra.ty));
2695 return .{ .aggregate = .{2722 return .{ .aggregate = .{
2696 .ty = extra.ty,2723 .ty = extra.ty,
2697 .storage = .{ .bytes = ip.string_bytes.items[@enumToInt(extra.bytes)..][0..len] },2724 .storage = .{ .bytes = ip.string_bytes.items[@enumToInt(extra.bytes)..][0..len] },
...@@ -2699,7 +2726,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2699,7 +2726,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2699 },2726 },
2700 .aggregate => {2727 .aggregate => {
2701 const extra = ip.extraDataTrail(Aggregate, data);2728 const extra = ip.extraDataTrail(Aggregate, data);
2702 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));2729 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(extra.data.ty));
2703 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);2730 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
2704 return .{ .aggregate = .{2731 return .{ .aggregate = .{
2705 .ty = extra.data.ty,2732 .ty = extra.data.ty,
...@@ -3145,7 +3172,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3145,7 +3172,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3145 }),3172 }),
3146 }),3173 }),
3147 .int => |int| {3174 .int => |int| {
3148 assert(int != .none);3175 assert(ip.typeOf(int) == .usize_type);
3149 ip.items.appendAssumeCapacity(.{3176 ip.items.appendAssumeCapacity(.{
3150 .tag = .ptr_int,3177 .tag = .ptr_int,
3151 .data = try ip.addExtra(gpa, PtrAddr{3178 .data = try ip.addExtra(gpa, PtrAddr{
...@@ -3452,7 +3479,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3452,7 +3479,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34523479
3453 .enum_tag => |enum_tag| {3480 .enum_tag => |enum_tag| {
3454 assert(ip.isEnumType(enum_tag.ty));3481 assert(ip.isEnumType(enum_tag.ty));
3455 assert(ip.indexToKey(enum_tag.int) == .int);3482 switch (ip.indexToKey(enum_tag.ty)) {
3483 .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))),
3484 .enum_type => |enum_type| assert(ip.typeOf(enum_tag.int) == enum_type.tag_ty),
3485 else => unreachable,
3486 }
3456 ip.items.appendAssumeCapacity(.{3487 ip.items.appendAssumeCapacity(.{
3457 .tag = .enum_tag,3488 .tag = .enum_tag,
3458 .data = try ip.addExtra(gpa, enum_tag),3489 .data = try ip.addExtra(gpa, enum_tag),
...@@ -3501,21 +3532,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3501,21 +3532,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35013532
3502 .aggregate => |aggregate| {3533 .aggregate => |aggregate| {
3503 const ty_key = ip.indexToKey(aggregate.ty);3534 const ty_key = ip.indexToKey(aggregate.ty);
3504 const aggregate_len = ip.aggregateTypeLen(aggregate.ty);3535 const len = ip.aggregateTypeLen(aggregate.ty);
3536 const child = switch (ty_key) {
3537 .array_type => |array_type| array_type.child,
3538 .vector_type => |vector_type| vector_type.child,
3539 .anon_struct_type, .struct_type => .none,
3540 else => unreachable,
3541 };
3542 const sentinel = switch (ty_key) {
3543 .array_type => |array_type| array_type.sentinel,
3544 .vector_type, .anon_struct_type, .struct_type => .none,
3545 else => unreachable,
3546 };
3547 const len_including_sentinel = len + @boolToInt(sentinel != .none);
3505 switch (aggregate.storage) {3548 switch (aggregate.storage) {
3506 .bytes => |bytes| {3549 .bytes => |bytes| {
3507 assert(ty_key.array_type.child == .u8_type);3550 assert(child == .u8_type);
3508 assert(bytes.len == aggregate_len);3551 if (bytes.len != len) {
3552 assert(bytes.len == len_including_sentinel);
3553 assert(bytes[len] == ip.indexToKey(sentinel).int.storage.u64);
3554 unreachable;
3555 }
3509 },3556 },
3510 .elems => |elems| {3557 .elems => |elems| {
3511 assert(elems.len == aggregate_len);3558 if (elems.len != len) {
3559 assert(elems.len == len_including_sentinel);
3560 assert(elems[len] == sentinel);
3561 unreachable;
3562 }
3563 },
3564 .repeated_elem => |elem| {
3565 assert(sentinel == .none or elem == sentinel);
3512 },3566 },
3513 .repeated_elem => {},
3514 }3567 }
3515 switch (ty_key) {3568 switch (ty_key) {
3516 inline .array_type, .vector_type => |seq_type| {3569 .array_type, .vector_type => {
3517 for (aggregate.storage.values()) |elem| {3570 for (aggregate.storage.values()) |elem| {
3518 assert(ip.typeOf(elem) == seq_type.child);3571 assert(ip.typeOf(elem) == child);
3519 }3572 }
3520 },3573 },
3521 .struct_type => |struct_type| {3574 .struct_type => |struct_type| {
...@@ -3534,7 +3587,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3534,7 +3587,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3534 else => unreachable,3587 else => unreachable,
3535 }3588 }
35363589
3537 if (aggregate_len == 0) {3590 if (len == 0) {
3538 ip.items.appendAssumeCapacity(.{3591 ip.items.appendAssumeCapacity(.{
3539 .tag = .only_possible_value,3592 .tag = .only_possible_value,
3540 .data = @enumToInt(aggregate.ty),3593 .data = @enumToInt(aggregate.ty),
...@@ -3543,41 +3596,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3543,41 +3596,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3543 }3596 }
35443597
3545 switch (ty_key) {3598 switch (ty_key) {
3546 .anon_struct_type => |anon_struct_type| {3599 .anon_struct_type => |anon_struct_type| opv: {
3547 if (switch (aggregate.storage) {3600 switch (aggregate.storage) {
3548 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {3601 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {
3549 if (value != ip.getIfExists(.{ .int = .{3602 if (value != ip.getIfExists(.{ .int = .{
3550 .ty = .u8_type,3603 .ty = .u8_type,
3551 .storage = .{ .u64 = byte },3604 .storage = .{ .u64 = byte },
3552 } })) break false;3605 } })) break :opv;
3553 } else true,3606 },
3554 .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems),3607 .elems => |elems| if (!std.mem.eql(
3608 Index,
3609 anon_struct_type.values,
3610 elems,
3611 )) break :opv,
3555 .repeated_elem => |elem| for (anon_struct_type.values) |value| {3612 .repeated_elem => |elem| for (anon_struct_type.values) |value| {
3556 if (value != elem) break false;3613 if (value != elem) break :opv;
3557 } else true,3614 },
3558 }) {
3559 // This encoding works thanks to the fact that, as we just verified,
3560 // the type itself contains a slice of values that can be provided
3561 // in the aggregate fields.
3562 ip.items.appendAssumeCapacity(.{
3563 .tag = .only_possible_value,
3564 .data = @enumToInt(aggregate.ty),
3565 });
3566 return @intToEnum(Index, ip.items.len - 1);
3567 }3615 }
3616 // This encoding works thanks to the fact that, as we just verified,
3617 // the type itself contains a slice of values that can be provided
3618 // in the aggregate fields.
3619 ip.items.appendAssumeCapacity(.{
3620 .tag = .only_possible_value,
3621 .data = @enumToInt(aggregate.ty),
3622 });
3623 return @intToEnum(Index, ip.items.len - 1);
3568 },3624 },
3569 else => {},3625 else => {},
3570 }3626 }
35713627
3572 if (switch (aggregate.storage) {3628 repeated: {
3573 .bytes => |bytes| for (bytes[1..]) |byte| {3629 switch (aggregate.storage) {
3574 if (byte != bytes[0]) break false;3630 .bytes => |bytes| for (bytes[1..@intCast(usize, len)]) |byte|
3575 } else true,3631 if (byte != bytes[0]) break :repeated,
3576 .elems => |elems| for (elems[1..]) |elem| {3632 .elems => |elems| for (elems[1..@intCast(usize, len)]) |elem|
3577 if (elem != elems[0]) break false;3633 if (elem != elems[0]) break :repeated,
3578 } else true,3634 .repeated_elem => {},
3579 .repeated_elem => true,3635 }
3580 }) {
3581 const elem = switch (aggregate.storage) {3636 const elem = switch (aggregate.storage) {
3582 .bytes => |bytes| elem: {3637 .bytes => |bytes| elem: {
3583 _ = ip.map.pop();3638 _ = ip.map.pop();
...@@ -3607,42 +3662,48 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3607,42 +3662,48 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3607 return @intToEnum(Index, ip.items.len - 1);3662 return @intToEnum(Index, ip.items.len - 1);
3608 }3663 }
36093664
3610 switch (ty_key) {3665 if (child == .u8_type) bytes: {
3611 .array_type => |array_type| if (array_type.child == .u8_type) {3666 const string_bytes_index = ip.string_bytes.items.len;
3612 const len_including_sentinel = aggregate_len + @boolToInt(array_type.sentinel != .none);3667 try ip.string_bytes.ensureUnusedCapacity(gpa, len_including_sentinel + 1);
3613 try ip.string_bytes.ensureUnusedCapacity(gpa, len_including_sentinel + 1);3668 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
3614 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);3669 switch (aggregate.storage) {
3615 var buffer: Key.Int.Storage.BigIntSpace = undefined;3670 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
3616 switch (aggregate.storage) {3671 .elems => |elems| for (elems) |elem| switch (ip.indexToKey(elem)) {
3617 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),3672 .undef => {
3618 .elems => |elems| for (elems) |elem| ip.string_bytes.appendAssumeCapacity(3673 ip.string_bytes.shrinkRetainingCapacity(string_bytes_index);
3619 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,3674 break :bytes;
3675 },
3676 .int => |int| ip.string_bytes.appendAssumeCapacity(
3677 @intCast(u8, int.storage.u64),
3620 ),3678 ),
3621 .repeated_elem => |elem| @memset(3679 else => unreachable,
3622 ip.string_bytes.addManyAsSliceAssumeCapacity(aggregate_len),3680 },
3623 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,3681 .repeated_elem => |elem| switch (ip.indexToKey(elem)) {
3682 .undef => break :bytes,
3683 .int => |int| @memset(
3684 ip.string_bytes.addManyAsSliceAssumeCapacity(len),
3685 @intCast(u8, int.storage.u64),
3624 ),3686 ),
3625 }3687 else => unreachable,
3626 if (array_type.sentinel != .none) ip.string_bytes.appendAssumeCapacity(3688 },
3627 ip.indexToKey(array_type.sentinel).int.storage.toBigInt(&buffer).to(u8) catch3689 }
3628 unreachable,3690 if (sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3629 );3691 @intCast(u8, ip.indexToKey(sentinel).int.storage.u64),
3630 const bytes = try ip.getOrPutTrailingString(gpa, len_including_sentinel);3692 );
3631 ip.items.appendAssumeCapacity(.{3693 const bytes = try ip.getOrPutTrailingString(gpa, len_including_sentinel);
3632 .tag = .bytes,3694 ip.items.appendAssumeCapacity(.{
3633 .data = ip.addExtraAssumeCapacity(Bytes{3695 .tag = .bytes,
3634 .ty = aggregate.ty,3696 .data = ip.addExtraAssumeCapacity(Bytes{
3635 .bytes = bytes.toString(),3697 .ty = aggregate.ty,
3636 }),3698 .bytes = bytes.toString(),
3637 });3699 }),
3638 return @intToEnum(Index, ip.items.len - 1);3700 });
3639 },3701 return @intToEnum(Index, ip.items.len - 1);
3640 else => {},
3641 }3702 }
36423703
3643 try ip.extra.ensureUnusedCapacity(3704 try ip.extra.ensureUnusedCapacity(
3644 gpa,3705 gpa,
3645 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,3706 @typeInfo(Aggregate).Struct.fields.len + len_including_sentinel,
3646 );3707 );
3647 ip.items.appendAssumeCapacity(.{3708 ip.items.appendAssumeCapacity(.{
3648 .tag = .aggregate,3709 .tag = .aggregate,
...@@ -3651,6 +3712,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3651,6 +3712,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3651 }),3712 }),
3652 });3713 });
3653 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));3714 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));
3715 if (sentinel != .none) ip.extra.appendAssumeCapacity(@enumToInt(sentinel));
3654 },3716 },
36553717
3656 .un => |un| {3718 .un => |un| {
...@@ -4183,10 +4245,12 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {...@@ -4183,10 +4245,12 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
4183/// Given an existing value, returns the same value but with the supplied type.4245/// Given an existing value, returns the same value but with the supplied type.
4184/// Only some combinations are allowed:4246/// Only some combinations are allowed:
4185/// * identity coercion4247/// * identity coercion
4248/// * undef => any
4186/// * int <=> int4249/// * int <=> int
4187/// * int <=> enum4250/// * int <=> enum
4188/// * enum_literal => enum4251/// * enum_literal => enum
4189/// * ptr <=> ptr4252/// * ptr <=> ptr
4253/// * int => ptr
4190/// * null_value => opt4254/// * null_value => opt
4191/// * payload => opt4255/// * payload => opt
4192/// * error set <=> error set4256/// * error set <=> error set
...@@ -4194,68 +4258,93 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {...@@ -4194,68 +4258,93 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
4194/// * error set => error union4258/// * error set => error union
4195/// * payload => error union4259/// * payload => error union
4196/// * fn <=> fn4260/// * fn <=> fn
4261/// * array <=> array
4262/// * array <=> vector
4263/// * vector <=> vector
4197pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {4264pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
4198 const old_ty = ip.typeOf(val);4265 const old_ty = ip.typeOf(val);
4199 if (old_ty == new_ty) return val;4266 if (old_ty == new_ty) return val;
4200 switch (ip.indexToKey(val)) {4267 switch (val) {
4201 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))4268 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4202 return ip.get(gpa, .{ .extern_func = .{4269 .null_value => if (ip.isOptionalType(new_ty))
4203 .ty = new_ty,4270 return ip.get(gpa, .{ .opt = .{
4204 .decl = extern_func.decl,
4205 .lib_name = extern_func.lib_name,
4206 } }),
4207 .func => |func| if (ip.isFunctionType(new_ty))
4208 return ip.get(gpa, .{ .func = .{
4209 .ty = new_ty,
4210 .index = func.index,
4211 } }),
4212 .int => |int| if (ip.isIntegerType(new_ty))
4213 return getCoercedInts(ip, gpa, int, new_ty)
4214 else if (ip.isEnumType(new_ty))
4215 return ip.get(gpa, .{ .enum_tag = .{
4216 .ty = new_ty,4271 .ty = new_ty,
4217 .int = val,4272 .val = .none,
4218 } }),4273 } }),
4219 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))4274 else => switch (ip.indexToKey(val)) {
4220 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),4275 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4221 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {4276 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
4222 .enum_type => |enum_type| {4277 return ip.get(gpa, .{ .extern_func = .{
4223 const index = enum_type.nameIndex(ip, enum_literal).?;4278 .ty = new_ty,
4279 .decl = extern_func.decl,
4280 .lib_name = extern_func.lib_name,
4281 } }),
4282 .func => |func| if (ip.isFunctionType(new_ty))
4283 return ip.get(gpa, .{ .func = .{
4284 .ty = new_ty,
4285 .index = func.index,
4286 } }),
4287 .int => |int| if (ip.isIntegerType(new_ty))
4288 return getCoercedInts(ip, gpa, int, new_ty)
4289 else if (ip.isEnumType(new_ty))
4224 return ip.get(gpa, .{ .enum_tag = .{4290 return ip.get(gpa, .{ .enum_tag = .{
4225 .ty = new_ty,4291 .ty = new_ty,
4226 .int = if (enum_type.values.len != 0)4292 .int = val,
4227 enum_type.values[index]4293 } })
4228 else4294 else if (ip.isPointerType(new_ty))
4229 try ip.get(gpa, .{ .int = .{4295 return ip.get(gpa, .{ .ptr = .{
4230 .ty = enum_type.tag_ty,4296 .ty = new_ty,
4231 .storage = .{ .u64 = index },4297 .addr = .{ .int = val },
4232 } }),4298 } }),
4233 } });4299 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
4300 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
4301 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
4302 .enum_type => |enum_type| {
4303 const index = enum_type.nameIndex(ip, enum_literal).?;
4304 return ip.get(gpa, .{ .enum_tag = .{
4305 .ty = new_ty,
4306 .int = if (enum_type.values.len != 0)
4307 enum_type.values[index]
4308 else
4309 try ip.get(gpa, .{ .int = .{
4310 .ty = enum_type.tag_ty,
4311 .storage = .{ .u64 = index },
4312 } }),
4313 } });
4314 },
4315 else => {},
4234 },4316 },
4235 else => {},4317 .ptr => |ptr| if (ip.isPointerType(new_ty))
4236 },4318 return ip.get(gpa, .{ .ptr = .{
4237 .ptr => |ptr| if (ip.isPointerType(new_ty))4319 .ty = new_ty,
4238 return ip.get(gpa, .{ .ptr = .{4320 .addr = ptr.addr,
4239 .ty = new_ty,4321 .len = ptr.len,
4240 .addr = ptr.addr,4322 } }),
4241 .len = ptr.len,4323 .err => |err| if (ip.isErrorSetType(new_ty))
4242 } }),4324 return ip.get(gpa, .{ .err = .{
4243 .err => |err| if (ip.isErrorSetType(new_ty))4325 .ty = new_ty,
4244 return ip.get(gpa, .{ .err = .{4326 .name = err.name,
4245 .ty = new_ty,4327 } })
4246 .name = err.name,4328 else if (ip.isErrorUnionType(new_ty))
4247 } })4329 return ip.get(gpa, .{ .error_union = .{
4248 else if (ip.isErrorUnionType(new_ty))4330 .ty = new_ty,
4249 return ip.get(gpa, .{ .error_union = .{4331 .val = .{ .err_name = err.name },
4250 .ty = new_ty,4332 } }),
4251 .val = .{ .err_name = err.name },4333 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4252 } }),4334 return ip.get(gpa, .{ .error_union = .{
4253 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))4335 .ty = new_ty,
4254 return ip.get(gpa, .{ .error_union = .{4336 .val = error_union.val,
4337 } }),
4338 .aggregate => |aggregate| return ip.get(gpa, .{ .aggregate = .{
4255 .ty = new_ty,4339 .ty = new_ty,
4256 .val = error_union.val,4340 .storage = switch (aggregate.storage) {
4341 .bytes => |bytes| .{ .bytes = bytes[0..@intCast(usize, ip.aggregateTypeLen(new_ty))] },
4342 .elems => |elems| .{ .elems = elems[0..@intCast(usize, ip.aggregateTypeLen(new_ty))] },
4343 .repeated_elem => |elem| .{ .repeated_elem = elem },
4344 },
4257 } }),4345 } }),
4258 else => {},4346 else => {},
4347 },
4259 }4348 }
4260 switch (ip.indexToKey(new_ty)) {4349 switch (ip.indexToKey(new_ty)) {
4261 .opt_type => |child_type| switch (val) {4350 .opt_type => |child_type| switch (val) {
...@@ -4527,7 +4616,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4527,7 +4616,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
45274616
4528 .type_function => b: {4617 .type_function => b: {
4529 const info = ip.extraData(TypeFunction, data);4618 const info = ip.extraData(TypeFunction, data);
4530 break :b @sizeOf(TypeFunction) + (@sizeOf(u32) * info.params_len);4619 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);
4531 },4620 },
45324621
4533 .undef => 0,4622 .undef => 0,
...@@ -4570,14 +4659,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4570,14 +4659,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
45704659
4571 .bytes => b: {4660 .bytes => b: {
4572 const info = ip.extraData(Bytes, data);4661 const info = ip.extraData(Bytes, data);
4573 const len = @intCast(u32, ip.aggregateTypeLen(info.ty));4662 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
4574 break :b @sizeOf(Bytes) + len +4663 break :b @sizeOf(Bytes) + len +
4575 @boolToInt(ip.string_bytes.items[@enumToInt(info.bytes) + len - 1] != 0);4664 @boolToInt(ip.string_bytes.items[@enumToInt(info.bytes) + len - 1] != 0);
4576 },4665 },
4577 .aggregate => b: {4666 .aggregate => b: {
4578 const info = ip.extraData(Aggregate, data);4667 const info = ip.extraData(Aggregate, data);
4579 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));4668 const fields_len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
4580 break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len);4669 break :b @sizeOf(Aggregate) + (@sizeOf(Index) * fields_len);
4581 },4670 },
4582 .repeated => @sizeOf(Repeated),4671 .repeated => @sizeOf(Repeated),
45834672
...@@ -4889,6 +4978,16 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {...@@ -4889,6 +4978,16 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
4889 };4978 };
4890}4979}
48914980
4981pub fn aggregateTypeLenIncludingSentinel(ip: InternPool, ty: Index) u64 {
4982 return switch (ip.indexToKey(ty)) {
4983 .struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
4984 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
4985 .array_type => |array_type| array_type.len + @boolToInt(array_type.sentinel != .none),
4986 .vector_type => |vector_type| vector_type.len,
4987 else => unreachable,
4988 };
4989}
4990
4892pub fn isNoReturn(ip: InternPool, ty: Index) bool {4991pub fn isNoReturn(ip: InternPool, ty: Index) bool {
4893 return switch (ty) {4992 return switch (ty) {
4894 .noreturn_type => true,4993 .noreturn_type => true,
src/Module.zig+35-48
...@@ -99,6 +99,7 @@ monomorphed_funcs: MonomorphedFuncsSet = .{},...@@ -99,6 +99,7 @@ monomorphed_funcs: MonomorphedFuncsSet = .{},
99/// The set of all comptime function calls that have been cached so that future calls99/// The set of all comptime function calls that have been cached so that future calls
100/// with the same parameters will get the same return value.100/// with the same parameters will get the same return value.
101memoized_calls: MemoizedCallSet = .{},101memoized_calls: MemoizedCallSet = .{},
102memoized_call_args: MemoizedCall.Args = .{},
102/// Contains the values from `@setAlignStack`. A sparse table is used here103/// Contains the values from `@setAlignStack`. A sparse table is used here
103/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while104/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
104/// functions are many.105/// functions are many.
...@@ -230,46 +231,30 @@ pub const MemoizedCallSet = std.HashMapUnmanaged(...@@ -230,46 +231,30 @@ pub const MemoizedCallSet = std.HashMapUnmanaged(
230);231);
231232
232pub const MemoizedCall = struct {233pub const MemoizedCall = struct {
233 module: *Module,234 args: *const Args,
235
236 pub const Args = std.ArrayListUnmanaged(InternPool.Index);
234237
235 pub const Key = struct {238 pub const Key = struct {
236 func: Fn.Index,239 func: Fn.Index,
237 args: []TypedValue,240 args_index: u32,
238 };241 args_count: u32,
239242
240 pub const Result = struct {243 pub fn args(key: Key, ctx: MemoizedCall) []InternPool.Index {
241 val: Value,244 return ctx.args.items[key.args_index..][0..key.args_count];
242 arena: std.heap.ArenaAllocator.State,245 }
243 };246 };
244247
245 pub fn eql(ctx: @This(), a: Key, b: Key) bool {248 pub const Result = InternPool.Index;
246 if (a.func != b.func) return false;
247
248 assert(a.args.len == b.args.len);
249 for (a.args, 0..) |a_arg, arg_i| {
250 const b_arg = b.args[arg_i];
251 if (!a_arg.eql(b_arg, ctx.module)) {
252 return false;
253 }
254 }
255249
256 return true;250 pub fn eql(ctx: MemoizedCall, a: Key, b: Key) bool {
251 return a.func == b.func and mem.eql(InternPool.Index, a.args(ctx), b.args(ctx));
257 }252 }
258253
259 /// Must match `Sema.GenericCallAdapter.hash`.254 pub fn hash(ctx: MemoizedCall, key: Key) u64 {
260 pub fn hash(ctx: @This(), key: Key) u64 {
261 var hasher = std.hash.Wyhash.init(0);255 var hasher = std.hash.Wyhash.init(0);
262
263 // The generic function Decl is guaranteed to be the first dependency
264 // of each of its instantiations.
265 std.hash.autoHash(&hasher, key.func);256 std.hash.autoHash(&hasher, key.func);
266257 std.hash.autoHashStrat(&hasher, key.args(ctx), .Deep);
267 // This logic must be kept in sync with the logic in `analyzeCall` that
268 // computes the hash.
269 for (key.args) |arg| {
270 arg.hash(&hasher, ctx.module);
271 }
272
273 return hasher.final();258 return hasher.final();
274 }259 }
275};260};
...@@ -883,6 +868,10 @@ pub const Decl = struct {...@@ -883,6 +868,10 @@ pub const Decl = struct {
883 return decl.ty.abiAlignment(mod);868 return decl.ty.abiAlignment(mod);
884 }869 }
885 }870 }
871
872 pub fn intern(decl: *Decl, mod: *Module) Allocator.Error!void {
873 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
874 }
886};875};
887876
888/// This state is attached to every Decl when Module emit_h is non-null.877/// This state is attached to every Decl when Module emit_h is non-null.
...@@ -3325,15 +3314,8 @@ pub fn deinit(mod: *Module) void {...@@ -3325,15 +3314,8 @@ pub fn deinit(mod: *Module) void {
3325 mod.test_functions.deinit(gpa);3314 mod.test_functions.deinit(gpa);
3326 mod.align_stack_fns.deinit(gpa);3315 mod.align_stack_fns.deinit(gpa);
3327 mod.monomorphed_funcs.deinit(gpa);3316 mod.monomorphed_funcs.deinit(gpa);
33283317 mod.memoized_call_args.deinit(gpa);
3329 {3318 mod.memoized_calls.deinit(gpa);
3330 var it = mod.memoized_calls.iterator();
3331 while (it.next()) |entry| {
3332 gpa.free(entry.key_ptr.args);
3333 entry.value_ptr.arena.promote(gpa).deinit();
3334 }
3335 mod.memoized_calls.deinit(gpa);
3336 }
33373319
3338 mod.decls_free_list.deinit(gpa);3320 mod.decls_free_list.deinit(gpa);
3339 mod.allocated_decls.deinit(gpa);3321 mod.allocated_decls.deinit(gpa);
...@@ -5894,6 +5876,7 @@ pub fn initNewAnonDecl(...@@ -5894,6 +5876,7 @@ pub fn initNewAnonDecl(
5894 typed_value: TypedValue,5876 typed_value: TypedValue,
5895 name: [:0]u8,5877 name: [:0]u8,
5896) !void {5878) !void {
5879 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
5897 errdefer mod.gpa.free(name);5880 errdefer mod.gpa.free(name);
58985881
5899 const new_decl = mod.declPtr(new_decl_index);5882 const new_decl = mod.declPtr(new_decl_index);
...@@ -6645,7 +6628,7 @@ pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {...@@ -6645,7 +6628,7 @@ pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
6645 if (decl.alive) return;6628 if (decl.alive) return;
6646 decl.alive = true;6629 decl.alive = true;
66476630
6648 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();6631 try decl.intern(mod);
66496632
6650 // This is the first time we are marking this Decl alive. We must6633 // This is the first time we are marking this Decl alive. We must
6651 // therefore recurse into its value and mark any Decl it references6634 // therefore recurse into its value and mark any Decl it references
...@@ -6749,15 +6732,19 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type...@@ -6749,15 +6732,19 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type
6749 }6732 }
6750 }6733 }
67516734
6752 // Canonicalize host_size. If it matches the bit size of the pointee type,6735 switch (info.vector_index) {
6753 // we change it to 0 here. If this causes an assertion trip, the pointee type6736 // Canonicalize host_size. If it matches the bit size of the pointee type,
6754 // needs to be resolved before calling this ptr() function.6737 // we change it to 0 here. If this causes an assertion trip, the pointee type
6755 if (info.host_size != 0) {6738 // needs to be resolved before calling this ptr() function.
6756 const elem_bit_size = info.elem_type.toType().bitSize(mod);6739 .none => if (info.host_size != 0) {
6757 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);6740 const elem_bit_size = info.elem_type.toType().bitSize(mod);
6758 if (info.host_size * 8 == elem_bit_size) {6741 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
6759 canon_info.host_size = 0;6742 if (info.host_size * 8 == elem_bit_size) {
6760 }6743 canon_info.host_size = 0;
6744 }
6745 },
6746 .runtime => {},
6747 _ => assert(@enumToInt(info.vector_index) < info.host_size),
6761 }6748 }
67626749
6763 return (try intern(mod, .{ .ptr_type = canon_info })).toType();6750 return (try intern(mod, .{ .ptr_type = canon_info })).toType();
src/RangeSet.zig+33-25
...@@ -1,18 +1,18 @@...@@ -1,18 +1,18 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;
2const Order = std.math.Order;3const Order = std.math.Order;
34
4const RangeSet = @This();5const InternPool = @import("InternPool.zig");
5const Module = @import("Module.zig");6const Module = @import("Module.zig");
7const RangeSet = @This();
6const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;8const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
7const Type = @import("type.zig").Type;
8const Value = @import("value.zig").Value;
99
10ranges: std.ArrayList(Range),10ranges: std.ArrayList(Range),
11module: *Module,11module: *Module,
1212
13pub const Range = struct {13pub const Range = struct {
14 first: Value,14 first: InternPool.Index,
15 last: Value,15 last: InternPool.Index,
16 src: SwitchProngSrc,16 src: SwitchProngSrc,
17};17};
1818
...@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {...@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {
2929
30pub fn add(30pub fn add(
31 self: *RangeSet,31 self: *RangeSet,
32 first: Value,32 first: InternPool.Index,
33 last: Value,33 last: InternPool.Index,
34 ty: Type,
35 src: SwitchProngSrc,34 src: SwitchProngSrc,
36) !?SwitchProngSrc {35) !?SwitchProngSrc {
36 const mod = self.module;
37 const ip = &mod.intern_pool;
38
39 const ty = ip.typeOf(first);
40 assert(ty == ip.typeOf(last));
41
37 for (self.ranges.items) |range| {42 for (self.ranges.items) |range| {
38 if (last.compareScalar(.gte, range.first, ty, self.module) and43 assert(ty == ip.typeOf(range.first));
39 first.compareScalar(.lte, range.last, ty, self.module))44 assert(ty == ip.typeOf(range.last));
45
46 if (last.toValue().compareScalar(.gte, range.first.toValue(), ty.toType(), mod) and
47 first.toValue().compareScalar(.lte, range.last.toValue(), ty.toType(), mod))
40 {48 {
41 return range.src; // They overlap.49 return range.src; // They overlap.
42 }50 }
43 }51 }
52
44 try self.ranges.append(.{53 try self.ranges.append(.{
45 .first = first,54 .first = first,
46 .last = last,55 .last = last,
...@@ -49,30 +58,29 @@ pub fn add(...@@ -49,30 +58,29 @@ pub fn add(
49 return null;58 return null;
50}59}
5160
52const LessThanContext = struct { ty: Type, module: *Module };
53
54/// Assumes a and b do not overlap61/// Assumes a and b do not overlap
55fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {62fn lessThan(mod: *Module, a: Range, b: Range) bool {
56 return a.first.compareScalar(.lt, b.first, ctx.ty, ctx.module);63 const ty = mod.intern_pool.typeOf(a.first).toType();
64 return a.first.toValue().compareScalar(.lt, b.first.toValue(), ty, mod);
57}65}
5866
59pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {67pub fn spans(self: *RangeSet, first: InternPool.Index, last: InternPool.Index) !bool {
68 const mod = self.module;
69 const ip = &mod.intern_pool;
70 assert(ip.typeOf(first) == ip.typeOf(last));
71
60 if (self.ranges.items.len == 0)72 if (self.ranges.items.len == 0)
61 return false;73 return false;
6274
63 const mod = self.module;75 std.mem.sort(Range, self.ranges.items, mod, lessThan);
64 std.mem.sort(Range, self.ranges.items, LessThanContext{
65 .ty = ty,
66 .module = mod,
67 }, lessThan);
6876
69 if (!self.ranges.items[0].first.eql(first, ty, mod) or77 if (self.ranges.items[0].first != first or
70 !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, mod))78 self.ranges.items[self.ranges.items.len - 1].last != last)
71 {79 {
72 return false;80 return false;
73 }81 }
7482
75 var space: Value.BigIntSpace = undefined;83 var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
7684
77 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);85 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
78 defer counter.deinit();86 defer counter.deinit();
...@@ -83,10 +91,10 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {...@@ -83,10 +91,10 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
83 const prev = self.ranges.items[i];91 const prev = self.ranges.items[i];
8492
85 // prev.last + 1 == cur.first93 // prev.last + 1 == cur.first
86 try counter.copy(prev.last.toBigInt(&space, mod));94 try counter.copy(prev.last.toValue().toBigInt(&space, mod));
87 try counter.addScalar(&counter, 1);95 try counter.addScalar(&counter, 1);
8896
89 const cur_start_int = cur.first.toBigInt(&space, mod);97 const cur_start_int = cur.first.toValue().toBigInt(&space, mod);
90 if (!cur_start_int.eq(counter.toConst())) {98 if (!cur_start_int.eq(counter.toConst())) {
91 return false;99 return false;
92 }100 }
src/Sema.zig+333-338
...@@ -1609,7 +1609,7 @@ fn analyzeBodyInner(...@@ -1609,7 +1609,7 @@ fn analyzeBodyInner(
1609 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1609 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1610 return err;1610 return err;
1611 };1611 };
1612 const inline_body = if (cond.val.toBool(mod)) then_body else else_body;1612 const inline_body = if (cond.val.toBool()) then_body else else_body;
16131613
1614 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1614 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1615 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1615 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -1630,7 +1630,7 @@ fn analyzeBodyInner(...@@ -1630,7 +1630,7 @@ fn analyzeBodyInner(
1630 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1630 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1631 return err;1631 return err;
1632 };1632 };
1633 const inline_body = if (cond.val.toBool(mod)) then_body else else_body;1633 const inline_body = if (cond.val.toBool()) then_body else else_body;
16341634
1635 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1635 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1636 const old_runtime_index = block.runtime_index;1636 const old_runtime_index = block.runtime_index;
...@@ -1663,7 +1663,7 @@ fn analyzeBodyInner(...@@ -1663,7 +1663,7 @@ fn analyzeBodyInner(
1663 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1663 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1664 return err;1664 return err;
1665 };1665 };
1666 if (is_non_err_val.toBool(mod)) {1666 if (is_non_err_val.toBool()) {
1667 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);1667 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
1668 }1668 }
1669 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1669 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -1689,7 +1689,7 @@ fn analyzeBodyInner(...@@ -1689,7 +1689,7 @@ fn analyzeBodyInner(
1689 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);1689 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
1690 return err;1690 return err;
1691 };1691 };
1692 if (is_non_err_val.toBool(mod)) {1692 if (is_non_err_val.toBool()) {
1693 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);1693 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1694 }1694 }
1695 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1695 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
...@@ -1778,12 +1778,11 @@ fn resolveConstBool(...@@ -1778,12 +1778,11 @@ fn resolveConstBool(
1778 zir_ref: Zir.Inst.Ref,1778 zir_ref: Zir.Inst.Ref,
1779 reason: []const u8,1779 reason: []const u8,
1780) !bool {1780) !bool {
1781 const mod = sema.mod;
1782 const air_inst = try sema.resolveInst(zir_ref);1781 const air_inst = try sema.resolveInst(zir_ref);
1783 const wanted_type = Type.bool;1782 const wanted_type = Type.bool;
1784 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1783 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1785 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);1784 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
1786 return val.toBool(mod);1785 return val.toBool();
1787}1786}
17881787
1789pub fn resolveConstString(1788pub fn resolveConstString(
...@@ -2488,7 +2487,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -2488,7 +2487,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2488 defer anon_decl.deinit();2487 defer anon_decl.deinit();
2489 const decl_index = try anon_decl.finish(2488 const decl_index = try anon_decl.finish(
2490 pointee_ty,2489 pointee_ty,
2491 Value.undef,2490 (try mod.intern(.{ .undef = pointee_ty.toIntern() })).toValue(),
2492 alignment.toByteUnits(0),2491 alignment.toByteUnits(0),
2493 );2492 );
2494 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;2493 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
...@@ -2611,7 +2610,7 @@ fn coerceResultPtr(...@@ -2611,7 +2610,7 @@ fn coerceResultPtr(
2611 .@"addrspace" = addr_space,2610 .@"addrspace" = addr_space,
2612 });2611 });
2613 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {2612 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2614 new_ptr = try sema.addConstant(ptr_operand_ty, ptr_val);2613 new_ptr = try sema.addConstant(ptr_operand_ty, try mod.getCoerced(ptr_val, ptr_operand_ty));
2615 } else {2614 } else {
2616 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);2615 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
2617 }2616 }
...@@ -3613,7 +3612,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai...@@ -3613,7 +3612,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
36133612
3614 // Detect if a comptime value simply needs to have its type changed.3613 // Detect if a comptime value simply needs to have its type changed.
3615 if (try sema.resolveMaybeUndefVal(alloc)) |val| {3614 if (try sema.resolveMaybeUndefVal(alloc)) |val| {
3616 return sema.addConstant(const_ptr_ty, val);3615 return sema.addConstant(const_ptr_ty, try mod.getCoerced(val, const_ptr_ty));
3617 }3616 }
36183617
3619 return block.addBitCast(const_ptr_ty, alloc);3618 return block.addBitCast(const_ptr_ty, alloc);
...@@ -3735,6 +3734,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3735,6 +3734,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3735 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);3734 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
37363735
3737 const decl = mod.declPtr(decl_index);3736 const decl = mod.declPtr(decl_index);
3737 if (iac.is_const) try decl.intern(mod);
3738 const final_elem_ty = decl.ty;3738 const final_elem_ty = decl.ty;
3739 const final_ptr_ty = try mod.ptrType(.{3739 const final_ptr_ty = try mod.ptrType(.{
3740 .elem_type = final_elem_ty.toIntern(),3740 .elem_type = final_elem_ty.toIntern(),
...@@ -3774,7 +3774,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3774,7 +3774,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3774 // Detect if the value is comptime-known. In such case, the3774 // Detect if the value is comptime-known. In such case, the
3775 // last 3 AIR instructions of the block will look like this:3775 // last 3 AIR instructions of the block will look like this:
3776 //3776 //
3777 // %a = interned3777 // %a = inferred_alloc
3778 // %b = bitcast(%a)3778 // %b = bitcast(%a)
3779 // %c = store(%b, %d)3779 // %c = store(%b, %d)
3780 //3780 //
...@@ -3814,22 +3814,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3814,22 +3814,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3814 }3814 }
3815 };3815 };
38163816
3817 const const_inst = while (true) {3817 while (true) {
3818 if (search_index == 0) break :ct;3818 if (search_index == 0) break :ct;
3819 search_index -= 1;3819 search_index -= 1;
38203820
3821 const candidate = block.instructions.items[search_index];3821 const candidate = block.instructions.items[search_index];
3822 if (candidate == ptr_inst) break;
3822 switch (air_tags[candidate]) {3823 switch (air_tags[candidate]) {
3823 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,3824 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3824 .interned => break candidate,
3825 else => break :ct,3825 else => break :ct,
3826 }3826 }
3827 };3827 }
38283828
3829 const store_op = air_datas[store_inst].bin_op;3829 const store_op = air_datas[store_inst].bin_op;
3830 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;3830 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;
3831 if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct;3831 if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct;
3832 if (air_datas[bitcast_inst].ty_op.operand != Air.indexToRef(const_inst)) break :ct;3832 if (air_datas[bitcast_inst].ty_op.operand != ptr) break :ct;
38333833
3834 const new_decl_index = d: {3834 const new_decl_index = d: {
3835 var anon_decl = try block.startAnonDecl();3835 var anon_decl = try block.startAnonDecl();
...@@ -3850,7 +3850,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3850,7 +3850,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3850 sema.air_instructions.set(ptr_inst, .{3850 sema.air_instructions.set(ptr_inst, .{
3851 .tag = .interned,3851 .tag = .interned,
3852 .data = .{ .interned = try mod.intern(.{ .ptr = .{3852 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3853 .ty = final_elem_ty.toIntern(),3853 .ty = final_ptr_ty.toIntern(),
3854 .addr = .{ .decl = new_decl_index },3854 .addr = .{ .decl = new_decl_index },
3855 } }) },3855 } }) },
3856 });3856 });
...@@ -4707,15 +4707,23 @@ fn zirValidateArrayInit(...@@ -4707,15 +4707,23 @@ fn zirValidateArrayInit(
4707 return;4707 return;
4708 }4708 }
47094709
4710 // If the array has one possible value, the value is always comptime-known.
4711 if (try sema.typeHasOnePossibleValue(array_ty)) |array_opv| {
4712 const array_init = try sema.addConstant(array_ty, array_opv);
4713 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
4714 return;
4715 }
4716
4710 var array_is_comptime = true;4717 var array_is_comptime = true;
4711 var first_block_index = block.instructions.items.len;4718 var first_block_index = block.instructions.items.len;
4712 var make_runtime = false;4719 var make_runtime = false;
47134720
4714 // Collect the comptime element values in case the array literal ends up4721 // Collect the comptime element values in case the array literal ends up
4715 // being comptime-known.4722 // being comptime-known.
4716 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel(mod));4723 const element_vals = try sema.arena.alloc(
4717 const element_vals = try sema.arena.alloc(InternPool.Index, array_len_s);4724 InternPool.Index,
4718 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);4725 try sema.usizeCast(block, init_src, array_len),
4726 );
4719 const air_tags = sema.air_instructions.items(.tag);4727 const air_tags = sema.air_instructions.items(.tag);
4720 const air_datas = sema.air_instructions.items(.data);4728 const air_datas = sema.air_instructions.items(.data);
47214729
...@@ -4727,12 +4735,6 @@ fn zirValidateArrayInit(...@@ -4727,12 +4735,6 @@ fn zirValidateArrayInit(
4727 element_vals[i] = opv.toIntern();4735 element_vals[i] = opv.toIntern();
4728 continue;4736 continue;
4729 }4737 }
4730 } else {
4731 // Array has one possible value, so value is always comptime-known
4732 if (opt_opv) |opv| {
4733 element_vals[i] = opv.toIntern();
4734 continue;
4735 }
4736 }4738 }
47374739
4738 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;4740 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
...@@ -4814,11 +4816,6 @@ fn zirValidateArrayInit(...@@ -4814,11 +4816,6 @@ fn zirValidateArrayInit(
48144816
4815 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert4817 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert
4816 // instead a single `store` to the array_ptr with a comptime struct value.4818 // instead a single `store` to the array_ptr with a comptime struct value.
4817 // Also to populate the sentinel value, if any.
4818 if (array_ty.sentinel(mod)) |sentinel_val| {
4819 element_vals[instrs.len] = sentinel_val.toIntern();
4820 }
4821
4822 block.instructions.shrinkRetainingCapacity(first_block_index);4819 block.instructions.shrinkRetainingCapacity(first_block_index);
48234820
4824 var array_val = try mod.intern(.{ .aggregate = .{4821 var array_val = try mod.intern(.{ .aggregate = .{
...@@ -6259,7 +6256,7 @@ fn popErrorReturnTrace(...@@ -6259,7 +6256,7 @@ fn popErrorReturnTrace(
6259 if (operand != .none) {6256 if (operand != .none) {
6260 is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand);6257 is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand);
6261 if (try sema.resolveDefinedValue(block, src, is_non_error_inst)) |cond_val|6258 if (try sema.resolveDefinedValue(block, src, is_non_error_inst)) |cond_val|
6262 is_non_error = cond_val.toBool(mod);6259 is_non_error = cond_val.toBool();
6263 } else is_non_error = true; // no operand means pop unconditionally6260 } else is_non_error = true; // no operand means pop unconditionally
62646261
6265 if (is_non_error == true) {6262 if (is_non_error == true) {
...@@ -6873,14 +6870,15 @@ fn analyzeCall(...@@ -6873,14 +6870,15 @@ fn analyzeCall(
68736870
6874 // If it's a comptime function call, we need to memoize it as long as no external6871 // If it's a comptime function call, we need to memoize it as long as no external
6875 // comptime memory is mutated.6872 // comptime memory is mutated.
6876 var memoized_call_key: Module.MemoizedCall.Key = undefined;6873 var memoized_call_key = Module.MemoizedCall.Key{
6874 .func = module_fn_index,
6875 .args_index = @intCast(u32, mod.memoized_call_args.items.len),
6876 .args_count = @intCast(u32, func_ty_info.param_types.len),
6877 };
6877 var delete_memoized_call_key = false;6878 var delete_memoized_call_key = false;
6878 defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);6879 defer if (delete_memoized_call_key) mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index);
6879 if (is_comptime_call) {6880 if (is_comptime_call) {
6880 memoized_call_key = .{6881 try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count);
6881 .func = module_fn_index,
6882 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
6883 };
6884 delete_memoized_call_key = true;6882 delete_memoized_call_key = true;
6885 }6883 }
68866884
...@@ -6916,8 +6914,7 @@ fn analyzeCall(...@@ -6916,8 +6914,7 @@ fn analyzeCall(
6916 uncasted_args,6914 uncasted_args,
6917 is_comptime_call,6915 is_comptime_call,
6918 &should_memoize,6916 &should_memoize,
6919 memoized_call_key,6917 mod.typeToFunc(func_ty).?.param_types,
6920 func_ty_info.param_types,
6921 func,6918 func,
6922 &has_comptime_args,6919 &has_comptime_args,
6923 ) catch |err| switch (err) {6920 ) catch |err| switch (err) {
...@@ -6934,8 +6931,7 @@ fn analyzeCall(...@@ -6934,8 +6931,7 @@ fn analyzeCall(
6934 uncasted_args,6931 uncasted_args,
6935 is_comptime_call,6932 is_comptime_call,
6936 &should_memoize,6933 &should_memoize,
6937 memoized_call_key,6934 mod.typeToFunc(func_ty).?.param_types,
6938 func_ty_info.param_types,
6939 func,6935 func,
6940 &has_comptime_args,6936 &has_comptime_args,
6941 );6937 );
...@@ -6988,9 +6984,19 @@ fn analyzeCall(...@@ -6988,9 +6984,19 @@ fn analyzeCall(
6988 // bug generating invalid LLVM IR.6984 // bug generating invalid LLVM IR.
6989 const res2: Air.Inst.Ref = res2: {6985 const res2: Air.Inst.Ref = res2: {
6990 if (should_memoize and is_comptime_call) {6986 if (should_memoize and is_comptime_call) {
6991 if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| {6987 const gop = try mod.memoized_calls.getOrPutContext(
6992 break :res2 try sema.addConstant(fn_ret_ty, result.val);6988 gpa,
6989 memoized_call_key,
6990 .{ .args = &mod.memoized_call_args },
6991 );
6992 if (gop.found_existing) {
6993 // We need to use the original memoized error set instead of fn_ret_ty.
6994 const result = gop.value_ptr.*;
6995 assert(result != .none); // recursive memoization?
6996 break :res2 try sema.addConstant(mod.intern_pool.typeOf(result).toType(), result.toValue());
6993 }6997 }
6998 gop.value_ptr.* = .none;
6999 delete_memoized_call_key = false;
6994 }7000 }
69957001
6996 const new_func_resolved_ty = try mod.funcType(new_fn_info);7002 const new_func_resolved_ty = try mod.funcType(new_fn_info);
...@@ -7049,26 +7055,10 @@ fn analyzeCall(...@@ -7049,26 +7055,10 @@ fn analyzeCall(
70497055
7050 if (should_memoize and is_comptime_call) {7056 if (should_memoize and is_comptime_call) {
7051 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");7057 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
70527058 mod.memoized_calls.getPtrContext(
7053 // TODO: check whether any external comptime memory was mutated by the7059 memoized_call_key,
7054 // comptime function call. If so, then do not memoize the call here.7060 .{ .args = &mod.memoized_call_args },
7055 // TODO: re-evaluate whether memoized_calls needs its own arena. I think7061 ).?.* = try result_val.intern(fn_ret_ty, mod);
7056 // it should be fine to use the Decl arena for the function.
7057 {
7058 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
7059 errdefer arena_allocator.deinit();
7060 const arena = arena_allocator.allocator();
7061
7062 for (memoized_call_key.args) |*arg| {
7063 arg.* = try arg.*.copy(arena);
7064 }
7065
7066 try mod.memoized_calls.putContext(gpa, memoized_call_key, .{
7067 .val = try result_val.copy(arena),
7068 .arena = arena_allocator.state,
7069 }, .{ .module = mod });
7070 delete_memoized_call_key = false;
7071 }
7072 }7062 }
70737063
7074 break :res2 result;7064 break :res2 result;
...@@ -7214,11 +7204,11 @@ fn analyzeInlineCallArg(...@@ -7214,11 +7204,11 @@ fn analyzeInlineCallArg(
7214 uncasted_args: []const Air.Inst.Ref,7204 uncasted_args: []const Air.Inst.Ref,
7215 is_comptime_call: bool,7205 is_comptime_call: bool,
7216 should_memoize: *bool,7206 should_memoize: *bool,
7217 memoized_call_key: Module.MemoizedCall.Key,
7218 raw_param_types: []const InternPool.Index,7207 raw_param_types: []const InternPool.Index,
7219 func_inst: Air.Inst.Ref,7208 func_inst: Air.Inst.Ref,
7220 has_comptime_args: *bool,7209 has_comptime_args: *bool,
7221) !void {7210) !void {
7211 const mod = sema.mod;
7222 const zir_tags = sema.code.instructions.items(.tag);7212 const zir_tags = sema.code.instructions.items(.tag);
7223 switch (zir_tags[inst]) {7213 switch (zir_tags[inst]) {
7224 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,7214 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
...@@ -7276,11 +7266,8 @@ fn analyzeInlineCallArg(...@@ -7276,11 +7266,8 @@ fn analyzeInlineCallArg(
7276 try sema.resolveLazyValue(arg_val);7266 try sema.resolveLazyValue(arg_val);
7277 },7267 },
7278 }7268 }
7279 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);7269 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7280 memoized_call_key.args[arg_i.*] = .{7270 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(param_ty.toType(), mod));
7281 .ty = param_ty.toType(),
7282 .val = arg_val,
7283 };
7284 } else {7271 } else {
7285 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);7272 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
7286 }7273 }
...@@ -7315,11 +7302,8 @@ fn analyzeInlineCallArg(...@@ -7315,11 +7302,8 @@ fn analyzeInlineCallArg(
7315 try sema.resolveLazyValue(arg_val);7302 try sema.resolveLazyValue(arg_val);
7316 },7303 },
7317 }7304 }
7318 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7319 memoized_call_key.args[arg_i.*] = .{7306 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(sema.typeOf(uncasted_arg), mod));
7320 .ty = sema.typeOf(uncasted_arg),
7321 .val = arg_val,
7322 };
7323 } else {7307 } else {
7324 if (zir_tags[inst] == .param_anytype_comptime) {7308 if (zir_tags[inst] == .param_anytype_comptime) {
7325 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7309 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
...@@ -8279,7 +8263,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8279,7 +8263,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8279 const int_tag_ty = try enum_tag_ty.intTagType(mod);8263 const int_tag_ty = try enum_tag_ty.intTagType(mod);
82808264
8281 if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {8265 if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {
8282 return sema.addConstant(int_tag_ty, opv);8266 return sema.addConstant(int_tag_ty, try mod.getCoerced(opv, int_tag_ty));
8283 }8267 }
82848268
8285 if (try sema.resolveMaybeUndefVal(enum_tag)) |enum_tag_val| {8269 if (try sema.resolveMaybeUndefVal(enum_tag)) |enum_tag_val| {
...@@ -8310,7 +8294,10 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -8310,7 +8294,10 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
8310 if (dest_ty.isNonexhaustiveEnum(mod)) {8294 if (dest_ty.isNonexhaustiveEnum(mod)) {
8311 const int_tag_ty = try dest_ty.intTagType(mod);8295 const int_tag_ty = try dest_ty.intTagType(mod);
8312 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {8296 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
8313 return sema.addConstant(dest_ty, int_val);8297 return sema.addConstant(dest_ty, (try mod.intern(.{ .enum_tag = .{
8298 .ty = dest_ty.toIntern(),
8299 .int = int_val.toIntern(),
8300 } })).toValue());
8314 }8301 }
8315 const msg = msg: {8302 const msg = msg: {
8316 const msg = try sema.errMsg(8303 const msg = try sema.errMsg(
...@@ -8657,8 +8644,10 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air...@@ -8657,8 +8644,10 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
8657 const result_ty = operand_ty.errorUnionSet(mod);8644 const result_ty = operand_ty.errorUnionSet(mod);
86588645
8659 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8646 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8660 assert(val.getError(mod) != null);8647 return sema.addConstant(result_ty, (try mod.intern(.{ .err = .{
8661 return sema.addConstant(result_ty, val);8648 .ty = result_ty.toIntern(),
8649 .name = mod.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name,
8650 } })).toValue());
8662 }8651 }
86638652
8664 try sema.requireRuntimeBlock(block, src, null);8653 try sema.requireRuntimeBlock(block, src, null);
...@@ -10737,7 +10726,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10737,7 +10726,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10737 block,10726 block,
10738 &range_set,10727 &range_set,
10739 item_ref,10728 item_ref,
10740 operand_ty,
10741 src_node_offset,10729 src_node_offset,
10742 .{ .scalar = scalar_i },10730 .{ .scalar = scalar_i },
10743 );10731 );
...@@ -10760,7 +10748,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10760,7 +10748,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10760 block,10748 block,
10761 &range_set,10749 &range_set,
10762 item_ref,10750 item_ref,
10763 operand_ty,
10764 src_node_offset,10751 src_node_offset,
10765 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },10752 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
10766 );10753 );
...@@ -10778,7 +10765,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10778,7 +10765,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10778 &range_set,10765 &range_set,
10779 item_first,10766 item_first,
10780 item_last,10767 item_last,
10781 operand_ty,
10782 src_node_offset,10768 src_node_offset,
10783 .{ .range = .{ .prong = multi_i, .item = range_i } },10769 .{ .range = .{ .prong = multi_i, .item = range_i } },
10784 );10770 );
...@@ -10792,7 +10778,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10792,7 +10778,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10792 if (operand_ty.zigTypeTag(mod) == .Int) {10778 if (operand_ty.zigTypeTag(mod) == .Int) {
10793 const min_int = try operand_ty.minInt(mod, operand_ty);10779 const min_int = try operand_ty.minInt(mod, operand_ty);
10794 const max_int = try operand_ty.maxInt(mod, operand_ty);10780 const max_int = try operand_ty.maxInt(mod, operand_ty);
10795 if (try range_set.spans(min_int, max_int, operand_ty)) {10781 if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) {
10796 if (special_prong == .@"else") {10782 if (special_prong == .@"else") {
10797 return sema.fail(10783 return sema.fail(
10798 block,10784 block,
...@@ -10894,11 +10880,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10894,11 +10880,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10894 );10880 );
10895 }10881 }
1089610882
10897 var seen_values = ValueSrcMap.initContext(gpa, .{10883 var seen_values = ValueSrcMap{};
10898 .ty = operand_ty,10884 defer seen_values.deinit(gpa);
10899 .mod = mod,
10900 });
10901 defer seen_values.deinit();
1090210885
10903 var extra_index: usize = special.end;10886 var extra_index: usize = special.end;
10904 {10887 {
...@@ -11664,10 +11647,10 @@ const RangeSetUnhandledIterator = struct {...@@ -11664,10 +11647,10 @@ const RangeSetUnhandledIterator = struct {
11664 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);11647 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
11665 }11648 }
11666 it.first = false;11649 it.first = false;
11667 if (it.cur.compareScalar(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {11650 if (it.cur.compareScalar(.lt, it.ranges[it.range_i].first.toValue(), it.ty, it.sema.mod)) {
11668 return it.cur;11651 return it.cur;
11669 }11652 }
11670 it.cur = it.ranges[it.range_i].last;11653 it.cur = it.ranges[it.range_i].last.toValue();
11671 }11654 }
11672 if (!it.first) {11655 if (!it.first) {
11673 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);11656 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
...@@ -11687,16 +11670,15 @@ fn resolveSwitchItemVal(...@@ -11687,16 +11670,15 @@ fn resolveSwitchItemVal(
11687 switch_node_offset: i32,11670 switch_node_offset: i32,
11688 switch_prong_src: Module.SwitchProngSrc,11671 switch_prong_src: Module.SwitchProngSrc,
11689 range_expand: Module.SwitchProngSrc.RangeExpand,11672 range_expand: Module.SwitchProngSrc.RangeExpand,
11690) CompileError!TypedValue {11673) CompileError!InternPool.Index {
11691 const mod = sema.mod;11674 const mod = sema.mod;
11692 const item = try sema.resolveInst(item_ref);11675 const item = try sema.resolveInst(item_ref);
11693 const item_ty = sema.typeOf(item);
11694 // Constructing a LazySrcLoc is costly because we only have the switch AST node.11676 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
11695 // Only if we know for sure we need to report a compile error do we resolve the11677 // Only if we know for sure we need to report a compile error do we resolve the
11696 // full source locations.11678 // full source locations.
11697 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {11679 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {
11698 try sema.resolveLazyValue(val);11680 try sema.resolveLazyValue(val);
11699 return TypedValue{ .ty = item_ty, .val = val };11681 return val.toIntern();
11700 } else |err| switch (err) {11682 } else |err| switch (err) {
11701 error.NeededSourceLocation => {11683 error.NeededSourceLocation => {
11702 const src = switch_prong_src.resolve(mod, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand);11684 const src = switch_prong_src.resolve(mod, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand);
...@@ -11713,18 +11695,17 @@ fn validateSwitchRange(...@@ -11713,18 +11695,17 @@ fn validateSwitchRange(
11713 range_set: *RangeSet,11695 range_set: *RangeSet,
11714 first_ref: Zir.Inst.Ref,11696 first_ref: Zir.Inst.Ref,
11715 last_ref: Zir.Inst.Ref,11697 last_ref: Zir.Inst.Ref,
11716 operand_ty: Type,
11717 src_node_offset: i32,11698 src_node_offset: i32,
11718 switch_prong_src: Module.SwitchProngSrc,11699 switch_prong_src: Module.SwitchProngSrc,
11719) CompileError!void {11700) CompileError!void {
11720 const mod = sema.mod;11701 const mod = sema.mod;
11721 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;11702 const first = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first);
11722 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;11703 const last = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last);
11723 if (first_val.compareScalar(.gt, last_val, operand_ty, mod)) {11704 if (first.toValue().compareScalar(.gt, last.toValue(), mod.intern_pool.typeOf(first).toType(), mod)) {
11724 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first);11705 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first);
11725 return sema.fail(block, src, "range start value is greater than the end value", .{});11706 return sema.fail(block, src, "range start value is greater than the end value", .{});
11726 }11707 }
11727 const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src);11708 const maybe_prev_src = try range_set.add(first, last, switch_prong_src);
11728 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11709 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11729}11710}
1173011711
...@@ -11733,12 +11714,11 @@ fn validateSwitchItem(...@@ -11733,12 +11714,11 @@ fn validateSwitchItem(
11733 block: *Block,11714 block: *Block,
11734 range_set: *RangeSet,11715 range_set: *RangeSet,
11735 item_ref: Zir.Inst.Ref,11716 item_ref: Zir.Inst.Ref,
11736 operand_ty: Type,
11737 src_node_offset: i32,11717 src_node_offset: i32,
11738 switch_prong_src: Module.SwitchProngSrc,11718 switch_prong_src: Module.SwitchProngSrc,
11739) CompileError!void {11719) CompileError!void {
11740 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11720 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11741 const maybe_prev_src = try range_set.add(item_val, item_val, operand_ty, switch_prong_src);11721 const maybe_prev_src = try range_set.add(item, item, switch_prong_src);
11742 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11722 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11743}11723}
1174411724
...@@ -11751,9 +11731,11 @@ fn validateSwitchItemEnum(...@@ -11751,9 +11731,11 @@ fn validateSwitchItemEnum(
11751 src_node_offset: i32,11731 src_node_offset: i32,
11752 switch_prong_src: Module.SwitchProngSrc,11732 switch_prong_src: Module.SwitchProngSrc,
11753) CompileError!void {11733) CompileError!void {
11754 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);11734 const ip = &sema.mod.intern_pool;
11755 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {11735 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11756 const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);11736 const int = ip.indexToKey(item).enum_tag.int;
11737 const field_index = ip.indexToKey(ip.typeOf(item)).enum_type.tagValueIndex(ip, int) orelse {
11738 const maybe_prev_src = try range_set.add(int, int, switch_prong_src);
11757 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);11739 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
11758 };11740 };
11759 const maybe_prev_src = seen_fields[field_index];11741 const maybe_prev_src = seen_fields[field_index];
...@@ -11770,9 +11752,9 @@ fn validateSwitchItemError(...@@ -11770,9 +11752,9 @@ fn validateSwitchItemError(
11770 switch_prong_src: Module.SwitchProngSrc,11752 switch_prong_src: Module.SwitchProngSrc,
11771) CompileError!void {11753) CompileError!void {
11772 const ip = &sema.mod.intern_pool;11754 const ip = &sema.mod.intern_pool;
11773 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);11755 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11774 // TODO: Do i need to typecheck here?11756 // TODO: Do i need to typecheck here?
11775 const error_name = ip.stringToSlice(ip.indexToKey(item_tv.val.toIntern()).err.name);11757 const error_name = ip.stringToSlice(ip.indexToKey(item).err.name);
11776 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|11758 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
11777 prev.value11759 prev.value
11778 else11760 else
...@@ -11822,8 +11804,8 @@ fn validateSwitchItemBool(...@@ -11822,8 +11804,8 @@ fn validateSwitchItemBool(
11822 switch_prong_src: Module.SwitchProngSrc,11804 switch_prong_src: Module.SwitchProngSrc,
11823) CompileError!void {11805) CompileError!void {
11824 const mod = sema.mod;11806 const mod = sema.mod;
11825 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11807 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11826 if (item_val.toBool(mod)) {11808 if (item.toValue().toBool()) {
11827 true_count.* += 1;11809 true_count.* += 1;
11828 } else {11810 } else {
11829 false_count.* += 1;11811 false_count.* += 1;
...@@ -11835,7 +11817,7 @@ fn validateSwitchItemBool(...@@ -11835,7 +11817,7 @@ fn validateSwitchItemBool(
11835 }11817 }
11836}11818}
1183711819
11838const ValueSrcMap = std.HashMap(Value, Module.SwitchProngSrc, Value.HashContext, std.hash_map.default_max_load_percentage);11820const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc);
1183911821
11840fn validateSwitchItemSparse(11822fn validateSwitchItemSparse(
11841 sema: *Sema,11823 sema: *Sema,
...@@ -11845,8 +11827,8 @@ fn validateSwitchItemSparse(...@@ -11845,8 +11827,8 @@ fn validateSwitchItemSparse(
11845 src_node_offset: i32,11827 src_node_offset: i32,
11846 switch_prong_src: Module.SwitchProngSrc,11828 switch_prong_src: Module.SwitchProngSrc,
11847) CompileError!void {11829) CompileError!void {
11848 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;11830 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11849 const kv = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;11831 const kv = (try seen_values.fetchPut(sema.gpa, item, switch_prong_src)) orelse return;
11850 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);11832 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);
11851}11833}
1185211834
...@@ -13047,8 +13029,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13047,8 +13029,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13047 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);13029 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
1304813030
13049 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {13031 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
13050 const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null);
13051
13052 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))13032 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
13053 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?13033 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
13054 else13034 else
...@@ -13065,7 +13045,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13065,7 +13045,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13065 } });13045 } });
13066 }13046 }
1306713047
13068 const element_vals = try sema.arena.alloc(InternPool.Index, final_len_including_sent);13048 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
13069 var elem_i: usize = 0;13049 var elem_i: usize = 0;
13070 while (elem_i < result_len) {13050 while (elem_i < result_len) {
13071 var lhs_i: usize = 0;13051 var lhs_i: usize = 0;
...@@ -13075,9 +13055,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13075,9 +13055,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13075 elem_i += 1;13055 elem_i += 1;
13076 }13056 }
13077 }13057 }
13078 if (lhs_info.sentinel) |sent_val| {
13079 element_vals[result_len] = sent_val.toIntern();
13080 }
13081 break :v try mod.intern(.{ .aggregate = .{13058 break :v try mod.intern(.{ .aggregate = .{
13082 .ty = result_ty.toIntern(),13059 .ty = result_ty.toIntern(),
13083 .storage = .{ .elems = element_vals },13060 .storage = .{ .elems = element_vals },
...@@ -14896,13 +14873,18 @@ fn analyzeArithmetic(...@@ -14896,13 +14873,18 @@ fn analyzeArithmetic(
14896 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),14873 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
14897 else => unreachable,14874 else => unreachable,
14898 };14875 };
14876 const scalar_one = switch (scalar_tag) {
14877 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0),
14878 .ComptimeInt, .Int => try mod.intValue(scalar_type, 1),
14879 else => unreachable,
14880 };
14899 if (maybe_lhs_val) |lhs_val| {14881 if (maybe_lhs_val) |lhs_val| {
14900 if (!lhs_val.isUndef(mod)) {14882 if (!lhs_val.isUndef(mod)) {
14901 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14883 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14902 const zero_val = try sema.splat(resolved_type, scalar_zero);14884 const zero_val = try sema.splat(resolved_type, scalar_zero);
14903 return sema.addConstant(resolved_type, zero_val);14885 return sema.addConstant(resolved_type, zero_val);
14904 }14886 }
14905 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14887 if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
14906 return casted_rhs;14888 return casted_rhs;
14907 }14889 }
14908 }14890 }
...@@ -14916,7 +14898,7 @@ fn analyzeArithmetic(...@@ -14916,7 +14898,7 @@ fn analyzeArithmetic(
14916 const zero_val = try sema.splat(resolved_type, scalar_zero);14898 const zero_val = try sema.splat(resolved_type, scalar_zero);
14917 return sema.addConstant(resolved_type, zero_val);14899 return sema.addConstant(resolved_type, zero_val);
14918 }14900 }
14919 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {14901 if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
14920 return casted_lhs;14902 return casted_lhs;
14921 }14903 }
14922 if (maybe_lhs_val) |lhs_val| {14904 if (maybe_lhs_val) |lhs_val| {
...@@ -15524,7 +15506,7 @@ fn cmpSelf(...@@ -15524,7 +15506,7 @@ fn cmpSelf(
15524 } else {15506 } else {
15525 if (resolved_type.zigTypeTag(mod) == .Bool) {15507 if (resolved_type.zigTypeTag(mod) == .Bool) {
15526 // We can lower bool eq/neq more efficiently.15508 // We can lower bool eq/neq more efficiently.
15527 return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(mod), rhs_src);15509 return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src);
15528 }15510 }
15529 break :src rhs_src;15511 break :src rhs_src;
15530 }15512 }
...@@ -15534,7 +15516,7 @@ fn cmpSelf(...@@ -15534,7 +15516,7 @@ fn cmpSelf(
15534 if (resolved_type.zigTypeTag(mod) == .Bool) {15516 if (resolved_type.zigTypeTag(mod) == .Bool) {
15535 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {15517 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {
15536 if (rhs_val.isUndef(mod)) return sema.addConstUndef(Type.bool);15518 if (rhs_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
15537 return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(mod), lhs_src);15519 return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src);
15538 }15520 }
15539 }15521 }
15540 break :src lhs_src;15522 break :src lhs_src;
...@@ -15840,6 +15822,7 @@ fn zirBuiltinSrc(...@@ -15840,6 +15822,7 @@ fn zirBuiltinSrc(
15840 break :blk try mod.intern(.{ .ptr = .{15822 break :blk try mod.intern(.{ .ptr = .{
15841 .ty = .slice_const_u8_sentinel_0_type,15823 .ty = .slice_const_u8_sentinel_0_type,
15842 .addr = .{ .decl = new_decl },15824 .addr = .{ .decl = new_decl },
15825 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
15843 } });15826 } });
15844 };15827 };
1584515828
...@@ -15864,6 +15847,7 @@ fn zirBuiltinSrc(...@@ -15864,6 +15847,7 @@ fn zirBuiltinSrc(
15864 break :blk try mod.intern(.{ .ptr = .{15847 break :blk try mod.intern(.{ .ptr = .{
15865 .ty = .slice_const_u8_sentinel_0_type,15848 .ty = .slice_const_u8_sentinel_0_type,
15866 .addr = .{ .decl = new_decl },15849 .addr = .{ .decl = new_decl },
15850 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
15867 } });15851 } });
15868 };15852 };
1586915853
...@@ -16314,6 +16298,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16314,6 +16298,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16314 break :v try mod.intern(.{ .ptr = .{16298 break :v try mod.intern(.{ .ptr = .{
16315 .ty = slice_errors_ty.toIntern(),16299 .ty = slice_errors_ty.toIntern(),
16316 .addr = .{ .decl = new_decl },16300 .addr = .{ .decl = new_decl },
16301 .len = (try mod.intValue(Type.usize, vals.len)).toIntern(),
16317 } });16302 } });
16318 } else .none;16303 } else .none;
16319 const errors_val = try mod.intern(.{ .opt = .{16304 const errors_val = try mod.intern(.{ .opt = .{
...@@ -16438,6 +16423,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16438,6 +16423,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16438 .is_const = true,16423 .is_const = true,
16439 })).toIntern(),16424 })).toIntern(),
16440 .addr = .{ .decl = new_decl },16425 .addr = .{ .decl = new_decl },
16426 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
16441 } });16427 } });
16442 };16428 };
1644316429
...@@ -17141,7 +17127,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17141,7 +17127,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17141 if (try sema.resolveMaybeUndefVal(operand)) |val| {17127 if (try sema.resolveMaybeUndefVal(operand)) |val| {
17142 return if (val.isUndef(mod))17128 return if (val.isUndef(mod))
17143 sema.addConstUndef(Type.bool)17129 sema.addConstUndef(Type.bool)
17144 else if (val.toBool(mod))17130 else if (val.toBool())
17145 Air.Inst.Ref.bool_false17131 Air.Inst.Ref.bool_false
17146 else17132 else
17147 Air.Inst.Ref.bool_true;17133 Air.Inst.Ref.bool_true;
...@@ -17169,9 +17155,9 @@ fn zirBoolBr(...@@ -17169,9 +17155,9 @@ fn zirBoolBr(
17169 const gpa = sema.gpa;17155 const gpa = sema.gpa;
1717017156
17171 if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| {17157 if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| {
17172 if (is_bool_or and lhs_val.toBool(mod)) {17158 if (is_bool_or and lhs_val.toBool()) {
17173 return Air.Inst.Ref.bool_true;17159 return Air.Inst.Ref.bool_true;
17174 } else if (!is_bool_or and !lhs_val.toBool(mod)) {17160 } else if (!is_bool_or and !lhs_val.toBool()) {
17175 return Air.Inst.Ref.bool_false;17161 return Air.Inst.Ref.bool_false;
17176 }17162 }
17177 // comptime-known left-hand side. No need for a block here; the result17163 // comptime-known left-hand side. No need for a block here; the result
...@@ -17215,9 +17201,9 @@ fn zirBoolBr(...@@ -17215,9 +17201,9 @@ fn zirBoolBr(
17215 const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);17201 const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
17216 if (!sema.typeOf(rhs_result).isNoReturn(mod)) {17202 if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
17217 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {17203 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {
17218 if (is_bool_or and rhs_val.toBool(mod)) {17204 if (is_bool_or and rhs_val.toBool()) {
17219 return Air.Inst.Ref.bool_true;17205 return Air.Inst.Ref.bool_true;
17220 } else if (!is_bool_or and !rhs_val.toBool(mod)) {17206 } else if (!is_bool_or and !rhs_val.toBool()) {
17221 return Air.Inst.Ref.bool_false;17207 return Air.Inst.Ref.bool_false;
17222 }17208 }
17223 }17209 }
...@@ -17371,7 +17357,7 @@ fn zirCondbr(...@@ -17371,7 +17357,7 @@ fn zirCondbr(
17371 const cond = try sema.coerce(parent_block, Type.bool, uncasted_cond, cond_src);17357 const cond = try sema.coerce(parent_block, Type.bool, uncasted_cond, cond_src);
1737217358
17373 if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| {17359 if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| {
17374 const body = if (cond_val.toBool(mod)) then_body else else_body;17360 const body = if (cond_val.toBool()) then_body else else_body;
1737517361
17376 try sema.maybeErrorUnwrapCondbr(parent_block, body, extra.data.condition, cond_src);17362 try sema.maybeErrorUnwrapCondbr(parent_block, body, extra.data.condition, cond_src);
17377 // We use `analyzeBodyInner` since we want to propagate any possible17363 // We use `analyzeBodyInner` since we want to propagate any possible
...@@ -17444,7 +17430,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -17444,7 +17430,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
17444 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);17430 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
17445 if (is_non_err != .none) {17431 if (is_non_err != .none) {
17446 const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?;17432 const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?;
17447 if (is_non_err_val.toBool(mod)) {17433 if (is_non_err_val.toBool()) {
17448 return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false);17434 return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false);
17449 }17435 }
17450 // We can analyze the body directly in the parent block because we know there are17436 // We can analyze the body directly in the parent block because we know there are
...@@ -17491,7 +17477,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -17491,7 +17477,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
17491 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);17477 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
17492 if (is_non_err != .none) {17478 if (is_non_err != .none) {
17493 const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?;17479 const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?;
17494 if (is_non_err_val.toBool(mod)) {17480 if (is_non_err_val.toBool()) {
17495 return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false);17481 return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false);
17496 }17482 }
17497 // We can analyze the body directly in the parent block because we know there are17483 // We can analyze the body directly in the parent block because we know there are
...@@ -18858,7 +18844,7 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -18858,7 +18844,7 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
18858 const operand = try sema.resolveInst(inst_data.operand);18844 const operand = try sema.resolveInst(inst_data.operand);
18859 if (try sema.resolveMaybeUndefVal(operand)) |val| {18845 if (try sema.resolveMaybeUndefVal(operand)) |val| {
18860 if (val.isUndef(mod)) return sema.addConstUndef(Type.u1);18846 if (val.isUndef(mod)) return sema.addConstUndef(Type.u1);
18861 if (val.toBool(mod)) return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 1));18847 if (val.toBool()) return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 1));
18862 return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));18848 return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
18863 }18849 }
18864 return block.addUnOp(.bool_to_int, operand);18850 return block.addUnOp(.bool_to_int, operand);
...@@ -19171,12 +19157,12 @@ fn zirReify(...@@ -19171,12 +19157,12 @@ fn zirReify(
1917119157
19172 const ty = try mod.ptrType(.{19158 const ty = try mod.ptrType(.{
19173 .size = ptr_size,19159 .size = ptr_size,
19174 .is_const = is_const_val.toBool(mod),19160 .is_const = is_const_val.toBool(),
19175 .is_volatile = is_volatile_val.toBool(mod),19161 .is_volatile = is_volatile_val.toBool(),
19176 .alignment = abi_align,19162 .alignment = abi_align,
19177 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),19163 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),
19178 .elem_type = elem_ty.toIntern(),19164 .elem_type = elem_ty.toIntern(),
19179 .is_allowzero = is_allowzero_val.toBool(mod),19165 .is_allowzero = is_allowzero_val.toBool(),
19180 .sentinel = actual_sentinel,19166 .sentinel = actual_sentinel,
19181 });19167 });
19182 return sema.addType(ty);19168 return sema.addType(ty);
...@@ -19267,7 +19253,7 @@ fn zirReify(...@@ -19267,7 +19253,7 @@ fn zirReify(
19267 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});19253 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
19268 }19254 }
1926919255
19270 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool(mod));19256 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());
19271 },19257 },
19272 .Enum => {19258 .Enum => {
19273 const fields = ip.typeOf(union_val.val).toType().structFields(mod);19259 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
...@@ -19305,7 +19291,7 @@ fn zirReify(...@@ -19305,7 +19291,7 @@ fn zirReify(
19305 .namespace = .none,19291 .namespace = .none,
19306 .fields_len = fields_len,19292 .fields_len = fields_len,
19307 .has_values = true,19293 .has_values = true,
19308 .tag_mode = if (!is_exhaustive_val.toBool(mod))19294 .tag_mode = if (!is_exhaustive_val.toBool())
19309 .nonexhaustive19295 .nonexhaustive
19310 else19296 else
19311 .explicit,19297 .explicit,
...@@ -19619,12 +19605,12 @@ fn zirReify(...@@ -19619,12 +19605,12 @@ fn zirReify(
19619 const return_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex("return_type").?);19605 const return_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex("return_type").?);
19620 const params_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex("params").?);19606 const params_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex("params").?);
1962119607
19622 const is_generic = is_generic_val.toBool(mod);19608 const is_generic = is_generic_val.toBool();
19623 if (is_generic) {19609 if (is_generic) {
19624 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});19610 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
19625 }19611 }
1962619612
19627 const is_var_args = is_var_args_val.toBool(mod);19613 const is_var_args = is_var_args_val.toBool();
19628 const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val);19614 const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val);
19629 if (is_var_args and cc != .C) {19615 if (is_var_args and cc != .C) {
19630 return sema.fail(block, src, "varargs functions must have C calling convention", .{});19616 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
...@@ -19653,9 +19639,9 @@ fn zirReify(...@@ -19653,9 +19639,9 @@ fn zirReify(
19653 const arg_val = arg.castTag(.aggregate).?.data;19639 const arg_val = arg.castTag(.aggregate).?.data;
19654 // TODO use reflection instead of magic numbers here19640 // TODO use reflection instead of magic numbers here
19655 // is_generic: bool,19641 // is_generic: bool,
19656 const arg_is_generic = arg_val[0].toBool(mod);19642 const arg_is_generic = arg_val[0].toBool();
19657 // is_noalias: bool,19643 // is_noalias: bool,
19658 const arg_is_noalias = arg_val[1].toBool(mod);19644 const arg_is_noalias = arg_val[1].toBool();
19659 // type: ?type,19645 // type: ?type,
19660 const param_type_opt_val = arg_val[2];19646 const param_type_opt_val = arg_val[2];
1966119647
...@@ -19783,9 +19769,9 @@ fn reifyStruct(...@@ -19783,9 +19769,9 @@ fn reifyStruct(
1978319769
19784 if (layout == .Packed) {19770 if (layout == .Packed) {
19785 if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});19771 if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
19786 if (is_comptime_val.toBool(mod)) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{});19772 if (is_comptime_val.toBool()) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{});
19787 }19773 }
19788 if (layout == .Extern and is_comptime_val.toBool(mod)) {19774 if (layout == .Extern and is_comptime_val.toBool()) {
19789 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});19775 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});
19790 }19776 }
1979119777
...@@ -19827,7 +19813,7 @@ fn reifyStruct(...@@ -19827,7 +19813,7 @@ fn reifyStruct(
19827 opt_val;19813 opt_val;
19828 break :blk try payload_val.copy(new_decl_arena_allocator);19814 break :blk try payload_val.copy(new_decl_arena_allocator);
19829 } else Value.@"unreachable";19815 } else Value.@"unreachable";
19830 if (is_comptime_val.toBool(mod) and default_val.toIntern() == .unreachable_value) {19816 if (is_comptime_val.toBool() and default_val.toIntern() == .unreachable_value) {
19831 return sema.fail(block, src, "comptime field without default initialization value", .{});19817 return sema.fail(block, src, "comptime field without default initialization value", .{});
19832 }19818 }
1983319819
...@@ -19836,7 +19822,7 @@ fn reifyStruct(...@@ -19836,7 +19822,7 @@ fn reifyStruct(
19836 .ty = field_ty,19822 .ty = field_ty,
19837 .abi_align = abi_align,19823 .abi_align = abi_align,
19838 .default_val = default_val,19824 .default_val = default_val,
19839 .is_comptime = is_comptime_val.toBool(mod),19825 .is_comptime = is_comptime_val.toBool(),
19840 .offset = undefined,19826 .offset = undefined,
19841 };19827 };
1984219828
...@@ -20400,13 +20386,17 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20400,13 +20386,17 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20400 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) {20386 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) {
20401 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});20387 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});
20402 }20388 }
20403 if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) {20389 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(switch (mod.intern_pool.indexToKey(operand_val.toIntern())) {
20404 return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{20390 .undef, .ptr => operand_val,
20405 .ty = dest_ty.toIntern(),20391 .opt => |opt| switch (opt.val) {
20406 .val = operand_val.toIntern(),20392 .none => if (dest_ty.ptrAllowsZero(mod))
20407 } })).toValue());20393 Value.zero_usize
20408 }20394 else
20409 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty));20395 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}),
20396 else => opt.val.toValue(),
20397 },
20398 else => unreachable,
20399 }, aligned_dest_ty));
20410 }20400 }
2041120401
20412 try sema.requireRuntimeBlock(block, src, null);20402 try sema.requireRuntimeBlock(block, src, null);
...@@ -20534,10 +20524,10 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20534,10 +20524,10 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20534 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {20524 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {
20535 if (val.isUndef(mod)) return sema.addConstUndef(dest_ty);20525 if (val.isUndef(mod)) return sema.addConstUndef(dest_ty);
20536 if (!is_vector) {20526 if (!is_vector) {
20537 return sema.addConstant(20527 return sema.addConstant(dest_ty, try mod.getCoerced(
20538 dest_ty,
20539 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod),20528 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod),
20540 );20529 dest_ty,
20530 ));
20541 }20531 }
20542 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));20532 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));
20543 for (elems, 0..) |*elem, i| {20533 for (elems, 0..) |*elem, i| {
...@@ -21410,7 +21400,10 @@ fn zirCmpxchg(...@@ -21410,7 +21400,10 @@ fn zirCmpxchg(
2141021400
21411 // special case zero bit types21401 // special case zero bit types
21412 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {21402 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {
21413 return sema.addConstant(result_ty, Value.null);21403 return sema.addConstant(result_ty, (try mod.intern(.{ .opt = .{
21404 .ty = result_ty.toIntern(),
21405 .val = .none,
21406 } })).toValue());
21414 }21407 }
2141521408
21416 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {21409 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
...@@ -21633,8 +21626,7 @@ fn analyzeShuffle(...@@ -21633,8 +21626,7 @@ fn analyzeShuffle(
21633 .{ b_len, b_src, b_ty },21626 .{ b_len, b_src, b_ty },
21634 };21627 };
2163521628
21636 var i: usize = 0;21629 for (0..@intCast(usize, mask_len)) |i| {
21637 while (i < mask_len) : (i += 1) {
21638 const elem = try mask.elemValue(sema.mod, i);21630 const elem = try mask.elemValue(sema.mod, i);
21639 if (elem.isUndef(mod)) continue;21631 if (elem.isUndef(mod)) continue;
21640 const int = elem.toSignedInt(mod);21632 const int = elem.toSignedInt(mod);
...@@ -21670,7 +21662,7 @@ fn analyzeShuffle(...@@ -21670,7 +21662,7 @@ fn analyzeShuffle(
21670 if (try sema.resolveMaybeUndefVal(a)) |a_val| {21662 if (try sema.resolveMaybeUndefVal(a)) |a_val| {
21671 if (try sema.resolveMaybeUndefVal(b)) |b_val| {21663 if (try sema.resolveMaybeUndefVal(b)) |b_val| {
21672 const values = try sema.arena.alloc(InternPool.Index, mask_len);21664 const values = try sema.arena.alloc(InternPool.Index, mask_len);
21673 for (values) |*value| {21665 for (values, 0..) |*value, i| {
21674 const mask_elem_val = try mask.elemValue(sema.mod, i);21666 const mask_elem_val = try mask.elemValue(sema.mod, i);
21675 if (mask_elem_val.isUndef(mod)) {21667 if (mask_elem_val.isUndef(mod)) {
21676 value.* = try mod.intern(.{ .undef = elem_ty.toIntern() });21668 value.* = try mod.intern(.{ .undef = elem_ty.toIntern() });
...@@ -21698,11 +21690,10 @@ fn analyzeShuffle(...@@ -21698,11 +21690,10 @@ fn analyzeShuffle(
21698 const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));21690 const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));
2169921691
21700 const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);21692 const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);
21701 i = 0;21693 for (@intCast(usize, 0)..@intCast(usize, min_len)) |i| {
21702 while (i < min_len) : (i += 1) {
21703 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, i)).toIntern();21694 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, i)).toIntern();
21704 }21695 }
21705 while (i < max_len) : (i += 1) {21696 for (@intCast(usize, min_len)..@intCast(usize, max_len)) |i| {
21706 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, -1)).toIntern();21697 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, -1)).toIntern();
21707 }21698 }
21708 const expand_mask = try mod.intern(.{ .aggregate = .{21699 const expand_mask = try mod.intern(.{ .aggregate = .{
...@@ -21783,7 +21774,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -21783,7 +21774,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
21783 const elems = try sema.gpa.alloc(InternPool.Index, vec_len);21774 const elems = try sema.gpa.alloc(InternPool.Index, vec_len);
21784 for (elems, 0..) |*elem, i| {21775 for (elems, 0..) |*elem, i| {
21785 const pred_elem_val = try pred_val.elemValue(mod, i);21776 const pred_elem_val = try pred_val.elemValue(mod, i);
21786 const should_choose_a = pred_elem_val.toBool(mod);21777 const should_choose_a = pred_elem_val.toBool();
21787 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);21778 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);
21788 }21779 }
2178921780
...@@ -22853,15 +22844,15 @@ fn zirVarExtended(...@@ -22853,15 +22844,15 @@ fn zirVarExtended(
22853 else22844 else
22854 uncasted_init;22845 uncasted_init;
2285522846
22856 break :blk (try sema.resolveMaybeUndefVal(init)) orelse22847 break :blk ((try sema.resolveMaybeUndefVal(init)) orelse
22857 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known");22848 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known")).toIntern();
22858 } else Value.@"unreachable";22849 } else .none;
2285922850
22860 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);22851 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2286122852
22862 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{22853 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
22863 .ty = var_ty.toIntern(),22854 .ty = var_ty.toIntern(),
22864 .init = init_val.toIntern(),22855 .init = init_val,
22865 .decl = sema.owner_decl_index,22856 .decl = sema.owner_decl_index,
22866 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(22857 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
22867 sema.gpa,22858 sema.gpa,
...@@ -23284,7 +23275,7 @@ fn resolveExternOptions(...@@ -23284,7 +23275,7 @@ fn resolveExternOptions(
23284 .name = name,23275 .name = name,
23285 .library_name = library_name,23276 .library_name = library_name,
23286 .linkage = linkage,23277 .linkage = linkage,
23287 .is_thread_local = is_thread_local_val.toBool(mod),23278 .is_thread_local = is_thread_local_val.toBool(),
23288 };23279 };
23289}23280}
2329023281
...@@ -26190,7 +26181,7 @@ fn coerceExtra(...@@ -26190,7 +26181,7 @@ fn coerceExtra(
26190 .addr = .{ .int = (if (dest_info.@"align" != 0)26181 .addr = .{ .int = (if (dest_info.@"align" != 0)
26191 try mod.intValue(Type.usize, dest_info.@"align")26182 try mod.intValue(Type.usize, dest_info.@"align")
26192 else26183 else
26193 try dest_info.pointee_type.lazyAbiAlignment(mod)).toIntern() },26184 try mod.getCoerced(try dest_info.pointee_type.lazyAbiAlignment(mod), Type.usize)).toIntern() },
26194 .len = (try mod.intValue(Type.usize, 0)).toIntern(),26185 .len = (try mod.intValue(Type.usize, 0)).toIntern(),
26195 } })).toValue());26186 } })).toValue());
26196 }26187 }
...@@ -27785,7 +27776,7 @@ fn beginComptimePtrMutation(...@@ -27785,7 +27776,7 @@ fn beginComptimePtrMutation(
27785 const payload = try arena.create(Value.Payload.SubValue);27776 const payload = try arena.create(Value.Payload.SubValue);
27786 payload.* = .{27777 payload.* = .{
27787 .base = .{ .tag = .eu_payload },27778 .base = .{ .tag = .eu_payload },
27788 .data = Value.undef,27779 .data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
27789 };27780 };
2779027781
27791 val_ptr.* = Value.initPayload(&payload.base);27782 val_ptr.* = Value.initPayload(&payload.base);
...@@ -27824,7 +27815,7 @@ fn beginComptimePtrMutation(...@@ -27824,7 +27815,7 @@ fn beginComptimePtrMutation(
27824 const payload = try arena.create(Value.Payload.SubValue);27815 const payload = try arena.create(Value.Payload.SubValue);
27825 payload.* = .{27816 payload.* = .{
27826 .base = .{ .tag = .opt_payload },27817 .base = .{ .tag = .opt_payload },
27827 .data = Value.undef,27818 .data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
27828 };27819 };
2782927820
27830 val_ptr.* = Value.initPayload(&payload.base);27821 val_ptr.* = Value.initPayload(&payload.base);
...@@ -27898,30 +27889,6 @@ fn beginComptimePtrMutation(...@@ -27898,30 +27889,6 @@ fn beginComptimePtrMutation(
27898 }27889 }
2789927890
27900 switch (val_ptr.ip_index) {27891 switch (val_ptr.ip_index) {
27901 .undef => {
27902 // An array has been initialized to undefined at comptime and now we
27903 // are for the first time setting an element. We must change the representation
27904 // of the array from `undef` to `array`.
27905 const arena = parent.beginArena(sema.mod);
27906 defer parent.finishArena(sema.mod);
27907
27908 const array_len_including_sentinel =
27909 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
27910 const elems = try arena.alloc(Value, array_len_including_sentinel);
27911 @memset(elems, Value.undef);
27912
27913 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
27914
27915 return beginComptimePtrMutationInner(
27916 sema,
27917 block,
27918 src,
27919 elem_ty,
27920 &elems[elem_ptr.index],
27921 ptr_elem_ty,
27922 parent.mut_decl,
27923 );
27924 },
27925 .none => switch (val_ptr.tag()) {27892 .none => switch (val_ptr.tag()) {
27926 .bytes => {27893 .bytes => {
27927 // An array is memory-optimized to store a slice of bytes, but we are about27894 // An array is memory-optimized to store a slice of bytes, but we are about
...@@ -27999,7 +27966,33 @@ fn beginComptimePtrMutation(...@@ -27999,7 +27966,33 @@ fn beginComptimePtrMutation(
2799927966
28000 else => unreachable,27967 else => unreachable,
28001 },27968 },
28002 else => unreachable,27969 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
27970 .undef => {
27971 // An array has been initialized to undefined at comptime and now we
27972 // are for the first time setting an element. We must change the representation
27973 // of the array from `undef` to `array`.
27974 const arena = parent.beginArena(sema.mod);
27975 defer parent.finishArena(sema.mod);
27976
27977 const array_len_including_sentinel =
27978 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
27979 const elems = try arena.alloc(Value, array_len_including_sentinel);
27980 @memset(elems, (try mod.intern(.{ .undef = elem_ty.toIntern() })).toValue());
27981
27982 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
27983
27984 return beginComptimePtrMutationInner(
27985 sema,
27986 block,
27987 src,
27988 elem_ty,
27989 &elems[elem_ptr.index],
27990 ptr_elem_ty,
27991 parent.mut_decl,
27992 );
27993 },
27994 else => unreachable,
27995 },
28003 }27996 }
28004 },27997 },
28005 else => {27998 else => {
...@@ -28052,83 +28045,6 @@ fn beginComptimePtrMutation(...@@ -28052,83 +28045,6 @@ fn beginComptimePtrMutation(
28052 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);28045 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);
28053 switch (parent.pointee) {28046 switch (parent.pointee) {
28054 .direct => |val_ptr| switch (val_ptr.ip_index) {28047 .direct => |val_ptr| switch (val_ptr.ip_index) {
28055 .undef => {
28056 // A struct or union has been initialized to undefined at comptime and now we
28057 // are for the first time setting a field. We must change the representation
28058 // of the struct/union from `undef` to `struct`/`union`.
28059 const arena = parent.beginArena(sema.mod);
28060 defer parent.finishArena(sema.mod);
28061
28062 switch (parent.ty.zigTypeTag(mod)) {
28063 .Struct => {
28064 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
28065 @memset(fields, Value.undef);
28066
28067 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
28068
28069 return beginComptimePtrMutationInner(
28070 sema,
28071 block,
28072 src,
28073 parent.ty.structFieldType(field_index, mod),
28074 &fields[field_index],
28075 ptr_elem_ty,
28076 parent.mut_decl,
28077 );
28078 },
28079 .Union => {
28080 const payload = try arena.create(Value.Payload.Union);
28081 const tag_ty = parent.ty.unionTagTypeHypothetical(mod);
28082 payload.* = .{ .data = .{
28083 .tag = try mod.enumValueFieldIndex(tag_ty, field_index),
28084 .val = Value.undef,
28085 } };
28086
28087 val_ptr.* = Value.initPayload(&payload.base);
28088
28089 return beginComptimePtrMutationInner(
28090 sema,
28091 block,
28092 src,
28093 parent.ty.structFieldType(field_index, mod),
28094 &payload.data.val,
28095 ptr_elem_ty,
28096 parent.mut_decl,
28097 );
28098 },
28099 .Pointer => {
28100 assert(parent.ty.isSlice(mod));
28101 val_ptr.* = try Value.Tag.slice.create(arena, .{
28102 .ptr = Value.undef,
28103 .len = Value.undef,
28104 });
28105
28106 switch (field_index) {
28107 Value.slice_ptr_index => return beginComptimePtrMutationInner(
28108 sema,
28109 block,
28110 src,
28111 parent.ty.slicePtrFieldType(mod),
28112 &val_ptr.castTag(.slice).?.data.ptr,
28113 ptr_elem_ty,
28114 parent.mut_decl,
28115 ),
28116 Value.slice_len_index => return beginComptimePtrMutationInner(
28117 sema,
28118 block,
28119 src,
28120 Type.usize,
28121 &val_ptr.castTag(.slice).?.data.len,
28122 ptr_elem_ty,
28123 parent.mut_decl,
28124 ),
28125
28126 else => unreachable,
28127 }
28128 },
28129 else => unreachable,
28130 }
28131 },
28132 .empty_struct => {28048 .empty_struct => {
28133 const duped = try sema.arena.create(Value);28049 const duped = try sema.arena.create(Value);
28134 duped.* = val_ptr.*;28050 duped.* = val_ptr.*;
...@@ -28210,10 +28126,92 @@ fn beginComptimePtrMutation(...@@ -28210,10 +28126,92 @@ fn beginComptimePtrMutation(
2821028126
28211 else => unreachable,28127 else => unreachable,
28212 },28128 },
28129 else => unreachable,
28130 },
28131 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
28132 .undef => {
28133 // A struct or union has been initialized to undefined at comptime and now we
28134 // are for the first time setting a field. We must change the representation
28135 // of the struct/union from `undef` to `struct`/`union`.
28136 const arena = parent.beginArena(sema.mod);
28137 defer parent.finishArena(sema.mod);
28138
28139 switch (parent.ty.zigTypeTag(mod)) {
28140 .Struct => {
28141 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
28142 for (fields, 0..) |*field, i| field.* = (try mod.intern(.{
28143 .undef = parent.ty.structFieldType(i, mod).toIntern(),
28144 })).toValue();
28145
28146 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
28147
28148 return beginComptimePtrMutationInner(
28149 sema,
28150 block,
28151 src,
28152 parent.ty.structFieldType(field_index, mod),
28153 &fields[field_index],
28154 ptr_elem_ty,
28155 parent.mut_decl,
28156 );
28157 },
28158 .Union => {
28159 const payload = try arena.create(Value.Payload.Union);
28160 const tag_ty = parent.ty.unionTagTypeHypothetical(mod);
28161 const payload_ty = parent.ty.structFieldType(field_index, mod);
28162 payload.* = .{ .data = .{
28163 .tag = try mod.enumValueFieldIndex(tag_ty, field_index),
28164 .val = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
28165 } };
2821328166
28167 val_ptr.* = Value.initPayload(&payload.base);
28168
28169 return beginComptimePtrMutationInner(
28170 sema,
28171 block,
28172 src,
28173 payload_ty,
28174 &payload.data.val,
28175 ptr_elem_ty,
28176 parent.mut_decl,
28177 );
28178 },
28179 .Pointer => {
28180 assert(parent.ty.isSlice(mod));
28181 const ptr_ty = parent.ty.slicePtrFieldType(mod);
28182 val_ptr.* = try Value.Tag.slice.create(arena, .{
28183 .ptr = (try mod.intern(.{ .undef = ptr_ty.toIntern() })).toValue(),
28184 .len = (try mod.intern(.{ .undef = .usize_type })).toValue(),
28185 });
28186
28187 switch (field_index) {
28188 Value.slice_ptr_index => return beginComptimePtrMutationInner(
28189 sema,
28190 block,
28191 src,
28192 ptr_ty,
28193 &val_ptr.castTag(.slice).?.data.ptr,
28194 ptr_elem_ty,
28195 parent.mut_decl,
28196 ),
28197 Value.slice_len_index => return beginComptimePtrMutationInner(
28198 sema,
28199 block,
28200 src,
28201 Type.usize,
28202 &val_ptr.castTag(.slice).?.data.len,
28203 ptr_elem_ty,
28204 parent.mut_decl,
28205 ),
28206
28207 else => unreachable,
28208 }
28209 },
28210 else => unreachable,
28211 }
28212 },
28214 else => unreachable,28213 else => unreachable,
28215 },28214 },
28216 else => unreachable,
28217 },28215 },
28218 .reinterpret => |reinterpret| {28216 .reinterpret => |reinterpret| {
28219 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);28217 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);
...@@ -28370,18 +28368,22 @@ fn beginComptimePtrLoad(...@@ -28370,18 +28368,22 @@ fn beginComptimePtrLoad(
28370 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or28368 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28371 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;28369 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28372 if (coerce_in_mem_ok) {28370 if (coerce_in_mem_ok) {
28373 const payload_val = switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {28371 const payload_val = switch (tv.val.ip_index) {
28374 .error_union => |error_union| switch (error_union.val) {28372 .none => tv.val.cast(Value.Payload.SubValue).?.data,
28375 .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),28373 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),
28376 .payload => |payload| payload,28374 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
28377 },28375 .error_union => |error_union| switch (error_union.val) {
28378 .opt => |opt| switch (opt.val) {28376 .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),
28379 .none => return sema.fail(block, src, "attempt to use null value", .{}),28377 .payload => |payload| payload,
28380 else => opt.val,28378 },
28381 },28379 .opt => |opt| switch (opt.val) {
28382 else => unreachable,28380 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28381 else => opt.val,
28382 },
28383 else => unreachable,
28384 }.toValue(),
28383 };28385 };
28384 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val.toValue() };28386 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
28385 break :blk deref;28387 break :blk deref;
28386 }28388 }
28387 }28389 }
...@@ -28960,7 +28962,7 @@ fn coerceArrayLike(...@@ -28960,7 +28962,7 @@ fn coerceArrayLike(
28960 if (in_memory_result == .ok) {28962 if (in_memory_result == .ok) {
28961 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {28963 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
28962 // These types share the same comptime value representation.28964 // These types share the same comptime value representation.
28963 return sema.addConstant(dest_ty, inst_val);28965 return sema.addConstant(dest_ty, try mod.getCoerced(inst_val, dest_ty));
28964 }28966 }
28965 try sema.requireRuntimeBlock(block, inst_src, null);28967 try sema.requireRuntimeBlock(block, inst_src, null);
28966 return block.addBitCast(dest_ty, inst);28968 return block.addBitCast(dest_ty, inst);
...@@ -29024,7 +29026,7 @@ fn coerceTupleToArray(...@@ -29024,7 +29026,7 @@ fn coerceTupleToArray(
29024 return sema.failWithOwnedErrorMsg(msg);29026 return sema.failWithOwnedErrorMsg(msg);
29025 }29027 }
2902629028
29027 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLenIncludingSentinel(mod));29029 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_len);
29028 const element_vals = try sema.arena.alloc(InternPool.Index, dest_elems);29030 const element_vals = try sema.arena.alloc(InternPool.Index, dest_elems);
29029 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems);29031 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems);
29030 const dest_elem_ty = dest_ty.childType(mod);29032 const dest_elem_ty = dest_ty.childType(mod);
...@@ -29430,7 +29432,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo...@@ -29430,7 +29432,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
29430 const ptr_ty = try mod.ptrType(.{29432 const ptr_ty = try mod.ptrType(.{
29431 .elem_type = decl_tv.ty.toIntern(),29433 .elem_type = decl_tv.ty.toIntern(),
29432 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),29434 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29433 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else false,29435 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29434 .address_space = decl.@"addrspace",29436 .address_space = decl.@"addrspace",
29435 });29437 });
29436 if (analyze_fn_body) {29438 if (analyze_fn_body) {
...@@ -29513,7 +29515,7 @@ fn analyzeLoad(...@@ -29513,7 +29515,7 @@ fn analyzeLoad(
2951329515
29514 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {29516 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
29515 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {29517 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
29516 return sema.addConstant(elem_ty, elem_val);29518 return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
29517 }29519 }
29518 }29520 }
2951929521
...@@ -32610,8 +32612,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32610,8 +32612,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3261032612
32611 var int_tag_ty: Type = undefined;32613 var int_tag_ty: Type = undefined;
32612 var enum_field_names: []InternPool.NullTerminatedString = &.{};32614 var enum_field_names: []InternPool.NullTerminatedString = &.{};
32613 var enum_field_vals: []InternPool.Index = &.{};32615 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
32614 var enum_field_vals_map: std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false) = .{};
32615 var explicit_tags_seen: []bool = &.{};32616 var explicit_tags_seen: []bool = &.{};
32616 var explicit_enum_info: ?InternPool.Key.EnumType = null;32617 var explicit_enum_info: ?InternPool.Key.EnumType = null;
32617 if (tag_type_ref != .none) {32618 if (tag_type_ref != .none) {
...@@ -32638,9 +32639,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32638,9 +32639,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32638 };32639 };
32639 return sema.failWithOwnedErrorMsg(msg);32640 return sema.failWithOwnedErrorMsg(msg);
32640 }32641 }
32642 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
32643 try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len);
32641 }32644 }
32642 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
32643 enum_field_vals = try sema.arena.alloc(InternPool.Index, fields_len);
32644 } else {32645 } else {
32645 // The provided type is the enum tag type.32646 // The provided type is the enum tag type.
32646 union_obj.tag_ty = provided_ty;32647 union_obj.tag_ty = provided_ty;
...@@ -32712,8 +32713,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32712,8 +32713,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32712 break :blk try sema.resolveInst(tag_ref);32713 break :blk try sema.resolveInst(tag_ref);
32713 } else .none;32714 } else .none;
3271432715
32715 if (enum_field_vals.len != 0) {32716 if (enum_field_vals.capacity() > 0) {
32716 const copied_val = if (tag_ref != .none) blk: {32717 const enum_tag_val = if (tag_ref != .none) blk: {
32717 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {32718 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
32718 error.NeededSourceLocation => {32719 error.NeededSourceLocation => {
32719 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{32720 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
...@@ -32737,16 +32738,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32737,16 +32738,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3273732738
32738 break :blk val;32739 break :blk val;
32739 };32740 };
32740 enum_field_vals[field_i] = copied_val.toIntern();32741 const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern());
32741 const gop = enum_field_vals_map.getOrPutAssumeCapacityContext(copied_val, .{
32742 .ty = int_tag_ty,
32743 .mod = mod,
32744 });
32745 if (gop.found_existing) {32742 if (gop.found_existing) {
32746 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;32743 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
32747 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;32744 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
32748 const msg = msg: {32745 const msg = msg: {
32749 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, mod)});32746 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(int_tag_ty, mod)});
32750 errdefer msg.destroy(gpa);32747 errdefer msg.destroy(gpa);
32751 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});32748 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
32752 break :msg msg;32749 break :msg msg;
...@@ -32907,8 +32904,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32907,8 +32904,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32907 };32904 };
32908 return sema.failWithOwnedErrorMsg(msg);32905 return sema.failWithOwnedErrorMsg(msg);
32909 }32906 }
32910 } else if (enum_field_vals.len != 0) {32907 } else if (enum_field_vals.count() > 0) {
32911 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals, union_obj);32908 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_obj);
32912 } else {32909 } else {
32913 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_obj);32910 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_obj);
32914 }32911 }
...@@ -33180,8 +33177,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33180,8 +33177,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33180 .struct_type => |struct_type| {33177 .struct_type => |struct_type| {
33181 const resolved_ty = try sema.resolveTypeFields(ty);33178 const resolved_ty = try sema.resolveTypeFields(ty);
33182 if (mod.structPtrUnwrap(struct_type.index)) |s| {33179 if (mod.structPtrUnwrap(struct_type.index)) |s| {
33183 for (s.fields.values(), 0..) |field, i| {33180 const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());
33184 if (field.is_comptime) continue;33181 for (field_vals, s.fields.values(), 0..) |*field_val, field, i| {
33182 if (field.is_comptime) {
33183 field_val.* = try field.default_val.intern(field.ty, mod);
33184 continue;
33185 }
33185 if (field.ty.eql(resolved_ty, sema.mod)) {33186 if (field.ty.eql(resolved_ty, sema.mod)) {
33186 const msg = try Module.ErrorMsg.create(33187 const msg = try Module.ErrorMsg.create(
33187 sema.gpa,33188 sema.gpa,
...@@ -33192,24 +33193,25 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33192,24 +33193,25 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33192 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});33193 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33193 return sema.failWithOwnedErrorMsg(msg);33194 return sema.failWithOwnedErrorMsg(msg);
33194 }33195 }
33195 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {33196 if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {
33196 return null;33197 field_val.* = try field_opv.intern(field.ty, mod);
33197 }33198 } else return null;
33198 }33199 }
33200
33201 // In this case the struct has no runtime-known fields and
33202 // therefore has one possible value.
33203 return (try mod.intern(.{ .aggregate = .{
33204 .ty = ty.toIntern(),
33205 .storage = .{ .elems = field_vals },
33206 } })).toValue();
33199 }33207 }
33200 // In this case the struct has no runtime-known fields and
33201 // therefore has one possible value.
3320233208
33203 // TODO: this is incorrect for structs with comptime fields, I think33209 // In this case the struct has no fields at all and
33204 // we should use a temporary allocator to construct an aggregate that33210 // therefore has one possible value.
33205 // is populated with the comptime values and then intern that value here.33211 return (try mod.intern(.{ .aggregate = .{
33206 // This TODO is repeated in the redundant implementation of
33207 // one-possible-value in type.zig.
33208 const empty = try mod.intern(.{ .aggregate = .{
33209 .ty = ty.toIntern(),33212 .ty = ty.toIntern(),
33210 .storage = .{ .elems = &.{} },33213 .storage = .{ .elems = &.{} },
33211 } });33214 } })).toValue();
33212 return empty.toValue();
33213 },33215 },
3321433216
33215 .anon_struct_type => |tuple| {33217 .anon_struct_type => |tuple| {
...@@ -33268,20 +33270,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33268,20 +33270,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33268 },33270 },
33269 .auto, .explicit => switch (enum_type.names.len) {33271 .auto, .explicit => switch (enum_type.names.len) {
33270 0 => return Value.@"unreachable",33272 0 => return Value.@"unreachable",
33271 1 => {33273 1 => return try mod.getCoerced((if (enum_type.values.len == 0)
33272 if (enum_type.values.len == 0) {33274 try mod.intern(.{ .int = .{
33273 const only = try mod.intern(.{ .enum_tag = .{33275 .ty = enum_type.tag_ty,
33274 .ty = ty.toIntern(),33276 .storage = .{ .u64 = 0 },
33275 .int = try mod.intern(.{ .int = .{33277 } })
33276 .ty = enum_type.tag_ty,33278 else
33277 .storage = .{ .u64 = 0 },33279 enum_type.values[0]).toValue(), ty),
33278 } }),
33279 } });
33280 return only.toValue();
33281 } else {
33282 return enum_type.values[0].toValue();
33283 }
33284 },
33285 else => return null,33280 else => return null,
33286 },33281 },
33287 },33282 },
...@@ -33427,7 +33422,7 @@ fn analyzeComptimeAlloc(...@@ -33427,7 +33422,7 @@ fn analyzeComptimeAlloc(
33427 // There will be stores before the first load, but they may be to sub-elements or33422 // There will be stores before the first load, but they may be to sub-elements or
33428 // sub-fields. So we need to initialize with undef to allow the mechanism to expand33423 // sub-fields. So we need to initialize with undef to allow the mechanism to expand
33429 // into fields/elements and have those overridden with stored values.33424 // into fields/elements and have those overridden with stored values.
33430 Value.undef,33425 (try sema.mod.intern(.{ .undef = var_type.toIntern() })).toValue(),
33431 alignment,33426 alignment,
33432 );33427 );
33433 const decl = sema.mod.declPtr(decl_index);33428 const decl = sema.mod.declPtr(decl_index);
...@@ -34028,16 +34023,16 @@ fn intSubWithOverflow(...@@ -34028,16 +34023,16 @@ fn intSubWithOverflow(
34028 const lhs_elem = try lhs.elemValue(sema.mod, i);34023 const lhs_elem = try lhs.elemValue(sema.mod, i);
34029 const rhs_elem = try rhs.elemValue(sema.mod, i);34024 const rhs_elem = try rhs.elemValue(sema.mod, i);
34030 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);34025 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
34031 of.* = try of_math_result.overflow_bit.intern(Type.bool, mod);34026 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34032 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);34027 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
34033 }34028 }
34034 return Value.OverflowArithmeticResult{34029 return Value.OverflowArithmeticResult{
34035 .overflow_bit = (try mod.intern(.{ .aggregate = .{34030 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34036 .ty = ty.toIntern(),34031 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34037 .storage = .{ .elems = overflowed_data },34032 .storage = .{ .elems = overflowed_data },
34038 } })).toValue(),34033 } })).toValue(),
34039 .wrapped_result = (try mod.intern(.{ .aggregate = .{34034 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34040 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),34035 .ty = ty.toIntern(),
34041 .storage = .{ .elems = result_data },34036 .storage = .{ .elems = result_data },
34042 } })).toValue(),34037 } })).toValue(),
34043 };34038 };
...@@ -34066,7 +34061,7 @@ fn intSubWithOverflowScalar(...@@ -34066,7 +34061,7 @@ fn intSubWithOverflowScalar(
34066 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);34061 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
34067 const wrapped_result = try mod.intValue_big(ty, result_bigint.toConst());34062 const wrapped_result = try mod.intValue_big(ty, result_bigint.toConst());
34068 return Value.OverflowArithmeticResult{34063 return Value.OverflowArithmeticResult{
34069 .overflow_bit = Value.boolToInt(overflowed),34064 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
34070 .wrapped_result = wrapped_result,34065 .wrapped_result = wrapped_result,
34071 };34066 };
34072}34067}
...@@ -34273,16 +34268,16 @@ fn intAddWithOverflow(...@@ -34273,16 +34268,16 @@ fn intAddWithOverflow(
34273 const lhs_elem = try lhs.elemValue(sema.mod, i);34268 const lhs_elem = try lhs.elemValue(sema.mod, i);
34274 const rhs_elem = try rhs.elemValue(sema.mod, i);34269 const rhs_elem = try rhs.elemValue(sema.mod, i);
34275 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);34270 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
34276 of.* = try of_math_result.overflow_bit.intern(Type.bool, mod);34271 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34277 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);34272 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
34278 }34273 }
34279 return Value.OverflowArithmeticResult{34274 return Value.OverflowArithmeticResult{
34280 .overflow_bit = (try mod.intern(.{ .aggregate = .{34275 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34281 .ty = ty.toIntern(),34276 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34282 .storage = .{ .elems = overflowed_data },34277 .storage = .{ .elems = overflowed_data },
34283 } })).toValue(),34278 } })).toValue(),
34284 .wrapped_result = (try mod.intern(.{ .aggregate = .{34279 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34285 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),34280 .ty = ty.toIntern(),
34286 .storage = .{ .elems = result_data },34281 .storage = .{ .elems = result_data },
34287 } })).toValue(),34282 } })).toValue(),
34288 };34283 };
...@@ -34311,7 +34306,7 @@ fn intAddWithOverflowScalar(...@@ -34311,7 +34306,7 @@ fn intAddWithOverflowScalar(
34311 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);34306 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
34312 const result = try mod.intValue_big(ty, result_bigint.toConst());34307 const result = try mod.intValue_big(ty, result_bigint.toConst());
34313 return Value.OverflowArithmeticResult{34308 return Value.OverflowArithmeticResult{
34314 .overflow_bit = Value.boolToInt(overflowed),34309 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
34315 .wrapped_result = result,34310 .wrapped_result = result,
34316 };34311 };
34317}34312}
...@@ -34384,7 +34379,7 @@ fn compareVector(...@@ -34384,7 +34379,7 @@ fn compareVector(
34384 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);34379 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);
34385 }34380 }
34386 return (try mod.intern(.{ .aggregate = .{34381 return (try mod.intern(.{ .aggregate = .{
34387 .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .u1_type })).toIntern(),34382 .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .bool_type })).toIntern(),
34388 .storage = .{ .elems = result_data },34383 .storage = .{ .elems = result_data },
34389 } })).toValue();34384 } })).toValue();
34390}34385}
src/codegen.zig+1-1
...@@ -957,7 +957,7 @@ pub fn genTypedValue(...@@ -957,7 +957,7 @@ pub fn genTypedValue(
957 }957 }
958 },958 },
959 .Bool => {959 .Bool => {
960 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool(mod)) });960 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
961 },961 },
962 .Optional => {962 .Optional => {
963 if (typed_value.ty.isPtrLikeOptional(mod)) {963 if (typed_value.ty.isPtrLikeOptional(mod)) {
src/codegen/llvm.zig+19-15
...@@ -2003,7 +2003,7 @@ pub const Object = struct {...@@ -2003,7 +2003,7 @@ pub const Object = struct {
2003 mod.intern_pool.stringToSlice(tuple.names[i])2003 mod.intern_pool.stringToSlice(tuple.names[i])
2004 else2004 else
2005 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2005 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2006 defer gpa.free(field_name);2006 defer if (tuple.names.len == 0) gpa.free(field_name);
20072007
2008 try di_fields.append(gpa, dib.createMemberType(2008 try di_fields.append(gpa, dib.createMemberType(
2009 fwd_decl.toScope(),2009 fwd_decl.toScope(),
...@@ -2461,13 +2461,13 @@ pub const DeclGen = struct {...@@ -2461,13 +2461,13 @@ pub const DeclGen = struct {
2461 if (decl.@"linksection") |section| global.setSection(section);2461 if (decl.@"linksection") |section| global.setSection(section);
2462 assert(decl.has_tv);2462 assert(decl.has_tv);
2463 const init_val = if (decl.val.getVariable(mod)) |variable| init_val: {2463 const init_val = if (decl.val.getVariable(mod)) |variable| init_val: {
2464 break :init_val variable.init.toValue();2464 break :init_val variable.init;
2465 } else init_val: {2465 } else init_val: {
2466 global.setGlobalConstant(.True);2466 global.setGlobalConstant(.True);
2467 break :init_val decl.val;2467 break :init_val decl.val.toIntern();
2468 };2468 };
2469 if (init_val.toIntern() != .unreachable_value) {2469 if (init_val != .none) {
2470 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val });2470 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() });
2471 if (global.globalGetValueType() == llvm_init.typeOf()) {2471 if (global.globalGetValueType() == llvm_init.typeOf()) {
2472 global.setInitializer(llvm_init);2472 global.setInitializer(llvm_init);
2473 } else {2473 } else {
...@@ -2748,7 +2748,7 @@ pub const DeclGen = struct {...@@ -2748,7 +2748,7 @@ pub const DeclGen = struct {
2748 if (std.debug.runtime_safety and false) check: {2748 if (std.debug.runtime_safety and false) check: {
2749 if (t.zigTypeTag(mod) == .Opaque) break :check;2749 if (t.zigTypeTag(mod) == .Opaque) break :check;
2750 if (!t.hasRuntimeBits(mod)) break :check;2750 if (!t.hasRuntimeBits(mod)) break :check;
2751 if (!llvm_ty.isSized().toBool(mod)) break :check;2751 if (!llvm_ty.isSized().toBool()) break :check;
27522752
2753 const zig_size = t.abiSize(mod);2753 const zig_size = t.abiSize(mod);
2754 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);2754 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);
...@@ -3239,7 +3239,7 @@ pub const DeclGen = struct {...@@ -3239,7 +3239,7 @@ pub const DeclGen = struct {
3239 => unreachable, // non-runtime values3239 => unreachable, // non-runtime values
3240 .false, .true => {3240 .false, .true => {
3241 const llvm_type = try dg.lowerType(tv.ty);3241 const llvm_type = try dg.lowerType(tv.ty);
3242 return if (tv.val.toBool(mod)) llvm_type.constAllOnes() else llvm_type.constNull();3242 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
3243 },3243 },
3244 },3244 },
3245 .variable,3245 .variable,
...@@ -3522,15 +3522,19 @@ pub const DeclGen = struct {...@@ -3522,15 +3522,19 @@ pub const DeclGen = struct {
3522 const elem_ty = vector_type.child.toType();3522 const elem_ty = vector_type.child.toType();
3523 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len);3523 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len);
3524 defer dg.gpa.free(llvm_elems);3524 defer dg.gpa.free(llvm_elems);
3525 const llvm_i8 = dg.context.intType(8);
3525 for (llvm_elems, 0..) |*llvm_elem, i| {3526 for (llvm_elems, 0..) |*llvm_elem, i| {
3526 llvm_elem.* = try dg.lowerValue(.{3527 llvm_elem.* = switch (aggregate.storage) {
3527 .ty = elem_ty,3528 .bytes => |bytes| llvm_i8.constInt(bytes[i], .False),
3528 .val = switch (aggregate.storage) {3529 .elems => |elems| try dg.lowerValue(.{
3529 .bytes => unreachable,3530 .ty = elem_ty,
3530 .elems => |elems| elems[i],3531 .val = elems[i].toValue(),
3531 .repeated_elem => |elem| elem,3532 }),
3532 }.toValue(),3533 .repeated_elem => |elem| try dg.lowerValue(.{
3533 });3534 .ty = elem_ty,
3535 .val = elem.toValue(),
3536 }),
3537 };
3534 }3538 }
3535 return llvm.constVector(3539 return llvm.constVector(
3536 llvm_elems.ptr,3540 llvm_elems.ptr,
src/codegen/spirv.zig+3-47
...@@ -654,7 +654,7 @@ pub const DeclGen = struct {...@@ -654,7 +654,7 @@ pub const DeclGen = struct {
654 .@"unreachable",654 .@"unreachable",
655 .generic_poison,655 .generic_poison,
656 => unreachable, // non-runtime values656 => unreachable, // non-runtime values
657 .false, .true => try self.addConstBool(val.toBool(mod)),657 .false, .true => try self.addConstBool(val.toBool()),
658 },658 },
659 .variable,659 .variable,
660 .extern_func,660 .extern_func,
...@@ -974,7 +974,6 @@ pub const DeclGen = struct {...@@ -974,7 +974,6 @@ pub const DeclGen = struct {
974 /// This function should only be called during function code generation.974 /// This function should only be called during function code generation.
975 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {975 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {
976 const mod = self.module;976 const mod = self.module;
977 const target = self.getTarget();
978 const result_ty_ref = try self.resolveType(ty, repr);977 const result_ty_ref = try self.resolveType(ty, repr);
979978
980 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });979 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
...@@ -991,51 +990,8 @@ pub const DeclGen = struct {...@@ -991,51 +990,8 @@ pub const DeclGen = struct {
991 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));990 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));
992 }991 }
993 },992 },
994 .Bool => switch (repr) {993 .Bool => {
995 .direct => return try self.spv.constBool(result_ty_ref, val.toBool(mod)),994 @compileError("TODO merge conflict failure");
996 .indirect => return try self.spv.constInt(result_ty_ref, @boolToInt(val.toBool(mod))),
997 },
998 .Float => return switch (ty.floatBits(target)) {
999 16 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float16 = val.toFloat(f16, mod) } } }),
1000 32 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float32 = val.toFloat(f32, mod) } } }),
1001 64 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float64 = val.toFloat(f64, mod) } } }),
1002 80, 128 => unreachable, // TODO
1003 else => unreachable,
1004 },
1005 .ErrorSet => {
1006 const value = switch (val.tag()) {
1007 .@"error" => blk: {
1008 const err_name = val.castTag(.@"error").?.data.name;
1009 const kv = try self.module.getErrorValue(err_name);
1010 break :blk @intCast(u16, kv.value);
1011 },
1012 .zero => 0,
1013 else => unreachable,
1014 };
1015
1016 return try self.spv.constInt(result_ty_ref, value);
1017 },
1018 .ErrorUnion => {
1019 const payload_ty = ty.errorUnionPayload();
1020 const is_pl = val.errorUnionIsPayload();
1021 const error_val = if (!is_pl) val else Value.initTag(.zero);
1022
1023 const eu_layout = self.errorUnionLayout(payload_ty);
1024 if (!eu_layout.payload_has_bits) {
1025 return try self.constant(Type.anyerror, error_val, repr);
1026 }
1027
1028 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
1029
1030 var members: [2]IdRef = undefined;
1031 if (eu_layout.error_first) {
1032 members[0] = try self.constant(Type.anyerror, error_val, .indirect);
1033 members[1] = try self.constant(payload_ty, payload_val, .indirect);
1034 } else {
1035 members[0] = try self.constant(payload_ty, payload_val, .indirect);
1036 members[1] = try self.constant(Type.anyerror, error_val, .indirect);
1037 }
1038 return try self.spv.constComposite(result_ty_ref, &members);
1039 },995 },
1040 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra996 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1041 // OpVariable that is not really required.997 // OpVariable that is not really required.
src/type.zig+21-14
...@@ -2481,25 +2481,32 @@ pub const Type = struct {...@@ -2481,25 +2481,32 @@ pub const Type = struct {
2481 .struct_type => |struct_type| {2481 .struct_type => |struct_type| {
2482 if (mod.structPtrUnwrap(struct_type.index)) |s| {2482 if (mod.structPtrUnwrap(struct_type.index)) |s| {
2483 assert(s.haveFieldTypes());2483 assert(s.haveFieldTypes());
2484 for (s.fields.values()) |field| {2484 const field_vals = try mod.gpa.alloc(InternPool.Index, s.fields.count());
2485 if (field.is_comptime) continue;2485 defer mod.gpa.free(field_vals);
2486 if ((try field.ty.onePossibleValue(mod)) != null) continue;2486 for (field_vals, s.fields.values()) |*field_val, field| {
2487 return null;2487 if (field.is_comptime) {
2488 field_val.* = try field.default_val.intern(field.ty, mod);
2489 continue;
2490 }
2491 if (try field.ty.onePossibleValue(mod)) |field_opv| {
2492 field_val.* = try field_opv.intern(field.ty, mod);
2493 } else return null;
2488 }2494 }
2495
2496 // In this case the struct has no runtime-known fields and
2497 // therefore has one possible value.
2498 return (try mod.intern(.{ .aggregate = .{
2499 .ty = ty.toIntern(),
2500 .storage = .{ .elems = field_vals },
2501 } })).toValue();
2489 }2502 }
2490 // In this case the struct has no runtime-known fields and
2491 // therefore has one possible value.
24922503
2493 // TODO: this is incorrect for structs with comptime fields, I think2504 // In this case the struct has no fields at all and
2494 // we should use a temporary allocator to construct an aggregate that2505 // therefore has one possible value.
2495 // is populated with the comptime values and then intern that value here.2506 return (try mod.intern(.{ .aggregate = .{
2496 // This TODO is repeated in the redundant implementation of
2497 // one-possible-value logic in Sema.zig.
2498 const empty = try mod.intern(.{ .aggregate = .{
2499 .ty = ty.toIntern(),2507 .ty = ty.toIntern(),
2500 .storage = .{ .elems = &.{} },2508 .storage = .{ .elems = &.{} },
2501 } });2509 } })).toValue();
2502 return empty.toValue();
2503 },2510 },
25042511
2505 .anon_struct_type => |tuple| {2512 .anon_struct_type => |tuple| {
src/value.zig+47-153
...@@ -385,7 +385,7 @@ pub const Value = struct {...@@ -385,7 +385,7 @@ pub const Value = struct {
385 } });385 } });
386 },386 },
387 .aggregate => {387 .aggregate => {
388 const old_elems = val.castTag(.aggregate).?.data;388 const old_elems = val.castTag(.aggregate).?.data[0..ty.arrayLen(mod)];
389 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);389 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
390 defer mod.gpa.free(new_elems);390 defer mod.gpa.free(new_elems);
391 const ty_key = mod.intern_pool.indexToKey(ty.toIntern());391 const ty_key = mod.intern_pool.indexToKey(ty.toIntern());
...@@ -656,7 +656,7 @@ pub const Value = struct {...@@ -656,7 +656,7 @@ pub const Value = struct {
656 };656 };
657 }657 }
658658
659 pub fn toBool(val: Value, _: *const Module) bool {659 pub fn toBool(val: Value) bool {
660 return switch (val.toIntern()) {660 return switch (val.toIntern()) {
661 .bool_true => true,661 .bool_true => true,
662 .bool_false => false,662 .bool_false => false,
...@@ -697,7 +697,7 @@ pub const Value = struct {...@@ -697,7 +697,7 @@ pub const Value = struct {
697 switch (ty.zigTypeTag(mod)) {697 switch (ty.zigTypeTag(mod)) {
698 .Void => {},698 .Void => {},
699 .Bool => {699 .Bool => {
700 buffer[0] = @boolToInt(val.toBool(mod));700 buffer[0] = @boolToInt(val.toBool());
701 },701 },
702 .Int, .Enum => {702 .Int, .Enum => {
703 const int_info = ty.intInfo(mod);703 const int_info = ty.intInfo(mod);
...@@ -736,13 +736,20 @@ pub const Value = struct {...@@ -736,13 +736,20 @@ pub const Value = struct {
736 },736 },
737 .Struct => switch (ty.containerLayout(mod)) {737 .Struct => switch (ty.containerLayout(mod)) {
738 .Auto => return error.IllDefinedMemoryLayout,738 .Auto => return error.IllDefinedMemoryLayout,
739 .Extern => {739 .Extern => for (ty.structFields(mod).values(), 0..) |field, i| {
740 const fields = ty.structFields(mod).values();740 const off = @intCast(usize, ty.structFieldOffset(i, mod));
741 const field_vals = val.castTag(.aggregate).?.data;741 const field_val = switch (val.ip_index) {
742 for (fields, 0..) |field, i| {742 .none => val.castTag(.aggregate).?.data[i],
743 const off = @intCast(usize, ty.structFieldOffset(i, mod));743 else => switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {
744 try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);744 .bytes => |bytes| {
745 }745 buffer[off] = bytes[i];
746 continue;
747 },
748 .elems => |elems| elems[i],
749 .repeated_elem => |elem| elem,
750 }.toValue(),
751 };
752 try writeToMemory(field_val, field.ty, mod, buffer[off..]);
746 },753 },
747 .Packed => {754 .Packed => {
748 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;755 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
...@@ -812,7 +819,7 @@ pub const Value = struct {...@@ -812,7 +819,7 @@ pub const Value = struct {
812 .Little => bit_offset / 8,819 .Little => bit_offset / 8,
813 .Big => buffer.len - bit_offset / 8 - 1,820 .Big => buffer.len - bit_offset / 8 - 1,
814 };821 };
815 if (val.toBool(mod)) {822 if (val.toBool()) {
816 buffer[byte_index] |= (@as(u8, 1) << @intCast(u3, bit_offset % 8));823 buffer[byte_index] |= (@as(u8, 1) << @intCast(u3, bit_offset % 8));
817 } else {824 } else {
818 buffer[byte_index] &= ~(@as(u8, 1) << @intCast(u3, bit_offset % 8));825 buffer[byte_index] &= ~(@as(u8, 1) << @intCast(u3, bit_offset % 8));
...@@ -1331,24 +1338,7 @@ pub const Value = struct {...@@ -1331,24 +1338,7 @@ pub const Value = struct {
1331 .gt => {},1338 .gt => {},
1332 }1339 }
13331340
1334 const lhs_float = lhs.isFloat(mod);1341 if (lhs.isFloat(mod) or rhs.isFloat(mod)) {
1335 const rhs_float = rhs.isFloat(mod);
1336 if (lhs_float and rhs_float) {
1337 const lhs_tag = lhs.tag();
1338 const rhs_tag = rhs.tag();
1339 if (lhs_tag == rhs_tag) {
1340 const lhs_storage = mod.intern_pool.indexToKey(lhs.toIntern()).float.storage;
1341 const rhs_storage = mod.intern_pool.indexToKey(rhs.toIntern()).float.storage;
1342 const lhs128: f128 = switch (lhs_storage) {
1343 inline else => |x| x,
1344 };
1345 const rhs128: f128 = switch (rhs_storage) {
1346 inline else => |x| x,
1347 };
1348 return std.math.order(lhs128, rhs128);
1349 }
1350 }
1351 if (lhs_float or rhs_float) {
1352 const lhs_f128 = lhs.toFloat(f128, mod);1342 const lhs_f128 = lhs.toFloat(f128, mod);
1353 const rhs_f128 = rhs.toFloat(f128, mod);1343 const rhs_f128 = rhs.toFloat(f128, mod);
1354 return std.math.order(lhs_f128, rhs_f128);1344 return std.math.order(lhs_f128, rhs_f128);
...@@ -1669,86 +1659,6 @@ pub const Value = struct {...@@ -1669,86 +1659,6 @@ pub const Value = struct {
1669 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);1659 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
1670 }1660 }
16711661
1672 /// This function is used by hash maps and so treats floating-point NaNs as equal
1673 /// to each other, and not equal to other floating-point values.
1674 pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
1675 if (val.ip_index != .none) {
1676 // The InternPool data structure hashes based on Key to make interned objects
1677 // unique. An Index can be treated simply as u32 value for the
1678 // purpose of Type/Value hashing and equality.
1679 std.hash.autoHash(hasher, val.toIntern());
1680 return;
1681 }
1682 const zig_ty_tag = ty.zigTypeTag(mod);
1683 std.hash.autoHash(hasher, zig_ty_tag);
1684 if (val.isUndef(mod)) return;
1685 // The value is runtime-known and shouldn't affect the hash.
1686 if (val.isRuntimeValue(mod)) return;
1687
1688 switch (zig_ty_tag) {
1689 .Opaque => unreachable, // Cannot hash opaque types
1690
1691 .Void,
1692 .NoReturn,
1693 .Undefined,
1694 .Null,
1695 => {},
1696
1697 .Type,
1698 .Float,
1699 .ComptimeFloat,
1700 .Bool,
1701 .Int,
1702 .ComptimeInt,
1703 .Pointer,
1704 .Optional,
1705 .ErrorUnion,
1706 .ErrorSet,
1707 .Enum,
1708 .EnumLiteral,
1709 .Fn,
1710 => unreachable, // handled via ip_index check above
1711 .Array, .Vector => {
1712 const len = ty.arrayLen(mod);
1713 const elem_ty = ty.childType(mod);
1714 var index: usize = 0;
1715 while (index < len) : (index += 1) {
1716 const elem_val = val.elemValue(mod, index) catch |err| switch (err) {
1717 // Will be solved when arrays and vectors get migrated to the intern pool.
1718 error.OutOfMemory => @panic("OOM"),
1719 };
1720 elem_val.hash(elem_ty, hasher, mod);
1721 }
1722 },
1723 .Struct => {
1724 switch (val.tag()) {
1725 .aggregate => {
1726 const field_values = val.castTag(.aggregate).?.data;
1727 for (field_values, 0..) |field_val, i| {
1728 const field_ty = ty.structFieldType(i, mod);
1729 field_val.hash(field_ty, hasher, mod);
1730 }
1731 },
1732 else => unreachable,
1733 }
1734 },
1735 .Union => {
1736 const union_obj = val.cast(Payload.Union).?.data;
1737 if (ty.unionTagType(mod)) |tag_ty| {
1738 union_obj.tag.hash(tag_ty, hasher, mod);
1739 }
1740 const active_field_ty = ty.unionFieldType(union_obj.tag, mod);
1741 union_obj.val.hash(active_field_ty, hasher, mod);
1742 },
1743 .Frame => {
1744 @panic("TODO implement hashing frame values");
1745 },
1746 .AnyFrame => {
1747 @panic("TODO implement hashing anyframe values");
1748 },
1749 }
1750 }
1751
1752 /// This is a more conservative hash function that produces equal hashes for values1662 /// This is a more conservative hash function that produces equal hashes for values
1753 /// that can coerce into each other.1663 /// that can coerce into each other.
1754 /// This function is used by hash maps and so treats floating-point NaNs as equal1664 /// This function is used by hash maps and so treats floating-point NaNs as equal
...@@ -1820,35 +1730,6 @@ pub const Value = struct {...@@ -1820,35 +1730,6 @@ pub const Value = struct {
1820 }1730 }
1821 }1731 }
18221732
1823 pub const ArrayHashContext = struct {
1824 ty: Type,
1825 mod: *Module,
1826
1827 pub fn hash(self: @This(), val: Value) u32 {
1828 const other_context: HashContext = .{ .ty = self.ty, .mod = self.mod };
1829 return @truncate(u32, other_context.hash(val));
1830 }
1831 pub fn eql(self: @This(), a: Value, b: Value, b_index: usize) bool {
1832 _ = b_index;
1833 return a.eql(b, self.ty, self.mod);
1834 }
1835 };
1836
1837 pub const HashContext = struct {
1838 ty: Type,
1839 mod: *Module,
1840
1841 pub fn hash(self: @This(), val: Value) u64 {
1842 var hasher = std.hash.Wyhash.init(0);
1843 val.hash(self.ty, &hasher, self.mod);
1844 return hasher.final();
1845 }
1846
1847 pub fn eql(self: @This(), a: Value, b: Value) bool {
1848 return a.eql(b, self.ty, self.mod);
1849 }
1850 };
1851
1852 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {1733 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
1853 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1734 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1854 .ptr => |ptr| switch (ptr.addr) {1735 .ptr => |ptr| switch (ptr.addr) {
...@@ -1919,14 +1800,25 @@ pub const Value = struct {...@@ -1919,14 +1800,25 @@ pub const Value = struct {
1919 }1800 }
19201801
1921 pub fn sliceLen(val: Value, mod: *Module) u64 {1802 pub fn sliceLen(val: Value, mod: *Module) u64 {
1922 return mod.intern_pool.sliceLen(val.toIntern()).toValue().toUnsignedInt(mod);1803 const ptr = mod.intern_pool.indexToKey(val.toIntern()).ptr;
1804 return switch (ptr.len) {
1805 .none => switch (mod.intern_pool.indexToKey(switch (ptr.addr) {
1806 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
1807 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),
1808 .comptime_field => |comptime_field| mod.intern_pool.typeOf(comptime_field),
1809 else => unreachable,
1810 })) {
1811 .array_type => |array_type| array_type.len,
1812 else => 1,
1813 },
1814 else => ptr.len.toValue().toUnsignedInt(mod),
1815 };
1923 }1816 }
19241817
1925 /// Asserts the value is a single-item pointer to an array, or an array,1818 /// Asserts the value is a single-item pointer to an array, or an array,
1926 /// or an unknown-length pointer, and returns the element value at the index.1819 /// or an unknown-length pointer, and returns the element value at the index.
1927 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {1820 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
1928 return switch (val.ip_index) {1821 return switch (val.ip_index) {
1929 .undef => Value.undef,
1930 .none => switch (val.tag()) {1822 .none => switch (val.tag()) {
1931 .repeated => val.castTag(.repeated).?.data,1823 .repeated => val.castTag(.repeated).?.data,
1932 .aggregate => val.castTag(.aggregate).?.data[index],1824 .aggregate => val.castTag(.aggregate).?.data[index],
...@@ -1934,6 +1826,9 @@ pub const Value = struct {...@@ -1934,6 +1826,9 @@ pub const Value = struct {
1934 else => unreachable,1826 else => unreachable,
1935 },1827 },
1936 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {1828 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1829 .undef => |ty| (try mod.intern(.{
1830 .undef = ty.toType().elemType2(mod).toIntern(),
1831 })).toValue(),
1937 .ptr => |ptr| switch (ptr.addr) {1832 .ptr => |ptr| switch (ptr.addr) {
1938 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),1833 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
1939 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),1834 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),
...@@ -2492,7 +2387,7 @@ pub const Value = struct {...@@ -2492,7 +2387,7 @@ pub const Value = struct {
2492 }2387 }
24932388
2494 return OverflowArithmeticResult{2389 return OverflowArithmeticResult{
2495 .overflow_bit = boolToInt(overflowed),2390 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
2496 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),2391 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
2497 };2392 };
2498 }2393 }
...@@ -2645,7 +2540,8 @@ pub const Value = struct {...@@ -2645,7 +2540,8 @@ pub const Value = struct {
26452540
2646 /// operands must be integers; handles undefined.2541 /// operands must be integers; handles undefined.
2647 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2542 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2648 if (val.isUndef(mod)) return Value.undef;2543 if (val.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2544 if (ty.toIntern() == .bool_type) return makeBool(!val.toBool());
26492545
2650 const info = ty.intInfo(mod);2546 const info = ty.intInfo(mod);
26512547
...@@ -2687,7 +2583,8 @@ pub const Value = struct {...@@ -2687,7 +2583,8 @@ pub const Value = struct {
26872583
2688 /// operands must be integers; handles undefined.2584 /// operands must be integers; handles undefined.
2689 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2585 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2690 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;2586 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2587 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() and rhs.toBool());
26912588
2692 // TODO is this a performance issue? maybe we should try the operation without2589 // TODO is this a performance issue? maybe we should try the operation without
2693 // resorting to BigInt first.2590 // resorting to BigInt first.
...@@ -2725,7 +2622,8 @@ pub const Value = struct {...@@ -2725,7 +2622,8 @@ pub const Value = struct {
27252622
2726 /// operands must be integers; handles undefined.2623 /// operands must be integers; handles undefined.
2727 pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2624 pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2728 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;2625 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2626 if (ty.toIntern() == .bool_type) return makeBool(!(lhs.toBool() and rhs.toBool()));
27292627
2730 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);2628 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
2731 const all_ones = if (ty.isSignedInt(mod)) try mod.intValue(ty, -1) else try ty.maxIntScalar(mod, ty);2629 const all_ones = if (ty.isSignedInt(mod)) try mod.intValue(ty, -1) else try ty.maxIntScalar(mod, ty);
...@@ -2752,7 +2650,8 @@ pub const Value = struct {...@@ -2752,7 +2650,8 @@ pub const Value = struct {
27522650
2753 /// operands must be integers; handles undefined.2651 /// operands must be integers; handles undefined.
2754 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2652 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2755 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;2653 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2654 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() or rhs.toBool());
27562655
2757 // TODO is this a performance issue? maybe we should try the operation without2656 // TODO is this a performance issue? maybe we should try the operation without
2758 // resorting to BigInt first.2657 // resorting to BigInt first.
...@@ -2789,7 +2688,8 @@ pub const Value = struct {...@@ -2789,7 +2688,8 @@ pub const Value = struct {
27892688
2790 /// operands must be integers; handles undefined.2689 /// operands must be integers; handles undefined.
2791 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {2690 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2792 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;2691 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2692 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() != rhs.toBool());
27932693
2794 // TODO is this a performance issue? maybe we should try the operation without2694 // TODO is this a performance issue? maybe we should try the operation without
2795 // resorting to BigInt first.2695 // resorting to BigInt first.
...@@ -3233,7 +3133,7 @@ pub const Value = struct {...@@ -3233,7 +3133,7 @@ pub const Value = struct {
3233 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);3133 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);
3234 }3134 }
3235 return OverflowArithmeticResult{3135 return OverflowArithmeticResult{
3236 .overflow_bit = boolToInt(overflowed),3136 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3237 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),3137 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
3238 };3138 };
3239 }3139 }
...@@ -4267,12 +4167,6 @@ pub const Value = struct {...@@ -4267,12 +4167,6 @@ pub const Value = struct {
4267 return if (x) Value.true else Value.false;4167 return if (x) Value.true else Value.false;
4268 }4168 }
42694169
4270 pub fn boolToInt(x: bool) Value {
4271 const zero: Value = .{ .ip_index = .zero, .legacy = undefined };
4272 const one: Value = .{ .ip_index = .one, .legacy = undefined };
4273 return if (x) one else zero;
4274 }
4275
4276 pub const RuntimeIndex = InternPool.RuntimeIndex;4170 pub const RuntimeIndex = InternPool.RuntimeIndex;
42774171
4278 /// This function is used in the debugger pretty formatters in tools/ to fetch the4172 /// This function is used in the debugger pretty formatters in tools/ to fetch the
tools/lldb_pretty_printers.py+3-3
...@@ -354,8 +354,8 @@ def Zir_Inst__Zir_Inst_Ref_SummaryProvider(value, _=None):...@@ -354,8 +354,8 @@ def Zir_Inst__Zir_Inst_Ref_SummaryProvider(value, _=None):
354354
355def Air_Inst__Air_Inst_Ref_SummaryProvider(value, _=None):355def Air_Inst__Air_Inst_Ref_SummaryProvider(value, _=None):
356 members = value.type.enum_members356 members = value.type.enum_members
357 # ignore .none357 # ignore .var_args_param_type and .none
358 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned + 1 - len(members))358 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned + 2 - len(members))
359359
360class Module_Decl__Module_Decl_Index_SynthProvider:360class Module_Decl__Module_Decl_Index_SynthProvider:
361 def __init__(self, value, _=None): self.value = value361 def __init__(self, value, _=None): self.value = value
...@@ -365,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:...@@ -365,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:
365 mod = frame.FindVariable('mod') or frame.FindVariable('module')365 mod = frame.FindVariable('mod') or frame.FindVariable('module')
366 if mod: break366 if mod: break
367 else: return367 else: return
368 self.ptr = mod.GetChildMemberWithName('allocated_decls').GetChildAtIndex(self.value.unsigned).Clone('decl')368 self.ptr = mod.GetChildMemberWithName('allocated_decls').GetChildAtIndex(self.value.unsigned).address_of.Clone('decl')
369 except: pass369 except: pass
370 def has_children(self): return True370 def has_children(self): return True
371 def num_children(self): return 1371 def num_children(self): return 1