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) {
14161416 only_possible_value: DataIsIndex,
14171417 union_value: struct { data: *Key.Union },
14181418 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 },
14201425 repeated: struct { data: *Repeated },
14211426
14221427 memoized_decl: struct { data: *Key.MemoizedDecl },
......@@ -4437,7 +4442,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
44374442 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
44384443 },
44394444 } }),
4440 else => try ip.getCoerced(gpa, opt.val, new_ty),
4445 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
44414446 },
44424447 .err => |err| if (ip.isErrorSetType(new_ty))
44434448 return ip.get(gpa, .{ .err = .{
......@@ -4622,7 +4627,7 @@ pub fn isErrorUnionType(ip: InternPool, ty: Index) bool {
46224627
46234628pub fn isAggregateType(ip: InternPool, ty: Index) bool {
46244629 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,
46264631 else => false,
46274632 };
46284633}
src/Module.zig+6-23
......@@ -6678,14 +6678,14 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
66786678
66796679pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
66806680 var canon_info = info;
6681 const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod);
66816682
66826683 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
66836684 // type, we change it to 0 here. If this causes an assertion trip because the
66846685 // pointee type needs to be resolved more, that needs to be done before calling
66856686 // this ptr() function.
66866687 if (info.alignment.toByteUnitsOptional()) |info_align| {
6687 const elem_align = info.elem_type.toType().abiAlignment(mod);
6688 if (info.elem_type.toType().layoutIsResolved(mod) and info_align == elem_align) {
6688 if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {
66896689 canon_info.alignment = .none;
66906690 }
66916691 }
......@@ -6694,7 +6694,7 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type
66946694 // Canonicalize host_size. If it matches the bit size of the pointee type,
66956695 // we change it to 0 here. If this causes an assertion trip, the pointee type
66966696 // 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) {
66986698 const elem_bit_size = info.elem_type.toType().bitSize(mod);
66996699 assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
67006700 if (info.host_size * 8 == elem_bit_size) {
......@@ -6782,21 +6782,7 @@ pub fn errorSetFromUnsortedNames(
67826782
67836783/// Supports optionals in addition to pointers.
67846784pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6785 if (ty.isPtrLikeOptional(mod)) {
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 }
6785 return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
68006786}
68016787
68026788/// 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
68046790 assert(ty.zigTypeTag(mod) == .Pointer);
68056791 const i = try intern(mod, .{ .ptr = .{
68066792 .ty = ty.toIntern(),
6807 .addr = .{ .int = try intern(mod, .{ .int = .{
6808 .ty = .usize_type,
6809 .storage = .{ .u64 = x },
6810 } }) },
6793 .addr = .{ .int = try mod.intValue_u64(Type.usize, x) },
68116794 } });
68126795 return i.toValue();
68136796}
......@@ -6954,7 +6937,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
69546937 const key = mod.intern_pool.indexToKey(val.toIntern());
69556938 switch (key.int.storage) {
69566939 .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);
69586941 assert(sign);
69596942 // Protect against overflow in the following negation.
69606943 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
95109510 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});
95119511 }
95129512 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 );
95149517 }
95159518 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
95169519 return block.addUnOp(.ptrtoint, ptr);
......@@ -27879,7 +27882,7 @@ fn beginComptimePtrMutation(
2787927882 .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),
2788027883 .opt => |opt| switch (opt.val) {
2788127884 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),
27882 else => opt.val,
27885 else => |payload| payload,
2788327886 },
2788427887 else => unreachable,
2788527888 };
......@@ -28438,7 +28441,7 @@ fn beginComptimePtrLoad(
2843828441 },
2843928442 .opt => |opt| switch (opt.val) {
2844028443 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28441 else => opt.val,
28444 else => |payload| payload,
2844228445 },
2844328446 else => unreachable,
2844428447 }.toValue(),
......@@ -28591,7 +28594,7 @@ fn beginComptimePtrLoad(
2859128594 },
2859228595 .opt => |opt| switch (opt.val) {
2859328596 .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),
2859528598 },
2859628599 else => unreachable,
2859728600 };
......@@ -28931,35 +28934,53 @@ fn coerceAnonStructToUnion(
2893128934) !Air.Inst.Ref {
2893228935 const mod = sema.mod;
2893328936 const inst_ty = sema.typeOf(inst);
28934 const field_count = inst_ty.structFieldCount(mod);
28935 if (field_count != 1) {
28936 const msg = msg: {
28937 const msg = if (field_count > 1) try sema.errMsg(
28938 block,
28939 inst_src,
28940 "cannot initialize multiple union fields at once; unions can only have one active field",
28941 .{},
28942 ) else try sema.errMsg(
28943 block,
28944 inst_src,
28945 "union initializer must initialize one field",
28946 .{},
28947 );
28948 errdefer msg.destroy(sema.gpa);
28937 const field_info: union(enum) {
28938 name: []const u8,
28939 count: usize,
28940 } = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
28941 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
28942 .{ .name = mod.intern_pool.stringToSlice(anon_struct_type.names[0]) }
28943 else
28944 .{ .count = anon_struct_type.names.len },
28945 .struct_type => |struct_type| name: {
28946 const field_names = mod.structPtrUnwrap(struct_type.index).?.fields.keys();
28947 break :name if (field_names.len == 1)
28948 .{ .name = field_names[0] }
28949 else
28950 .{ .count = field_names.len };
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 out
28951 // the extra fields.
28975 // TODO add notes for where the anon struct was created to point out
28976 // the extra fields.
2895228977
28953 try sema.addDeclaredHereNote(msg, union_ty);
28954 break :msg msg;
28955 };
28956 return sema.failWithOwnedErrorMsg(msg);
28978 try sema.addDeclaredHereNote(msg, union_ty);
28979 break :msg msg;
28980 };
28981 return sema.failWithOwnedErrorMsg(msg);
28982 },
2895728983 }
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);
2896328984}
2896428985
2896528986fn coerceAnonStructToUnionPtrs(
......@@ -29193,16 +29214,27 @@ fn coerceTupleToStruct(
2919329214 @memset(field_refs, .none);
2919429215
2919529216 const inst_ty = sema.typeOf(inst);
29196 const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
2919729217 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| {
2919929227 const field_i = @intCast(u32, field_index_usize);
2920029228 const field_src = inst_src; // TODO better source location
29201 const field_name = if (anon_struct.names.len != 0)
29202 // https://github.com/ziglang/zig/issues/15709
29203 @as([]const u8, mod.intern_pool.stringToSlice(anon_struct.names[field_i]))
29204 else
29205 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
29229 // https://github.com/ziglang/zig/issues/15709
29230 const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29231 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29232 mod.intern_pool.stringToSlice(anon_struct_type.names[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 };
2920629238 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
2920729239 const field = fields.values()[field_index];
2920829240 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
......@@ -29281,40 +29313,72 @@ fn coerceTupleToTuple(
2928129313 inst_src: LazySrcLoc,
2928229314) !Air.Inst.Ref {
2928329315 const mod = sema.mod;
29284 const dest_tuple = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type;
29285 const field_vals = try sema.arena.alloc(InternPool.Index, dest_tuple.types.len);
29316 const dest_field_count = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
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);
2928629325 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2928729326 @memset(field_refs, .none);
2928829327
2928929328 const inst_ty = sema.typeOf(inst);
29290 const src_tuple = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
29291 if (src_tuple.types.len > dest_tuple.types.len) return error.NotCoercible;
29329 const src_field_count = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
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
2929329339 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| {
2929529341 const field_i = @intCast(u32, field_index_usize);
2929629342 const field_src = inst_src; // TODO better source location
29297 const field_name = if (src_tuple.names.len != 0)
29298 // https://github.com/ziglang/zig/issues/15709
29299 @as([]const u8, mod.intern_pool.stringToSlice(src_tuple.names[field_i]))
29300 else
29301 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
29343 // https://github.com/ziglang/zig/issues/15709
29344 const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29345 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29346 mod.intern_pool.stringToSlice(anon_struct_type.names[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
2930329353 if (mem.eql(u8, field_name, "len")) {
2930429354 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
2930529355 }
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
2930729371 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2930829372
2930929373 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);
2931129375 field_refs[field_index] = coerced;
2931229376 if (default_val != .none) {
2931329377 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
2931429378 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
2931529379 };
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)) {
2931829382 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
2931929383 }
2932029384 }
......@@ -29331,14 +29395,18 @@ fn coerceTupleToTuple(
2933129395 var root_msg: ?*Module.ErrorMsg = null;
2933229396 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
2933329397
29334 for (
29335 dest_tuple.types,
29336 dest_tuple.values,
29337 field_refs,
29338 0..,
29339 ) |field_ty, default_val, *field_ref, i| {
29398 for (field_refs, 0..) |*field_ref, i| {
2934029399 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
2934229410 const field_src = inst_src; // TODO better source location
2934329411 if (default_val == .none) {
2934429412 if (tuple_ty.isTuple(mod)) {
......@@ -29362,7 +29430,12 @@ fn coerceTupleToTuple(
2936229430 if (runtime_src == null) {
2936329431 field_vals[i] = default_val;
2936429432 } 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());
2936629439 }
2936729440 }
2936829441
......@@ -33959,11 +34032,20 @@ fn anonStructFieldIndex(
3395934032 field_src: LazySrcLoc,
3396034033) !u32 {
3396134034 const mod = sema.mod;
33962 const anon_struct = mod.intern_pool.indexToKey(struct_ty.toIntern()).anon_struct_type;
33963 for (anon_struct.names, 0..) |name, i| {
33964 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
33965 return @intCast(u32, i);
33966 }
34035 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
34036 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {
34037 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
34038 return @intCast(u32, i);
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,
3396734049 }
3396834050 return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{
3396934051 field_name, struct_ty.fmt(sema.mod),
......@@ -34006,6 +34088,10 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
3400634088 );
3400734089 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3400834090 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 }
3400934095 return mod.intValue_big(scalar_ty, result_bigint.toConst());
3401034096}
3401134097
src/TypedValue.zig+2-2
......@@ -254,8 +254,8 @@ pub fn print(
254254 .ptr => return writer.writeAll("(ptr)"),
255255 .opt => |opt| switch (opt.val) {
256256 .none => return writer.writeAll("null"),
257 else => {
258 val = opt.val.toValue();
257 else => |payload| {
258 val = payload.toValue();
259259 ty = ty.optionalChild(mod);
260260 },
261261 },
src/codegen/c.zig+2-2
......@@ -1313,7 +1313,7 @@ pub const DeclGen = struct {
13131313
13141314 if (ty.optionalReprIsPayload(mod)) switch (opt.val) {
13151315 .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),
13171317 };
13181318
13191319 if (!location.isInitializer()) {
......@@ -1325,7 +1325,7 @@ pub const DeclGen = struct {
13251325 try writer.writeAll("{ .payload = ");
13261326 try dg.renderValue(writer, payload_ty, switch (opt.val) {
13271327 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
1328 else => opt.val,
1328 else => |payload| payload,
13291329 }.toValue(), initializer_type);
13301330 try writer.writeAll(", .is_null = ");
13311331 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 {
34303430 const llvm_ty = try dg.lowerType(tv.ty);
34313431 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
34323432 .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() }),
34343434 };
34353435 assert(payload_ty.zigTypeTag(mod) != .Fn);
34363436
src/type.zig+2-2
......@@ -630,7 +630,6 @@ pub const Type = struct {
630630 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
631631 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
632632 .int_type,
633 .ptr_type,
634633 .vector_type,
635634 => true,
636635
......@@ -646,6 +645,7 @@ pub const Type = struct {
646645
647646 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
648647 .opt_type => ty.isPtrLikeOptional(mod),
648 .ptr_type => |ptr_type| ptr_type.size != .Slice,
649649
650650 .simple_type => |t| switch (t) {
651651 .f16,
......@@ -1578,7 +1578,7 @@ pub const Type = struct {
15781578 .int_type => |int_type| return int_type.bits,
15791579 .ptr_type => |ptr_type| switch (ptr_type.size) {
15801580 .Slice => return target.ptrBitWidth() * 2,
1581 else => return target.ptrBitWidth() * 2,
1581 else => return target.ptrBitWidth(),
15821582 },
15831583 .anyframe_type => return target.ptrBitWidth(),
15841584
src/value.zig+128-98
......@@ -363,7 +363,7 @@ pub const Value = struct {
363363 },
364364 .slice => {
365365 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);
367367 var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;
368368 assert(ptr_key.len == .none);
369369 ptr_key.ty = ty.toIntern();
......@@ -547,7 +547,6 @@ pub const Value = struct {
547547 return switch (val.toIntern()) {
548548 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
549549 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
550 .undef => unreachable,
551550 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
552551 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
553552 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
......@@ -564,19 +563,10 @@ pub const Value = struct {
564563 },
565564 },
566565 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
567 .ptr => |ptr| switch (ptr.len) {
568 .none => switch (ptr.addr) {
569 .int => |int| int.toValue().toBigIntAdvanced(space, mod, opt_sema),
570 .elem => |elem| {
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 },
566 .opt, .ptr => BigIntMutable.init(
567 &space.limbs,
568 (try val.getUnsignedIntAdvanced(mod, opt_sema)).?,
569 ).toConst(),
580570 else => unreachable,
581571 },
582572 };
......@@ -614,10 +604,11 @@ pub const Value = struct {
614604 /// Asserts not undefined.
615605 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
616606 return switch (val.toIntern()) {
607 .undef => unreachable,
617608 .bool_false => 0,
618609 .bool_true => 1,
619 .undef => unreachable,
620610 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
611 .undef => unreachable,
621612 .int => |int| switch (int.storage) {
622613 .big_int => |big_int| big_int.to(u64) catch null,
623614 .u64 => |x| x,
......@@ -631,6 +622,26 @@ pub const Value = struct {
631622 else
632623 ty.toType().abiSize(mod),
633624 },
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 },
634645 else => null,
635646 },
636647 };
......@@ -646,7 +657,6 @@ pub const Value = struct {
646657 return switch (val.toIntern()) {
647658 .bool_false => 0,
648659 .bool_true => 1,
649 .undef => unreachable,
650660 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
651661 .int => |int| switch (int.storage) {
652662 .big_int => |big_int| big_int.to(i64) catch unreachable,
......@@ -830,24 +840,14 @@ pub const Value = struct {
830840 }
831841 },
832842 .Int, .Enum => {
843 if (buffer.len == 0) return;
833844 const bits = ty.intInfo(mod).bits;
834 const abi_size = @intCast(usize, ty.abiSize(mod));
835
836 const int_val = try val.enumToInt(ty, mod);
845 if (bits == 0) return;
837846
838 if (abi_size == 0) return;
839 if (abi_size <= @sizeOf(u64)) {
840 const ip_key = mod.intern_pool.indexToKey(int_val.toIntern());
841 const int: u64 = switch (ip_key.int.storage) {
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);
847 switch (mod.intern_pool.indexToKey((try val.enumToInt(ty, mod)).toIntern()).int.storage) {
848 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
849 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
850 else => unreachable,
851851 }
852852 },
853853 .Float => switch (ty.floatBits(target)) {
......@@ -1075,25 +1075,40 @@ pub const Value = struct {
10751075 return Value.true;
10761076 }
10771077 },
1078 .Int, .Enum => {
1078 .Int, .Enum => |ty_tag| {
10791079 if (buffer.len == 0) return mod.intValue(ty, 0);
10801080 const int_info = ty.intInfo(mod);
1081 const abi_size = @intCast(usize, ty.abiSize(mod));
1082
10831081 const bits = int_info.bits;
10841082 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);
1094 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
1095 return mod.intValue_big(ty, bigint.toConst());
1084 // Fast path for integers <= u64
1085 if (bits <= 64) {
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);
10961101 }
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());
10971112 },
10981113 .Float => return (try mod.intern(.{ .float = .{
10991114 .ty = ty.toIntern(),
......@@ -1764,7 +1779,7 @@ pub const Value = struct {
17641779 },
17651780 .opt => |opt| switch (opt.val) {
17661781 .none => false,
1767 else => opt.val.toValue().canMutateComptimeVarState(mod),
1782 else => |payload| payload.toValue().canMutateComptimeVarState(mod),
17681783 },
17691784 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
17701785 if (elem.toValue().canMutateComptimeVarState(mod)) break true;
......@@ -1949,43 +1964,51 @@ pub const Value = struct {
19491964 start: usize,
19501965 end: usize,
19511966 ) error{OutOfMemory}!Value {
1952 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1953 .ptr => |ptr| switch (ptr.addr) {
1954 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
1955 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
1956 .sliceArray(mod, arena, start, end),
1957 .comptime_field => |comptime_field| comptime_field.toValue()
1958 .sliceArray(mod, arena, start, end),
1959 .elem => |elem| elem.base.toValue()
1960 .sliceArray(mod, arena, start + elem.index, end + elem.index),
1967 return switch (val.ip_index) {
1968 .none => switch (val.tag()) {
1969 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
1970 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
1971 .repeated => val,
1972 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
19611973 else => unreachable,
19621974 },
1963 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
1964 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {
1965 .array_type => |array_type| try mod.arrayType(.{
1966 .len = @intCast(u32, end - start),
1967 .child = array_type.child,
1968 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1969 }),
1970 .vector_type => |vector_type| try mod.vectorType(.{
1971 .len = @intCast(u32, end - start),
1972 .child = vector_type.child,
1973 }),
1975 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1976 .ptr => |ptr| switch (ptr.addr) {
1977 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
1978 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
1979 .sliceArray(mod, arena, start, end),
1980 .comptime_field => |comptime_field| comptime_field.toValue()
1981 .sliceArray(mod, arena, start, end),
1982 .elem => |elem| elem.base.toValue()
1983 .sliceArray(mod, arena, start + elem.index, end + elem.index),
19741984 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 },
19801985 },
1981 } })).toValue(),
1982 else => unreachable,
1986 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
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 },
19832007 };
19842008 }
19852009
19862010 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
19872011 return switch (val.ip_index) {
1988 .undef => Value.undef,
19892012 .none => switch (val.tag()) {
19902013 .aggregate => {
19912014 const field_values = val.castTag(.aggregate).?.data;
......@@ -1999,6 +2022,9 @@ pub const Value = struct {
19992022 else => unreachable,
20002023 },
20012024 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
2025 .undef => |ty| (try mod.intern(.{
2026 .undef = ty.toType().structFieldType(index, mod).toIntern(),
2027 })).toValue(),
20022028 .aggregate => |aggregate| switch (aggregate.storage) {
20032029 .bytes => |bytes| try mod.intern(.{ .int = .{
20042030 .ty = .u8_type,
......@@ -2108,6 +2134,7 @@ pub const Value = struct {
21082134 .null_value => true,
21092135
21102136 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2137 .undef => unreachable,
21112138 .int => {
21122139 var buf: BigIntSpace = undefined;
21132140 return val.toBigInt(&buf, mod).eqZero();
......@@ -2141,9 +2168,13 @@ pub const Value = struct {
21412168
21422169 /// Value of the optional, null if optional has no payload.
21432170 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2144 return switch (mod.intern_pool.indexToKey(val.toIntern()).opt.val) {
2145 .none => null,
2146 else => |index| index.toValue(),
2171 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2172 .opt => |opt| switch (opt.val) {
2173 .none => null,
2174 else => |payload| payload.toValue(),
2175 },
2176 .ptr => val,
2177 else => unreachable,
21472178 };
21482179 }
21492180
......@@ -2152,6 +2183,7 @@ pub const Value = struct {
21522183 return switch (self.toIntern()) {
21532184 .undef => unreachable,
21542185 else => switch (mod.intern_pool.indexToKey(self.toIntern())) {
2186 .undef => unreachable,
21552187 .float => true,
21562188 else => false,
21572189 },
......@@ -2182,28 +2214,26 @@ pub const Value = struct {
21822214 }
21832215
21842216 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
2185 return switch (val.toIntern()) {
2186 .undef => val,
2187 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2188 .int => |int| switch (int.storage) {
2189 .big_int => |big_int| {
2190 const float = bigIntToFloat(big_int.limbs, big_int.positive);
2191 return mod.floatValue(float_ty, float);
2192 },
2193 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
2194 .lazy_align => |ty| if (opt_sema) |sema| {
2195 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2196 } else {
2197 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
2198 },
2199 .lazy_size => |ty| if (opt_sema) |sema| {
2200 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2201 } else {
2202 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
2203 },
2217 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2218 .undef => (try mod.intern(.{ .undef = float_ty.toIntern() })).toValue(),
2219 .int => |int| switch (int.storage) {
2220 .big_int => |big_int| {
2221 const float = bigIntToFloat(big_int.limbs, big_int.positive);
2222 return mod.floatValue(float_ty, float);
2223 },
2224 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
2225 .lazy_align => |ty| if (opt_sema) |sema| {
2226 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2227 } else {
2228 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
2229 },
2230 .lazy_size => |ty| if (opt_sema) |sema| {
2231 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2232 } else {
2233 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
22042234 },
2205 else => unreachable,
22062235 },
2236 else => unreachable,
22072237 };
22082238 }
22092239
tools/lldb_pretty_printers.py+13-13
......@@ -455,21 +455,21 @@ class InternPool_Index_SynthProvider:
455455 elif encoding_field.name == 'trailing':
456456 trailing_data = lldb.SBData()
457457 for trailing_field in encoding_field.type.fields:
458 if trailing_field.type.IsAggregateType():
459 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
460 len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
461 trailing_data.Append(lldb.SBData.CreateDataFromInt(len, trailing_data.GetAddressByteSize()))
462 extra_index += len
463 else:
464 pass
458 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
459 trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
460 trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize()))
461 extra_index += trailing_len
465462 self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)
466463 else:
467 path = encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split('.')
468 if path[0] == 'data':
469 dynamic_value = self.data
470 for name in path[1:]:
471 dynamic_value = dynamic_value.GetChildMemberWithName(name)
472 dynamic_values[encoding_field.name] = dynamic_value
464 for path in encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split(' orelse '):
465 if path.startswith('data.'):
466 root = self.data
467 path = path[len('data'):]
468 else: return
469 dynamic_value = root.GetValueForExpressionPath(path)
470 if dynamic_value:
471 dynamic_values[encoding_field.name] = dynamic_value
472 break
473473 except: pass
474474 def has_children(self): return True
475475 def num_children(self): return 2 + (self.trailing is not None)