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) {
621621
622622 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash, ip: *const InternPool) void {
623623 const KeyTag = @typeInfo(Key).Union.tag_type.?;
624 const key_tag: KeyTag = key;
625 std.hash.autoHash(hasher, key_tag);
624 std.hash.autoHash(hasher, @as(KeyTag, key));
626625 switch (key) {
627626 inline .int_type,
628627 .ptr_type,
......@@ -710,39 +709,58 @@ pub const Key = union(enum) {
710709
711710 .aggregate => |aggregate| {
712711 std.hash.autoHash(hasher, aggregate.ty);
713 switch (ip.indexToKey(aggregate.ty)) {
714 .array_type => |array_type| if (array_type.child == .u8_type) {
715 switch (aggregate.storage) {
716 .bytes => |bytes| for (bytes) |byte| std.hash.autoHash(hasher, byte),
717 .elems => |elems| {
718 var buffer: Key.Int.Storage.BigIntSpace = undefined;
719 for (elems) |elem| std.hash.autoHash(
712 const len = ip.aggregateTypeLen(aggregate.ty);
713 const child = switch (ip.indexToKey(aggregate.ty)) {
714 .array_type => |array_type| array_type.child,
715 .vector_type => |vector_type| vector_type.child,
716 .anon_struct_type, .struct_type => .none,
717 else => unreachable,
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(
720732 hasher,
721 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
722 unreachable,
723 );
724 },
725 .repeated_elem => |elem| {
726 const len = ip.aggregateTypeLen(aggregate.ty);
727 var buffer: Key.Int.Storage.BigIntSpace = undefined;
728 const byte = ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
729 unreachable;
730 var i: u64 = 0;
731 while (i < len) : (i += 1) std.hash.autoHash(hasher, byte);
732 },
733 }
734 return;
735 },
736 else => {},
733 @intCast(u8, int.storage.u64),
734 ),
735 else => unreachable,
736 }
737 },
738 .repeated_elem => |elem| {
739 const elem_key = ip.indexToKey(elem);
740 var remaining = len;
741 while (remaining > 0) : (remaining -= 1) {
742 std.hash.autoHash(hasher, @as(KeyTag, elem_key));
743 switch (elem_key) {
744 .undef => {},
745 .int => |int| std.hash.autoHash(
746 hasher,
747 @intCast(u8, int.storage.u64),
748 ),
749 else => unreachable,
750 }
751 }
752 },
753 }
754 return;
737755 }
738756
739757 switch (aggregate.storage) {
740758 .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),
742761 .repeated_elem => |elem| {
743 const len = ip.aggregateTypeLen(aggregate.ty);
744 var i: u64 = 0;
745 while (i < len) : (i += 1) std.hash.autoHash(hasher, elem);
762 var remaining = len;
763 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(hasher, elem);
746764 },
747765 }
748766 },
......@@ -960,9 +978,10 @@ pub const Key = union(enum) {
960978 const b_info = b.aggregate;
961979 if (a_info.ty != b_info.ty) return false;
962980
981 const len = ip.aggregateTypeLen(a_info.ty);
963982 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;
964983 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| {
966985 const a_elem = switch (a_info.storage) {
967986 .bytes => |bytes| ip.getIfExists(.{ .int = .{
968987 .ty = .u8_type,
......@@ -987,11 +1006,19 @@ pub const Key = union(enum) {
9871006 switch (a_info.storage) {
9881007 .bytes => |a_bytes| {
9891008 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 );
9911014 },
9921015 .elems => |a_elems| {
9931016 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 );
9951022 },
9961023 .repeated_elem => |a_elem| {
9971024 const b_elem = b_info.storage.repeated_elem;
......@@ -2691,7 +2718,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26912718 },
26922719 .bytes => {
26932720 const extra = ip.extraData(Bytes, data);
2694 const len = @intCast(u32, ip.aggregateTypeLen(extra.ty));
2721 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(extra.ty));
26952722 return .{ .aggregate = .{
26962723 .ty = extra.ty,
26972724 .storage = .{ .bytes = ip.string_bytes.items[@enumToInt(extra.bytes)..][0..len] },
......@@ -2699,7 +2726,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26992726 },
27002727 .aggregate => {
27012728 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));
27032730 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
27042731 return .{ .aggregate = .{
27052732 .ty = extra.data.ty,
......@@ -3145,7 +3172,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
31453172 }),
31463173 }),
31473174 .int => |int| {
3148 assert(int != .none);
3175 assert(ip.typeOf(int) == .usize_type);
31493176 ip.items.appendAssumeCapacity(.{
31503177 .tag = .ptr_int,
31513178 .data = try ip.addExtra(gpa, PtrAddr{
......@@ -3452,7 +3479,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34523479
34533480 .enum_tag => |enum_tag| {
34543481 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 }
34563487 ip.items.appendAssumeCapacity(.{
34573488 .tag = .enum_tag,
34583489 .data = try ip.addExtra(gpa, enum_tag),
......@@ -3501,21 +3532,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35013532
35023533 .aggregate => |aggregate| {
35033534 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);
35053548 switch (aggregate.storage) {
35063549 .bytes => |bytes| {
3507 assert(ty_key.array_type.child == .u8_type);
3508 assert(bytes.len == aggregate_len);
3550 assert(child == .u8_type);
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 }
35093556 },
35103557 .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);
35123566 },
3513 .repeated_elem => {},
35143567 }
35153568 switch (ty_key) {
3516 inline .array_type, .vector_type => |seq_type| {
3569 .array_type, .vector_type => {
35173570 for (aggregate.storage.values()) |elem| {
3518 assert(ip.typeOf(elem) == seq_type.child);
3571 assert(ip.typeOf(elem) == child);
35193572 }
35203573 },
35213574 .struct_type => |struct_type| {
......@@ -3534,7 +3587,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35343587 else => unreachable,
35353588 }
35363589
3537 if (aggregate_len == 0) {
3590 if (len == 0) {
35383591 ip.items.appendAssumeCapacity(.{
35393592 .tag = .only_possible_value,
35403593 .data = @enumToInt(aggregate.ty),
......@@ -3543,41 +3596,43 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
35433596 }
35443597
35453598 switch (ty_key) {
3546 .anon_struct_type => |anon_struct_type| {
3547 if (switch (aggregate.storage) {
3599 .anon_struct_type => |anon_struct_type| opv: {
3600 switch (aggregate.storage) {
35483601 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {
35493602 if (value != ip.getIfExists(.{ .int = .{
35503603 .ty = .u8_type,
35513604 .storage = .{ .u64 = byte },
3552 } })) break false;
3553 } else true,
3554 .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems),
3605 } })) break :opv;
3606 },
3607 .elems => |elems| if (!std.mem.eql(
3608 Index,
3609 anon_struct_type.values,
3610 elems,
3611 )) break :opv,
35553612 .repeated_elem => |elem| for (anon_struct_type.values) |value| {
3556 if (value != elem) break false;
3557 } else true,
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);
3613 if (value != elem) break :opv;
3614 },
35673615 }
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);
35683624 },
35693625 else => {},
35703626 }
35713627
3572 if (switch (aggregate.storage) {
3573 .bytes => |bytes| for (bytes[1..]) |byte| {
3574 if (byte != bytes[0]) break false;
3575 } else true,
3576 .elems => |elems| for (elems[1..]) |elem| {
3577 if (elem != elems[0]) break false;
3578 } else true,
3579 .repeated_elem => true,
3580 }) {
3628 repeated: {
3629 switch (aggregate.storage) {
3630 .bytes => |bytes| for (bytes[1..@intCast(usize, len)]) |byte|
3631 if (byte != bytes[0]) break :repeated,
3632 .elems => |elems| for (elems[1..@intCast(usize, len)]) |elem|
3633 if (elem != elems[0]) break :repeated,
3634 .repeated_elem => {},
3635 }
35813636 const elem = switch (aggregate.storage) {
35823637 .bytes => |bytes| elem: {
35833638 _ = ip.map.pop();
......@@ -3607,42 +3662,48 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36073662 return @intToEnum(Index, ip.items.len - 1);
36083663 }
36093664
3610 switch (ty_key) {
3611 .array_type => |array_type| if (array_type.child == .u8_type) {
3612 const len_including_sentinel = aggregate_len + @boolToInt(array_type.sentinel != .none);
3613 try ip.string_bytes.ensureUnusedCapacity(gpa, len_including_sentinel + 1);
3614 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
3615 var buffer: Key.Int.Storage.BigIntSpace = undefined;
3616 switch (aggregate.storage) {
3617 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
3618 .elems => |elems| for (elems) |elem| ip.string_bytes.appendAssumeCapacity(
3619 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,
3665 if (child == .u8_type) bytes: {
3666 const string_bytes_index = ip.string_bytes.items.len;
3667 try ip.string_bytes.ensureUnusedCapacity(gpa, len_including_sentinel + 1);
3668 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
3669 switch (aggregate.storage) {
3670 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
3671 .elems => |elems| for (elems) |elem| switch (ip.indexToKey(elem)) {
3672 .undef => {
3673 ip.string_bytes.shrinkRetainingCapacity(string_bytes_index);
3674 break :bytes;
3675 },
3676 .int => |int| ip.string_bytes.appendAssumeCapacity(
3677 @intCast(u8, int.storage.u64),
36203678 ),
3621 .repeated_elem => |elem| @memset(
3622 ip.string_bytes.addManyAsSliceAssumeCapacity(aggregate_len),
3623 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,
3679 else => unreachable,
3680 },
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),
36243686 ),
3625 }
3626 if (array_type.sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3627 ip.indexToKey(array_type.sentinel).int.storage.toBigInt(&buffer).to(u8) catch
3628 unreachable,
3629 );
3630 const bytes = try ip.getOrPutTrailingString(gpa, len_including_sentinel);
3631 ip.items.appendAssumeCapacity(.{
3632 .tag = .bytes,
3633 .data = ip.addExtraAssumeCapacity(Bytes{
3634 .ty = aggregate.ty,
3635 .bytes = bytes.toString(),
3636 }),
3637 });
3638 return @intToEnum(Index, ip.items.len - 1);
3639 },
3640 else => {},
3687 else => unreachable,
3688 },
3689 }
3690 if (sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3691 @intCast(u8, ip.indexToKey(sentinel).int.storage.u64),
3692 );
3693 const bytes = try ip.getOrPutTrailingString(gpa, len_including_sentinel);
3694 ip.items.appendAssumeCapacity(.{
3695 .tag = .bytes,
3696 .data = ip.addExtraAssumeCapacity(Bytes{
3697 .ty = aggregate.ty,
3698 .bytes = bytes.toString(),
3699 }),
3700 });
3701 return @intToEnum(Index, ip.items.len - 1);
36413702 }
36423703
36433704 try ip.extra.ensureUnusedCapacity(
36443705 gpa,
3645 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,
3706 @typeInfo(Aggregate).Struct.fields.len + len_including_sentinel,
36463707 );
36473708 ip.items.appendAssumeCapacity(.{
36483709 .tag = .aggregate,
......@@ -3651,6 +3712,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
36513712 }),
36523713 });
36533714 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));
3715 if (sentinel != .none) ip.extra.appendAssumeCapacity(@enumToInt(sentinel));
36543716 },
36553717
36563718 .un => |un| {
......@@ -4183,10 +4245,12 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
41834245/// Given an existing value, returns the same value but with the supplied type.
41844246/// Only some combinations are allowed:
41854247/// * identity coercion
4248/// * undef => any
41864249/// * int <=> int
41874250/// * int <=> enum
41884251/// * enum_literal => enum
41894252/// * ptr <=> ptr
4253/// * int => ptr
41904254/// * null_value => opt
41914255/// * payload => opt
41924256/// * error set <=> error set
......@@ -4194,68 +4258,93 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
41944258/// * error set => error union
41954259/// * payload => error union
41964260/// * fn <=> fn
4261/// * array <=> array
4262/// * array <=> vector
4263/// * vector <=> vector
41974264pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
41984265 const old_ty = ip.typeOf(val);
41994266 if (old_ty == new_ty) return val;
4200 switch (ip.indexToKey(val)) {
4201 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
4202 return ip.get(gpa, .{ .extern_func = .{
4203 .ty = new_ty,
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 = .{
4267 switch (val) {
4268 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4269 .null_value => if (ip.isOptionalType(new_ty))
4270 return ip.get(gpa, .{ .opt = .{
42164271 .ty = new_ty,
4217 .int = val,
4272 .val = .none,
42184273 } }),
4219 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
4220 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
4221 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
4222 .enum_type => |enum_type| {
4223 const index = enum_type.nameIndex(ip, enum_literal).?;
4274 else => switch (ip.indexToKey(val)) {
4275 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4276 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
4277 return ip.get(gpa, .{ .extern_func = .{
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))
42244290 return ip.get(gpa, .{ .enum_tag = .{
42254291 .ty = new_ty,
4226 .int = if (enum_type.values.len != 0)
4227 enum_type.values[index]
4228 else
4229 try ip.get(gpa, .{ .int = .{
4230 .ty = enum_type.tag_ty,
4231 .storage = .{ .u64 = index },
4232 } }),
4233 } });
4292 .int = val,
4293 } })
4294 else if (ip.isPointerType(new_ty))
4295 return ip.get(gpa, .{ .ptr = .{
4296 .ty = new_ty,
4297 .addr = .{ .int = val },
4298 } }),
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 => {},
42344316 },
4235 else => {},
4236 },
4237 .ptr => |ptr| if (ip.isPointerType(new_ty))
4238 return ip.get(gpa, .{ .ptr = .{
4239 .ty = new_ty,
4240 .addr = ptr.addr,
4241 .len = ptr.len,
4242 } }),
4243 .err => |err| if (ip.isErrorSetType(new_ty))
4244 return ip.get(gpa, .{ .err = .{
4245 .ty = new_ty,
4246 .name = err.name,
4247 } })
4248 else if (ip.isErrorUnionType(new_ty))
4249 return ip.get(gpa, .{ .error_union = .{
4250 .ty = new_ty,
4251 .val = .{ .err_name = err.name },
4252 } }),
4253 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4254 return ip.get(gpa, .{ .error_union = .{
4317 .ptr => |ptr| if (ip.isPointerType(new_ty))
4318 return ip.get(gpa, .{ .ptr = .{
4319 .ty = new_ty,
4320 .addr = ptr.addr,
4321 .len = ptr.len,
4322 } }),
4323 .err => |err| if (ip.isErrorSetType(new_ty))
4324 return ip.get(gpa, .{ .err = .{
4325 .ty = new_ty,
4326 .name = err.name,
4327 } })
4328 else if (ip.isErrorUnionType(new_ty))
4329 return ip.get(gpa, .{ .error_union = .{
4330 .ty = new_ty,
4331 .val = .{ .err_name = err.name },
4332 } }),
4333 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4334 return ip.get(gpa, .{ .error_union = .{
4335 .ty = new_ty,
4336 .val = error_union.val,
4337 } }),
4338 .aggregate => |aggregate| return ip.get(gpa, .{ .aggregate = .{
42554339 .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 },
42574345 } }),
4258 else => {},
4346 else => {},
4347 },
42594348 }
42604349 switch (ip.indexToKey(new_ty)) {
42614350 .opt_type => |child_type| switch (val) {
......@@ -4527,7 +4616,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
45274616
45284617 .type_function => b: {
45294618 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);
45314620 },
45324621
45334622 .undef => 0,
......@@ -4570,14 +4659,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
45704659
45714660 .bytes => b: {
45724661 const info = ip.extraData(Bytes, data);
4573 const len = @intCast(u32, ip.aggregateTypeLen(info.ty));
4662 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
45744663 break :b @sizeOf(Bytes) + len +
45754664 @boolToInt(ip.string_bytes.items[@enumToInt(info.bytes) + len - 1] != 0);
45764665 },
45774666 .aggregate => b: {
45784667 const info = ip.extraData(Aggregate, data);
4579 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
4580 break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len);
4668 const fields_len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
4669 break :b @sizeOf(Aggregate) + (@sizeOf(Index) * fields_len);
45814670 },
45824671 .repeated => @sizeOf(Repeated),
45834672
......@@ -4889,6 +4978,16 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
48894978 };
48904979}
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
48924991pub fn isNoReturn(ip: InternPool, ty: Index) bool {
48934992 return switch (ty) {
48944993 .noreturn_type => true,
src/Module.zig+35-48
......@@ -99,6 +99,7 @@ monomorphed_funcs: MonomorphedFuncsSet = .{},
9999/// The set of all comptime function calls that have been cached so that future calls
100100/// with the same parameters will get the same return value.
101101memoized_calls: MemoizedCallSet = .{},
102memoized_call_args: MemoizedCall.Args = .{},
102103/// Contains the values from `@setAlignStack`. A sparse table is used here
103104/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
104105/// functions are many.
......@@ -230,46 +231,30 @@ pub const MemoizedCallSet = std.HashMapUnmanaged(
230231);
231232
232233pub const MemoizedCall = struct {
233 module: *Module,
234 args: *const Args,
235
236 pub const Args = std.ArrayListUnmanaged(InternPool.Index);
234237
235238 pub const Key = struct {
236239 func: Fn.Index,
237 args: []TypedValue,
238 };
240 args_index: u32,
241 args_count: u32,
239242
240 pub const Result = struct {
241 val: Value,
242 arena: std.heap.ArenaAllocator.State,
243 pub fn args(key: Key, ctx: MemoizedCall) []InternPool.Index {
244 return ctx.args.items[key.args_index..][0..key.args_count];
245 }
243246 };
244247
245 pub fn eql(ctx: @This(), a: Key, b: Key) bool {
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 }
248 pub const Result = InternPool.Index;
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));
257252 }
258253
259 /// Must match `Sema.GenericCallAdapter.hash`.
260 pub fn hash(ctx: @This(), key: Key) u64 {
254 pub fn hash(ctx: MemoizedCall, key: Key) u64 {
261255 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.
265256 std.hash.autoHash(&hasher, key.func);
266
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
257 std.hash.autoHashStrat(&hasher, key.args(ctx), .Deep);
273258 return hasher.final();
274259 }
275260};
......@@ -883,6 +868,10 @@ pub const Decl = struct {
883868 return decl.ty.abiAlignment(mod);
884869 }
885870 }
871
872 pub fn intern(decl: *Decl, mod: *Module) Allocator.Error!void {
873 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
874 }
886875};
887876
888877/// This state is attached to every Decl when Module emit_h is non-null.
......@@ -3325,15 +3314,8 @@ pub fn deinit(mod: *Module) void {
33253314 mod.test_functions.deinit(gpa);
33263315 mod.align_stack_fns.deinit(gpa);
33273316 mod.monomorphed_funcs.deinit(gpa);
3328
3329 {
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 }
3317 mod.memoized_call_args.deinit(gpa);
3318 mod.memoized_calls.deinit(gpa);
33373319
33383320 mod.decls_free_list.deinit(gpa);
33393321 mod.allocated_decls.deinit(gpa);
......@@ -5894,6 +5876,7 @@ pub fn initNewAnonDecl(
58945876 typed_value: TypedValue,
58955877 name: [:0]u8,
58965878) !void {
5879 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
58975880 errdefer mod.gpa.free(name);
58985881
58995882 const new_decl = mod.declPtr(new_decl_index);
......@@ -6645,7 +6628,7 @@ pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
66456628 if (decl.alive) return;
66466629 decl.alive = true;
66476630
6648 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
6631 try decl.intern(mod);
66496632
66506633 // This is the first time we are marking this Decl alive. We must
66516634 // 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
67496732 }
67506733 }
67516734
6752 // Canonicalize host_size. If it matches the bit size of the pointee type,
6753 // we change it to 0 here. If this causes an assertion trip, the pointee type
6754 // needs to be resolved before calling this ptr() function.
6755 if (info.host_size != 0) {
6756 const elem_bit_size = info.elem_type.toType().bitSize(mod);
6757 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
6758 if (info.host_size * 8 == elem_bit_size) {
6759 canon_info.host_size = 0;
6760 }
6735 switch (info.vector_index) {
6736 // Canonicalize host_size. If it matches the bit size of the pointee type,
6737 // we change it to 0 here. If this causes an assertion trip, the pointee type
6738 // needs to be resolved before calling this ptr() function.
6739 .none => if (info.host_size != 0) {
6740 const elem_bit_size = info.elem_type.toType().bitSize(mod);
6741 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
6742 if (info.host_size * 8 == elem_bit_size) {
6743 canon_info.host_size = 0;
6744 }
6745 },
6746 .runtime => {},
6747 _ => assert(@enumToInt(info.vector_index) < info.host_size),
67616748 }
67626749
67636750 return (try intern(mod, .{ .ptr_type = canon_info })).toType();
src/RangeSet.zig+33-25
......@@ -1,18 +1,18 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const Order = std.math.Order;
34
4const RangeSet = @This();
5const InternPool = @import("InternPool.zig");
56const Module = @import("Module.zig");
7const RangeSet = @This();
68const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
7const Type = @import("type.zig").Type;
8const Value = @import("value.zig").Value;
99
1010ranges: std.ArrayList(Range),
1111module: *Module,
1212
1313pub const Range = struct {
14 first: Value,
15 last: Value,
14 first: InternPool.Index,
15 last: InternPool.Index,
1616 src: SwitchProngSrc,
1717};
1818
......@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {
2929
3030pub fn add(
3131 self: *RangeSet,
32 first: Value,
33 last: Value,
34 ty: Type,
32 first: InternPool.Index,
33 last: InternPool.Index,
3534 src: SwitchProngSrc,
3635) !?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
3742 for (self.ranges.items) |range| {
38 if (last.compareScalar(.gte, range.first, ty, self.module) and
39 first.compareScalar(.lte, range.last, ty, self.module))
43 assert(ty == ip.typeOf(range.first));
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))
4048 {
4149 return range.src; // They overlap.
4250 }
4351 }
52
4453 try self.ranges.append(.{
4554 .first = first,
4655 .last = last,
......@@ -49,30 +58,29 @@ pub fn add(
4958 return null;
5059}
5160
52const LessThanContext = struct { ty: Type, module: *Module };
53
5461/// Assumes a and b do not overlap
55fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {
56 return a.first.compareScalar(.lt, b.first, ctx.ty, ctx.module);
62fn lessThan(mod: *Module, a: Range, b: Range) bool {
63 const ty = mod.intern_pool.typeOf(a.first).toType();
64 return a.first.toValue().compareScalar(.lt, b.first.toValue(), ty, mod);
5765}
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
6072 if (self.ranges.items.len == 0)
6173 return false;
6274
63 const mod = self.module;
64 std.mem.sort(Range, self.ranges.items, LessThanContext{
65 .ty = ty,
66 .module = mod,
67 }, lessThan);
75 std.mem.sort(Range, self.ranges.items, mod, lessThan);
6876
69 if (!self.ranges.items[0].first.eql(first, ty, mod) or
70 !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, mod))
77 if (self.ranges.items[0].first != first or
78 self.ranges.items[self.ranges.items.len - 1].last != last)
7179 {
7280 return false;
7381 }
7482
75 var space: Value.BigIntSpace = undefined;
83 var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
7684
7785 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
7886 defer counter.deinit();
......@@ -83,10 +91,10 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
8391 const prev = self.ranges.items[i];
8492
8593 // prev.last + 1 == cur.first
86 try counter.copy(prev.last.toBigInt(&space, mod));
94 try counter.copy(prev.last.toValue().toBigInt(&space, mod));
8795 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);
9098 if (!cur_start_int.eq(counter.toConst())) {
9199 return false;
92100 }
src/Sema.zig+333-338
......@@ -1609,7 +1609,7 @@ fn analyzeBodyInner(
16091609 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16101610 return err;
16111611 };
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
16141614 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
16151615 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -1630,7 +1630,7 @@ fn analyzeBodyInner(
16301630 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16311631 return err;
16321632 };
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
16351635 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
16361636 const old_runtime_index = block.runtime_index;
......@@ -1663,7 +1663,7 @@ fn analyzeBodyInner(
16631663 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16641664 return err;
16651665 };
1666 if (is_non_err_val.toBool(mod)) {
1666 if (is_non_err_val.toBool()) {
16671667 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
16681668 }
16691669 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -1689,7 +1689,7 @@ fn analyzeBodyInner(
16891689 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16901690 return err;
16911691 };
1692 if (is_non_err_val.toBool(mod)) {
1692 if (is_non_err_val.toBool()) {
16931693 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
16941694 }
16951695 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -1778,12 +1778,11 @@ fn resolveConstBool(
17781778 zir_ref: Zir.Inst.Ref,
17791779 reason: []const u8,
17801780) !bool {
1781 const mod = sema.mod;
17821781 const air_inst = try sema.resolveInst(zir_ref);
17831782 const wanted_type = Type.bool;
17841783 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
17851784 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
1786 return val.toBool(mod);
1785 return val.toBool();
17871786}
17881787
17891788pub fn resolveConstString(
......@@ -2488,7 +2487,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24882487 defer anon_decl.deinit();
24892488 const decl_index = try anon_decl.finish(
24902489 pointee_ty,
2491 Value.undef,
2490 (try mod.intern(.{ .undef = pointee_ty.toIntern() })).toValue(),
24922491 alignment.toByteUnits(0),
24932492 );
24942493 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
......@@ -2611,7 +2610,7 @@ fn coerceResultPtr(
26112610 .@"addrspace" = addr_space,
26122611 });
26132612 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));
26152614 } else {
26162615 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
26172616 }
......@@ -3613,7 +3612,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
36133612
36143613 // Detect if a comptime value simply needs to have its type changed.
36153614 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));
36173616 }
36183617
36193618 return block.addBitCast(const_ptr_ty, alloc);
......@@ -3735,6 +3734,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37353734 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
37363735
37373736 const decl = mod.declPtr(decl_index);
3737 if (iac.is_const) try decl.intern(mod);
37383738 const final_elem_ty = decl.ty;
37393739 const final_ptr_ty = try mod.ptrType(.{
37403740 .elem_type = final_elem_ty.toIntern(),
......@@ -3774,7 +3774,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37743774 // Detect if the value is comptime-known. In such case, the
37753775 // last 3 AIR instructions of the block will look like this:
37763776 //
3777 // %a = interned
3777 // %a = inferred_alloc
37783778 // %b = bitcast(%a)
37793779 // %c = store(%b, %d)
37803780 //
......@@ -3814,22 +3814,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38143814 }
38153815 };
38163816
3817 const const_inst = while (true) {
3817 while (true) {
38183818 if (search_index == 0) break :ct;
38193819 search_index -= 1;
38203820
38213821 const candidate = block.instructions.items[search_index];
3822 if (candidate == ptr_inst) break;
38223823 switch (air_tags[candidate]) {
38233824 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3824 .interned => break candidate,
38253825 else => break :ct,
38263826 }
3827 };
3827 }
38283828
38293829 const store_op = air_datas[store_inst].bin_op;
38303830 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;
38313831 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
38343834 const new_decl_index = d: {
38353835 var anon_decl = try block.startAnonDecl();
......@@ -3850,7 +3850,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38503850 sema.air_instructions.set(ptr_inst, .{
38513851 .tag = .interned,
38523852 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3853 .ty = final_elem_ty.toIntern(),
3853 .ty = final_ptr_ty.toIntern(),
38543854 .addr = .{ .decl = new_decl_index },
38553855 } }) },
38563856 });
......@@ -4707,15 +4707,23 @@ fn zirValidateArrayInit(
47074707 return;
47084708 }
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
47104717 var array_is_comptime = true;
47114718 var first_block_index = block.instructions.items.len;
47124719 var make_runtime = false;
47134720
47144721 // Collect the comptime element values in case the array literal ends up
47154722 // being comptime-known.
4716 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel(mod));
4717 const element_vals = try sema.arena.alloc(InternPool.Index, array_len_s);
4718 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);
4723 const element_vals = try sema.arena.alloc(
4724 InternPool.Index,
4725 try sema.usizeCast(block, init_src, array_len),
4726 );
47194727 const air_tags = sema.air_instructions.items(.tag);
47204728 const air_datas = sema.air_instructions.items(.data);
47214729
......@@ -4727,12 +4735,6 @@ fn zirValidateArrayInit(
47274735 element_vals[i] = opv.toIntern();
47284736 continue;
47294737 }
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 }
47364738 }
47374739
47384740 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
......@@ -4814,11 +4816,6 @@ fn zirValidateArrayInit(
48144816
48154817 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert
48164818 // 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
48224819 block.instructions.shrinkRetainingCapacity(first_block_index);
48234820
48244821 var array_val = try mod.intern(.{ .aggregate = .{
......@@ -6259,7 +6256,7 @@ fn popErrorReturnTrace(
62596256 if (operand != .none) {
62606257 is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand);
62616258 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();
62636260 } else is_non_error = true; // no operand means pop unconditionally
62646261
62656262 if (is_non_error == true) {
......@@ -6873,14 +6870,15 @@ fn analyzeCall(
68736870
68746871 // If it's a comptime function call, we need to memoize it as long as no external
68756872 // 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 };
68776878 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);
68796880 if (is_comptime_call) {
6880 memoized_call_key = .{
6881 .func = module_fn_index,
6882 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
6883 };
6881 try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count);
68846882 delete_memoized_call_key = true;
68856883 }
68866884
......@@ -6916,8 +6914,7 @@ fn analyzeCall(
69166914 uncasted_args,
69176915 is_comptime_call,
69186916 &should_memoize,
6919 memoized_call_key,
6920 func_ty_info.param_types,
6917 mod.typeToFunc(func_ty).?.param_types,
69216918 func,
69226919 &has_comptime_args,
69236920 ) catch |err| switch (err) {
......@@ -6934,8 +6931,7 @@ fn analyzeCall(
69346931 uncasted_args,
69356932 is_comptime_call,
69366933 &should_memoize,
6937 memoized_call_key,
6938 func_ty_info.param_types,
6934 mod.typeToFunc(func_ty).?.param_types,
69396935 func,
69406936 &has_comptime_args,
69416937 );
......@@ -6988,9 +6984,19 @@ fn analyzeCall(
69886984 // bug generating invalid LLVM IR.
69896985 const res2: Air.Inst.Ref = res2: {
69906986 if (should_memoize and is_comptime_call) {
6991 if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| {
6992 break :res2 try sema.addConstant(fn_ret_ty, result.val);
6987 const gop = try mod.memoized_calls.getOrPutContext(
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());
69936997 }
6998 gop.value_ptr.* = .none;
6999 delete_memoized_call_key = false;
69947000 }
69957001
69967002 const new_func_resolved_ty = try mod.funcType(new_fn_info);
......@@ -7049,26 +7055,10 @@ fn analyzeCall(
70497055
70507056 if (should_memoize and is_comptime_call) {
70517057 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7052
7053 // TODO: check whether any external comptime memory was mutated by the
7054 // comptime function call. If so, then do not memoize the call here.
7055 // TODO: re-evaluate whether memoized_calls needs its own arena. I think
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 }
7058 mod.memoized_calls.getPtrContext(
7059 memoized_call_key,
7060 .{ .args = &mod.memoized_call_args },
7061 ).?.* = try result_val.intern(fn_ret_ty, mod);
70727062 }
70737063
70747064 break :res2 result;
......@@ -7214,11 +7204,11 @@ fn analyzeInlineCallArg(
72147204 uncasted_args: []const Air.Inst.Ref,
72157205 is_comptime_call: bool,
72167206 should_memoize: *bool,
7217 memoized_call_key: Module.MemoizedCall.Key,
72187207 raw_param_types: []const InternPool.Index,
72197208 func_inst: Air.Inst.Ref,
72207209 has_comptime_args: *bool,
72217210) !void {
7211 const mod = sema.mod;
72227212 const zir_tags = sema.code.instructions.items(.tag);
72237213 switch (zir_tags[inst]) {
72247214 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
......@@ -7276,11 +7266,8 @@ fn analyzeInlineCallArg(
72767266 try sema.resolveLazyValue(arg_val);
72777267 },
72787268 }
7279 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
7280 memoized_call_key.args[arg_i.*] = .{
7281 .ty = param_ty.toType(),
7282 .val = arg_val,
7283 };
7269 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7270 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(param_ty.toType(), mod));
72847271 } else {
72857272 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
72867273 }
......@@ -7315,11 +7302,8 @@ fn analyzeInlineCallArg(
73157302 try sema.resolveLazyValue(arg_val);
73167303 },
73177304 }
7318 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
7319 memoized_call_key.args[arg_i.*] = .{
7320 .ty = sema.typeOf(uncasted_arg),
7321 .val = arg_val,
7322 };
7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7306 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(sema.typeOf(uncasted_arg), mod));
73237307 } else {
73247308 if (zir_tags[inst] == .param_anytype_comptime) {
73257309 _ = 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
82798263 const int_tag_ty = try enum_tag_ty.intTagType(mod);
82808264
82818265 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));
82838267 }
82848268
82858269 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
83108294 if (dest_ty.isNonexhaustiveEnum(mod)) {
83118295 const int_tag_ty = try dest_ty.intTagType(mod);
83128296 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());
83148301 }
83158302 const msg = msg: {
83168303 const msg = try sema.errMsg(
......@@ -8657,8 +8644,10 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
86578644 const result_ty = operand_ty.errorUnionSet(mod);
86588645
86598646 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8660 assert(val.getError(mod) != null);
8661 return sema.addConstant(result_ty, val);
8647 return sema.addConstant(result_ty, (try mod.intern(.{ .err = .{
8648 .ty = result_ty.toIntern(),
8649 .name = mod.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name,
8650 } })).toValue());
86628651 }
86638652
86648653 try sema.requireRuntimeBlock(block, src, null);
......@@ -10737,7 +10726,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1073710726 block,
1073810727 &range_set,
1073910728 item_ref,
10740 operand_ty,
1074110729 src_node_offset,
1074210730 .{ .scalar = scalar_i },
1074310731 );
......@@ -10760,7 +10748,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1076010748 block,
1076110749 &range_set,
1076210750 item_ref,
10763 operand_ty,
1076410751 src_node_offset,
1076510752 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
1076610753 );
......@@ -10778,7 +10765,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1077810765 &range_set,
1077910766 item_first,
1078010767 item_last,
10781 operand_ty,
1078210768 src_node_offset,
1078310769 .{ .range = .{ .prong = multi_i, .item = range_i } },
1078410770 );
......@@ -10792,7 +10778,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1079210778 if (operand_ty.zigTypeTag(mod) == .Int) {
1079310779 const min_int = try operand_ty.minInt(mod, operand_ty);
1079410780 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())) {
1079610782 if (special_prong == .@"else") {
1079710783 return sema.fail(
1079810784 block,
......@@ -10894,11 +10880,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1089410880 );
1089510881 }
1089610882
10897 var seen_values = ValueSrcMap.initContext(gpa, .{
10898 .ty = operand_ty,
10899 .mod = mod,
10900 });
10901 defer seen_values.deinit();
10883 var seen_values = ValueSrcMap{};
10884 defer seen_values.deinit(gpa);
1090210885
1090310886 var extra_index: usize = special.end;
1090410887 {
......@@ -11664,10 +11647,10 @@ const RangeSetUnhandledIterator = struct {
1166411647 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
1166511648 }
1166611649 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)) {
1166811651 return it.cur;
1166911652 }
11670 it.cur = it.ranges[it.range_i].last;
11653 it.cur = it.ranges[it.range_i].last.toValue();
1167111654 }
1167211655 if (!it.first) {
1167311656 it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
......@@ -11687,16 +11670,15 @@ fn resolveSwitchItemVal(
1168711670 switch_node_offset: i32,
1168811671 switch_prong_src: Module.SwitchProngSrc,
1168911672 range_expand: Module.SwitchProngSrc.RangeExpand,
11690) CompileError!TypedValue {
11673) CompileError!InternPool.Index {
1169111674 const mod = sema.mod;
1169211675 const item = try sema.resolveInst(item_ref);
11693 const item_ty = sema.typeOf(item);
1169411676 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
1169511677 // Only if we know for sure we need to report a compile error do we resolve the
1169611678 // full source locations.
1169711679 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {
1169811680 try sema.resolveLazyValue(val);
11699 return TypedValue{ .ty = item_ty, .val = val };
11681 return val.toIntern();
1170011682 } else |err| switch (err) {
1170111683 error.NeededSourceLocation => {
1170211684 const src = switch_prong_src.resolve(mod, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand);
......@@ -11713,18 +11695,17 @@ fn validateSwitchRange(
1171311695 range_set: *RangeSet,
1171411696 first_ref: Zir.Inst.Ref,
1171511697 last_ref: Zir.Inst.Ref,
11716 operand_ty: Type,
1171711698 src_node_offset: i32,
1171811699 switch_prong_src: Module.SwitchProngSrc,
1171911700) CompileError!void {
1172011701 const mod = sema.mod;
11721 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
11722 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
11723 if (first_val.compareScalar(.gt, last_val, operand_ty, mod)) {
11702 const first = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first);
11703 const last = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last);
11704 if (first.toValue().compareScalar(.gt, last.toValue(), mod.intern_pool.typeOf(first).toType(), mod)) {
1172411705 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first);
1172511706 return sema.fail(block, src, "range start value is greater than the end value", .{});
1172611707 }
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);
1172811709 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1172911710}
1173011711
......@@ -11733,12 +11714,11 @@ fn validateSwitchItem(
1173311714 block: *Block,
1173411715 range_set: *RangeSet,
1173511716 item_ref: Zir.Inst.Ref,
11736 operand_ty: Type,
1173711717 src_node_offset: i32,
1173811718 switch_prong_src: Module.SwitchProngSrc,
1173911719) CompileError!void {
11740 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11741 const maybe_prev_src = try range_set.add(item_val, item_val, operand_ty, switch_prong_src);
11720 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11721 const maybe_prev_src = try range_set.add(item, item, switch_prong_src);
1174211722 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1174311723}
1174411724
......@@ -11751,9 +11731,11 @@ fn validateSwitchItemEnum(
1175111731 src_node_offset: i32,
1175211732 switch_prong_src: Module.SwitchProngSrc,
1175311733) CompileError!void {
11754 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11755 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
11756 const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);
11734 const ip = &sema.mod.intern_pool;
11735 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
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);
1175711739 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1175811740 };
1175911741 const maybe_prev_src = seen_fields[field_index];
......@@ -11770,9 +11752,9 @@ fn validateSwitchItemError(
1177011752 switch_prong_src: Module.SwitchProngSrc,
1177111753) CompileError!void {
1177211754 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);
1177411756 // 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);
1177611758 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
1177711759 prev.value
1177811760 else
......@@ -11822,8 +11804,8 @@ fn validateSwitchItemBool(
1182211804 switch_prong_src: Module.SwitchProngSrc,
1182311805) CompileError!void {
1182411806 const mod = sema.mod;
11825 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11826 if (item_val.toBool(mod)) {
11807 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11808 if (item.toValue().toBool()) {
1182711809 true_count.* += 1;
1182811810 } else {
1182911811 false_count.* += 1;
......@@ -11835,7 +11817,7 @@ fn validateSwitchItemBool(
1183511817 }
1183611818}
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
1184011822fn validateSwitchItemSparse(
1184111823 sema: *Sema,
......@@ -11845,8 +11827,8 @@ fn validateSwitchItemSparse(
1184511827 src_node_offset: i32,
1184611828 switch_prong_src: Module.SwitchProngSrc,
1184711829) CompileError!void {
11848 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11849 const kv = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;
11830 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11831 const kv = (try seen_values.fetchPut(sema.gpa, item, switch_prong_src)) orelse return;
1185011832 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);
1185111833}
1185211834
......@@ -13047,8 +13029,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1304713029 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
1304813030
1304913031 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
13050 const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null);
13051
1305213032 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
1305313033 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
1305413034 else
......@@ -13065,7 +13045,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1306513045 } });
1306613046 }
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);
1306913049 var elem_i: usize = 0;
1307013050 while (elem_i < result_len) {
1307113051 var lhs_i: usize = 0;
......@@ -13075,9 +13055,6 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1307513055 elem_i += 1;
1307613056 }
1307713057 }
13078 if (lhs_info.sentinel) |sent_val| {
13079 element_vals[result_len] = sent_val.toIntern();
13080 }
1308113058 break :v try mod.intern(.{ .aggregate = .{
1308213059 .ty = result_ty.toIntern(),
1308313060 .storage = .{ .elems = element_vals },
......@@ -14896,13 +14873,18 @@ fn analyzeArithmetic(
1489614873 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
1489714874 else => unreachable,
1489814875 };
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 };
1489914881 if (maybe_lhs_val) |lhs_val| {
1490014882 if (!lhs_val.isUndef(mod)) {
1490114883 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
1490214884 const zero_val = try sema.splat(resolved_type, scalar_zero);
1490314885 return sema.addConstant(resolved_type, zero_val);
1490414886 }
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)) {
1490614888 return casted_rhs;
1490714889 }
1490814890 }
......@@ -14916,7 +14898,7 @@ fn analyzeArithmetic(
1491614898 const zero_val = try sema.splat(resolved_type, scalar_zero);
1491714899 return sema.addConstant(resolved_type, zero_val);
1491814900 }
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)) {
1492014902 return casted_lhs;
1492114903 }
1492214904 if (maybe_lhs_val) |lhs_val| {
......@@ -15524,7 +15506,7 @@ fn cmpSelf(
1552415506 } else {
1552515507 if (resolved_type.zigTypeTag(mod) == .Bool) {
1552615508 // 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);
1552815510 }
1552915511 break :src rhs_src;
1553015512 }
......@@ -15534,7 +15516,7 @@ fn cmpSelf(
1553415516 if (resolved_type.zigTypeTag(mod) == .Bool) {
1553515517 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {
1553615518 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);
1553815520 }
1553915521 }
1554015522 break :src lhs_src;
......@@ -15840,6 +15822,7 @@ fn zirBuiltinSrc(
1584015822 break :blk try mod.intern(.{ .ptr = .{
1584115823 .ty = .slice_const_u8_sentinel_0_type,
1584215824 .addr = .{ .decl = new_decl },
15825 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1584315826 } });
1584415827 };
1584515828
......@@ -15864,6 +15847,7 @@ fn zirBuiltinSrc(
1586415847 break :blk try mod.intern(.{ .ptr = .{
1586515848 .ty = .slice_const_u8_sentinel_0_type,
1586615849 .addr = .{ .decl = new_decl },
15850 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
1586715851 } });
1586815852 };
1586915853
......@@ -16314,6 +16298,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1631416298 break :v try mod.intern(.{ .ptr = .{
1631516299 .ty = slice_errors_ty.toIntern(),
1631616300 .addr = .{ .decl = new_decl },
16301 .len = (try mod.intValue(Type.usize, vals.len)).toIntern(),
1631716302 } });
1631816303 } else .none;
1631916304 const errors_val = try mod.intern(.{ .opt = .{
......@@ -16438,6 +16423,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1643816423 .is_const = true,
1643916424 })).toIntern(),
1644016425 .addr = .{ .decl = new_decl },
16426 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
1644116427 } });
1644216428 };
1644316429
......@@ -17141,7 +17127,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1714117127 if (try sema.resolveMaybeUndefVal(operand)) |val| {
1714217128 return if (val.isUndef(mod))
1714317129 sema.addConstUndef(Type.bool)
17144 else if (val.toBool(mod))
17130 else if (val.toBool())
1714517131 Air.Inst.Ref.bool_false
1714617132 else
1714717133 Air.Inst.Ref.bool_true;
......@@ -17169,9 +17155,9 @@ fn zirBoolBr(
1716917155 const gpa = sema.gpa;
1717017156
1717117157 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()) {
1717317159 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()) {
1717517161 return Air.Inst.Ref.bool_false;
1717617162 }
1717717163 // comptime-known left-hand side. No need for a block here; the result
......@@ -17215,9 +17201,9 @@ fn zirBoolBr(
1721517201 const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
1721617202 if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
1721717203 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()) {
1721917205 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()) {
1722117207 return Air.Inst.Ref.bool_false;
1722217208 }
1722317209 }
......@@ -17371,7 +17357,7 @@ fn zirCondbr(
1737117357 const cond = try sema.coerce(parent_block, Type.bool, uncasted_cond, cond_src);
1737217358
1737317359 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
1737617362 try sema.maybeErrorUnwrapCondbr(parent_block, body, extra.data.condition, cond_src);
1737717363 // 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!
1744417430 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
1744517431 if (is_non_err != .none) {
1744617432 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()) {
1744817434 return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false);
1744917435 }
1745017436 // 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
1749117477 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
1749217478 if (is_non_err != .none) {
1749317479 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()) {
1749517481 return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false);
1749617482 }
1749717483 // 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
1885818844 const operand = try sema.resolveInst(inst_data.operand);
1885918845 if (try sema.resolveMaybeUndefVal(operand)) |val| {
1886018846 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));
1886218848 return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
1886318849 }
1886418850 return block.addUnOp(.bool_to_int, operand);
......@@ -19171,12 +19157,12 @@ fn zirReify(
1917119157
1917219158 const ty = try mod.ptrType(.{
1917319159 .size = ptr_size,
19174 .is_const = is_const_val.toBool(mod),
19175 .is_volatile = is_volatile_val.toBool(mod),
19160 .is_const = is_const_val.toBool(),
19161 .is_volatile = is_volatile_val.toBool(),
1917619162 .alignment = abi_align,
1917719163 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),
1917819164 .elem_type = elem_ty.toIntern(),
19179 .is_allowzero = is_allowzero_val.toBool(mod),
19165 .is_allowzero = is_allowzero_val.toBool(),
1918019166 .sentinel = actual_sentinel,
1918119167 });
1918219168 return sema.addType(ty);
......@@ -19267,7 +19253,7 @@ fn zirReify(
1926719253 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
1926819254 }
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());
1927119257 },
1927219258 .Enum => {
1927319259 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
......@@ -19305,7 +19291,7 @@ fn zirReify(
1930519291 .namespace = .none,
1930619292 .fields_len = fields_len,
1930719293 .has_values = true,
19308 .tag_mode = if (!is_exhaustive_val.toBool(mod))
19294 .tag_mode = if (!is_exhaustive_val.toBool())
1930919295 .nonexhaustive
1931019296 else
1931119297 .explicit,
......@@ -19619,12 +19605,12 @@ fn zirReify(
1961919605 const return_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex("return_type").?);
1962019606 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();
1962319609 if (is_generic) {
1962419610 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
1962519611 }
1962619612
19627 const is_var_args = is_var_args_val.toBool(mod);
19613 const is_var_args = is_var_args_val.toBool();
1962819614 const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val);
1962919615 if (is_var_args and cc != .C) {
1963019616 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
......@@ -19653,9 +19639,9 @@ fn zirReify(
1965319639 const arg_val = arg.castTag(.aggregate).?.data;
1965419640 // TODO use reflection instead of magic numbers here
1965519641 // is_generic: bool,
19656 const arg_is_generic = arg_val[0].toBool(mod);
19642 const arg_is_generic = arg_val[0].toBool();
1965719643 // is_noalias: bool,
19658 const arg_is_noalias = arg_val[1].toBool(mod);
19644 const arg_is_noalias = arg_val[1].toBool();
1965919645 // type: ?type,
1966019646 const param_type_opt_val = arg_val[2];
1966119647
......@@ -19783,9 +19769,9 @@ fn reifyStruct(
1978319769
1978419770 if (layout == .Packed) {
1978519771 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", .{});
1978719773 }
19788 if (layout == .Extern and is_comptime_val.toBool(mod)) {
19774 if (layout == .Extern and is_comptime_val.toBool()) {
1978919775 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});
1979019776 }
1979119777
......@@ -19827,7 +19813,7 @@ fn reifyStruct(
1982719813 opt_val;
1982819814 break :blk try payload_val.copy(new_decl_arena_allocator);
1982919815 } 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) {
1983119817 return sema.fail(block, src, "comptime field without default initialization value", .{});
1983219818 }
1983319819
......@@ -19836,7 +19822,7 @@ fn reifyStruct(
1983619822 .ty = field_ty,
1983719823 .abi_align = abi_align,
1983819824 .default_val = default_val,
19839 .is_comptime = is_comptime_val.toBool(mod),
19825 .is_comptime = is_comptime_val.toBool(),
1984019826 .offset = undefined,
1984119827 };
1984219828
......@@ -20400,13 +20386,17 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2040020386 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) {
2040120387 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});
2040220388 }
20403 if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) {
20404 return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{
20405 .ty = dest_ty.toIntern(),
20406 .val = operand_val.toIntern(),
20407 } })).toValue());
20408 }
20409 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty));
20389 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(switch (mod.intern_pool.indexToKey(operand_val.toIntern())) {
20390 .undef, .ptr => operand_val,
20391 .opt => |opt| switch (opt.val) {
20392 .none => if (dest_ty.ptrAllowsZero(mod))
20393 Value.zero_usize
20394 else
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));
2041020400 }
2041120401
2041220402 try sema.requireRuntimeBlock(block, src, null);
......@@ -20534,10 +20524,10 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2053420524 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {
2053520525 if (val.isUndef(mod)) return sema.addConstUndef(dest_ty);
2053620526 if (!is_vector) {
20537 return sema.addConstant(
20538 dest_ty,
20527 return sema.addConstant(dest_ty, try mod.getCoerced(
2053920528 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod),
20540 );
20529 dest_ty,
20530 ));
2054120531 }
2054220532 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));
2054320533 for (elems, 0..) |*elem, i| {
......@@ -21410,7 +21400,10 @@ fn zirCmpxchg(
2141021400
2141121401 // special case zero bit types
2141221402 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());
2141421407 }
2141521408
2141621409 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
......@@ -21633,8 +21626,7 @@ fn analyzeShuffle(
2163321626 .{ b_len, b_src, b_ty },
2163421627 };
2163521628
21636 var i: usize = 0;
21637 while (i < mask_len) : (i += 1) {
21629 for (0..@intCast(usize, mask_len)) |i| {
2163821630 const elem = try mask.elemValue(sema.mod, i);
2163921631 if (elem.isUndef(mod)) continue;
2164021632 const int = elem.toSignedInt(mod);
......@@ -21670,7 +21662,7 @@ fn analyzeShuffle(
2167021662 if (try sema.resolveMaybeUndefVal(a)) |a_val| {
2167121663 if (try sema.resolveMaybeUndefVal(b)) |b_val| {
2167221664 const values = try sema.arena.alloc(InternPool.Index, mask_len);
21673 for (values) |*value| {
21665 for (values, 0..) |*value, i| {
2167421666 const mask_elem_val = try mask.elemValue(sema.mod, i);
2167521667 if (mask_elem_val.isUndef(mod)) {
2167621668 value.* = try mod.intern(.{ .undef = elem_ty.toIntern() });
......@@ -21698,11 +21690,10 @@ fn analyzeShuffle(
2169821690 const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));
2169921691
2170021692 const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);
21701 i = 0;
21702 while (i < min_len) : (i += 1) {
21693 for (@intCast(usize, 0)..@intCast(usize, min_len)) |i| {
2170321694 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, i)).toIntern();
2170421695 }
21705 while (i < max_len) : (i += 1) {
21696 for (@intCast(usize, min_len)..@intCast(usize, max_len)) |i| {
2170621697 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, -1)).toIntern();
2170721698 }
2170821699 const expand_mask = try mod.intern(.{ .aggregate = .{
......@@ -21783,7 +21774,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2178321774 const elems = try sema.gpa.alloc(InternPool.Index, vec_len);
2178421775 for (elems, 0..) |*elem, i| {
2178521776 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();
2178721778 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);
2178821779 }
2178921780
......@@ -22853,15 +22844,15 @@ fn zirVarExtended(
2285322844 else
2285422845 uncasted_init;
2285522846
22856 break :blk (try sema.resolveMaybeUndefVal(init)) orelse
22857 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known");
22858 } else Value.@"unreachable";
22847 break :blk ((try sema.resolveMaybeUndefVal(init)) orelse
22848 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known")).toIntern();
22849 } else .none;
2285922850
2286022851 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2286122852
2286222853 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
2286322854 .ty = var_ty.toIntern(),
22864 .init = init_val.toIntern(),
22855 .init = init_val,
2286522856 .decl = sema.owner_decl_index,
2286622857 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
2286722858 sema.gpa,
......@@ -23284,7 +23275,7 @@ fn resolveExternOptions(
2328423275 .name = name,
2328523276 .library_name = library_name,
2328623277 .linkage = linkage,
23287 .is_thread_local = is_thread_local_val.toBool(mod),
23278 .is_thread_local = is_thread_local_val.toBool(),
2328823279 };
2328923280}
2329023281
......@@ -26190,7 +26181,7 @@ fn coerceExtra(
2619026181 .addr = .{ .int = (if (dest_info.@"align" != 0)
2619126182 try mod.intValue(Type.usize, dest_info.@"align")
2619226183 else
26193 try dest_info.pointee_type.lazyAbiAlignment(mod)).toIntern() },
26184 try mod.getCoerced(try dest_info.pointee_type.lazyAbiAlignment(mod), Type.usize)).toIntern() },
2619426185 .len = (try mod.intValue(Type.usize, 0)).toIntern(),
2619526186 } })).toValue());
2619626187 }
......@@ -27785,7 +27776,7 @@ fn beginComptimePtrMutation(
2778527776 const payload = try arena.create(Value.Payload.SubValue);
2778627777 payload.* = .{
2778727778 .base = .{ .tag = .eu_payload },
27788 .data = Value.undef,
27779 .data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
2778927780 };
2779027781
2779127782 val_ptr.* = Value.initPayload(&payload.base);
......@@ -27824,7 +27815,7 @@ fn beginComptimePtrMutation(
2782427815 const payload = try arena.create(Value.Payload.SubValue);
2782527816 payload.* = .{
2782627817 .base = .{ .tag = .opt_payload },
27827 .data = Value.undef,
27818 .data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
2782827819 };
2782927820
2783027821 val_ptr.* = Value.initPayload(&payload.base);
......@@ -27898,30 +27889,6 @@ fn beginComptimePtrMutation(
2789827889 }
2789927890
2790027891 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 },
2792527892 .none => switch (val_ptr.tag()) {
2792627893 .bytes => {
2792727894 // An array is memory-optimized to store a slice of bytes, but we are about
......@@ -27999,7 +27966,33 @@ fn beginComptimePtrMutation(
2799927966
2800027967 else => unreachable,
2800127968 },
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 },
2800327996 }
2800427997 },
2800527998 else => {
......@@ -28052,83 +28045,6 @@ fn beginComptimePtrMutation(
2805228045 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);
2805328046 switch (parent.pointee) {
2805428047 .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 },
2813228048 .empty_struct => {
2813328049 const duped = try sema.arena.create(Value);
2813428050 duped.* = val_ptr.*;
......@@ -28210,10 +28126,92 @@ fn beginComptimePtrMutation(
2821028126
2821128127 else => unreachable,
2821228128 },
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 },
2821428213 else => unreachable,
2821528214 },
28216 else => unreachable,
2821728215 },
2821828216 .reinterpret => |reinterpret| {
2821928217 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);
......@@ -28370,18 +28368,22 @@ fn beginComptimePtrLoad(
2837028368 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
2837128369 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
2837228370 if (coerce_in_mem_ok) {
28373 const payload_val = switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
28374 .error_union => |error_union| switch (error_union.val) {
28375 .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),
28376 .payload => |payload| payload,
28377 },
28378 .opt => |opt| switch (opt.val) {
28379 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28380 else => opt.val,
28381 },
28382 else => unreachable,
28371 const payload_val = switch (tv.val.ip_index) {
28372 .none => tv.val.cast(Value.Payload.SubValue).?.data,
28373 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),
28374 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
28375 .error_union => |error_union| switch (error_union.val) {
28376 .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),
28377 .payload => |payload| payload,
28378 },
28379 .opt => |opt| switch (opt.val) {
28380 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28381 else => opt.val,
28382 },
28383 else => unreachable,
28384 }.toValue(),
2838328385 };
28384 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val.toValue() };
28386 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
2838528387 break :blk deref;
2838628388 }
2838728389 }
......@@ -28960,7 +28962,7 @@ fn coerceArrayLike(
2896028962 if (in_memory_result == .ok) {
2896128963 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
2896228964 // 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));
2896428966 }
2896528967 try sema.requireRuntimeBlock(block, inst_src, null);
2896628968 return block.addBitCast(dest_ty, inst);
......@@ -29024,7 +29026,7 @@ fn coerceTupleToArray(
2902429026 return sema.failWithOwnedErrorMsg(msg);
2902529027 }
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);
2902829030 const element_vals = try sema.arena.alloc(InternPool.Index, dest_elems);
2902929031 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems);
2903029032 const dest_elem_ty = dest_ty.childType(mod);
......@@ -29430,7 +29432,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
2943029432 const ptr_ty = try mod.ptrType(.{
2943129433 .elem_type = decl_tv.ty.toIntern(),
2943229434 .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,
2943429436 .address_space = decl.@"addrspace",
2943529437 });
2943629438 if (analyze_fn_body) {
......@@ -29513,7 +29515,7 @@ fn analyzeLoad(
2951329515
2951429516 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
2951529517 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));
2951729519 }
2951829520 }
2951929521
......@@ -32610,8 +32612,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3261032612
3261132613 var int_tag_ty: Type = undefined;
3261232614 var enum_field_names: []InternPool.NullTerminatedString = &.{};
32613 var enum_field_vals: []InternPool.Index = &.{};
32614 var enum_field_vals_map: std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false) = .{};
32615 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
3261532616 var explicit_tags_seen: []bool = &.{};
3261632617 var explicit_enum_info: ?InternPool.Key.EnumType = null;
3261732618 if (tag_type_ref != .none) {
......@@ -32638,9 +32639,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3263832639 };
3263932640 return sema.failWithOwnedErrorMsg(msg);
3264032641 }
32642 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
32643 try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len);
3264132644 }
32642 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
32643 enum_field_vals = try sema.arena.alloc(InternPool.Index, fields_len);
3264432645 } else {
3264532646 // The provided type is the enum tag type.
3264632647 union_obj.tag_ty = provided_ty;
......@@ -32712,8 +32713,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3271232713 break :blk try sema.resolveInst(tag_ref);
3271332714 } else .none;
3271432715
32715 if (enum_field_vals.len != 0) {
32716 const copied_val = if (tag_ref != .none) blk: {
32716 if (enum_field_vals.capacity() > 0) {
32717 const enum_tag_val = if (tag_ref != .none) blk: {
3271732718 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
3271832719 error.NeededSourceLocation => {
3271932720 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
......@@ -32737,16 +32738,12 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3273732738
3273832739 break :blk val;
3273932740 };
32740 enum_field_vals[field_i] = copied_val.toIntern();
32741 const gop = enum_field_vals_map.getOrPutAssumeCapacityContext(copied_val, .{
32742 .ty = int_tag_ty,
32743 .mod = mod,
32744 });
32741 const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern());
3274532742 if (gop.found_existing) {
3274632743 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
3274732744 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
3274832745 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)});
3275032747 errdefer msg.destroy(gpa);
3275132748 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
3275232749 break :msg msg;
......@@ -32907,8 +32904,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3290732904 };
3290832905 return sema.failWithOwnedErrorMsg(msg);
3290932906 }
32910 } else if (enum_field_vals.len != 0) {
32911 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals, union_obj);
32907 } else if (enum_field_vals.count() > 0) {
32908 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_obj);
3291232909 } else {
3291332910 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_obj);
3291432911 }
......@@ -33180,8 +33177,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3318033177 .struct_type => |struct_type| {
3318133178 const resolved_ty = try sema.resolveTypeFields(ty);
3318233179 if (mod.structPtrUnwrap(struct_type.index)) |s| {
33183 for (s.fields.values(), 0..) |field, i| {
33184 if (field.is_comptime) continue;
33180 const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());
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 }
3318533186 if (field.ty.eql(resolved_ty, sema.mod)) {
3318633187 const msg = try Module.ErrorMsg.create(
3318733188 sema.gpa,
......@@ -33192,24 +33193,25 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3319233193 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
3319333194 return sema.failWithOwnedErrorMsg(msg);
3319433195 }
33195 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33196 return null;
33197 }
33196 if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {
33197 field_val.* = try field_opv.intern(field.ty, mod);
33198 } else return null;
3319833199 }
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();
3319933207 }
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 think
33204 // we should use a temporary allocator to construct an aggregate that
33205 // is populated with the comptime values and then intern that value here.
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 // In this case the struct has no fields at all and
33210 // therefore has one possible value.
33211 return (try mod.intern(.{ .aggregate = .{
3320933212 .ty = ty.toIntern(),
3321033213 .storage = .{ .elems = &.{} },
33211 } });
33212 return empty.toValue();
33214 } })).toValue();
3321333215 },
3321433216
3321533217 .anon_struct_type => |tuple| {
......@@ -33268,20 +33270,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3326833270 },
3326933271 .auto, .explicit => switch (enum_type.names.len) {
3327033272 0 => return Value.@"unreachable",
33271 1 => {
33272 if (enum_type.values.len == 0) {
33273 const only = try mod.intern(.{ .enum_tag = .{
33274 .ty = ty.toIntern(),
33275 .int = try mod.intern(.{ .int = .{
33276 .ty = enum_type.tag_ty,
33277 .storage = .{ .u64 = 0 },
33278 } }),
33279 } });
33280 return only.toValue();
33281 } else {
33282 return enum_type.values[0].toValue();
33283 }
33284 },
33273 1 => return try mod.getCoerced((if (enum_type.values.len == 0)
33274 try mod.intern(.{ .int = .{
33275 .ty = enum_type.tag_ty,
33276 .storage = .{ .u64 = 0 },
33277 } })
33278 else
33279 enum_type.values[0]).toValue(), ty),
3328533280 else => return null,
3328633281 },
3328733282 },
......@@ -33427,7 +33422,7 @@ fn analyzeComptimeAlloc(
3342733422 // There will be stores before the first load, but they may be to sub-elements or
3342833423 // sub-fields. So we need to initialize with undef to allow the mechanism to expand
3342933424 // into fields/elements and have those overridden with stored values.
33430 Value.undef,
33425 (try sema.mod.intern(.{ .undef = var_type.toIntern() })).toValue(),
3343133426 alignment,
3343233427 );
3343333428 const decl = sema.mod.declPtr(decl_index);
......@@ -34028,16 +34023,16 @@ fn intSubWithOverflow(
3402834023 const lhs_elem = try lhs.elemValue(sema.mod, i);
3402934024 const rhs_elem = try rhs.elemValue(sema.mod, i);
3403034025 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);
3403234027 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
3403334028 }
3403434029 return Value.OverflowArithmeticResult{
3403534030 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34036 .ty = ty.toIntern(),
34031 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
3403734032 .storage = .{ .elems = overflowed_data },
3403834033 } })).toValue(),
3403934034 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34040 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34035 .ty = ty.toIntern(),
3404134036 .storage = .{ .elems = result_data },
3404234037 } })).toValue(),
3404334038 };
......@@ -34066,7 +34061,7 @@ fn intSubWithOverflowScalar(
3406634061 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
3406734062 const wrapped_result = try mod.intValue_big(ty, result_bigint.toConst());
3406834063 return Value.OverflowArithmeticResult{
34069 .overflow_bit = Value.boolToInt(overflowed),
34064 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3407034065 .wrapped_result = wrapped_result,
3407134066 };
3407234067}
......@@ -34273,16 +34268,16 @@ fn intAddWithOverflow(
3427334268 const lhs_elem = try lhs.elemValue(sema.mod, i);
3427434269 const rhs_elem = try rhs.elemValue(sema.mod, i);
3427534270 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);
3427734272 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
3427834273 }
3427934274 return Value.OverflowArithmeticResult{
3428034275 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34281 .ty = ty.toIntern(),
34276 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
3428234277 .storage = .{ .elems = overflowed_data },
3428334278 } })).toValue(),
3428434279 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34285 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34280 .ty = ty.toIntern(),
3428634281 .storage = .{ .elems = result_data },
3428734282 } })).toValue(),
3428834283 };
......@@ -34311,7 +34306,7 @@ fn intAddWithOverflowScalar(
3431134306 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
3431234307 const result = try mod.intValue_big(ty, result_bigint.toConst());
3431334308 return Value.OverflowArithmeticResult{
34314 .overflow_bit = Value.boolToInt(overflowed),
34309 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3431534310 .wrapped_result = result,
3431634311 };
3431734312}
......@@ -34384,7 +34379,7 @@ fn compareVector(
3438434379 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);
3438534380 }
3438634381 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(),
3438834383 .storage = .{ .elems = result_data },
3438934384 } })).toValue();
3439034385}
src/codegen.zig+1-1
......@@ -957,7 +957,7 @@ pub fn genTypedValue(
957957 }
958958 },
959959 .Bool => {
960 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool(mod)) });
960 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
961961 },
962962 .Optional => {
963963 if (typed_value.ty.isPtrLikeOptional(mod)) {
src/codegen/llvm.zig+19-15
......@@ -2003,7 +2003,7 @@ pub const Object = struct {
20032003 mod.intern_pool.stringToSlice(tuple.names[i])
20042004 else
20052005 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
20082008 try di_fields.append(gpa, dib.createMemberType(
20092009 fwd_decl.toScope(),
......@@ -2461,13 +2461,13 @@ pub const DeclGen = struct {
24612461 if (decl.@"linksection") |section| global.setSection(section);
24622462 assert(decl.has_tv);
24632463 const init_val = if (decl.val.getVariable(mod)) |variable| init_val: {
2464 break :init_val variable.init.toValue();
2464 break :init_val variable.init;
24652465 } else init_val: {
24662466 global.setGlobalConstant(.True);
2467 break :init_val decl.val;
2467 break :init_val decl.val.toIntern();
24682468 };
2469 if (init_val.toIntern() != .unreachable_value) {
2470 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val });
2469 if (init_val != .none) {
2470 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() });
24712471 if (global.globalGetValueType() == llvm_init.typeOf()) {
24722472 global.setInitializer(llvm_init);
24732473 } else {
......@@ -2748,7 +2748,7 @@ pub const DeclGen = struct {
27482748 if (std.debug.runtime_safety and false) check: {
27492749 if (t.zigTypeTag(mod) == .Opaque) break :check;
27502750 if (!t.hasRuntimeBits(mod)) break :check;
2751 if (!llvm_ty.isSized().toBool(mod)) break :check;
2751 if (!llvm_ty.isSized().toBool()) break :check;
27522752
27532753 const zig_size = t.abiSize(mod);
27542754 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);
......@@ -3239,7 +3239,7 @@ pub const DeclGen = struct {
32393239 => unreachable, // non-runtime values
32403240 .false, .true => {
32413241 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();
32433243 },
32443244 },
32453245 .variable,
......@@ -3522,15 +3522,19 @@ pub const DeclGen = struct {
35223522 const elem_ty = vector_type.child.toType();
35233523 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len);
35243524 defer dg.gpa.free(llvm_elems);
3525 const llvm_i8 = dg.context.intType(8);
35253526 for (llvm_elems, 0..) |*llvm_elem, i| {
3526 llvm_elem.* = try dg.lowerValue(.{
3527 .ty = elem_ty,
3528 .val = switch (aggregate.storage) {
3529 .bytes => unreachable,
3530 .elems => |elems| elems[i],
3531 .repeated_elem => |elem| elem,
3532 }.toValue(),
3533 });
3527 llvm_elem.* = switch (aggregate.storage) {
3528 .bytes => |bytes| llvm_i8.constInt(bytes[i], .False),
3529 .elems => |elems| try dg.lowerValue(.{
3530 .ty = elem_ty,
3531 .val = elems[i].toValue(),
3532 }),
3533 .repeated_elem => |elem| try dg.lowerValue(.{
3534 .ty = elem_ty,
3535 .val = elem.toValue(),
3536 }),
3537 };
35343538 }
35353539 return llvm.constVector(
35363540 llvm_elems.ptr,
src/codegen/spirv.zig+3-47
......@@ -654,7 +654,7 @@ pub const DeclGen = struct {
654654 .@"unreachable",
655655 .generic_poison,
656656 => unreachable, // non-runtime values
657 .false, .true => try self.addConstBool(val.toBool(mod)),
657 .false, .true => try self.addConstBool(val.toBool()),
658658 },
659659 .variable,
660660 .extern_func,
......@@ -974,7 +974,6 @@ pub const DeclGen = struct {
974974 /// This function should only be called during function code generation.
975975 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {
976976 const mod = self.module;
977 const target = self.getTarget();
978977 const result_ty_ref = try self.resolveType(ty, repr);
979978
980979 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
......@@ -991,51 +990,8 @@ pub const DeclGen = struct {
991990 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));
992991 }
993992 },
994 .Bool => switch (repr) {
995 .direct => return try self.spv.constBool(result_ty_ref, val.toBool(mod)),
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);
993 .Bool => {
994 @compileError("TODO merge conflict failure");
1039995 },
1040996 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1041997 // OpVariable that is not really required.
src/type.zig+21-14
......@@ -2481,25 +2481,32 @@ pub const Type = struct {
24812481 .struct_type => |struct_type| {
24822482 if (mod.structPtrUnwrap(struct_type.index)) |s| {
24832483 assert(s.haveFieldTypes());
2484 for (s.fields.values()) |field| {
2485 if (field.is_comptime) continue;
2486 if ((try field.ty.onePossibleValue(mod)) != null) continue;
2487 return null;
2484 const field_vals = try mod.gpa.alloc(InternPool.Index, s.fields.count());
2485 defer mod.gpa.free(field_vals);
2486 for (field_vals, s.fields.values()) |*field_val, field| {
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;
24882494 }
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();
24892502 }
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 think
2494 // we should use a temporary allocator to construct an aggregate that
2495 // is populated with the comptime values and then intern that value here.
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 = .{
2504 // In this case the struct has no fields at all and
2505 // therefore has one possible value.
2506 return (try mod.intern(.{ .aggregate = .{
24992507 .ty = ty.toIntern(),
25002508 .storage = .{ .elems = &.{} },
2501 } });
2502 return empty.toValue();
2509 } })).toValue();
25032510 },
25042511
25052512 .anon_struct_type => |tuple| {
src/value.zig+47-153
......@@ -385,7 +385,7 @@ pub const Value = struct {
385385 } });
386386 },
387387 .aggregate => {
388 const old_elems = val.castTag(.aggregate).?.data;
388 const old_elems = val.castTag(.aggregate).?.data[0..ty.arrayLen(mod)];
389389 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
390390 defer mod.gpa.free(new_elems);
391391 const ty_key = mod.intern_pool.indexToKey(ty.toIntern());
......@@ -656,7 +656,7 @@ pub const Value = struct {
656656 };
657657 }
658658
659 pub fn toBool(val: Value, _: *const Module) bool {
659 pub fn toBool(val: Value) bool {
660660 return switch (val.toIntern()) {
661661 .bool_true => true,
662662 .bool_false => false,
......@@ -697,7 +697,7 @@ pub const Value = struct {
697697 switch (ty.zigTypeTag(mod)) {
698698 .Void => {},
699699 .Bool => {
700 buffer[0] = @boolToInt(val.toBool(mod));
700 buffer[0] = @boolToInt(val.toBool());
701701 },
702702 .Int, .Enum => {
703703 const int_info = ty.intInfo(mod);
......@@ -736,13 +736,20 @@ pub const Value = struct {
736736 },
737737 .Struct => switch (ty.containerLayout(mod)) {
738738 .Auto => return error.IllDefinedMemoryLayout,
739 .Extern => {
740 const fields = ty.structFields(mod).values();
741 const field_vals = val.castTag(.aggregate).?.data;
742 for (fields, 0..) |field, i| {
743 const off = @intCast(usize, ty.structFieldOffset(i, mod));
744 try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
745 }
739 .Extern => for (ty.structFields(mod).values(), 0..) |field, i| {
740 const off = @intCast(usize, ty.structFieldOffset(i, mod));
741 const field_val = switch (val.ip_index) {
742 .none => val.castTag(.aggregate).?.data[i],
743 else => switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {
744 .bytes => |bytes| {
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..]);
746753 },
747754 .Packed => {
748755 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
......@@ -812,7 +819,7 @@ pub const Value = struct {
812819 .Little => bit_offset / 8,
813820 .Big => buffer.len - bit_offset / 8 - 1,
814821 };
815 if (val.toBool(mod)) {
822 if (val.toBool()) {
816823 buffer[byte_index] |= (@as(u8, 1) << @intCast(u3, bit_offset % 8));
817824 } else {
818825 buffer[byte_index] &= ~(@as(u8, 1) << @intCast(u3, bit_offset % 8));
......@@ -1331,24 +1338,7 @@ pub const Value = struct {
13311338 .gt => {},
13321339 }
13331340
1334 const lhs_float = lhs.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) {
1341 if (lhs.isFloat(mod) or rhs.isFloat(mod)) {
13521342 const lhs_f128 = lhs.toFloat(f128, mod);
13531343 const rhs_f128 = rhs.toFloat(f128, mod);
13541344 return std.math.order(lhs_f128, rhs_f128);
......@@ -1669,86 +1659,6 @@ pub const Value = struct {
16691659 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
16701660 }
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
17521662 /// This is a more conservative hash function that produces equal hashes for values
17531663 /// that can coerce into each other.
17541664 /// This function is used by hash maps and so treats floating-point NaNs as equal
......@@ -1820,35 +1730,6 @@ pub const Value = struct {
18201730 }
18211731 }
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
18521733 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
18531734 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
18541735 .ptr => |ptr| switch (ptr.addr) {
......@@ -1919,14 +1800,25 @@ pub const Value = struct {
19191800 }
19201801
19211802 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 };
19231816 }
19241817
19251818 /// Asserts the value is a single-item pointer to an array, or an array,
19261819 /// or an unknown-length pointer, and returns the element value at the index.
19271820 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
19281821 return switch (val.ip_index) {
1929 .undef => Value.undef,
19301822 .none => switch (val.tag()) {
19311823 .repeated => val.castTag(.repeated).?.data,
19321824 .aggregate => val.castTag(.aggregate).?.data[index],
......@@ -1934,6 +1826,9 @@ pub const Value = struct {
19341826 else => unreachable,
19351827 },
19361828 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1829 .undef => |ty| (try mod.intern(.{
1830 .undef = ty.toType().elemType2(mod).toIntern(),
1831 })).toValue(),
19371832 .ptr => |ptr| switch (ptr.addr) {
19381833 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
19391834 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),
......@@ -2492,7 +2387,7 @@ pub const Value = struct {
24922387 }
24932388
24942389 return OverflowArithmeticResult{
2495 .overflow_bit = boolToInt(overflowed),
2390 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
24962391 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
24972392 };
24982393 }
......@@ -2645,7 +2540,8 @@ pub const Value = struct {
26452540
26462541 /// operands must be integers; handles undefined.
26472542 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
26502546 const info = ty.intInfo(mod);
26512547
......@@ -2687,7 +2583,8 @@ pub const Value = struct {
26872583
26882584 /// operands must be integers; handles undefined.
26892585 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
26922589 // TODO is this a performance issue? maybe we should try the operation without
26932590 // resorting to BigInt first.
......@@ -2725,7 +2622,8 @@ pub const Value = struct {
27252622
27262623 /// operands must be integers; handles undefined.
27272624 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
27302628 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
27312629 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 {
27522650
27532651 /// operands must be integers; handles undefined.
27542652 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
27572656 // TODO is this a performance issue? maybe we should try the operation without
27582657 // resorting to BigInt first.
......@@ -2789,7 +2688,8 @@ pub const Value = struct {
27892688
27902689 /// operands must be integers; handles undefined.
27912690 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
27942694 // TODO is this a performance issue? maybe we should try the operation without
27952695 // resorting to BigInt first.
......@@ -3233,7 +3133,7 @@ pub const Value = struct {
32333133 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);
32343134 }
32353135 return OverflowArithmeticResult{
3236 .overflow_bit = boolToInt(overflowed),
3136 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
32373137 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
32383138 };
32393139 }
......@@ -4267,12 +4167,6 @@ pub const Value = struct {
42674167 return if (x) Value.true else Value.false;
42684168 }
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
42764170 pub const RuntimeIndex = InternPool.RuntimeIndex;
42774171
42784172 /// 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):
354354
355355def Air_Inst__Air_Inst_Ref_SummaryProvider(value, _=None):
356356 members = value.type.enum_members
357 # ignore .none
358 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned + 1 - len(members))
357 # 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 + 2 - len(members))
359359
360360class Module_Decl__Module_Decl_Index_SynthProvider:
361361 def __init__(self, value, _=None): self.value = value
......@@ -365,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:
365365 mod = frame.FindVariable('mod') or frame.FindVariable('module')
366366 if mod: break
367367 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')
369369 except: pass
370370 def has_children(self): return True
371371 def num_children(self): return 1