authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-29 00:10:36-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log32692569656d9a178abb24f8fb7893395700cb62
treec2f10d2ed2d1d5e0e6c1cd2d532c6d76d401a466
parent3064d2aa7b9a8ea836cb70884b0640fe902ecc29

behavior: fix more compiler crashes


9 files changed, 309 insertions(+), 205 deletions(-)

src/InternPool.zig+8-3
...@@ -1416,7 +1416,12 @@ pub const Index = enum(u32) {...@@ -1416,7 +1416,12 @@ pub const Index = enum(u32) {
1416 only_possible_value: DataIsIndex,1416 only_possible_value: DataIsIndex,
1417 union_value: struct { data: *Key.Union },1417 union_value: struct { data: *Key.Union },
1418 bytes: struct { data: *Bytes },1418 bytes: struct { data: *Bytes },
1419 aggregate: struct { data: *Aggregate },1419 aggregate: struct {
1420 const @"data.ty.data.len orelse data.ty.data.fields_len" = opaque {};
1421 data: *Aggregate,
1422 @"trailing.element_values.len": *@"data.ty.data.len orelse data.ty.data.fields_len",
1423 trailing: struct { element_values: []Index },
1424 },
1420 repeated: struct { data: *Repeated },1425 repeated: struct { data: *Repeated },
14211426
1422 memoized_decl: struct { data: *Key.MemoizedDecl },1427 memoized_decl: struct { data: *Key.MemoizedDecl },
...@@ -4437,7 +4442,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -4437,7 +4442,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
4437 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),4442 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4438 },4443 },
4439 } }),4444 } }),
4440 else => try ip.getCoerced(gpa, opt.val, new_ty),4445 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
4441 },4446 },
4442 .err => |err| if (ip.isErrorSetType(new_ty))4447 .err => |err| if (ip.isErrorSetType(new_ty))
4443 return ip.get(gpa, .{ .err = .{4448 return ip.get(gpa, .{ .err = .{
...@@ -4622,7 +4627,7 @@ pub fn isErrorUnionType(ip: InternPool, ty: Index) bool {...@@ -4622,7 +4627,7 @@ pub fn isErrorUnionType(ip: InternPool, ty: Index) bool {
46224627
4623pub fn isAggregateType(ip: InternPool, ty: Index) bool {4628pub fn isAggregateType(ip: InternPool, ty: Index) bool {
4624 return switch (ip.indexToKey(ty)) {4629 return switch (ip.indexToKey(ty)) {
4625 .array_wype, .vector_type, .anon_struct_type, .struct_type => true,4630 .array_type, .vector_type, .anon_struct_type, .struct_type => true,
4626 else => false,4631 else => false,
4627 };4632 };
4628}4633}
src/Module.zig+6-23
...@@ -6678,14 +6678,14 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!...@@ -6678,14 +6678,14 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
66786678
6679pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {6679pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
6680 var canon_info = info;6680 var canon_info = info;
6681 const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod);
66816682
6682 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee6683 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
6683 // type, we change it to 0 here. If this causes an assertion trip because the6684 // type, we change it to 0 here. If this causes an assertion trip because the
6684 // pointee type needs to be resolved more, that needs to be done before calling6685 // pointee type needs to be resolved more, that needs to be done before calling
6685 // this ptr() function.6686 // this ptr() function.
6686 if (info.alignment.toByteUnitsOptional()) |info_align| {6687 if (info.alignment.toByteUnitsOptional()) |info_align| {
6687 const elem_align = info.elem_type.toType().abiAlignment(mod);6688 if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {
6688 if (info.elem_type.toType().layoutIsResolved(mod) and info_align == elem_align) {
6689 canon_info.alignment = .none;6689 canon_info.alignment = .none;
6690 }6690 }
6691 }6691 }
...@@ -6694,7 +6694,7 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type...@@ -6694,7 +6694,7 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type
6694 // Canonicalize host_size. If it matches the bit size of the pointee type,6694 // Canonicalize host_size. If it matches the bit size of the pointee type,
6695 // we change it to 0 here. If this causes an assertion trip, the pointee type6695 // we change it to 0 here. If this causes an assertion trip, the pointee type
6696 // needs to be resolved before calling this ptr() function.6696 // needs to be resolved before calling this ptr() function.
6697 .none => if (info.host_size != 0) {6697 .none => if (have_elem_layout and info.host_size != 0) {
6698 const elem_bit_size = info.elem_type.toType().bitSize(mod);6698 const elem_bit_size = info.elem_type.toType().bitSize(mod);
6699 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);6699 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
6700 if (info.host_size * 8 == elem_bit_size) {6700 if (info.host_size * 8 == elem_bit_size) {
...@@ -6782,21 +6782,7 @@ pub fn errorSetFromUnsortedNames(...@@ -6782,21 +6782,7 @@ pub fn errorSetFromUnsortedNames(
67826782
6783/// Supports optionals in addition to pointers.6783/// Supports optionals in addition to pointers.
6784pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {6784pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6785 if (ty.isPtrLikeOptional(mod)) {6785 return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
6786 const i = try intern(mod, .{ .opt = .{
6787 .ty = ty.toIntern(),
6788 .val = try intern(mod, .{ .ptr = .{
6789 .ty = ty.childType(mod).toIntern(),
6790 .addr = .{ .int = try intern(mod, .{ .int = .{
6791 .ty = .usize_type,
6792 .storage = .{ .u64 = x },
6793 } }) },
6794 } }),
6795 } });
6796 return i.toValue();
6797 } else {
6798 return ptrIntValue_ptronly(mod, ty, x);
6799 }
6800}6786}
68016787
6802/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.6788/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.
...@@ -6804,10 +6790,7 @@ pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value...@@ -6804,10 +6790,7 @@ pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value
6804 assert(ty.zigTypeTag(mod) == .Pointer);6790 assert(ty.zigTypeTag(mod) == .Pointer);
6805 const i = try intern(mod, .{ .ptr = .{6791 const i = try intern(mod, .{ .ptr = .{
6806 .ty = ty.toIntern(),6792 .ty = ty.toIntern(),
6807 .addr = .{ .int = try intern(mod, .{ .int = .{6793 .addr = .{ .int = try mod.intValue_u64(Type.usize, x) },
6808 .ty = .usize_type,
6809 .storage = .{ .u64 = x },
6810 } }) },
6811 } });6794 } });
6812 return i.toValue();6795 return i.toValue();
6813}6796}
...@@ -6954,7 +6937,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {...@@ -6954,7 +6937,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
6954 const key = mod.intern_pool.indexToKey(val.toIntern());6937 const key = mod.intern_pool.indexToKey(val.toIntern());
6955 switch (key.int.storage) {6938 switch (key.int.storage) {
6956 .i64 => |x| {6939 .i64 => |x| {
6957 if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted);6940 if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted) + @boolToInt(sign);
6958 assert(sign);6941 assert(sign);
6959 // Protect against overflow in the following negation.6942 // Protect against overflow in the following negation.
6960 if (x == std.math.minInt(i64)) return 64;6943 if (x == std.math.minInt(i64)) return 64;
src/Sema.zig+147-61
...@@ -9510,7 +9510,10 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -9510,7 +9510,10 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9510 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});9510 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});
9511 }9511 }
9512 if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| {9512 if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| {
9513 return sema.addConstant(Type.usize, try mod.getCoerced(ptr_val, Type.usize));9513 return sema.addConstant(
9514 Type.usize,
9515 try mod.intValue(Type.usize, (try ptr_val.getUnsignedIntAdvanced(mod, sema)).?),
9516 );
9514 }9517 }
9515 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);9518 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
9516 return block.addUnOp(.ptrtoint, ptr);9519 return block.addUnOp(.ptrtoint, ptr);
...@@ -27879,7 +27882,7 @@ fn beginComptimePtrMutation(...@@ -27879,7 +27882,7 @@ fn beginComptimePtrMutation(
27879 .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),27882 .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),
27880 .opt => |opt| switch (opt.val) {27883 .opt => |opt| switch (opt.val) {
27881 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),27884 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),
27882 else => opt.val,27885 else => |payload| payload,
27883 },27886 },
27884 else => unreachable,27887 else => unreachable,
27885 };27888 };
...@@ -28438,7 +28441,7 @@ fn beginComptimePtrLoad(...@@ -28438,7 +28441,7 @@ fn beginComptimePtrLoad(
28438 },28441 },
28439 .opt => |opt| switch (opt.val) {28442 .opt => |opt| switch (opt.val) {
28440 .none => return sema.fail(block, src, "attempt to use null value", .{}),28443 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28441 else => opt.val,28444 else => |payload| payload,
28442 },28445 },
28443 else => unreachable,28446 else => unreachable,
28444 }.toValue(),28447 }.toValue(),
...@@ -28591,7 +28594,7 @@ fn beginComptimePtrLoad(...@@ -28591,7 +28594,7 @@ fn beginComptimePtrLoad(
28591 },28594 },
28592 .opt => |opt| switch (opt.val) {28595 .opt => |opt| switch (opt.val) {
28593 .none => return sema.fail(block, src, "attempt to use null value", .{}),28596 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28594 else => try sema.beginComptimePtrLoad(block, src, opt.val.toValue(), null),28597 else => |payload| try sema.beginComptimePtrLoad(block, src, payload.toValue(), null),
28595 },28598 },
28596 else => unreachable,28599 else => unreachable,
28597 };28600 };
...@@ -28931,35 +28934,53 @@ fn coerceAnonStructToUnion(...@@ -28931,35 +28934,53 @@ fn coerceAnonStructToUnion(
28931) !Air.Inst.Ref {28934) !Air.Inst.Ref {
28932 const mod = sema.mod;28935 const mod = sema.mod;
28933 const inst_ty = sema.typeOf(inst);28936 const inst_ty = sema.typeOf(inst);
28934 const field_count = inst_ty.structFieldCount(mod);28937 const field_info: union(enum) {
28935 if (field_count != 1) {28938 name: []const u8,
28936 const msg = msg: {28939 count: usize,
28937 const msg = if (field_count > 1) try sema.errMsg(28940 } = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
28938 block,28941 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
28939 inst_src,28942 .{ .name = mod.intern_pool.stringToSlice(anon_struct_type.names[0]) }
28940 "cannot initialize multiple union fields at once; unions can only have one active field",28943 else
28941 .{},28944 .{ .count = anon_struct_type.names.len },
28942 ) else try sema.errMsg(28945 .struct_type => |struct_type| name: {
28943 block,28946 const field_names = mod.structPtrUnwrap(struct_type.index).?.fields.keys();
28944 inst_src,28947 break :name if (field_names.len == 1)
28945 "union initializer must initialize one field",28948 .{ .name = field_names[0] }
28946 .{},28949 else
28947 );28950 .{ .count = field_names.len };
28948 errdefer msg.destroy(sema.gpa);28951 },
28952 else => unreachable,
28953 };
28954 switch (field_info) {
28955 .name => |field_name| {
28956 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
28957 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
28958 },
28959 .count => |field_count| {
28960 assert(field_count != 1);
28961 const msg = msg: {
28962 const msg = if (field_count > 1) try sema.errMsg(
28963 block,
28964 inst_src,
28965 "cannot initialize multiple union fields at once; unions can only have one active field",
28966 .{},
28967 ) else try sema.errMsg(
28968 block,
28969 inst_src,
28970 "union initializer must initialize one field",
28971 .{},
28972 );
28973 errdefer msg.destroy(sema.gpa);
2894928974
28950 // TODO add notes for where the anon struct was created to point out28975 // TODO add notes for where the anon struct was created to point out
28951 // the extra fields.28976 // the extra fields.
2895228977
28953 try sema.addDeclaredHereNote(msg, union_ty);28978 try sema.addDeclaredHereNote(msg, union_ty);
28954 break :msg msg;28979 break :msg msg;
28955 };28980 };
28956 return sema.failWithOwnedErrorMsg(msg);28981 return sema.failWithOwnedErrorMsg(msg);
28982 },
28957 }28983 }
28958
28959 const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
28960 const field_name = mod.intern_pool.stringToSlice(anon_struct.names[0]);
28961 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
28962 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
28963}28984}
2896428985
28965fn coerceAnonStructToUnionPtrs(28986fn coerceAnonStructToUnionPtrs(
...@@ -29193,16 +29214,27 @@ fn coerceTupleToStruct(...@@ -29193,16 +29214,27 @@ fn coerceTupleToStruct(
29193 @memset(field_refs, .none);29214 @memset(field_refs, .none);
2919429215
29195 const inst_ty = sema.typeOf(inst);29216 const inst_ty = sema.typeOf(inst);
29196 const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
29197 var runtime_src: ?LazySrcLoc = null;29217 var runtime_src: ?LazySrcLoc = null;
29198 for (0..anon_struct.types.len) |field_index_usize| {29218 const field_count = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29219 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29220 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29221 struct_obj.fields.count()
29222 else
29223 0,
29224 else => unreachable,
29225 };
29226 for (0..field_count) |field_index_usize| {
29199 const field_i = @intCast(u32, field_index_usize);29227 const field_i = @intCast(u32, field_index_usize);
29200 const field_src = inst_src; // TODO better source location29228 const field_src = inst_src; // TODO better source location
29201 const field_name = if (anon_struct.names.len != 0)29229 // https://github.com/ziglang/zig/issues/15709
29202 // https://github.com/ziglang/zig/issues/1570929230 const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29203 @as([]const u8, mod.intern_pool.stringToSlice(anon_struct.names[field_i]))29231 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29204 else29232 mod.intern_pool.stringToSlice(anon_struct_type.names[field_i])
29205 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});29233 else
29234 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}),
29235 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
29236 else => unreachable,
29237 };
29206 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);29238 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
29207 const field = fields.values()[field_index];29239 const field = fields.values()[field_index];
29208 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29240 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
...@@ -29281,40 +29313,72 @@ fn coerceTupleToTuple(...@@ -29281,40 +29313,72 @@ fn coerceTupleToTuple(
29281 inst_src: LazySrcLoc,29313 inst_src: LazySrcLoc,
29282) !Air.Inst.Ref {29314) !Air.Inst.Ref {
29283 const mod = sema.mod;29315 const mod = sema.mod;
29284 const dest_tuple = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type;29316 const dest_field_count = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
29285 const field_vals = try sema.arena.alloc(InternPool.Index, dest_tuple.types.len);29317 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29318 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29319 struct_obj.fields.count()
29320 else
29321 0,
29322 else => unreachable,
29323 };
29324 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
29286 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);29325 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
29287 @memset(field_refs, .none);29326 @memset(field_refs, .none);
2928829327
29289 const inst_ty = sema.typeOf(inst);29328 const inst_ty = sema.typeOf(inst);
29290 const src_tuple = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;29329 const src_field_count = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29291 if (src_tuple.types.len > dest_tuple.types.len) return error.NotCoercible;29330 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29331 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29332 struct_obj.fields.count()
29333 else
29334 0,
29335 else => unreachable,
29336 };
29337 if (src_field_count > dest_field_count) return error.NotCoercible;
2929229338
29293 var runtime_src: ?LazySrcLoc = null;29339 var runtime_src: ?LazySrcLoc = null;
29294 for (dest_tuple.types, dest_tuple.values, 0..) |field_ty, default_val, field_index_usize| {29340 for (0..dest_field_count) |field_index_usize| {
29295 const field_i = @intCast(u32, field_index_usize);29341 const field_i = @intCast(u32, field_index_usize);
29296 const field_src = inst_src; // TODO better source location29342 const field_src = inst_src; // TODO better source location
29297 const field_name = if (src_tuple.names.len != 0)29343 // https://github.com/ziglang/zig/issues/15709
29298 // https://github.com/ziglang/zig/issues/1570929344 const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29299 @as([]const u8, mod.intern_pool.stringToSlice(src_tuple.names[field_i]))29345 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29300 else29346 mod.intern_pool.stringToSlice(anon_struct_type.names[field_i])
29301 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});29347 else
29348 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}),
29349 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
29350 else => unreachable,
29351 };
2930229352
29303 if (mem.eql(u8, field_name, "len")) {29353 if (mem.eql(u8, field_name, "len")) {
29304 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});29354 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
29305 }29355 }
2930629356
29357 const field_ty = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
29358 .anon_struct_type => |anon_struct_type| anon_struct_type.types[field_index_usize].toType(),
29359 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].ty,
29360 else => unreachable,
29361 };
29362 const default_val = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
29363 .anon_struct_type => |anon_struct_type| anon_struct_type.values[field_index_usize],
29364 .struct_type => |struct_type| switch (mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].default_val.toIntern()) {
29365 .unreachable_value => .none,
29366 else => |default_val| default_val,
29367 },
29368 else => unreachable,
29369 };
29370
29307 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);29371 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2930829372
29309 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);29373 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
29310 const coerced = try sema.coerce(block, field_ty.toType(), elem_ref, field_src);29374 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
29311 field_refs[field_index] = coerced;29375 field_refs[field_index] = coerced;
29312 if (default_val != .none) {29376 if (default_val != .none) {
29313 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {29377 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
29314 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");29378 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
29315 };29379 };
2931629380
29317 if (!init_val.eql(default_val.toValue(), field_ty.toType(), sema.mod)) {29381 if (!init_val.eql(default_val.toValue(), field_ty, sema.mod)) {
29318 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);29382 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
29319 }29383 }
29320 }29384 }
...@@ -29331,14 +29395,18 @@ fn coerceTupleToTuple(...@@ -29331,14 +29395,18 @@ fn coerceTupleToTuple(
29331 var root_msg: ?*Module.ErrorMsg = null;29395 var root_msg: ?*Module.ErrorMsg = null;
29332 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);29396 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
2933329397
29334 for (29398 for (field_refs, 0..) |*field_ref, i| {
29335 dest_tuple.types,
29336 dest_tuple.values,
29337 field_refs,
29338 0..,
29339 ) |field_ty, default_val, *field_ref, i| {
29340 if (field_ref.* != .none) continue;29399 if (field_ref.* != .none) continue;
2934129400
29401 const default_val = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
29402 .anon_struct_type => |anon_struct_type| anon_struct_type.values[i],
29403 .struct_type => |struct_type| switch (mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].default_val.toIntern()) {
29404 .unreachable_value => .none,
29405 else => |default_val| default_val,
29406 },
29407 else => unreachable,
29408 };
29409
29342 const field_src = inst_src; // TODO better source location29410 const field_src = inst_src; // TODO better source location
29343 if (default_val == .none) {29411 if (default_val == .none) {
29344 if (tuple_ty.isTuple(mod)) {29412 if (tuple_ty.isTuple(mod)) {
...@@ -29362,7 +29430,12 @@ fn coerceTupleToTuple(...@@ -29362,7 +29430,12 @@ fn coerceTupleToTuple(
29362 if (runtime_src == null) {29430 if (runtime_src == null) {
29363 field_vals[i] = default_val;29431 field_vals[i] = default_val;
29364 } else {29432 } else {
29365 field_ref.* = try sema.addConstant(field_ty.toType(), default_val.toValue());29433 const field_ty = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
29434 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i].toType(),
29435 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].ty,
29436 else => unreachable,
29437 };
29438 field_ref.* = try sema.addConstant(field_ty, default_val.toValue());
29366 }29439 }
29367 }29440 }
2936829441
...@@ -33959,11 +34032,20 @@ fn anonStructFieldIndex(...@@ -33959,11 +34032,20 @@ fn anonStructFieldIndex(
33959 field_src: LazySrcLoc,34032 field_src: LazySrcLoc,
33960) !u32 {34033) !u32 {
33961 const mod = sema.mod;34034 const mod = sema.mod;
33962 const anon_struct = mod.intern_pool.indexToKey(struct_ty.toIntern()).anon_struct_type;34035 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
33963 for (anon_struct.names, 0..) |name, i| {34036 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {
33964 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {34037 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
33965 return @intCast(u32, i);34038 return @intCast(u32, i);
33966 }34039 }
34040 },
34041 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
34042 for (struct_obj.fields.keys(), 0..) |name, i| {
34043 if (mem.eql(u8, name, field_name)) {
34044 return @intCast(u32, i);
34045 }
34046 }
34047 },
34048 else => unreachable,
33967 }34049 }
33968 return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{34050 return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{
33969 field_name, struct_ty.fmt(sema.mod),34051 field_name, struct_ty.fmt(sema.mod),
...@@ -34006,6 +34088,10 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {...@@ -34006,6 +34088,10 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
34006 );34088 );
34007 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };34089 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
34008 result_bigint.add(lhs_bigint, rhs_bigint);34090 result_bigint.add(lhs_bigint, rhs_bigint);
34091 if (scalar_ty.toIntern() != .comptime_int_type) {
34092 const int_info = scalar_ty.intInfo(mod);
34093 result_bigint.truncate(result_bigint.toConst(), int_info.signedness, int_info.bits);
34094 }
34009 return mod.intValue_big(scalar_ty, result_bigint.toConst());34095 return mod.intValue_big(scalar_ty, result_bigint.toConst());
34010}34096}
3401134097
src/TypedValue.zig+2-2
...@@ -254,8 +254,8 @@ pub fn print(...@@ -254,8 +254,8 @@ pub fn print(
254 .ptr => return writer.writeAll("(ptr)"),254 .ptr => return writer.writeAll("(ptr)"),
255 .opt => |opt| switch (opt.val) {255 .opt => |opt| switch (opt.val) {
256 .none => return writer.writeAll("null"),256 .none => return writer.writeAll("null"),
257 else => {257 else => |payload| {
258 val = opt.val.toValue();258 val = payload.toValue();
259 ty = ty.optionalChild(mod);259 ty = ty.optionalChild(mod);
260 },260 },
261 },261 },
src/codegen/c.zig+2-2
...@@ -1313,7 +1313,7 @@ pub const DeclGen = struct {...@@ -1313,7 +1313,7 @@ pub const DeclGen = struct {
13131313
1314 if (ty.optionalReprIsPayload(mod)) switch (opt.val) {1314 if (ty.optionalReprIsPayload(mod)) switch (opt.val) {
1315 .none => return writer.writeByte('0'),1315 .none => return writer.writeByte('0'),
1316 else => return dg.renderValue(writer, payload_ty, opt.val.toValue(), location),1316 else => |payload| return dg.renderValue(writer, payload_ty, payload.toValue(), location),
1317 };1317 };
13181318
1319 if (!location.isInitializer()) {1319 if (!location.isInitializer()) {
...@@ -1325,7 +1325,7 @@ pub const DeclGen = struct {...@@ -1325,7 +1325,7 @@ pub const DeclGen = struct {
1325 try writer.writeAll("{ .payload = ");1325 try writer.writeAll("{ .payload = ");
1326 try dg.renderValue(writer, payload_ty, switch (opt.val) {1326 try dg.renderValue(writer, payload_ty, switch (opt.val) {
1327 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),1327 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
1328 else => opt.val,1328 else => |payload| payload,
1329 }.toValue(), initializer_type);1329 }.toValue(), initializer_type);
1330 try writer.writeAll(", .is_null = ");1330 try writer.writeAll(", .is_null = ");
1331 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);1331 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
src/codegen/llvm.zig+1-1
...@@ -3430,7 +3430,7 @@ pub const DeclGen = struct {...@@ -3430,7 +3430,7 @@ pub const DeclGen = struct {
3430 const llvm_ty = try dg.lowerType(tv.ty);3430 const llvm_ty = try dg.lowerType(tv.ty);
3431 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {3431 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
3432 .none => llvm_ty.constNull(),3432 .none => llvm_ty.constNull(),
3433 else => dg.lowerValue(.{ .ty = payload_ty, .val = opt.val.toValue() }),3433 else => |payload| dg.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }),
3434 };3434 };
3435 assert(payload_ty.zigTypeTag(mod) != .Fn);3435 assert(payload_ty.zigTypeTag(mod) != .Fn);
34363436
src/type.zig+2-2
...@@ -630,7 +630,6 @@ pub const Type = struct {...@@ -630,7 +630,6 @@ pub const Type = struct {
630 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {630 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
631 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {631 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
632 .int_type,632 .int_type,
633 .ptr_type,
634 .vector_type,633 .vector_type,
635 => true,634 => true,
636635
...@@ -646,6 +645,7 @@ pub const Type = struct {...@@ -646,6 +645,7 @@ pub const Type = struct {
646645
647 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),646 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
648 .opt_type => ty.isPtrLikeOptional(mod),647 .opt_type => ty.isPtrLikeOptional(mod),
648 .ptr_type => |ptr_type| ptr_type.size != .Slice,
649649
650 .simple_type => |t| switch (t) {650 .simple_type => |t| switch (t) {
651 .f16,651 .f16,
...@@ -1578,7 +1578,7 @@ pub const Type = struct {...@@ -1578,7 +1578,7 @@ pub const Type = struct {
1578 .int_type => |int_type| return int_type.bits,1578 .int_type => |int_type| return int_type.bits,
1579 .ptr_type => |ptr_type| switch (ptr_type.size) {1579 .ptr_type => |ptr_type| switch (ptr_type.size) {
1580 .Slice => return target.ptrBitWidth() * 2,1580 .Slice => return target.ptrBitWidth() * 2,
1581 else => return target.ptrBitWidth() * 2,1581 else => return target.ptrBitWidth(),
1582 },1582 },
1583 .anyframe_type => return target.ptrBitWidth(),1583 .anyframe_type => return target.ptrBitWidth(),
15841584
src/value.zig+128-98
...@@ -363,7 +363,7 @@ pub const Value = struct {...@@ -363,7 +363,7 @@ pub const Value = struct {
363 },363 },
364 .slice => {364 .slice => {
365 const pl = val.castTag(.slice).?.data;365 const pl = val.castTag(.slice).?.data;
366 const ptr = try pl.ptr.intern(ty.optionalChild(mod), mod);366 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
367 var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;367 var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;
368 assert(ptr_key.len == .none);368 assert(ptr_key.len == .none);
369 ptr_key.ty = ty.toIntern();369 ptr_key.ty = ty.toIntern();
...@@ -547,7 +547,6 @@ pub const Value = struct {...@@ -547,7 +547,6 @@ pub const Value = struct {
547 return switch (val.toIntern()) {547 return switch (val.toIntern()) {
548 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),548 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
549 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),549 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
550 .undef => unreachable,
551 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),550 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
552 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {551 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
553 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),552 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
...@@ -564,19 +563,10 @@ pub const Value = struct {...@@ -564,19 +563,10 @@ pub const Value = struct {
564 },563 },
565 },564 },
566 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),565 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
567 .ptr => |ptr| switch (ptr.len) {566 .opt, .ptr => BigIntMutable.init(
568 .none => switch (ptr.addr) {567 &space.limbs,
569 .int => |int| int.toValue().toBigIntAdvanced(space, mod, opt_sema),568 (try val.getUnsignedIntAdvanced(mod, opt_sema)).?,
570 .elem => |elem| {569 ).toConst(),
571 const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)).?;
572 const elem_size = ptr.ty.toType().elemType2(mod).abiSize(mod);
573 const new_addr = base_addr + elem.index * elem_size;
574 return BigIntMutable.init(&space.limbs, new_addr).toConst();
575 },
576 else => unreachable,
577 },
578 else => unreachable,
579 },
580 else => unreachable,570 else => unreachable,
581 },571 },
582 };572 };
...@@ -614,10 +604,11 @@ pub const Value = struct {...@@ -614,10 +604,11 @@ pub const Value = struct {
614 /// Asserts not undefined.604 /// Asserts not undefined.
615 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {605 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
616 return switch (val.toIntern()) {606 return switch (val.toIntern()) {
607 .undef => unreachable,
617 .bool_false => 0,608 .bool_false => 0,
618 .bool_true => 1,609 .bool_true => 1,
619 .undef => unreachable,
620 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {610 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
611 .undef => unreachable,
621 .int => |int| switch (int.storage) {612 .int => |int| switch (int.storage) {
622 .big_int => |big_int| big_int.to(u64) catch null,613 .big_int => |big_int| big_int.to(u64) catch null,
623 .u64 => |x| x,614 .u64 => |x| x,
...@@ -631,6 +622,26 @@ pub const Value = struct {...@@ -631,6 +622,26 @@ pub const Value = struct {
631 else622 else
632 ty.toType().abiSize(mod),623 ty.toType().abiSize(mod),
633 },624 },
625 .ptr => |ptr| switch (ptr.addr) {
626 .int => |int| int.toValue().getUnsignedIntAdvanced(mod, opt_sema),
627 .elem => |elem| {
628 const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
629 const elem_size = ptr.ty.toType().elemType2(mod).abiSize(mod);
630 return base_addr + elem.index * elem_size;
631 },
632 .field => |field| {
633 const struct_ty = ptr.ty.toType().childType(mod);
634 if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);
635 const base_addr = (try field.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
636 const field_offset = ptr.ty.toType().childType(mod).structFieldOffset(field.index, mod);
637 return base_addr + field_offset;
638 },
639 else => null,
640 },
641 .opt => |opt| switch (opt.val) {
642 .none => 0,
643 else => |payload| payload.toValue().getUnsignedIntAdvanced(mod, opt_sema),
644 },
634 else => null,645 else => null,
635 },646 },
636 };647 };
...@@ -646,7 +657,6 @@ pub const Value = struct {...@@ -646,7 +657,6 @@ pub const Value = struct {
646 return switch (val.toIntern()) {657 return switch (val.toIntern()) {
647 .bool_false => 0,658 .bool_false => 0,
648 .bool_true => 1,659 .bool_true => 1,
649 .undef => unreachable,
650 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {660 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
651 .int => |int| switch (int.storage) {661 .int => |int| switch (int.storage) {
652 .big_int => |big_int| big_int.to(i64) catch unreachable,662 .big_int => |big_int| big_int.to(i64) catch unreachable,
...@@ -830,24 +840,14 @@ pub const Value = struct {...@@ -830,24 +840,14 @@ pub const Value = struct {
830 }840 }
831 },841 },
832 .Int, .Enum => {842 .Int, .Enum => {
843 if (buffer.len == 0) return;
833 const bits = ty.intInfo(mod).bits;844 const bits = ty.intInfo(mod).bits;
834 const abi_size = @intCast(usize, ty.abiSize(mod));845 if (bits == 0) return;
835
836 const int_val = try val.enumToInt(ty, mod);
837846
838 if (abi_size == 0) return;847 switch (mod.intern_pool.indexToKey((try val.enumToInt(ty, mod)).toIntern()).int.storage) {
839 if (abi_size <= @sizeOf(u64)) {848 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
840 const ip_key = mod.intern_pool.indexToKey(int_val.toIntern());849 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
841 const int: u64 = switch (ip_key.int.storage) {850 else => unreachable,
842 .u64 => |x| x,
843 .i64 => |x| @bitCast(u64, x),
844 else => unreachable,
845 };
846 std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian);
847 } else {
848 var bigint_buffer: BigIntSpace = undefined;
849 const bigint = int_val.toBigInt(&bigint_buffer, mod);
850 bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian);
851 }851 }
852 },852 },
853 .Float => switch (ty.floatBits(target)) {853 .Float => switch (ty.floatBits(target)) {
...@@ -1075,25 +1075,40 @@ pub const Value = struct {...@@ -1075,25 +1075,40 @@ pub const Value = struct {
1075 return Value.true;1075 return Value.true;
1076 }1076 }
1077 },1077 },
1078 .Int, .Enum => {1078 .Int, .Enum => |ty_tag| {
1079 if (buffer.len == 0) return mod.intValue(ty, 0);1079 if (buffer.len == 0) return mod.intValue(ty, 0);
1080 const int_info = ty.intInfo(mod);1080 const int_info = ty.intInfo(mod);
1081 const abi_size = @intCast(usize, ty.abiSize(mod));
1082
1083 const bits = int_info.bits;1081 const bits = int_info.bits;
1084 if (bits == 0) return mod.intValue(ty, 0);1082 if (bits == 0) return mod.intValue(ty, 0);
1085 if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
1086 .signed => return mod.intValue(ty, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)),
1087 .unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
1088 } else { // Slow path, we have to construct a big-int
1089 const Limb = std.math.big.Limb;
1090 const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
1091 const limbs_buffer = try arena.alloc(Limb, limb_count);
10921083
1093 var bigint = BigIntMutable.init(limbs_buffer, 0);1084 // Fast path for integers <= u64
1094 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);1085 if (bits <= 64) {
1095 return mod.intValue_big(ty, bigint.toConst());1086 const int_ty = switch (ty_tag) {
1087 .Int => ty,
1088 .Enum => ty.intTagType(mod),
1089 else => unreachable,
1090 };
1091 return mod.getCoerced(switch (int_info.signedness) {
1092 .signed => return mod.intValue(
1093 int_ty,
1094 std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed),
1095 ),
1096 .unsigned => return mod.intValue(
1097 int_ty,
1098 std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned),
1099 ),
1100 }, ty);
1096 }1101 }
1102
1103 // Slow path, we have to construct a big-int
1104 const abi_size = @intCast(usize, ty.abiSize(mod));
1105 const Limb = std.math.big.Limb;
1106 const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
1107 const limbs_buffer = try arena.alloc(Limb, limb_count);
1108
1109 var bigint = BigIntMutable.init(limbs_buffer, 0);
1110 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
1111 return mod.intValue_big(ty, bigint.toConst());
1097 },1112 },
1098 .Float => return (try mod.intern(.{ .float = .{1113 .Float => return (try mod.intern(.{ .float = .{
1099 .ty = ty.toIntern(),1114 .ty = ty.toIntern(),
...@@ -1764,7 +1779,7 @@ pub const Value = struct {...@@ -1764,7 +1779,7 @@ pub const Value = struct {
1764 },1779 },
1765 .opt => |opt| switch (opt.val) {1780 .opt => |opt| switch (opt.val) {
1766 .none => false,1781 .none => false,
1767 else => opt.val.toValue().canMutateComptimeVarState(mod),1782 else => |payload| payload.toValue().canMutateComptimeVarState(mod),
1768 },1783 },
1769 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {1784 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
1770 if (elem.toValue().canMutateComptimeVarState(mod)) break true;1785 if (elem.toValue().canMutateComptimeVarState(mod)) break true;
...@@ -1949,43 +1964,51 @@ pub const Value = struct {...@@ -1949,43 +1964,51 @@ pub const Value = struct {
1949 start: usize,1964 start: usize,
1950 end: usize,1965 end: usize,
1951 ) error{OutOfMemory}!Value {1966 ) error{OutOfMemory}!Value {
1952 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1967 return switch (val.ip_index) {
1953 .ptr => |ptr| switch (ptr.addr) {1968 .none => switch (val.tag()) {
1954 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),1969 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
1955 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()1970 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
1956 .sliceArray(mod, arena, start, end),1971 .repeated => val,
1957 .comptime_field => |comptime_field| comptime_field.toValue()1972 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
1958 .sliceArray(mod, arena, start, end),
1959 .elem => |elem| elem.base.toValue()
1960 .sliceArray(mod, arena, start + elem.index, end + elem.index),
1961 else => unreachable,1973 else => unreachable,
1962 },1974 },
1963 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{1975 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1964 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {1976 .ptr => |ptr| switch (ptr.addr) {
1965 .array_type => |array_type| try mod.arrayType(.{1977 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
1966 .len = @intCast(u32, end - start),1978 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
1967 .child = array_type.child,1979 .sliceArray(mod, arena, start, end),
1968 .sentinel = if (end == array_type.len) array_type.sentinel else .none,1980 .comptime_field => |comptime_field| comptime_field.toValue()
1969 }),1981 .sliceArray(mod, arena, start, end),
1970 .vector_type => |vector_type| try mod.vectorType(.{1982 .elem => |elem| elem.base.toValue()
1971 .len = @intCast(u32, end - start),1983 .sliceArray(mod, arena, start + elem.index, end + elem.index),
1972 .child = vector_type.child,
1973 }),
1974 else => unreachable,1984 else => unreachable,
1975 }.toIntern(),
1976 .storage = switch (aggregate.storage) {
1977 .bytes => |bytes| .{ .bytes = bytes[start..end] },
1978 .elems => |elems| .{ .elems = elems[start..end] },
1979 .repeated_elem => |elem| .{ .repeated_elem = elem },
1980 },1985 },
1981 } })).toValue(),1986 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
1982 else => unreachable,1987 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {
1988 .array_type => |array_type| try mod.arrayType(.{
1989 .len = @intCast(u32, end - start),
1990 .child = array_type.child,
1991 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1992 }),
1993 .vector_type => |vector_type| try mod.vectorType(.{
1994 .len = @intCast(u32, end - start),
1995 .child = vector_type.child,
1996 }),
1997 else => unreachable,
1998 }.toIntern(),
1999 .storage = switch (aggregate.storage) {
2000 .bytes => |bytes| .{ .bytes = bytes[start..end] },
2001 .elems => |elems| .{ .elems = elems[start..end] },
2002 .repeated_elem => |elem| .{ .repeated_elem = elem },
2003 },
2004 } })).toValue(),
2005 else => unreachable,
2006 },
1983 };2007 };
1984 }2008 }
19852009
1986 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {2010 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
1987 return switch (val.ip_index) {2011 return switch (val.ip_index) {
1988 .undef => Value.undef,
1989 .none => switch (val.tag()) {2012 .none => switch (val.tag()) {
1990 .aggregate => {2013 .aggregate => {
1991 const field_values = val.castTag(.aggregate).?.data;2014 const field_values = val.castTag(.aggregate).?.data;
...@@ -1999,6 +2022,9 @@ pub const Value = struct {...@@ -1999,6 +2022,9 @@ pub const Value = struct {
1999 else => unreachable,2022 else => unreachable,
2000 },2023 },
2001 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {2024 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
2025 .undef => |ty| (try mod.intern(.{
2026 .undef = ty.toType().structFieldType(index, mod).toIntern(),
2027 })).toValue(),
2002 .aggregate => |aggregate| switch (aggregate.storage) {2028 .aggregate => |aggregate| switch (aggregate.storage) {
2003 .bytes => |bytes| try mod.intern(.{ .int = .{2029 .bytes => |bytes| try mod.intern(.{ .int = .{
2004 .ty = .u8_type,2030 .ty = .u8_type,
...@@ -2108,6 +2134,7 @@ pub const Value = struct {...@@ -2108,6 +2134,7 @@ pub const Value = struct {
2108 .null_value => true,2134 .null_value => true,
21092135
2110 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {2136 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2137 .undef => unreachable,
2111 .int => {2138 .int => {
2112 var buf: BigIntSpace = undefined;2139 var buf: BigIntSpace = undefined;
2113 return val.toBigInt(&buf, mod).eqZero();2140 return val.toBigInt(&buf, mod).eqZero();
...@@ -2141,9 +2168,13 @@ pub const Value = struct {...@@ -2141,9 +2168,13 @@ pub const Value = struct {
21412168
2142 /// Value of the optional, null if optional has no payload.2169 /// Value of the optional, null if optional has no payload.
2143 pub fn optionalValue(val: Value, mod: *const Module) ?Value {2170 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2144 return switch (mod.intern_pool.indexToKey(val.toIntern()).opt.val) {2171 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2145 .none => null,2172 .opt => |opt| switch (opt.val) {
2146 else => |index| index.toValue(),2173 .none => null,
2174 else => |payload| payload.toValue(),
2175 },
2176 .ptr => val,
2177 else => unreachable,
2147 };2178 };
2148 }2179 }
21492180
...@@ -2152,6 +2183,7 @@ pub const Value = struct {...@@ -2152,6 +2183,7 @@ pub const Value = struct {
2152 return switch (self.toIntern()) {2183 return switch (self.toIntern()) {
2153 .undef => unreachable,2184 .undef => unreachable,
2154 else => switch (mod.intern_pool.indexToKey(self.toIntern())) {2185 else => switch (mod.intern_pool.indexToKey(self.toIntern())) {
2186 .undef => unreachable,
2155 .float => true,2187 .float => true,
2156 else => false,2188 else => false,
2157 },2189 },
...@@ -2182,28 +2214,26 @@ pub const Value = struct {...@@ -2182,28 +2214,26 @@ pub const Value = struct {
2182 }2214 }
21832215
2184 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {2216 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
2185 return switch (val.toIntern()) {2217 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2186 .undef => val,2218 .undef => (try mod.intern(.{ .undef = float_ty.toIntern() })).toValue(),
2187 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {2219 .int => |int| switch (int.storage) {
2188 .int => |int| switch (int.storage) {2220 .big_int => |big_int| {
2189 .big_int => |big_int| {2221 const float = bigIntToFloat(big_int.limbs, big_int.positive);
2190 const float = bigIntToFloat(big_int.limbs, big_int.positive);2222 return mod.floatValue(float_ty, float);
2191 return mod.floatValue(float_ty, float);2223 },
2192 },2224 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
2193 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),2225 .lazy_align => |ty| if (opt_sema) |sema| {
2194 .lazy_align => |ty| if (opt_sema) |sema| {2226 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2195 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);2227 } else {
2196 } else {2228 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
2197 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);2229 },
2198 },2230 .lazy_size => |ty| if (opt_sema) |sema| {
2199 .lazy_size => |ty| if (opt_sema) |sema| {2231 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2200 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);2232 } else {
2201 } else {2233 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
2202 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
2203 },
2204 },2234 },
2205 else => unreachable,
2206 },2235 },
2236 else => unreachable,
2207 };2237 };
2208 }2238 }
22092239
tools/lldb_pretty_printers.py+13-13
...@@ -455,21 +455,21 @@ class InternPool_Index_SynthProvider:...@@ -455,21 +455,21 @@ class InternPool_Index_SynthProvider:
455 elif encoding_field.name == 'trailing':455 elif encoding_field.name == 'trailing':
456 trailing_data = lldb.SBData()456 trailing_data = lldb.SBData()
457 for trailing_field in encoding_field.type.fields:457 for trailing_field in encoding_field.type.fields:
458 if trailing_field.type.IsAggregateType():458 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
459 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)459 trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
460 len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned460 trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize()))
461 trailing_data.Append(lldb.SBData.CreateDataFromInt(len, trailing_data.GetAddressByteSize()))461 extra_index += trailing_len
462 extra_index += len
463 else:
464 pass
465 self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)462 self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)
466 else:463 else:
467 path = encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split('.')464 for path in encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split(' orelse '):
468 if path[0] == 'data':465 if path.startswith('data.'):
469 dynamic_value = self.data466 root = self.data
470 for name in path[1:]:467 path = path[len('data'):]
471 dynamic_value = dynamic_value.GetChildMemberWithName(name)468 else: return
472 dynamic_values[encoding_field.name] = dynamic_value469 dynamic_value = root.GetValueForExpressionPath(path)
470 if dynamic_value:
471 dynamic_values[encoding_field.name] = dynamic_value
472 break
473 except: pass473 except: pass
474 def has_children(self): return True474 def has_children(self): return True
475 def num_children(self): return 2 + (self.trailing is not None)475 def num_children(self): return 2 + (self.trailing is not None)