| author | |
| committer | |
| log | 32692569656d9a178abb24f8fb7893395700cb62 |
| tree | c2f10d2ed2d1d5e0e6c1cd2d532c6d76d401a466 |
| parent | 3064d2aa7b9a8ea836cb70884b0640fe902ecc29 |
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 }, |
| 1421 | 1426 | ||
| 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 { |
| 4622 | 4627 | ||
| 4623 | pub fn isAggregateType(ip: InternPool, ty: Index) bool { | 4628 | pub 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! |
| 6678 | 6678 | ||
| 6679 | pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type { | 6679 | pub 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); | ||
| 6681 | 6682 | ||
| 6682 | // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee | 6683 | // 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 the | 6684 | // 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 calling | 6685 | // 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 type | 6695 | // 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( |
| 6782 | 6782 | ||
| 6783 | /// Supports optionals in addition to pointers. | 6783 | /// Supports optionals in addition to pointers. |
| 6784 | pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value { | 6784 | pub 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 | } |
| 6801 | 6787 | ||
| 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); | ||
| 28949 | 28974 | ||
| 28950 | // TODO add notes for where the anon struct was created to point out | 28975 | // TODO add notes for where the anon struct was created to point out |
| 28951 | // the extra fields. | 28976 | // the extra fields. |
| 28952 | 28977 | ||
| 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 | } |
| 28964 | 28985 | ||
| 28965 | fn coerceAnonStructToUnionPtrs( | 28986 | fn coerceAnonStructToUnionPtrs( |
| ... | @@ -29193,16 +29214,27 @@ fn coerceTupleToStruct( | ... | @@ -29193,16 +29214,27 @@ fn coerceTupleToStruct( |
| 29193 | @memset(field_refs, .none); | 29214 | @memset(field_refs, .none); |
| 29194 | 29215 | ||
| 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 location | 29228 | 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/15709 | 29230 | 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 | else | 29232 | 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); |
| 29288 | 29327 | ||
| 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; | ||
| 29292 | 29338 | ||
| 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 location | 29342 | 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/15709 | 29344 | 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 | else | 29346 | 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 | }; | ||
| 29302 | 29352 | ||
| 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 | } |
| 29306 | 29356 | ||
| 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); |
| 29308 | 29372 | ||
| 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 | }; |
| 29316 | 29380 | ||
| 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); |
| 29333 | 29397 | ||
| 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; |
| 29341 | 29400 | ||
| 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 location | 29410 | 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 | } |
| 29368 | 29441 | ||
| ... | @@ -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 | } |
| 34011 | 34097 |
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 { |
| 1313 | 1313 | ||
| 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 | }; |
| 1318 | 1318 | ||
| 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); |
| 3436 | 3436 |
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, |
| 636 | 635 | ||
| ... | @@ -646,6 +645,7 @@ pub const Type = struct { | ... | @@ -646,6 +645,7 @@ pub const Type = struct { |
| 646 | 645 | ||
| 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, | ||
| 649 | 649 | ||
| 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(), |
| 1584 | 1584 |
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 | else | 622 | 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); | ||
| 837 | 846 | ||
| 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); | ||
| 1092 | 1083 | ||
| 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 | } |
| 1985 | 2009 | ||
| 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, |
| 2109 | 2135 | ||
| 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 { |
| 2141 | 2168 | ||
| 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 | } |
| 2149 | 2180 | ||
| ... | @@ -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 | } |
| 2183 | 2215 | ||
| 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 | } |
| 2209 | 2239 |
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].unsigned | 460 | 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.data | 466 | 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_value | 469 | dynamic_value = root.GetValueForExpressionPath(path) |
| 470 | if dynamic_value: | ||
| 471 | dynamic_values[encoding_field.name] = dynamic_value | ||
| 472 | break | ||
| 473 | except: pass | 473 | except: pass |
| 474 | def has_children(self): return True | 474 | 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) |