| 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 | 1416 | only_possible_value: DataIsIndex, |
| 1417 | 1417 | union_value: struct { data: *Key.Union }, |
| 1418 | 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 | 1425 | repeated: struct { data: *Repeated }, |
| 1421 | 1426 | |
| 1422 | 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 | 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 | 4447 | .err => |err| if (ip.isErrorSetType(new_ty)) |
| 4443 | 4448 | return ip.get(gpa, .{ .err = .{ |
| ... | ... | @@ -4622,7 +4627,7 @@ pub fn isErrorUnionType(ip: InternPool, ty: Index) bool { |
| 4622 | 4627 | |
| 4623 | 4628 | pub fn isAggregateType(ip: InternPool, ty: Index) bool { |
| 4624 | 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 | 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 | 6678 | |
| 6679 | 6679 | pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type { |
| 6680 | 6680 | var canon_info = info; |
| 6681 | const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod); | |
| 6681 | 6682 | |
| 6682 | 6683 | // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee |
| 6683 | 6684 | // type, we change it to 0 here. If this causes an assertion trip because the |
| 6684 | 6685 | // pointee type needs to be resolved more, that needs to be done before calling |
| 6685 | 6686 | // this ptr() function. |
| 6686 | 6687 | 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)) { | |
| 6689 | 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 | 6694 | // Canonicalize host_size. If it matches the bit size of the pointee type, |
| 6695 | 6695 | // we change it to 0 here. If this causes an assertion trip, the pointee type |
| 6696 | 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 | 6698 | const elem_bit_size = info.elem_type.toType().bitSize(mod); |
| 6699 | 6699 | assert(info.bit_offset + elem_bit_size <= info.host_size * 8); |
| 6700 | 6700 | if (info.host_size * 8 == elem_bit_size) { |
| ... | ... | @@ -6782,21 +6782,7 @@ pub fn errorSetFromUnsortedNames( |
| 6782 | 6782 | |
| 6783 | 6783 | /// Supports optionals in addition to pointers. |
| 6784 | 6784 | pub 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); | |
| 6800 | 6786 | } |
| 6801 | 6787 | |
| 6802 | 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 | 6790 | assert(ty.zigTypeTag(mod) == .Pointer); |
| 6805 | 6791 | const i = try intern(mod, .{ .ptr = .{ |
| 6806 | 6792 | .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) }, | |
| 6811 | 6794 | } }); |
| 6812 | 6795 | return i.toValue(); |
| 6813 | 6796 | } |
| ... | ... | @@ -6954,7 +6937,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { |
| 6954 | 6937 | const key = mod.intern_pool.indexToKey(val.toIntern()); |
| 6955 | 6938 | switch (key.int.storage) { |
| 6956 | 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 | 6941 | assert(sign); |
| 6959 | 6942 | // Protect against overflow in the following negation. |
| 6960 | 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 | 9510 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}); |
| 9511 | 9511 | } |
| 9512 | 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 | 9518 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); |
| 9516 | 9519 | return block.addUnOp(.ptrtoint, ptr); |
| ... | ... | @@ -27879,7 +27882,7 @@ fn beginComptimePtrMutation( |
| 27879 | 27882 | .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }), |
| 27880 | 27883 | .opt => |opt| switch (opt.val) { |
| 27881 | 27884 | .none => try mod.intern(.{ .undef = payload_ty.toIntern() }), |
| 27882 | else => opt.val, | |
| 27885 | else => |payload| payload, | |
| 27883 | 27886 | }, |
| 27884 | 27887 | else => unreachable, |
| 27885 | 27888 | }; |
| ... | ... | @@ -28438,7 +28441,7 @@ fn beginComptimePtrLoad( |
| 28438 | 28441 | }, |
| 28439 | 28442 | .opt => |opt| switch (opt.val) { |
| 28440 | 28443 | .none => return sema.fail(block, src, "attempt to use null value", .{}), |
| 28441 | else => opt.val, | |
| 28444 | else => |payload| payload, | |
| 28442 | 28445 | }, |
| 28443 | 28446 | else => unreachable, |
| 28444 | 28447 | }.toValue(), |
| ... | ... | @@ -28591,7 +28594,7 @@ fn beginComptimePtrLoad( |
| 28591 | 28594 | }, |
| 28592 | 28595 | .opt => |opt| switch (opt.val) { |
| 28593 | 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 | 28599 | else => unreachable, |
| 28597 | 28600 | }; |
| ... | ... | @@ -28931,35 +28934,53 @@ fn coerceAnonStructToUnion( |
| 28931 | 28934 | ) !Air.Inst.Ref { |
| 28932 | 28935 | const mod = sema.mod; |
| 28933 | 28936 | 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); | |
| 28949 | 28974 | |
| 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. | |
| 28952 | 28977 | |
| 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 | }, | |
| 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 | 28986 | fn coerceAnonStructToUnionPtrs( |
| ... | ... | @@ -29193,16 +29214,27 @@ fn coerceTupleToStruct( |
| 29193 | 29214 | @memset(field_refs, .none); |
| 29194 | 29215 | |
| 29195 | 29216 | const inst_ty = sema.typeOf(inst); |
| 29196 | const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type; | |
| 29197 | 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 | 29227 | const field_i = @intCast(u32, field_index_usize); |
| 29200 | 29228 | 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 | }; | |
| 29206 | 29238 | const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| 29207 | 29239 | const field = fields.values()[field_index]; |
| 29208 | 29240 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| ... | ... | @@ -29281,40 +29313,72 @@ fn coerceTupleToTuple( |
| 29281 | 29313 | inst_src: LazySrcLoc, |
| 29282 | 29314 | ) !Air.Inst.Ref { |
| 29283 | 29315 | 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); | |
| 29286 | 29325 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 29287 | 29326 | @memset(field_refs, .none); |
| 29288 | 29327 | |
| 29289 | 29328 | 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; | |
| 29292 | 29338 | |
| 29293 | 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 | 29341 | const field_i = @intCast(u32, field_index_usize); |
| 29296 | 29342 | 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 | }; | |
| 29302 | 29352 | |
| 29303 | 29353 | if (mem.eql(u8, field_name, "len")) { |
| 29304 | 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 | 29371 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); |
| 29308 | 29372 | |
| 29309 | 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 | 29375 | field_refs[field_index] = coerced; |
| 29312 | 29376 | if (default_val != .none) { |
| 29313 | 29377 | const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { |
| 29314 | 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 | 29382 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i); |
| 29319 | 29383 | } |
| 29320 | 29384 | } |
| ... | ... | @@ -29331,14 +29395,18 @@ fn coerceTupleToTuple( |
| 29331 | 29395 | var root_msg: ?*Module.ErrorMsg = null; |
| 29332 | 29396 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 29333 | 29397 | |
| 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| { | |
| 29340 | 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 | 29410 | const field_src = inst_src; // TODO better source location |
| 29343 | 29411 | if (default_val == .none) { |
| 29344 | 29412 | if (tuple_ty.isTuple(mod)) { |
| ... | ... | @@ -29362,7 +29430,12 @@ fn coerceTupleToTuple( |
| 29362 | 29430 | if (runtime_src == null) { |
| 29363 | 29431 | field_vals[i] = default_val; |
| 29364 | 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 | 34032 | field_src: LazySrcLoc, |
| 33960 | 34033 | ) !u32 { |
| 33961 | 34034 | 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, | |
| 33967 | 34049 | } |
| 33968 | 34050 | return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{ |
| 33969 | 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 | 34088 | ); |
| 34007 | 34089 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 34008 | 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 | 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 | 254 | .ptr => return writer.writeAll("(ptr)"), |
| 255 | 255 | .opt => |opt| switch (opt.val) { |
| 256 | 256 | .none => return writer.writeAll("null"), |
| 257 | else => { | |
| 258 | val = opt.val.toValue(); | |
| 257 | else => |payload| { | |
| 258 | val = payload.toValue(); | |
| 259 | 259 | ty = ty.optionalChild(mod); |
| 260 | 260 | }, |
| 261 | 261 | }, |
src/codegen/c.zig+2-2| ... | ... | @@ -1313,7 +1313,7 @@ pub const DeclGen = struct { |
| 1313 | 1313 | |
| 1314 | 1314 | if (ty.optionalReprIsPayload(mod)) switch (opt.val) { |
| 1315 | 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 | 1319 | if (!location.isInitializer()) { |
| ... | ... | @@ -1325,7 +1325,7 @@ pub const DeclGen = struct { |
| 1325 | 1325 | try writer.writeAll("{ .payload = "); |
| 1326 | 1326 | try dg.renderValue(writer, payload_ty, switch (opt.val) { |
| 1327 | 1327 | .none => try mod.intern(.{ .undef = payload_ty.ip_index }), |
| 1328 | else => opt.val, | |
| 1328 | else => |payload| payload, | |
| 1329 | 1329 | }.toValue(), initializer_type); |
| 1330 | 1330 | try writer.writeAll(", .is_null = "); |
| 1331 | 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 | 3430 | const llvm_ty = try dg.lowerType(tv.ty); |
| 3431 | 3431 | if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) { |
| 3432 | 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 | 3435 | assert(payload_ty.zigTypeTag(mod) != .Fn); |
| 3436 | 3436 |
src/type.zig+2-2| ... | ... | @@ -630,7 +630,6 @@ pub const Type = struct { |
| 630 | 630 | pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool { |
| 631 | 631 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 632 | 632 | .int_type, |
| 633 | .ptr_type, | |
| 634 | 633 | .vector_type, |
| 635 | 634 | => true, |
| 636 | 635 | |
| ... | ... | @@ -646,6 +645,7 @@ pub const Type = struct { |
| 646 | 645 | |
| 647 | 646 | .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod), |
| 648 | 647 | .opt_type => ty.isPtrLikeOptional(mod), |
| 648 | .ptr_type => |ptr_type| ptr_type.size != .Slice, | |
| 649 | 649 | |
| 650 | 650 | .simple_type => |t| switch (t) { |
| 651 | 651 | .f16, |
| ... | ... | @@ -1578,7 +1578,7 @@ pub const Type = struct { |
| 1578 | 1578 | .int_type => |int_type| return int_type.bits, |
| 1579 | 1579 | .ptr_type => |ptr_type| switch (ptr_type.size) { |
| 1580 | 1580 | .Slice => return target.ptrBitWidth() * 2, |
| 1581 | else => return target.ptrBitWidth() * 2, | |
| 1581 | else => return target.ptrBitWidth(), | |
| 1582 | 1582 | }, |
| 1583 | 1583 | .anyframe_type => return target.ptrBitWidth(), |
| 1584 | 1584 |
src/value.zig+128-98| ... | ... | @@ -363,7 +363,7 @@ pub const Value = struct { |
| 363 | 363 | }, |
| 364 | 364 | .slice => { |
| 365 | 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 | 367 | var ptr_key = mod.intern_pool.indexToKey(ptr).ptr; |
| 368 | 368 | assert(ptr_key.len == .none); |
| 369 | 369 | ptr_key.ty = ty.toIntern(); |
| ... | ... | @@ -547,7 +547,6 @@ pub const Value = struct { |
| 547 | 547 | return switch (val.toIntern()) { |
| 548 | 548 | .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(), |
| 549 | 549 | .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(), |
| 550 | .undef => unreachable, | |
| 551 | 550 | .null_value => BigIntMutable.init(&space.limbs, 0).toConst(), |
| 552 | 551 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 553 | 552 | .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema), |
| ... | ... | @@ -564,19 +563,10 @@ pub const Value = struct { |
| 564 | 563 | }, |
| 565 | 564 | }, |
| 566 | 565 | .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(), | |
| 580 | 570 | else => unreachable, |
| 581 | 571 | }, |
| 582 | 572 | }; |
| ... | ... | @@ -614,10 +604,11 @@ pub const Value = struct { |
| 614 | 604 | /// Asserts not undefined. |
| 615 | 605 | pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 { |
| 616 | 606 | return switch (val.toIntern()) { |
| 607 | .undef => unreachable, | |
| 617 | 608 | .bool_false => 0, |
| 618 | 609 | .bool_true => 1, |
| 619 | .undef => unreachable, | |
| 620 | 610 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 611 | .undef => unreachable, | |
| 621 | 612 | .int => |int| switch (int.storage) { |
| 622 | 613 | .big_int => |big_int| big_int.to(u64) catch null, |
| 623 | 614 | .u64 => |x| x, |
| ... | ... | @@ -631,6 +622,26 @@ pub const Value = struct { |
| 631 | 622 | else |
| 632 | 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 | 645 | else => null, |
| 635 | 646 | }, |
| 636 | 647 | }; |
| ... | ... | @@ -646,7 +657,6 @@ pub const Value = struct { |
| 646 | 657 | return switch (val.toIntern()) { |
| 647 | 658 | .bool_false => 0, |
| 648 | 659 | .bool_true => 1, |
| 649 | .undef => unreachable, | |
| 650 | 660 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 651 | 661 | .int => |int| switch (int.storage) { |
| 652 | 662 | .big_int => |big_int| big_int.to(i64) catch unreachable, |
| ... | ... | @@ -830,24 +840,14 @@ pub const Value = struct { |
| 830 | 840 | } |
| 831 | 841 | }, |
| 832 | 842 | .Int, .Enum => { |
| 843 | if (buffer.len == 0) return; | |
| 833 | 844 | 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; | |
| 837 | 846 | |
| 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, | |
| 851 | 851 | } |
| 852 | 852 | }, |
| 853 | 853 | .Float => switch (ty.floatBits(target)) { |
| ... | ... | @@ -1075,25 +1075,40 @@ pub const Value = struct { |
| 1075 | 1075 | return Value.true; |
| 1076 | 1076 | } |
| 1077 | 1077 | }, |
| 1078 | .Int, .Enum => { | |
| 1078 | .Int, .Enum => |ty_tag| { | |
| 1079 | 1079 | if (buffer.len == 0) return mod.intValue(ty, 0); |
| 1080 | 1080 | const int_info = ty.intInfo(mod); |
| 1081 | const abi_size = @intCast(usize, ty.abiSize(mod)); | |
| 1082 | ||
| 1083 | 1081 | const bits = int_info.bits; |
| 1084 | 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); | |
| 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); | |
| 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 | 1113 | .Float => return (try mod.intern(.{ .float = .{ |
| 1099 | 1114 | .ty = ty.toIntern(), |
| ... | ... | @@ -1764,7 +1779,7 @@ pub const Value = struct { |
| 1764 | 1779 | }, |
| 1765 | 1780 | .opt => |opt| switch (opt.val) { |
| 1766 | 1781 | .none => false, |
| 1767 | else => opt.val.toValue().canMutateComptimeVarState(mod), | |
| 1782 | else => |payload| payload.toValue().canMutateComptimeVarState(mod), | |
| 1768 | 1783 | }, |
| 1769 | 1784 | .aggregate => |aggregate| for (aggregate.storage.values()) |elem| { |
| 1770 | 1785 | if (elem.toValue().canMutateComptimeVarState(mod)) break true; |
| ... | ... | @@ -1949,43 +1964,51 @@ pub const Value = struct { |
| 1949 | 1964 | start: usize, |
| 1950 | 1965 | end: usize, |
| 1951 | 1966 | ) 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]), | |
| 1961 | 1973 | else => unreachable, |
| 1962 | 1974 | }, |
| 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), | |
| 1974 | 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(), | |
| 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 | }, | |
| 1983 | 2007 | }; |
| 1984 | 2008 | } |
| 1985 | 2009 | |
| 1986 | 2010 | pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value { |
| 1987 | 2011 | return switch (val.ip_index) { |
| 1988 | .undef => Value.undef, | |
| 1989 | 2012 | .none => switch (val.tag()) { |
| 1990 | 2013 | .aggregate => { |
| 1991 | 2014 | const field_values = val.castTag(.aggregate).?.data; |
| ... | ... | @@ -1999,6 +2022,9 @@ pub const Value = struct { |
| 1999 | 2022 | else => unreachable, |
| 2000 | 2023 | }, |
| 2001 | 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 | 2028 | .aggregate => |aggregate| switch (aggregate.storage) { |
| 2003 | 2029 | .bytes => |bytes| try mod.intern(.{ .int = .{ |
| 2004 | 2030 | .ty = .u8_type, |
| ... | ... | @@ -2108,6 +2134,7 @@ pub const Value = struct { |
| 2108 | 2134 | .null_value => true, |
| 2109 | 2135 | |
| 2110 | 2136 | else => return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 2137 | .undef => unreachable, | |
| 2111 | 2138 | .int => { |
| 2112 | 2139 | var buf: BigIntSpace = undefined; |
| 2113 | 2140 | return val.toBigInt(&buf, mod).eqZero(); |
| ... | ... | @@ -2141,9 +2168,13 @@ pub const Value = struct { |
| 2141 | 2168 | |
| 2142 | 2169 | /// Value of the optional, null if optional has no payload. |
| 2143 | 2170 | 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, | |
| 2147 | 2178 | }; |
| 2148 | 2179 | } |
| 2149 | 2180 | |
| ... | ... | @@ -2152,6 +2183,7 @@ pub const Value = struct { |
| 2152 | 2183 | return switch (self.toIntern()) { |
| 2153 | 2184 | .undef => unreachable, |
| 2154 | 2185 | else => switch (mod.intern_pool.indexToKey(self.toIntern())) { |
| 2186 | .undef => unreachable, | |
| 2155 | 2187 | .float => true, |
| 2156 | 2188 | else => false, |
| 2157 | 2189 | }, |
| ... | ... | @@ -2182,28 +2214,26 @@ pub const Value = struct { |
| 2182 | 2214 | } |
| 2183 | 2215 | |
| 2184 | 2216 | 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); | |
| 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 | 455 | elif encoding_field.name == 'trailing': |
| 456 | 456 | trailing_data = lldb.SBData() |
| 457 | 457 | 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 | |
| 465 | 462 | self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type) |
| 466 | 463 | 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 | |
| 473 | 473 | except: pass |
| 474 | 474 | def has_children(self): return True |
| 475 | 475 | def num_children(self): return 2 + (self.trailing is not None) |