authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-20 17:55:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:54-07:00
log7e19c9566860e78ad536aaa678af8c32531fade9
treed6e90d6c1cf0d13bee52b8107804837658486927
parent65d65f5dda144d76ea9bbd82b2b5aacb09d7ae34

Sema: move `inferred_alloc_const/mut_type` to InternPool

Now, all types are migrated to use `InternPool`. The `Type.Tag` enum is deleted in this commit.

11 files changed, 594 insertions(+), 866 deletions(-)

src/Air.zig+2
...@@ -905,6 +905,8 @@ pub const Inst = struct {...@@ -905,6 +905,8 @@ pub const Inst = struct {
905 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),905 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),
906 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),906 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
907 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),907 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
908 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
909 inferred_alloc_mut_type = @enumToInt(InternPool.Index.inferred_alloc_mut_type),
908 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),910 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
909 undef = @enumToInt(InternPool.Index.undef),911 undef = @enumToInt(InternPool.Index.undef),
910 zero = @enumToInt(InternPool.Index.zero),912 zero = @enumToInt(InternPool.Index.zero),
src/InternPool.zig+13-4
...@@ -959,6 +959,8 @@ pub const Index = enum(u32) {...@@ -959,6 +959,8 @@ pub const Index = enum(u32) {
959 const_slice_u8_sentinel_0_type,959 const_slice_u8_sentinel_0_type,
960 anyerror_void_error_union_type,960 anyerror_void_error_union_type,
961 generic_poison_type,961 generic_poison_type,
962 inferred_alloc_const_type,
963 inferred_alloc_mut_type,
962 /// `@TypeOf(.{})`964 /// `@TypeOf(.{})`
963 empty_struct_type,965 empty_struct_type,
964966
...@@ -1009,10 +1011,7 @@ pub const Index = enum(u32) {...@@ -1009,10 +1011,7 @@ pub const Index = enum(u32) {
10091011
1010 pub fn toType(i: Index) @import("type.zig").Type {1012 pub fn toType(i: Index) @import("type.zig").Type {
1011 assert(i != .none);1013 assert(i != .none);
1012 return .{1014 return .{ .ip_index = i };
1013 .ip_index = i,
1014 .legacy = undefined,
1015 };
1016 }1015 }
10171016
1018 pub fn toValue(i: Index) @import("value.zig").Value {1017 pub fn toValue(i: Index) @import("value.zig").Value {
...@@ -1195,6 +1194,10 @@ pub const static_keys = [_]Key{...@@ -1195,6 +1194,10 @@ pub const static_keys = [_]Key{
11951194
1196 // generic_poison_type1195 // generic_poison_type
1197 .{ .simple_type = .generic_poison },1196 .{ .simple_type = .generic_poison },
1197 // inferred_alloc_const_type
1198 .{ .simple_type = .inferred_alloc_const },
1199 // inferred_alloc_mut_type
1200 .{ .simple_type = .inferred_alloc_mut },
11981201
1199 // empty_struct_type1202 // empty_struct_type
1200 .{ .anon_struct_type = .{1203 .{ .anon_struct_type = .{
...@@ -1568,6 +1571,12 @@ pub const SimpleType = enum(u32) {...@@ -1568,6 +1571,12 @@ pub const SimpleType = enum(u32) {
1568 type_info,1571 type_info,
15691572
1570 generic_poison,1573 generic_poison,
1574 /// TODO: remove this from `SimpleType`; instead make it only a special `Index` tag like
1575 /// `var_args_param_type`.
1576 inferred_alloc_const,
1577 /// TODO: remove this from `SimpleType`; instead make it only a special `Index` tag like
1578 /// `var_args_param_type`.
1579 inferred_alloc_mut,
1571};1580};
15721581
1573pub const SimpleValue = enum(u32) {1582pub const SimpleValue = enum(u32) {
src/Module.zig+1-1
...@@ -6818,7 +6818,7 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {...@@ -6818,7 +6818,7 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6818}6818}
68196819
6820pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {6820pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
6821 const info = ptr_ty.ptrInfoIp(mod.intern_pool);6821 const info = Type.ptrInfoIp(mod.intern_pool, ptr_ty.toIntern());
6822 return mod.ptrType(.{6822 return mod.ptrType(.{
6823 .elem_type = new_child.toIntern(),6823 .elem_type = new_child.toIntern(),
68246824
src/Sema.zig+51-45
...@@ -904,10 +904,10 @@ fn analyzeBodyInner(...@@ -904,10 +904,10 @@ fn analyzeBodyInner(
904 const air_inst: Air.Inst.Ref = switch (tags[inst]) {904 const air_inst: Air.Inst.Ref = switch (tags[inst]) {
905 // zig fmt: off905 // zig fmt: off
906 .alloc => try sema.zirAlloc(block, inst),906 .alloc => try sema.zirAlloc(block, inst),
907 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),907 .alloc_inferred => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_const_type }),
908 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),908 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_mut_type }),
909 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_const)),909 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_const_type }),
910 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_mut)),910 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_mut_type }),
911 .alloc_mut => try sema.zirAllocMut(block, inst),911 .alloc_mut => try sema.zirAllocMut(block, inst),
912 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),912 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),
913 .make_ptr_const => try sema.zirMakePtrConst(block, inst),913 .make_ptr_const => try sema.zirMakePtrConst(block, inst),
...@@ -3471,9 +3471,9 @@ fn zirAllocExtended(...@@ -3471,9 +3471,9 @@ fn zirAllocExtended(
3471 } else 0;3471 } else 0;
34723472
3473 const inferred_alloc_ty = if (small.is_const)3473 const inferred_alloc_ty = if (small.is_const)
3474 Type.initTag(.inferred_alloc_const)3474 Type{ .ip_index = .inferred_alloc_const_type }
3475 else3475 else
3476 Type.initTag(.inferred_alloc_mut);3476 Type{ .ip_index = .inferred_alloc_mut_type };
34773477
3478 if (block.is_comptime or small.is_comptime) {3478 if (block.is_comptime or small.is_comptime) {
3479 if (small.has_type) {3479 if (small.has_type) {
...@@ -3707,9 +3707,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3707,9 +3707,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3707 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);3707 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
3708 const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload;3708 const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload;
3709 const ptr_val = sema.air_values.items[value_index];3709 const ptr_val = sema.air_values.items[value_index];
3710 const var_is_mut = switch (sema.typeOf(ptr).tag()) {3710 const var_is_mut = switch (sema.typeOf(ptr).toIntern()) {
3711 .inferred_alloc_const => false,3711 .inferred_alloc_const_type => false,
3712 .inferred_alloc_mut => true,3712 .inferred_alloc_mut_type => true,
3713 else => unreachable,
3713 };3714 };
3714 const target = sema.mod.getTarget();3715 const target = sema.mod.getTarget();
37153716
...@@ -7451,7 +7452,7 @@ fn instantiateGenericCall(...@@ -7451,7 +7452,7 @@ fn instantiateGenericCall(
7451 };7452 };
7452 arg_val.hashUncoerced(arg_ty, &hasher, mod);7453 arg_val.hashUncoerced(arg_ty, &hasher, mod);
7453 if (is_anytype) {7454 if (is_anytype) {
7454 arg_ty.hashWithHasher(&hasher, mod);7455 std.hash.autoHash(&hasher, arg_ty.toIntern());
7455 generic_args[i] = .{7456 generic_args[i] = .{
7456 .ty = arg_ty,7457 .ty = arg_ty,
7457 .val = arg_val,7458 .val = arg_val,
...@@ -7465,7 +7466,7 @@ fn instantiateGenericCall(...@@ -7465,7 +7466,7 @@ fn instantiateGenericCall(
7465 };7466 };
7466 }7467 }
7467 } else if (is_anytype) {7468 } else if (is_anytype) {
7468 arg_ty.hashWithHasher(&hasher, mod);7469 std.hash.autoHash(&hasher, arg_ty.toIntern());
7469 generic_args[i] = .{7470 generic_args[i] = .{
7470 .ty = arg_ty,7471 .ty = arg_ty,
7471 .val = Value.generic_poison,7472 .val = Value.generic_poison,
...@@ -8233,7 +8234,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8233,7 +8234,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8233 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;8234 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
8234 const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));8235 const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));
8235 return sema.addConstant(8236 return sema.addConstant(
8236 .{ .ip_index = .enum_literal_type, .legacy = undefined },8237 .{ .ip_index = .enum_literal_type },
8237 try Value.Tag.enum_literal.create(sema.arena, duped_name),8238 try Value.Tag.enum_literal.create(sema.arena, duped_name),
8238 );8239 );
8239}8240}
...@@ -13278,9 +13279,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13278,9 +13279,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13278 const rhs_val = maybe_rhs_val orelse unreachable;13279 const rhs_val = maybe_rhs_val orelse unreachable;
13279 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;13280 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;
13280 if (!rem.compareAllWithZero(.eq, mod)) {13281 if (!rem.compareAllWithZero(.eq, mod)) {
13281 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{13282 return sema.fail(
13282 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),13283 block,
13283 });13284 src,
13285 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",
13286 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(resolved_type, mod) },
13287 );
13284 }13288 }
13285 }13289 }
1328613290
...@@ -13386,7 +13390,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13386,7 +13390,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1338613390
13387 const air_tag = if (is_int) blk: {13391 const air_tag = if (is_int) blk: {
13388 if (lhs_ty.isSignedInt(mod) or rhs_ty.isSignedInt(mod)) {13392 if (lhs_ty.isSignedInt(mod) or rhs_ty.isSignedInt(mod)) {
13389 return sema.fail(block, src, "division with '{s}' and '{s}': signed integers must use @divTrunc, @divFloor, or @divExact", .{ @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()) });13393 return sema.fail(
13394 block,
13395 src,
13396 "division with '{}' and '{}': signed integers must use @divTrunc, @divFloor, or @divExact",
13397 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod) },
13398 );
13390 }13399 }
13391 break :blk Air.Inst.Tag.div_trunc;13400 break :blk Air.Inst.Tag.div_trunc;
13392 } else switch (block.float_mode) {13401 } else switch (block.float_mode) {
...@@ -23367,7 +23376,7 @@ fn validateRunTimeType(...@@ -23367,7 +23376,7 @@ fn validateRunTimeType(
23367 };23376 };
23368}23377}
2336923378
23370const TypeSet = std.HashMapUnmanaged(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage);23379const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void);
2337123380
23372fn explainWhyTypeIsComptime(23381fn explainWhyTypeIsComptime(
23373 sema: *Sema,23382 sema: *Sema,
...@@ -23453,7 +23462,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23453,7 +23462,7 @@ fn explainWhyTypeIsComptimeInner(
23453 },23462 },
2345423463
23455 .Struct => {23464 .Struct => {
23456 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;23465 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
2345723466
23458 if (mod.typeToStruct(ty)) |struct_obj| {23467 if (mod.typeToStruct(ty)) |struct_obj| {
23459 for (struct_obj.fields.values(), 0..) |field, i| {23468 for (struct_obj.fields.values(), 0..) |field, i| {
...@@ -23472,7 +23481,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23472,7 +23481,7 @@ fn explainWhyTypeIsComptimeInner(
23472 },23481 },
2347323482
23474 .Union => {23483 .Union => {
23475 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;23484 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
2347623485
23477 if (mod.typeToUnion(ty)) |union_obj| {23486 if (mod.typeToUnion(ty)) |union_obj| {
23478 for (union_obj.fields.values(), 0..) |field, i| {23487 for (union_obj.fields.values(), 0..) |field, i| {
...@@ -27459,8 +27468,8 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {...@@ -27459,8 +27468,8 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
27459 // different behavior depending on whether the types were inferred.27468 // different behavior depending on whether the types were inferred.
27460 // Something seems wrong here.27469 // Something seems wrong here.
27461 if (prev_ptr_ty.ip_index == .none) {27470 if (prev_ptr_ty.ip_index == .none) {
27462 if (prev_ptr_ty.tag() == .inferred_alloc_mut) return null;27471 if (prev_ptr_ty.ip_index == .inferred_alloc_mut_type) return null;
27463 if (prev_ptr_ty.tag() == .inferred_alloc_const) return null;27472 if (prev_ptr_ty.ip_index == .inferred_alloc_const_type) return null;
27464 }27473 }
2746527474
27466 const prev_ptr_child_ty = prev_ptr_ty.childType(mod);27475 const prev_ptr_child_ty = prev_ptr_ty.childType(mod);
...@@ -31677,6 +31686,9 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31677,6 +31686,9 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31677 .enum_literal,31686 .enum_literal,
31678 .type_info,31687 .type_info,
31679 => true,31688 => true,
31689
31690 .inferred_alloc_const => unreachable,
31691 .inferred_alloc_mut => unreachable,
31680 },31692 },
31681 .struct_type => |struct_type| {31693 .struct_type => |struct_type| {
31682 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;31694 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
...@@ -31931,6 +31943,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -31931,6 +31943,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31931 .bool_false => unreachable,31943 .bool_false => unreachable,
31932 .empty_struct => unreachable,31944 .empty_struct => unreachable,
31933 .generic_poison => unreachable,31945 .generic_poison => unreachable,
31946 .inferred_alloc_const_type => unreachable,
31947 .inferred_alloc_mut_type => unreachable,
3193431948
31935 .type_info_type => return sema.getBuiltinType("Type"),31949 .type_info_type => return sema.getBuiltinType("Type"),
31936 .extern_options_type => return sema.getBuiltinType("ExternOptions"),31950 .extern_options_type => return sema.getBuiltinType("ExternOptions"),
...@@ -33032,16 +33046,9 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -33032,16 +33046,9 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
33032/// TODO assert the return value matches `ty.onePossibleValue`33046/// TODO assert the return value matches `ty.onePossibleValue`
33033pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {33047pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33034 const mod = sema.mod;33048 const mod = sema.mod;
3303533049 return switch (ty.ip_index) {
33036 switch (ty.ip_index) {33050 .empty_struct_type => Value.empty_struct,
33037 .empty_struct_type => return Value.empty_struct,33051 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33038
33039 .none => switch (ty.tag()) {
33040 .inferred_alloc_const => unreachable,
33041 .inferred_alloc_mut => unreachable,
33042 },
33043
33044 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33045 .int_type => |int_type| {33052 .int_type => |int_type| {
33046 if (int_type.bits == 0) {33053 if (int_type.bits == 0) {
33047 return try mod.intValue(ty, 0);33054 return try mod.intValue(ty, 0);
...@@ -33123,6 +33130,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33123,6 +33130,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33123 .undefined => Value.undef,33130 .undefined => Value.undef,
3312433131
33125 .generic_poison => return error.GenericPoison,33132 .generic_poison => return error.GenericPoison,
33133 .inferred_alloc_const => unreachable,
33134 .inferred_alloc_mut => unreachable,
33126 },33135 },
33127 .struct_type => |struct_type| {33136 .struct_type => |struct_type| {
33128 const resolved_ty = try sema.resolveTypeFields(ty);33137 const resolved_ty = try sema.resolveTypeFields(ty);
...@@ -33245,7 +33254,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33245,7 +33254,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33245 .enum_tag => unreachable,33254 .enum_tag => unreachable,
33246 .aggregate => unreachable,33255 .aggregate => unreachable,
33247 },33256 },
33248 }33257 };
33249}33258}
3325033259
33251/// Returns the type of the AIR instruction.33260/// Returns the type of the AIR instruction.
...@@ -33563,16 +33572,15 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError...@@ -33563,16 +33572,15 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
33563/// This logic must be kept in sync with `Type.isPtrLikeOptional`.33572/// This logic must be kept in sync with `Type.isPtrLikeOptional`.
33564fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {33573fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
33565 const mod = sema.mod;33574 const mod = sema.mod;
3356633575 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33567 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33568 .ptr_type => |ptr_type| switch (ptr_type.size) {33576 .ptr_type => |ptr_type| switch (ptr_type.size) {
33569 .Slice => return null,33577 .Slice => null,
33570 .C => return ptr_type.elem_type.toType(),33578 .C => ptr_type.elem_type.toType(),
33571 .One, .Many => return ty,33579 .One, .Many => ty,
33572 },33580 },
33573 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {33581 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {
33574 .ptr_type => |ptr_type| switch (ptr_type.size) {33582 .ptr_type => |ptr_type| switch (ptr_type.size) {
33575 .Slice, .C => return null,33583 .Slice, .C => null,
33576 .Many, .One => {33584 .Many, .One => {
33577 if (ptr_type.is_allowzero) return null;33585 if (ptr_type.is_allowzero) return null;
3357833586
...@@ -33585,15 +33593,10 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {...@@ -33585,15 +33593,10 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
33585 return payload_ty;33593 return payload_ty;
33586 },33594 },
33587 },33595 },
33588 else => return null,33596 else => null,
33589 },33597 },
33590 else => return null,33598 else => null,
33591 };33599 };
33592
33593 switch (ty.tag()) {
33594 .inferred_alloc_const => unreachable,
33595 .inferred_alloc_mut => unreachable,
33596 }
33597}33600}
3359833601
33599/// `generic_poison` will return false.33602/// `generic_poison` will return false.
...@@ -33677,6 +33680,9 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33677,6 +33680,9 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33677 .enum_literal,33680 .enum_literal,
33678 .type_info,33681 .type_info,
33679 => true,33682 => true,
33683
33684 .inferred_alloc_const => unreachable,
33685 .inferred_alloc_mut => unreachable,
33680 },33686 },
33681 .struct_type => |struct_type| {33687 .struct_type => |struct_type| {
33682 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;33688 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
src/Zir.zig+2
...@@ -2112,6 +2112,8 @@ pub const Inst = struct {...@@ -2112,6 +2112,8 @@ pub const Inst = struct {
2112 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),2112 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),
2113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),2113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
2114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),2114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
2115 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
2116 inferred_alloc_mut_type = @enumToInt(InternPool.Index.inferred_alloc_mut_type),
2115 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),2117 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
2116 undef = @enumToInt(InternPool.Index.undef),2118 undef = @enumToInt(InternPool.Index.undef),
2117 zero = @enumToInt(InternPool.Index.zero),2119 zero = @enumToInt(InternPool.Index.zero),
src/codegen/c.zig+94-99
...@@ -5367,116 +5367,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5367,116 +5367,111 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5367 // Ensure complete type definition is visible before accessing fields.5367 // Ensure complete type definition is visible before accessing fields.
5368 _ = try f.typeToIndex(struct_ty, .complete);5368 _ = try f.typeToIndex(struct_ty, .complete);
53695369
5370 const field_name: CValue = switch (struct_ty.ip_index) {5370 const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5371 .none => switch (struct_ty.tag()) {5371 .struct_type => switch (struct_ty.containerLayout(mod)) {
5372 else => unreachable,5372 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
5373 },5373 .{ .field = extra.field_index }
5374 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {5374 else
5375 .struct_type => switch (struct_ty.containerLayout(mod)) {5375 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5376 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))5376 .Packed => {
5377 .{ .field = extra.field_index }5377 const struct_obj = mod.typeToStruct(struct_ty).?;
5378 else5378 const int_info = struct_ty.intInfo(mod);
5379 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5380 .Packed => {
5381 const struct_obj = mod.typeToStruct(struct_ty).?;
5382 const int_info = struct_ty.intInfo(mod);
5383
5384 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
53855379
5386 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);5380 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
5387 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
53885381
5389 const field_int_signedness = if (inst_ty.isAbiInt(mod))5382 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5390 inst_ty.intInfo(mod).signedness5383 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
5391 else
5392 .unsigned;
5393 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
53945384
5395 const temp_local = try f.allocLocal(inst, field_int_ty);5385 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5396 try f.writeCValue(writer, temp_local, .Other);5386 inst_ty.intInfo(mod).signedness
5397 try writer.writeAll(" = zig_wrap_");5387 else
5398 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);5388 .unsigned;
5399 try writer.writeAll("((");5389 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
5400 try f.renderType(writer, field_int_ty);5390
5391 const temp_local = try f.allocLocal(inst, field_int_ty);
5392 try f.writeCValue(writer, temp_local, .Other);
5393 try writer.writeAll(" = zig_wrap_");
5394 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
5395 try writer.writeAll("((");
5396 try f.renderType(writer, field_int_ty);
5397 try writer.writeByte(')');
5398 const cant_cast = int_info.bits > 64;
5399 if (cant_cast) {
5400 if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
5401 try writer.writeAll("zig_lo_");
5402 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5403 try writer.writeByte('(');
5404 }
5405 if (bit_offset > 0) {
5406 try writer.writeAll("zig_shr_");
5407 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5408 try writer.writeByte('(');
5409 }
5410 try f.writeCValue(writer, struct_byval, .Other);
5411 if (bit_offset > 0) {
5412 try writer.writeAll(", ");
5413 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5401 try writer.writeByte(')');5414 try writer.writeByte(')');
5402 const cant_cast = int_info.bits > 64;5415 }
5403 if (cant_cast) {5416 if (cant_cast) try writer.writeByte(')');
5404 if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});5417 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
5405 try writer.writeAll("zig_lo_");5418 try writer.writeAll(");\n");
5406 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);5419 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
5407 try writer.writeByte('(');
5408 }
5409 if (bit_offset > 0) {
5410 try writer.writeAll("zig_shr_");
5411 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
5412 try writer.writeByte('(');
5413 }
5414 try f.writeCValue(writer, struct_byval, .Other);
5415 if (bit_offset > 0) {
5416 try writer.writeAll(", ");
5417 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5418 try writer.writeByte(')');
5419 }
5420 if (cant_cast) try writer.writeByte(')');
5421 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
5422 try writer.writeAll(");\n");
5423 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
54245420
5425 const local = try f.allocLocal(inst, inst_ty);5421 const local = try f.allocLocal(inst, inst_ty);
5426 try writer.writeAll("memcpy(");5422 try writer.writeAll("memcpy(");
5427 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);5423 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
5428 try writer.writeAll(", ");5424 try writer.writeAll(", ");
5429 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);5425 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
5430 try writer.writeAll(", sizeof(");5426 try writer.writeAll(", sizeof(");
5431 try f.renderType(writer, inst_ty);5427 try f.renderType(writer, inst_ty);
5432 try writer.writeAll("));\n");5428 try writer.writeAll("));\n");
5433 try freeLocal(f, inst, temp_local.new_local, 0);5429 try freeLocal(f, inst, temp_local.new_local, 0);
5434 return local;5430 return local;
5435 },
5436 },5431 },
5432 },
54375433
5438 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)5434 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
5439 .{ .field = extra.field_index }5435 .{ .field = extra.field_index }
5440 else5436 else
5441 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },5437 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5438
5439 .union_type => |union_type| field_name: {
5440 const union_obj = mod.unionPtr(union_type.index);
5441 if (union_obj.layout == .Packed) {
5442 const operand_lval = if (struct_byval == .constant) blk: {
5443 const operand_local = try f.allocLocal(inst, struct_ty);
5444 try f.writeCValue(writer, operand_local, .Other);
5445 try writer.writeAll(" = ");
5446 try f.writeCValue(writer, struct_byval, .Initializer);
5447 try writer.writeAll(";\n");
5448 break :blk operand_local;
5449 } else struct_byval;
54425450
5443 .union_type => |union_type| field_name: {5451 const local = try f.allocLocal(inst, inst_ty);
5444 const union_obj = mod.unionPtr(union_type.index);5452 try writer.writeAll("memcpy(&");
5445 if (union_obj.layout == .Packed) {5453 try f.writeCValue(writer, local, .Other);
5446 const operand_lval = if (struct_byval == .constant) blk: {5454 try writer.writeAll(", &");
5447 const operand_local = try f.allocLocal(inst, struct_ty);5455 try f.writeCValue(writer, operand_lval, .Other);
5448 try f.writeCValue(writer, operand_local, .Other);5456 try writer.writeAll(", sizeof(");
5449 try writer.writeAll(" = ");5457 try f.renderType(writer, inst_ty);
5450 try f.writeCValue(writer, struct_byval, .Initializer);5458 try writer.writeAll("));\n");
5451 try writer.writeAll(";\n");
5452 break :blk operand_local;
5453 } else struct_byval;
5454
5455 const local = try f.allocLocal(inst, inst_ty);
5456 try writer.writeAll("memcpy(&");
5457 try f.writeCValue(writer, local, .Other);
5458 try writer.writeAll(", &");
5459 try f.writeCValue(writer, operand_lval, .Other);
5460 try writer.writeAll(", sizeof(");
5461 try f.renderType(writer, inst_ty);
5462 try writer.writeAll("));\n");
5463
5464 if (struct_byval == .constant) {
5465 try freeLocal(f, inst, operand_lval.new_local, 0);
5466 }
54675459
5468 return local;5460 if (struct_byval == .constant) {
5469 } else {5461 try freeLocal(f, inst, operand_lval.new_local, 0);
5470 const name = union_obj.fields.keys()[extra.field_index];
5471 break :field_name if (union_type.hasTag()) .{
5472 .payload_identifier = name,
5473 } else .{
5474 .identifier = name,
5475 };
5476 }5462 }
5477 },5463
5478 else => unreachable,5464 return local;
5465 } else {
5466 const name = union_obj.fields.keys()[extra.field_index];
5467 break :field_name if (union_type.hasTag()) .{
5468 .payload_identifier = name,
5469 } else .{
5470 .identifier = name,
5471 };
5472 }
5479 },5473 },
5474 else => unreachable,
5480 };5475 };
54815476
5482 const local = try f.allocLocal(inst, inst_ty);5477 const local = try f.allocLocal(inst, inst_ty);
src/codegen/llvm.zig+26-31
...@@ -381,12 +381,7 @@ pub const Object = struct {...@@ -381,12 +381,7 @@ pub const Object = struct {
381381
382 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we382 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
383 /// want to iterate over it while adding entries to it.383 /// want to iterate over it while adding entries to it.
384 pub const DITypeMap = std.ArrayHashMapUnmanaged(384 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
385 Type,
386 AnnotatedDITypePtr,
387 Type.HashContext32,
388 true,
389 );
390385
391 pub fn create(gpa: Allocator, options: link.Options) !*Object {386 pub fn create(gpa: Allocator, options: link.Options) !*Object {
392 const obj = try gpa.create(Object);387 const obj = try gpa.create(Object);
...@@ -1437,7 +1432,7 @@ pub const Object = struct {...@@ -1437,7 +1432,7 @@ pub const Object = struct {
1437 const gpa = o.gpa;1432 const gpa = o.gpa;
1438 // Be careful not to reference this `gop` variable after any recursive calls1433 // Be careful not to reference this `gop` variable after any recursive calls
1439 // to `lowerDebugType`.1434 // to `lowerDebugType`.
1440 const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .mod = o.module });1435 const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern());
1441 if (gop.found_existing) {1436 if (gop.found_existing) {
1442 const annotated = gop.value_ptr.*;1437 const annotated = gop.value_ptr.*;
1443 const di_type = annotated.toDIType();1438 const di_type = annotated.toDIType();
...@@ -1450,7 +1445,7 @@ pub const Object = struct {...@@ -1450,7 +1445,7 @@ pub const Object = struct {
1450 };1445 };
1451 return o.lowerDebugTypeImpl(entry, resolve, di_type);1446 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1452 }1447 }
1453 errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module }));1448 errdefer assert(o.di_type_map.orderedRemove(ty.toIntern()));
1454 const entry: Object.DITypeMap.Entry = .{1449 const entry: Object.DITypeMap.Entry = .{
1455 .key_ptr = gop.key_ptr,1450 .key_ptr = gop.key_ptr,
1456 .value_ptr = gop.value_ptr,1451 .value_ptr = gop.value_ptr,
...@@ -1465,7 +1460,7 @@ pub const Object = struct {...@@ -1465,7 +1460,7 @@ pub const Object = struct {
1465 resolve: DebugResolveStatus,1460 resolve: DebugResolveStatus,
1466 opt_fwd_decl: ?*llvm.DIType,1461 opt_fwd_decl: ?*llvm.DIType,
1467 ) Allocator.Error!*llvm.DIType {1462 ) Allocator.Error!*llvm.DIType {
1468 const ty = gop.key_ptr.*;1463 const ty = gop.key_ptr.toType();
1469 const gpa = o.gpa;1464 const gpa = o.gpa;
1470 const target = o.target;1465 const target = o.target;
1471 const dib = o.di_builder.?;1466 const dib = o.di_builder.?;
...@@ -1498,7 +1493,7 @@ pub const Object = struct {...@@ -1498,7 +1493,7 @@ pub const Object = struct {
1498 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);1493 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
1499 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`1494 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1500 // means we can't use `gop` anymore.1495 // means we can't use `gop` anymore.
1501 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });1496 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
1502 return enum_di_ty;1497 return enum_di_ty;
1503 }1498 }
15041499
...@@ -1558,7 +1553,7 @@ pub const Object = struct {...@@ -1558,7 +1553,7 @@ pub const Object = struct {
1558 "",1553 "",
1559 );1554 );
1560 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1555 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1561 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });1556 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
1562 return enum_di_ty;1557 return enum_di_ty;
1563 },1558 },
1564 .Float => {1559 .Float => {
...@@ -1577,7 +1572,7 @@ pub const Object = struct {...@@ -1577,7 +1572,7 @@ pub const Object = struct {
1577 },1572 },
1578 .Pointer => {1573 .Pointer => {
1579 // Normalize everything that the debug info does not represent.1574 // Normalize everything that the debug info does not represent.
1580 const ptr_info = ty.ptrInfoIp(mod.intern_pool);1575 const ptr_info = Type.ptrInfoIp(mod.intern_pool, ty.toIntern());
15811576
1582 if (ptr_info.sentinel != .none or1577 if (ptr_info.sentinel != .none or
1583 ptr_info.address_space != .generic or1578 ptr_info.address_space != .generic or
...@@ -1603,7 +1598,7 @@ pub const Object = struct {...@@ -1603,7 +1598,7 @@ pub const Object = struct {
1603 });1598 });
1604 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);1599 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
1605 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1600 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1606 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module });1601 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
1607 return ptr_di_ty;1602 return ptr_di_ty;
1608 }1603 }
16091604
...@@ -1682,7 +1677,7 @@ pub const Object = struct {...@@ -1682,7 +1677,7 @@ pub const Object = struct {
1682 );1677 );
1683 dib.replaceTemporary(fwd_decl, full_di_ty);1678 dib.replaceTemporary(fwd_decl, full_di_ty);
1684 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1679 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1685 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });1680 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
1686 return full_di_ty;1681 return full_di_ty;
1687 }1682 }
16881683
...@@ -1696,7 +1691,7 @@ pub const Object = struct {...@@ -1696,7 +1691,7 @@ pub const Object = struct {
1696 name,1691 name,
1697 );1692 );
1698 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1693 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1699 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module });1694 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));
1700 return ptr_di_ty;1695 return ptr_di_ty;
1701 },1696 },
1702 .Opaque => {1697 .Opaque => {
...@@ -1718,7 +1713,7 @@ pub const Object = struct {...@@ -1718,7 +1713,7 @@ pub const Object = struct {
1718 );1713 );
1719 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`1714 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
1720 // means we can't use `gop` anymore.1715 // means we can't use `gop` anymore.
1721 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .mod = o.module });1716 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty));
1722 return opaque_di_ty;1717 return opaque_di_ty;
1723 },1718 },
1724 .Array => {1719 .Array => {
...@@ -1729,7 +1724,7 @@ pub const Object = struct {...@@ -1729,7 +1724,7 @@ pub const Object = struct {
1729 @intCast(c_int, ty.arrayLen(mod)),1724 @intCast(c_int, ty.arrayLen(mod)),
1730 );1725 );
1731 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1726 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1732 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .mod = o.module });1727 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));
1733 return array_di_ty;1728 return array_di_ty;
1734 },1729 },
1735 .Vector => {1730 .Vector => {
...@@ -1761,7 +1756,7 @@ pub const Object = struct {...@@ -1761,7 +1756,7 @@ pub const Object = struct {
1761 ty.vectorLen(mod),1756 ty.vectorLen(mod),
1762 );1757 );
1763 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1758 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1764 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .mod = o.module });1759 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty));
1765 return vector_di_ty;1760 return vector_di_ty;
1766 },1761 },
1767 .Optional => {1762 .Optional => {
...@@ -1777,7 +1772,7 @@ pub const Object = struct {...@@ -1777,7 +1772,7 @@ pub const Object = struct {
1777 if (ty.optionalReprIsPayload(mod)) {1772 if (ty.optionalReprIsPayload(mod)) {
1778 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);1773 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
1779 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1774 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1780 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module });1775 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
1781 return ptr_di_ty;1776 return ptr_di_ty;
1782 }1777 }
17831778
...@@ -1850,7 +1845,7 @@ pub const Object = struct {...@@ -1850,7 +1845,7 @@ pub const Object = struct {
1850 );1845 );
1851 dib.replaceTemporary(fwd_decl, full_di_ty);1846 dib.replaceTemporary(fwd_decl, full_di_ty);
1852 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1847 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1853 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });1848 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
1854 return full_di_ty;1849 return full_di_ty;
1855 },1850 },
1856 .ErrorUnion => {1851 .ErrorUnion => {
...@@ -1858,7 +1853,7 @@ pub const Object = struct {...@@ -1858,7 +1853,7 @@ pub const Object = struct {
1858 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {1853 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1859 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);1854 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
1860 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1855 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1861 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module });1856 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));
1862 return err_set_di_ty;1857 return err_set_di_ty;
1863 }1858 }
1864 const name = try ty.nameAlloc(gpa, o.module);1859 const name = try ty.nameAlloc(gpa, o.module);
...@@ -1941,7 +1936,7 @@ pub const Object = struct {...@@ -1941,7 +1936,7 @@ pub const Object = struct {
1941 );1936 );
1942 dib.replaceTemporary(fwd_decl, full_di_ty);1937 dib.replaceTemporary(fwd_decl, full_di_ty);
1943 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1938 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1944 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });1939 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
1945 return full_di_ty;1940 return full_di_ty;
1946 },1941 },
1947 .ErrorSet => {1942 .ErrorSet => {
...@@ -2038,7 +2033,7 @@ pub const Object = struct {...@@ -2038,7 +2033,7 @@ pub const Object = struct {
2038 );2033 );
2039 dib.replaceTemporary(fwd_decl, full_di_ty);2034 dib.replaceTemporary(fwd_decl, full_di_ty);
2040 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2035 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2041 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2036 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2042 return full_di_ty;2037 return full_di_ty;
2043 },2038 },
2044 .struct_type => |struct_type| s: {2039 .struct_type => |struct_type| s: {
...@@ -2057,7 +2052,7 @@ pub const Object = struct {...@@ -2057,7 +2052,7 @@ pub const Object = struct {
2057 dib.replaceTemporary(fwd_decl, struct_di_ty);2052 dib.replaceTemporary(fwd_decl, struct_di_ty);
2058 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2053 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2059 // means we can't use `gop` anymore.2054 // means we can't use `gop` anymore.
2060 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });2055 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2061 return struct_di_ty;2056 return struct_di_ty;
2062 }2057 }
2063 },2058 },
...@@ -2070,7 +2065,7 @@ pub const Object = struct {...@@ -2070,7 +2065,7 @@ pub const Object = struct {
2070 dib.replaceTemporary(fwd_decl, struct_di_ty);2065 dib.replaceTemporary(fwd_decl, struct_di_ty);
2071 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2066 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2072 // means we can't use `gop` anymore.2067 // means we can't use `gop` anymore.
2073 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });2068 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2074 return struct_di_ty;2069 return struct_di_ty;
2075 }2070 }
20762071
...@@ -2126,7 +2121,7 @@ pub const Object = struct {...@@ -2126,7 +2121,7 @@ pub const Object = struct {
2126 );2121 );
2127 dib.replaceTemporary(fwd_decl, full_di_ty);2122 dib.replaceTemporary(fwd_decl, full_di_ty);
2128 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2123 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2129 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2124 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2130 return full_di_ty;2125 return full_di_ty;
2131 },2126 },
2132 .Union => {2127 .Union => {
...@@ -2155,7 +2150,7 @@ pub const Object = struct {...@@ -2155,7 +2150,7 @@ pub const Object = struct {
2155 dib.replaceTemporary(fwd_decl, union_di_ty);2150 dib.replaceTemporary(fwd_decl, union_di_ty);
2156 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2151 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2157 // means we can't use `gop` anymore.2152 // means we can't use `gop` anymore.
2158 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });2153 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
2159 return union_di_ty;2154 return union_di_ty;
2160 }2155 }
21612156
...@@ -2182,7 +2177,7 @@ pub const Object = struct {...@@ -2182,7 +2177,7 @@ pub const Object = struct {
2182 dib.replaceTemporary(fwd_decl, full_di_ty);2177 dib.replaceTemporary(fwd_decl, full_di_ty);
2183 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2178 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2184 // means we can't use `gop` anymore.2179 // means we can't use `gop` anymore.
2185 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2180 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2186 return full_di_ty;2181 return full_di_ty;
2187 }2182 }
21882183
...@@ -2241,7 +2236,7 @@ pub const Object = struct {...@@ -2241,7 +2236,7 @@ pub const Object = struct {
2241 if (layout.tag_size == 0) {2236 if (layout.tag_size == 0) {
2242 dib.replaceTemporary(fwd_decl, union_di_ty);2237 dib.replaceTemporary(fwd_decl, union_di_ty);
2243 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2238 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2244 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });2239 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
2245 return union_di_ty;2240 return union_di_ty;
2246 }2241 }
22472242
...@@ -2302,7 +2297,7 @@ pub const Object = struct {...@@ -2302,7 +2297,7 @@ pub const Object = struct {
2302 );2297 );
2303 dib.replaceTemporary(fwd_decl, full_di_ty);2298 dib.replaceTemporary(fwd_decl, full_di_ty);
2304 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2299 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2305 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });2300 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2306 return full_di_ty;2301 return full_di_ty;
2307 },2302 },
2308 .Fn => {2303 .Fn => {
...@@ -2349,7 +2344,7 @@ pub const Object = struct {...@@ -2349,7 +2344,7 @@ pub const Object = struct {
2349 0,2344 0,
2350 );2345 );
2351 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2346 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2352 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .mod = o.module });2347 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty));
2353 return fn_di_ty;2348 return fn_di_ty;
2354 },2349 },
2355 .ComptimeInt => unreachable,2350 .ComptimeInt => unreachable,
src/link/Dwarf.zig+4-15
...@@ -87,12 +87,7 @@ pub const DeclState = struct {...@@ -87,12 +87,7 @@ pub const DeclState = struct {
87 dbg_info: std.ArrayList(u8),87 dbg_info: std.ArrayList(u8),
88 abbrev_type_arena: std.heap.ArenaAllocator,88 abbrev_type_arena: std.heap.ArenaAllocator,
89 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},89 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},
90 abbrev_resolver: std.HashMapUnmanaged(90 abbrev_resolver: std.AutoHashMapUnmanaged(InternPool.Index, u32) = .{},
91 Type,
92 u32,
93 Type.HashContext64,
94 std.hash_map.default_max_load_percentage,
95 ) = .{},
96 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},91 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
97 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},92 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},
9893
...@@ -142,9 +137,7 @@ pub const DeclState = struct {...@@ -142,9 +137,7 @@ pub const DeclState = struct {
142 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section137 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section
143 /// which we use as our target of the relocation.138 /// which we use as our target of the relocation.
144 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {139 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {
145 const resolv = self.abbrev_resolver.getContext(ty, .{140 const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: {
146 .mod = self.mod,
147 }) orelse blk: {
148 const sym_index = @intCast(u32, self.abbrev_table.items.len);141 const sym_index = @intCast(u32, self.abbrev_table.items.len);
149 try self.abbrev_table.append(self.gpa, .{142 try self.abbrev_table.append(self.gpa, .{
150 .atom_index = atom_index,143 .atom_index = atom_index,
...@@ -152,12 +145,8 @@ pub const DeclState = struct {...@@ -152,12 +145,8 @@ pub const DeclState = struct {
152 .offset = undefined,145 .offset = undefined,
153 });146 });
154 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });147 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });
155 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{148 try self.abbrev_resolver.putNoClobber(self.gpa, ty.toIntern(), sym_index);
156 .mod = self.mod,149 break :blk sym_index;
157 });
158 break :blk self.abbrev_resolver.getContext(ty, .{
159 .mod = self.mod,
160 }).?;
161 };150 };
162 log.debug("{x}: %{d} + 0", .{ offset, resolv });151 log.debug("{x}: %{d} + 0", .{ offset, resolv });
163 try self.abbrev_relocs.append(self.gpa, .{152 try self.abbrev_relocs.append(self.gpa, .{
src/print_air.zig+1-7
...@@ -366,13 +366,7 @@ const Writer = struct {...@@ -366,13 +366,7 @@ const Writer = struct {
366 }366 }
367367
368 fn writeType(w: *Writer, s: anytype, ty: Type) !void {368 fn writeType(w: *Writer, s: anytype, ty: Type) !void {
369 switch (ty.ip_index) {369 return ty.print(s, w.module);
370 .none => switch (ty.tag()) {
371 .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
372 .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
373 },
374 else => try ty.print(s, w.module),
375 }
376 }370 }
377371
378 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {372 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
src/type.zig+398-658
...@@ -11,115 +11,99 @@ const TypedValue = @import("TypedValue.zig");...@@ -11,115 +11,99 @@ const TypedValue = @import("TypedValue.zig");
11const Sema = @import("Sema.zig");11const Sema = @import("Sema.zig");
12const InternPool = @import("InternPool.zig");12const InternPool = @import("InternPool.zig");
1313
14const file_struct = @This();14/// Both types and values are canonically represented by a single 32-bit integer
1515/// which is an index into an `InternPool` data structure.
16/// This struct abstracts around this storage by providing methods only
17/// applicable to types rather than values in general.
16pub const Type = struct {18pub const Type = struct {
17 /// We are migrating towards using this for every Type object. However, many
18 /// types are still represented the legacy way. This is indicated by using
19 /// InternPool.Index.none.
20 ip_index: InternPool.Index,19 ip_index: InternPool.Index,
2120
22 /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
23 /// This union takes advantage of the fact that the first page of memory
24 /// is unmapped, giving us 4096 possible enum tags that have no payload.
25 legacy: extern union {
26 /// If the tag value is less than Tag.no_payload_count, then no pointer
27 /// dereference is needed.
28 tag_if_small_enough: Tag,
29 ptr_otherwise: *Payload,
30 },
31
32 pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {21 pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {
33 return ty.zigTypeTagOrPoison(mod) catch unreachable;22 return ty.zigTypeTagOrPoison(mod) catch unreachable;
34 }23 }
3524
36 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {25 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
37 switch (ty.ip_index) {26 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
38 .none => switch (ty.tag()) {27 .int_type => .Int,
39 .inferred_alloc_const,28 .ptr_type => .Pointer,
40 .inferred_alloc_mut,29 .array_type => .Array,
41 => return .Pointer,30 .vector_type => .Vector,
42 },31 .opt_type => .Optional,
43 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {32 .error_union_type => .ErrorUnion,
44 .int_type => .Int,33 .error_set_type, .inferred_error_set_type => .ErrorSet,
45 .ptr_type => .Pointer,34 .struct_type, .anon_struct_type => .Struct,
46 .array_type => .Array,35 .union_type => .Union,
47 .vector_type => .Vector,36 .opaque_type => .Opaque,
48 .opt_type => .Optional,37 .enum_type => .Enum,
49 .error_union_type => .ErrorUnion,38 .func_type => .Fn,
50 .error_set_type, .inferred_error_set_type => .ErrorSet,39 .anyframe_type => .AnyFrame,
51 .struct_type, .anon_struct_type => .Struct,40 .simple_type => |s| switch (s) {
52 .union_type => .Union,41 .f16,
53 .opaque_type => .Opaque,42 .f32,
54 .enum_type => .Enum,43 .f64,
55 .func_type => .Fn,44 .f80,
56 .anyframe_type => .AnyFrame,45 .f128,
57 .simple_type => |s| switch (s) {46 .c_longdouble,
58 .f16,47 => .Float,
59 .f32,
60 .f64,
61 .f80,
62 .f128,
63 .c_longdouble,
64 => .Float,
6548
66 .usize,49 .usize,
67 .isize,50 .isize,
68 .c_char,51 .c_char,
69 .c_short,52 .c_short,
70 .c_ushort,53 .c_ushort,
71 .c_int,54 .c_int,
72 .c_uint,55 .c_uint,
73 .c_long,56 .c_long,
74 .c_ulong,57 .c_ulong,
75 .c_longlong,58 .c_longlong,
76 .c_ulonglong,59 .c_ulonglong,
77 => .Int,60 => .Int,
7861
79 .anyopaque => .Opaque,62 .anyopaque => .Opaque,
80 .bool => .Bool,63 .bool => .Bool,
81 .void => .Void,64 .void => .Void,
82 .type => .Type,65 .type => .Type,
83 .anyerror => .ErrorSet,66 .anyerror => .ErrorSet,
84 .comptime_int => .ComptimeInt,67 .comptime_int => .ComptimeInt,
85 .comptime_float => .ComptimeFloat,68 .comptime_float => .ComptimeFloat,
86 .noreturn => .NoReturn,69 .noreturn => .NoReturn,
87 .null => .Null,70 .null => .Null,
88 .undefined => .Undefined,71 .undefined => .Undefined,
89 .enum_literal => .EnumLiteral,72 .enum_literal => .EnumLiteral,
9073
91 .atomic_order,74 .atomic_order,
92 .atomic_rmw_op,75 .atomic_rmw_op,
93 .calling_convention,76 .calling_convention,
94 .address_space,77 .address_space,
95 .float_mode,78 .float_mode,
96 .reduce_op,79 .reduce_op,
97 .call_modifier,80 .call_modifier,
98 => .Enum,81 => .Enum,
9982
100 .prefetch_options,83 .prefetch_options,
101 .export_options,84 .export_options,
102 .extern_options,85 .extern_options,
103 => .Struct,86 => .Struct,
10487
105 .type_info => .Union,88 .type_info => .Union,
10689
107 .generic_poison => return error.GenericPoison,90 .generic_poison => return error.GenericPoison,
108 },
10991
110 // values, not types92 .inferred_alloc_const, .inferred_alloc_mut => return .Pointer,
111 .undef => unreachable,
112 .un => unreachable,
113 .extern_func => unreachable,
114 .int => unreachable,
115 .float => unreachable,
116 .ptr => unreachable,
117 .opt => unreachable,
118 .enum_tag => unreachable,
119 .simple_value => unreachable,
120 .aggregate => unreachable,
121 },93 },
122 }94
95 // values, not types
96 .undef => unreachable,
97 .un => unreachable,
98 .extern_func => unreachable,
99 .int => unreachable,
100 .float => unreachable,
101 .ptr => unreachable,
102 .opt => unreachable,
103 .enum_tag => unreachable,
104 .simple_value => unreachable,
105 .aggregate => unreachable,
106 };
123 }107 }
124108
125 pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {109 pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {
...@@ -171,68 +155,6 @@ pub const Type = struct {...@@ -171,68 +155,6 @@ pub const Type = struct {
171 };155 };
172 }156 }
173157
174 pub fn initTag(comptime small_tag: Tag) Type {
175 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
176 return Type{
177 .ip_index = .none,
178 .legacy = .{ .tag_if_small_enough = small_tag },
179 };
180 }
181
182 pub fn initPayload(payload: *Payload) Type {
183 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
184 return Type{
185 .ip_index = .none,
186 .legacy = .{ .ptr_otherwise = payload },
187 };
188 }
189
190 pub fn tag(ty: Type) Tag {
191 assert(ty.ip_index == .none);
192 if (@enumToInt(ty.legacy.tag_if_small_enough) < Tag.no_payload_count) {
193 return ty.legacy.tag_if_small_enough;
194 } else {
195 return ty.legacy.ptr_otherwise.tag;
196 }
197 }
198
199 /// Prefer `castTag` to this.
200 pub fn cast(self: Type, comptime T: type) ?*T {
201 if (self.ip_index != .none) {
202 return null;
203 }
204 if (@hasField(T, "base_tag")) {
205 return self.castTag(T.base_tag);
206 }
207 if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count) {
208 return null;
209 }
210 inline for (@typeInfo(Tag).Enum.fields) |field| {
211 if (field.value < Tag.no_payload_count)
212 continue;
213 const t = @intToEnum(Tag, field.value);
214 if (self.legacy.ptr_otherwise.tag == t) {
215 if (T == t.Type()) {
216 return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise);
217 }
218 return null;
219 }
220 }
221 unreachable;
222 }
223
224 pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() {
225 if (self.ip_index != .none) return null;
226
227 if (@enumToInt(self.legacy.tag_if_small_enough) < Tag.no_payload_count)
228 return null;
229
230 if (self.legacy.ptr_otherwise.tag == t)
231 return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise);
232
233 return null;
234 }
235
236 /// If it is a function pointer, returns the function type. Otherwise returns null.158 /// If it is a function pointer, returns the function type. Otherwise returns null.
237 pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {159 pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {
238 if (ty.zigTypeTag(mod) != .Pointer) return null;160 if (ty.zigTypeTag(mod) != .Pointer) return null;
...@@ -260,8 +182,8 @@ pub const Type = struct {...@@ -260,8 +182,8 @@ pub const Type = struct {
260 };182 };
261 }183 }
262184
263 pub fn ptrInfoIp(ty: Type, ip: InternPool) InternPool.Key.PtrType {185 pub fn ptrInfoIp(ip: InternPool, ty: InternPool.Index) InternPool.Key.PtrType {
264 return switch (ip.indexToKey(ty.ip_index)) {186 return switch (ip.indexToKey(ty)) {
265 .ptr_type => |p| p,187 .ptr_type => |p| p,
266 .opt_type => |child| switch (ip.indexToKey(child)) {188 .opt_type => |child| switch (ip.indexToKey(child)) {
267 .ptr_type => |p| p,189 .ptr_type => |p| p,
...@@ -272,135 +194,28 @@ pub const Type = struct {...@@ -272,135 +194,28 @@ pub const Type = struct {
272 }194 }
273195
274 pub fn ptrInfo(ty: Type, mod: *const Module) Payload.Pointer.Data {196 pub fn ptrInfo(ty: Type, mod: *const Module) Payload.Pointer.Data {
275 return Payload.Pointer.Data.fromKey(ptrInfoIp(ty, mod.intern_pool));197 return Payload.Pointer.Data.fromKey(ptrInfoIp(mod.intern_pool, ty.ip_index));
276 }
277
278 pub fn eql(a: Type, b: Type, mod: *Module) bool {
279 if (a.ip_index != .none or b.ip_index != .none) {
280 // The InternPool data structure hashes based on Key to make interned objects
281 // unique. An Index can be treated simply as u32 value for the
282 // purpose of Type/Value hashing and equality.
283 return a.ip_index == b.ip_index;
284 }
285 // As a shortcut, if the small tags / addresses match, we're done.
286 if (a.legacy.tag_if_small_enough == b.legacy.tag_if_small_enough) return true;
287
288 switch (a.tag()) {
289 .inferred_alloc_const,
290 .inferred_alloc_mut,
291 => {
292 if (b.zigTypeTag(mod) != .Pointer) return false;
293
294 const info_a = a.ptrInfo(mod);
295 const info_b = b.ptrInfo(mod);
296 if (!info_a.pointee_type.eql(info_b.pointee_type, mod))
297 return false;
298 if (info_a.@"align" != info_b.@"align")
299 return false;
300 if (info_a.@"addrspace" != info_b.@"addrspace")
301 return false;
302 if (info_a.bit_offset != info_b.bit_offset)
303 return false;
304 if (info_a.host_size != info_b.host_size)
305 return false;
306 if (info_a.vector_index != info_b.vector_index)
307 return false;
308 if (info_a.@"allowzero" != info_b.@"allowzero")
309 return false;
310 if (info_a.mutable != info_b.mutable)
311 return false;
312 if (info_a.@"volatile" != info_b.@"volatile")
313 return false;
314 if (info_a.size != info_b.size)
315 return false;
316
317 const sentinel_a = info_a.sentinel;
318 const sentinel_b = info_b.sentinel;
319 if (sentinel_a) |sa| {
320 if (sentinel_b) |sb| {
321 if (!sa.eql(sb, info_a.pointee_type, mod))
322 return false;
323 } else {
324 return false;
325 }
326 } else {
327 if (sentinel_b != null)
328 return false;
329 }
330
331 return true;
332 },
333 }
334 }198 }
335199
336 pub fn hash(self: Type, mod: *Module) u64 {200 pub fn eql(a: Type, b: Type, mod: *const Module) bool {
337 var hasher = std.hash.Wyhash.init(0);201 _ = mod; // TODO: remove this parameter
338 self.hashWithHasher(&hasher, mod);202 assert(a.ip_index != .none);
339 return hasher.final();203 assert(b.ip_index != .none);
204 // The InternPool data structure hashes based on Key to make interned objects
205 // unique. An Index can be treated simply as u32 value for the
206 // purpose of Type/Value hashing and equality.
207 return a.ip_index == b.ip_index;
340 }208 }
341209
342 pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {210 pub fn hash(ty: Type, mod: *const Module) u32 {
343 if (ty.ip_index != .none) {211 _ = mod; // TODO: remove this parameter
344 // The InternPool data structure hashes based on Key to make interned objects212 assert(ty.ip_index != .none);
345 // unique. An Index can be treated simply as u32 value for the213 // The InternPool data structure hashes based on Key to make interned objects
346 // purpose of Type/Value hashing and equality.214 // unique. An Index can be treated simply as u32 value for the
347 std.hash.autoHash(hasher, ty.ip_index);215 // purpose of Type/Value hashing and equality.
348 return;216 return std.hash.uint32(@enumToInt(ty.ip_index));
349 }
350 switch (ty.tag()) {
351 .inferred_alloc_const,
352 .inferred_alloc_mut,
353 => {
354 std.hash.autoHash(hasher, std.builtin.TypeId.Pointer);
355
356 const info = ty.ptrInfo(mod);
357 hashWithHasher(info.pointee_type, hasher, mod);
358 hashSentinel(info.sentinel, info.pointee_type, hasher, mod);
359 std.hash.autoHash(hasher, info.@"align");
360 std.hash.autoHash(hasher, info.@"addrspace");
361 std.hash.autoHash(hasher, info.bit_offset);
362 std.hash.autoHash(hasher, info.host_size);
363 std.hash.autoHash(hasher, info.vector_index);
364 std.hash.autoHash(hasher, info.@"allowzero");
365 std.hash.autoHash(hasher, info.mutable);
366 std.hash.autoHash(hasher, info.@"volatile");
367 std.hash.autoHash(hasher, info.size);
368 },
369 }
370 }
371
372 fn hashSentinel(opt_val: ?Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
373 if (opt_val) |s| {
374 std.hash.autoHash(hasher, true);
375 s.hash(ty, hasher, mod);
376 } else {
377 std.hash.autoHash(hasher, false);
378 }
379 }217 }
380218
381 pub const HashContext64 = struct {
382 mod: *Module,
383
384 pub fn hash(self: @This(), t: Type) u64 {
385 return t.hash(self.mod);
386 }
387 pub fn eql(self: @This(), a: Type, b: Type) bool {
388 return a.eql(b, self.mod);
389 }
390 };
391
392 pub const HashContext32 = struct {
393 mod: *Module,
394
395 pub fn hash(self: @This(), t: Type) u32 {
396 return @truncate(u32, t.hash(self.mod));
397 }
398 pub fn eql(self: @This(), a: Type, b: Type, b_index: usize) bool {
399 _ = b_index;
400 return a.eql(b, self.mod);
401 }
402 };
403
404 pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {219 pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
405 _ = ty;220 _ = ty;
406 _ = unused_fmt_string;221 _ = unused_fmt_string;
...@@ -460,214 +275,208 @@ pub const Type = struct {...@@ -460,214 +275,208 @@ pub const Type = struct {
460275
461 /// Prints a name suitable for `@typeName`.276 /// Prints a name suitable for `@typeName`.
462 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {277 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
463 switch (ty.ip_index) {278 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
464 .none => switch (ty.tag()) {279 .int_type => |int_type| {
465 .inferred_alloc_const => unreachable,280 const sign_char: u8 = switch (int_type.signedness) {
466 .inferred_alloc_mut => unreachable,281 .signed => 'i',
282 .unsigned => 'u',
283 };
284 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
467 },285 },
468 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {286 .ptr_type => {
469 .int_type => |int_type| {287 const info = ty.ptrInfo(mod);
470 const sign_char: u8 = switch (int_type.signedness) {
471 .signed => 'i',
472 .unsigned => 'u',
473 };
474 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
475 },
476 .ptr_type => {
477 const info = ty.ptrInfo(mod);
478
479 if (info.sentinel) |s| switch (info.size) {
480 .One, .C => unreachable,
481 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
482 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
483 } else switch (info.size) {
484 .One => try writer.writeAll("*"),
485 .Many => try writer.writeAll("[*]"),
486 .C => try writer.writeAll("[*c]"),
487 .Slice => try writer.writeAll("[]"),
488 }
489 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
490 if (info.@"align" != 0) {
491 try writer.print("align({d}", .{info.@"align"});
492 } else {
493 const alignment = info.pointee_type.abiAlignment(mod);
494 try writer.print("align({d}", .{alignment});
495 }
496288
497 if (info.bit_offset != 0 or info.host_size != 0) {289 if (info.sentinel) |s| switch (info.size) {
498 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });290 .One, .C => unreachable,
499 }291 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
500 if (info.vector_index == .runtime) {292 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
501 try writer.writeAll(":?");293 } else switch (info.size) {
502 } else if (info.vector_index != .none) {294 .One => try writer.writeAll("*"),
503 try writer.print(":{d}", .{@enumToInt(info.vector_index)});295 .Many => try writer.writeAll("[*]"),
504 }296 .C => try writer.writeAll("[*c]"),
505 try writer.writeAll(") ");297 .Slice => try writer.writeAll("[]"),
506 }298 }
507 if (info.@"addrspace" != .generic) {299 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
508 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});300 if (info.@"align" != 0) {
301 try writer.print("align({d}", .{info.@"align"});
302 } else {
303 const alignment = info.pointee_type.abiAlignment(mod);
304 try writer.print("align({d}", .{alignment});
509 }305 }
510 if (!info.mutable) try writer.writeAll("const ");
511 if (info.@"volatile") try writer.writeAll("volatile ");
512 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
513306
514 try print(info.pointee_type, writer, mod);307 if (info.bit_offset != 0 or info.host_size != 0) {
515 return;308 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
516 },
517 .array_type => |array_type| {
518 if (array_type.sentinel == .none) {
519 try writer.print("[{d}]", .{array_type.len});
520 try print(array_type.child.toType(), writer, mod);
521 } else {
522 try writer.print("[{d}:{}]", .{
523 array_type.len,
524 array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
525 });
526 try print(array_type.child.toType(), writer, mod);
527 }309 }
528 return;310 if (info.vector_index == .runtime) {
529 },311 try writer.writeAll(":?");
530 .vector_type => |vector_type| {312 } else if (info.vector_index != .none) {
531 try writer.print("@Vector({d}, ", .{vector_type.len});313 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
532 try print(vector_type.child.toType(), writer, mod);314 }
533 try writer.writeAll(")");315 try writer.writeAll(") ");
534 return;316 }
535 },317 if (info.@"addrspace" != .generic) {
536 .opt_type => |child| {318 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
537 try writer.writeByte('?');319 }
538 return print(child.toType(), writer, mod);320 if (!info.mutable) try writer.writeAll("const ");
539 },321 if (info.@"volatile") try writer.writeAll("volatile ");
540 .error_union_type => |error_union_type| {322 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
541 try print(error_union_type.error_set_type.toType(), writer, mod);
542 try writer.writeByte('!');
543 try print(error_union_type.payload_type.toType(), writer, mod);
544 return;
545 },
546 .inferred_error_set_type => |index| {
547 const ies = mod.inferredErrorSetPtr(index);
548 const func = ies.func;
549323
550 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");324 try print(info.pointee_type, writer, mod);
551 const owner_decl = mod.declPtr(func.owner_decl);325 return;
552 try owner_decl.renderFullyQualifiedName(mod, writer);326 },
553 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");327 .array_type => |array_type| {
554 },328 if (array_type.sentinel == .none) {
555 .error_set_type => |error_set_type| {329 try writer.print("[{d}]", .{array_type.len});
556 const names = error_set_type.names;330 try print(array_type.child.toType(), writer, mod);
557 try writer.writeAll("error{");331 } else {
558 for (names, 0..) |name, i| {332 try writer.print("[{d}:{}]", .{
559 if (i != 0) try writer.writeByte(',');333 array_type.len,
560 try writer.writeAll(mod.intern_pool.stringToSlice(name));334 array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
335 });
336 try print(array_type.child.toType(), writer, mod);
337 }
338 return;
339 },
340 .vector_type => |vector_type| {
341 try writer.print("@Vector({d}, ", .{vector_type.len});
342 try print(vector_type.child.toType(), writer, mod);
343 try writer.writeAll(")");
344 return;
345 },
346 .opt_type => |child| {
347 try writer.writeByte('?');
348 return print(child.toType(), writer, mod);
349 },
350 .error_union_type => |error_union_type| {
351 try print(error_union_type.error_set_type.toType(), writer, mod);
352 try writer.writeByte('!');
353 try print(error_union_type.payload_type.toType(), writer, mod);
354 return;
355 },
356 .inferred_error_set_type => |index| {
357 const ies = mod.inferredErrorSetPtr(index);
358 const func = ies.func;
359
360 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
361 const owner_decl = mod.declPtr(func.owner_decl);
362 try owner_decl.renderFullyQualifiedName(mod, writer);
363 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
364 },
365 .error_set_type => |error_set_type| {
366 const names = error_set_type.names;
367 try writer.writeAll("error{");
368 for (names, 0..) |name, i| {
369 if (i != 0) try writer.writeByte(',');
370 try writer.writeAll(mod.intern_pool.stringToSlice(name));
371 }
372 try writer.writeAll("}");
373 },
374 .simple_type => |s| return writer.writeAll(@tagName(s)),
375 .struct_type => |struct_type| {
376 if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
377 const decl = mod.declPtr(struct_obj.owner_decl);
378 try decl.renderFullyQualifiedName(mod, writer);
379 } else if (struct_type.namespace.unwrap()) |namespace_index| {
380 const namespace = mod.namespacePtr(namespace_index);
381 try namespace.renderFullyQualifiedName(mod, "", writer);
382 } else {
383 try writer.writeAll("@TypeOf(.{})");
384 }
385 },
386 .anon_struct_type => |anon_struct| {
387 try writer.writeAll("struct{");
388 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
389 if (i != 0) try writer.writeAll(", ");
390 if (val != .none) {
391 try writer.writeAll("comptime ");
561 }392 }
562 try writer.writeAll("}");393 if (anon_struct.names.len != 0) {
563 },394 const name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
564 .simple_type => |s| return writer.writeAll(@tagName(s)),395 try writer.writeAll(name);
565 .struct_type => |struct_type| {396 try writer.writeAll(": ");
566 if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
567 const decl = mod.declPtr(struct_obj.owner_decl);
568 try decl.renderFullyQualifiedName(mod, writer);
569 } else if (struct_type.namespace.unwrap()) |namespace_index| {
570 const namespace = mod.namespacePtr(namespace_index);
571 try namespace.renderFullyQualifiedName(mod, "", writer);
572 } else {
573 try writer.writeAll("@TypeOf(.{})");
574 }397 }
575 },
576 .anon_struct_type => |anon_struct| {
577 try writer.writeAll("struct{");
578 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
579 if (i != 0) try writer.writeAll(", ");
580 if (val != .none) {
581 try writer.writeAll("comptime ");
582 }
583 if (anon_struct.names.len != 0) {
584 const name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
585 try writer.writeAll(name);
586 try writer.writeAll(": ");
587 }
588398
589 try print(field_ty.toType(), writer, mod);399 try print(field_ty.toType(), writer, mod);
590400
591 if (val != .none) {401 if (val != .none) {
592 try writer.print(" = {}", .{val.toValue().fmtValue(field_ty.toType(), mod)});402 try writer.print(" = {}", .{val.toValue().fmtValue(field_ty.toType(), mod)});
593 }
594 }403 }
595 try writer.writeAll("}");404 }
596 },405 try writer.writeAll("}");
406 },
597407
598 .union_type => |union_type| {408 .union_type => |union_type| {
599 const union_obj = mod.unionPtr(union_type.index);409 const union_obj = mod.unionPtr(union_type.index);
600 const decl = mod.declPtr(union_obj.owner_decl);410 const decl = mod.declPtr(union_obj.owner_decl);
601 try decl.renderFullyQualifiedName(mod, writer);411 try decl.renderFullyQualifiedName(mod, writer);
602 },412 },
603 .opaque_type => |opaque_type| {413 .opaque_type => |opaque_type| {
604 const decl = mod.declPtr(opaque_type.decl);414 const decl = mod.declPtr(opaque_type.decl);
605 try decl.renderFullyQualifiedName(mod, writer);415 try decl.renderFullyQualifiedName(mod, writer);
606 },416 },
607 .enum_type => |enum_type| {417 .enum_type => |enum_type| {
608 const decl = mod.declPtr(enum_type.decl);418 const decl = mod.declPtr(enum_type.decl);
609 try decl.renderFullyQualifiedName(mod, writer);419 try decl.renderFullyQualifiedName(mod, writer);
610 },420 },
611 .func_type => |fn_info| {421 .func_type => |fn_info| {
612 if (fn_info.is_noinline) {422 if (fn_info.is_noinline) {
613 try writer.writeAll("noinline ");423 try writer.writeAll("noinline ");
614 }424 }
615 try writer.writeAll("fn(");425 try writer.writeAll("fn(");
616 for (fn_info.param_types, 0..) |param_ty, i| {426 for (fn_info.param_types, 0..) |param_ty, i| {
617 if (i != 0) try writer.writeAll(", ");427 if (i != 0) try writer.writeAll(", ");
618 if (std.math.cast(u5, i)) |index| {428 if (std.math.cast(u5, i)) |index| {
619 if (fn_info.paramIsComptime(index)) {429 if (fn_info.paramIsComptime(index)) {
620 try writer.writeAll("comptime ");430 try writer.writeAll("comptime ");
621 }
622 if (fn_info.paramIsNoalias(index)) {
623 try writer.writeAll("noalias ");
624 }
625 }
626 if (param_ty == .generic_poison_type) {
627 try writer.writeAll("anytype");
628 } else {
629 try print(param_ty.toType(), writer, mod);
630 }431 }
631 }432 if (fn_info.paramIsNoalias(index)) {
632 if (fn_info.is_var_args) {433 try writer.writeAll("noalias ");
633 if (fn_info.param_types.len != 0) {
634 try writer.writeAll(", ");
635 }434 }
636 try writer.writeAll("...");
637 }
638 try writer.writeAll(") ");
639 if (fn_info.alignment.toByteUnitsOptional()) |a| {
640 try writer.print("align({d}) ", .{a});
641 }
642 if (fn_info.cc != .Unspecified) {
643 try writer.writeAll("callconv(.");
644 try writer.writeAll(@tagName(fn_info.cc));
645 try writer.writeAll(") ");
646 }435 }
647 if (fn_info.return_type == .generic_poison_type) {436 if (param_ty == .generic_poison_type) {
648 try writer.writeAll("anytype");437 try writer.writeAll("anytype");
649 } else {438 } else {
650 try print(fn_info.return_type.toType(), writer, mod);439 try print(param_ty.toType(), writer, mod);
651 }440 }
652 },441 }
653 .anyframe_type => |child| {442 if (fn_info.is_var_args) {
654 if (child == .none) return writer.writeAll("anyframe");443 if (fn_info.param_types.len != 0) {
655 try writer.writeAll("anyframe->");444 try writer.writeAll(", ");
656 return print(child.toType(), writer, mod);445 }
657 },446 try writer.writeAll("...");
658447 }
659 // values, not types448 try writer.writeAll(") ");
660 .undef => unreachable,449 if (fn_info.alignment.toByteUnitsOptional()) |a| {
661 .un => unreachable,450 try writer.print("align({d}) ", .{a});
662 .simple_value => unreachable,451 }
663 .extern_func => unreachable,452 if (fn_info.cc != .Unspecified) {
664 .int => unreachable,453 try writer.writeAll("callconv(.");
665 .float => unreachable,454 try writer.writeAll(@tagName(fn_info.cc));
666 .ptr => unreachable,455 try writer.writeAll(") ");
667 .opt => unreachable,456 }
668 .enum_tag => unreachable,457 if (fn_info.return_type == .generic_poison_type) {
669 .aggregate => unreachable,458 try writer.writeAll("anytype");
459 } else {
460 try print(fn_info.return_type.toType(), writer, mod);
461 }
462 },
463 .anyframe_type => |child| {
464 if (child == .none) return writer.writeAll("anyframe");
465 try writer.writeAll("anyframe->");
466 return print(child.toType(), writer, mod);
670 },467 },
468
469 // values, not types
470 .undef => unreachable,
471 .un => unreachable,
472 .simple_value => unreachable,
473 .extern_func => unreachable,
474 .int => unreachable,
475 .float => unreachable,
476 .ptr => unreachable,
477 .opt => unreachable,
478 .enum_tag => unreachable,
479 .aggregate => unreachable,
671 }480 }
672 }481 }
673482
...@@ -699,15 +508,10 @@ pub const Type = struct {...@@ -699,15 +508,10 @@ pub const Type = struct {
699 ignore_comptime_only: bool,508 ignore_comptime_only: bool,
700 strat: AbiAlignmentAdvancedStrat,509 strat: AbiAlignmentAdvancedStrat,
701 ) RuntimeBitsError!bool {510 ) RuntimeBitsError!bool {
702 switch (ty.ip_index) {511 return switch (ty.ip_index) {
703 // False because it is a comptime-only type.512 // False because it is a comptime-only type.
704 .empty_struct_type => return false,513 .empty_struct_type => false,
705514 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
706 .none => switch (ty.tag()) {
707 .inferred_alloc_const => unreachable,
708 .inferred_alloc_mut => unreachable,
709 },
710 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
711 .int_type => |int_type| int_type.bits != 0,515 .int_type => |int_type| int_type.bits != 0,
712 .ptr_type => |ptr_type| {516 .ptr_type => |ptr_type| {
713 // Pointers to zero-bit types still have a runtime address; however, pointers517 // Pointers to zero-bit types still have a runtime address; however, pointers
...@@ -802,6 +606,8 @@ pub const Type = struct {...@@ -802,6 +606,8 @@ pub const Type = struct {
802 => false,606 => false,
803607
804 .generic_poison => unreachable,608 .generic_poison => unreachable,
609 .inferred_alloc_const => unreachable,
610 .inferred_alloc_mut => unreachable,
805 },611 },
806 .struct_type => |struct_type| {612 .struct_type => |struct_type| {
807 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {613 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
...@@ -880,7 +686,7 @@ pub const Type = struct {...@@ -880,7 +686,7 @@ pub const Type = struct {
880 .enum_tag => unreachable,686 .enum_tag => unreachable,
881 .aggregate => unreachable,687 .aggregate => unreachable,
882 },688 },
883 }689 };
884 }690 }
885691
886 /// true if and only if the type has a well-defined memory layout692 /// true if and only if the type has a well-defined memory layout
...@@ -950,6 +756,9 @@ pub const Type = struct {...@@ -950,6 +756,9 @@ pub const Type = struct {
950 .type_info,756 .type_info,
951 .generic_poison,757 .generic_poison,
952 => false,758 => false,
759
760 .inferred_alloc_const => unreachable,
761 .inferred_alloc_mut => unreachable,
953 },762 },
954 .struct_type => |struct_type| {763 .struct_type => |struct_type| {
955 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {764 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
...@@ -1167,10 +976,7 @@ pub const Type = struct {...@@ -1167,10 +976,7 @@ pub const Type = struct {
1167 .f80 => switch (target.c_type_bit_size(.longdouble)) {976 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1168 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },977 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
1169 else => {978 else => {
1170 const u80_ty: Type = .{979 const u80_ty: Type = .{ .ip_index = .u80_type };
1171 .ip_index = .u80_type,
1172 .legacy = undefined,
1173 };
1174 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) };980 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) };
1175 },981 },
1176 },982 },
...@@ -1194,6 +1000,8 @@ pub const Type = struct {...@@ -1194,6 +1000,8 @@ pub const Type = struct {
11941000
1195 .noreturn => unreachable,1001 .noreturn => unreachable,
1196 .generic_poison => unreachable,1002 .generic_poison => unreachable,
1003 .inferred_alloc_const => unreachable,
1004 .inferred_alloc_mut => unreachable,
1197 },1005 },
1198 .struct_type => |struct_type| {1006 .struct_type => |struct_type| {
1199 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse1007 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
...@@ -1562,10 +1370,7 @@ pub const Type = struct {...@@ -1562,10 +1370,7 @@ pub const Type = struct {
1562 .f80 => switch (target.c_type_bit_size(.longdouble)) {1370 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1563 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },1371 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1564 else => {1372 else => {
1565 const u80_ty: Type = .{1373 const u80_ty: Type = .{ .ip_index = .u80_type };
1566 .ip_index = .u80_type,
1567 .legacy = undefined,
1568 };
1569 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };1374 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
1570 },1375 },
1571 },1376 },
...@@ -1605,6 +1410,8 @@ pub const Type = struct {...@@ -1605,6 +1410,8 @@ pub const Type = struct {
1605 .type_info => unreachable,1410 .type_info => unreachable,
1606 .noreturn => unreachable,1411 .noreturn => unreachable,
1607 .generic_poison => unreachable,1412 .generic_poison => unreachable,
1413 .inferred_alloc_const => unreachable,
1414 .inferred_alloc_mut => unreachable,
1608 },1415 },
1609 .struct_type => |struct_type| switch (ty.containerLayout(mod)) {1416 .struct_type => |struct_type| switch (ty.containerLayout(mod)) {
1610 .Packed => {1417 .Packed => {
...@@ -1835,6 +1642,8 @@ pub const Type = struct {...@@ -1835,6 +1642,8 @@ pub const Type = struct {
1835 .undefined => unreachable,1642 .undefined => unreachable,
1836 .enum_literal => unreachable,1643 .enum_literal => unreachable,
1837 .generic_poison => unreachable,1644 .generic_poison => unreachable,
1645 .inferred_alloc_const => unreachable,
1646 .inferred_alloc_mut => unreachable,
18381647
1839 .atomic_order => unreachable, // missing call to resolveTypeFields1648 .atomic_order => unreachable, // missing call to resolveTypeFields
1840 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields1649 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields
...@@ -1927,17 +1736,13 @@ pub const Type = struct {...@@ -1927,17 +1736,13 @@ pub const Type = struct {
1927 }1736 }
19281737
1929 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {1738 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1930 switch (ty.ip_index) {1739 return switch (ty.ip_index) {
1931 .none => return switch (ty.tag()) {1740 .inferred_alloc_const_type, .inferred_alloc_mut_type => true,
1932 .inferred_alloc_const,1741 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1933 .inferred_alloc_mut,
1934 => true,
1935 },
1936 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1937 .ptr_type => |ptr_info| ptr_info.size == .One,1742 .ptr_type => |ptr_info| ptr_info.size == .One,
1938 else => false,1743 else => false,
1939 },1744 },
1940 }1745 };
1941 }1746 }
19421747
1943 /// Asserts `ty` is a pointer.1748 /// Asserts `ty` is a pointer.
...@@ -1948,11 +1753,7 @@ pub const Type = struct {...@@ -1948,11 +1753,7 @@ pub const Type = struct {
1948 /// Returns `null` if `ty` is not a pointer.1753 /// Returns `null` if `ty` is not a pointer.
1949 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {1754 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1950 return switch (ty.ip_index) {1755 return switch (ty.ip_index) {
1951 .none => switch (ty.tag()) {1756 .inferred_alloc_const_type, .inferred_alloc_mut_type => .One,
1952 .inferred_alloc_const,
1953 .inferred_alloc_mut,
1954 => .One,
1955 },
1956 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {1757 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1957 .ptr_type => |ptr_info| ptr_info.size,1758 .ptr_type => |ptr_info| ptr_info.size,
1958 else => null,1759 else => null,
...@@ -2625,10 +2426,6 @@ pub const Type = struct {...@@ -2625,10 +2426,6 @@ pub const Type = struct {
2625 while (true) switch (ty.ip_index) {2426 while (true) switch (ty.ip_index) {
2626 .empty_struct_type => return Value.empty_struct,2427 .empty_struct_type => return Value.empty_struct,
26272428
2628 .none => switch (ty.tag()) {
2629 .inferred_alloc_const => unreachable,
2630 .inferred_alloc_mut => unreachable,
2631 },
2632 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {2429 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2633 .int_type => |int_type| {2430 .int_type => |int_type| {
2634 if (int_type.bits == 0) {2431 if (int_type.bits == 0) {
...@@ -2710,6 +2507,8 @@ pub const Type = struct {...@@ -2710,6 +2507,8 @@ pub const Type = struct {
2710 .undefined => return Value.undef,2507 .undefined => return Value.undef,
27112508
2712 .generic_poison => unreachable,2509 .generic_poison => unreachable,
2510 .inferred_alloc_const => unreachable,
2511 .inferred_alloc_mut => unreachable,
2713 },2512 },
2714 .struct_type => |struct_type| {2513 .struct_type => |struct_type| {
2715 if (mod.structPtrUnwrap(struct_type.index)) |s| {2514 if (mod.structPtrUnwrap(struct_type.index)) |s| {
...@@ -2888,6 +2687,9 @@ pub const Type = struct {...@@ -2888,6 +2687,9 @@ pub const Type = struct {
2888 .enum_literal,2687 .enum_literal,
2889 .type_info,2688 .type_info,
2890 => true,2689 => true,
2690
2691 .inferred_alloc_const => unreachable,
2692 .inferred_alloc_mut => unreachable,
2891 },2693 },
2892 .struct_type => |struct_type| {2694 .struct_type => |struct_type| {
2893 // A struct with no fields is not comptime-only.2695 // A struct with no fields is not comptime-only.
...@@ -3343,61 +3145,56 @@ pub const Type = struct {...@@ -3343,61 +3145,56 @@ pub const Type = struct {
33433145
3344 /// Supports structs and unions.3146 /// Supports structs and unions.
3345 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {3147 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
3346 switch (ty.ip_index) {3148 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3347 .none => switch (ty.tag()) {3149 .struct_type => |struct_type| {
3348 else => unreachable,3150 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3349 },3151 assert(struct_obj.haveLayout());
3350 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {3152 assert(struct_obj.layout != .Packed);
3351 .struct_type => |struct_type| {3153 var it = ty.iterateStructOffsets(mod);
3352 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;3154 while (it.next()) |field_offset| {
3353 assert(struct_obj.haveLayout());3155 if (index == field_offset.field)
3354 assert(struct_obj.layout != .Packed);3156 return field_offset.offset;
3355 var it = ty.iterateStructOffsets(mod);3157 }
3356 while (it.next()) |field_offset| {
3357 if (index == field_offset.field)
3358 return field_offset.offset;
3359 }
3360
3361 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
3362 },
33633158
3364 .anon_struct_type => |tuple| {3159 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
3365 var offset: u64 = 0;3160 },
3366 var big_align: u32 = 0;
33673161
3368 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {3162 .anon_struct_type => |tuple| {
3369 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {3163 var offset: u64 = 0;
3370 // comptime field3164 var big_align: u32 = 0;
3371 if (i == index) return offset;
3372 continue;
3373 }
33743165
3375 const field_align = field_ty.toType().abiAlignment(mod);3166 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3376 big_align = @max(big_align, field_align);3167 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
3377 offset = std.mem.alignForwardGeneric(u64, offset, field_align);3168 // comptime field
3378 if (i == index) return offset;3169 if (i == index) return offset;
3379 offset += field_ty.toType().abiSize(mod);3170 continue;
3380 }3171 }
3381 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
3382 return offset;
3383 },
33843172
3385 .union_type => |union_type| {3173 const field_align = field_ty.toType().abiAlignment(mod);
3386 if (!union_type.hasTag())3174 big_align = @max(big_align, field_align);
3387 return 0;3175 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3388 const union_obj = mod.unionPtr(union_type.index);3176 if (i == index) return offset;
3389 const layout = union_obj.getLayout(mod, true);3177 offset += field_ty.toType().abiSize(mod);
3390 if (layout.tag_align >= layout.payload_align) {3178 }
3391 // {Tag, Payload}3179 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
3392 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);3180 return offset;
3393 } else {3181 },
3394 // {Payload, Tag}
3395 return 0;
3396 }
3397 },
33983182
3399 else => unreachable,3183 .union_type => |union_type| {
3184 if (!union_type.hasTag())
3185 return 0;
3186 const union_obj = mod.unionPtr(union_type.index);
3187 const layout = union_obj.getLayout(mod, true);
3188 if (layout.tag_align >= layout.payload_align) {
3189 // {Tag, Payload}
3190 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
3191 } else {
3192 // {Payload, Tag}
3193 return 0;
3194 }
3400 },3195 },
3196
3197 else => unreachable,
3401 }3198 }
3402 }3199 }
34033200
...@@ -3445,25 +3242,6 @@ pub const Type = struct {...@@ -3445,25 +3242,6 @@ pub const Type = struct {
3445 return ty.ip_index == .generic_poison_type;3242 return ty.ip_index == .generic_poison_type;
3446 }3243 }
34473244
3448 /// This enum does not directly correspond to `std.builtin.TypeId` because
3449 /// it has extra enum tags in it, as a way of using less memory. For example,
3450 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
3451 /// but with different alignment values, in this data structure they are represented
3452 /// with different enum tags, because the the former requires more payload data than the latter.
3453 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
3454 pub const Tag = enum(usize) {
3455 /// This is a special value that tracks a set of types that have been stored
3456 /// to an inferred allocation. It does not support most of the normal type queries.
3457 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
3458 inferred_alloc_mut,
3459 /// Same as `inferred_alloc_mut` but the local is `var` not `const`.
3460 inferred_alloc_const, // See last_no_payload_tag below.
3461 // After this, the tag requires a payload.
3462
3463 pub const last_no_payload_tag = Tag.inferred_alloc_const;
3464 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
3465 };
3466
3467 pub fn isTuple(ty: Type, mod: *Module) bool {3245 pub fn isTuple(ty: Type, mod: *Module) bool {
3468 return switch (ty.ip_index) {3246 return switch (ty.ip_index) {
3469 .none => false,3247 .none => false,
...@@ -3511,14 +3289,9 @@ pub const Type = struct {...@@ -3511,14 +3289,9 @@ pub const Type = struct {
3511 };3289 };
3512 }3290 }
35133291
3514 /// The sub-types are named after what fields they contain.
3515 pub const Payload = struct {3292 pub const Payload = struct {
3516 tag: Tag,
3517
3518 /// TODO: remove this data structure since we have `InternPool.Key.PtrType`.3293 /// TODO: remove this data structure since we have `InternPool.Key.PtrType`.
3519 pub const Pointer = struct {3294 pub const Pointer = struct {
3520 data: Data,
3521
3522 pub const Data = struct {3295 pub const Data = struct {
3523 pointee_type: Type,3296 pointee_type: Type,
3524 sentinel: ?Value = null,3297 sentinel: ?Value = null,
...@@ -3568,64 +3341,60 @@ pub const Type = struct {...@@ -3568,64 +3341,60 @@ pub const Type = struct {
3568 };3341 };
3569 };3342 };
35703343
3571 pub const @"u1": Type = .{ .ip_index = .u1_type, .legacy = undefined };3344 pub const @"u1": Type = .{ .ip_index = .u1_type };
3572 pub const @"u8": Type = .{ .ip_index = .u8_type, .legacy = undefined };3345 pub const @"u8": Type = .{ .ip_index = .u8_type };
3573 pub const @"u16": Type = .{ .ip_index = .u16_type, .legacy = undefined };3346 pub const @"u16": Type = .{ .ip_index = .u16_type };
3574 pub const @"u29": Type = .{ .ip_index = .u29_type, .legacy = undefined };3347 pub const @"u29": Type = .{ .ip_index = .u29_type };
3575 pub const @"u32": Type = .{ .ip_index = .u32_type, .legacy = undefined };3348 pub const @"u32": Type = .{ .ip_index = .u32_type };
3576 pub const @"u64": Type = .{ .ip_index = .u64_type, .legacy = undefined };3349 pub const @"u64": Type = .{ .ip_index = .u64_type };
3577 pub const @"u128": Type = .{ .ip_index = .u128_type, .legacy = undefined };3350 pub const @"u128": Type = .{ .ip_index = .u128_type };
35783351
3579 pub const @"i8": Type = .{ .ip_index = .i8_type, .legacy = undefined };3352 pub const @"i8": Type = .{ .ip_index = .i8_type };
3580 pub const @"i16": Type = .{ .ip_index = .i16_type, .legacy = undefined };3353 pub const @"i16": Type = .{ .ip_index = .i16_type };
3581 pub const @"i32": Type = .{ .ip_index = .i32_type, .legacy = undefined };3354 pub const @"i32": Type = .{ .ip_index = .i32_type };
3582 pub const @"i64": Type = .{ .ip_index = .i64_type, .legacy = undefined };3355 pub const @"i64": Type = .{ .ip_index = .i64_type };
3583 pub const @"i128": Type = .{ .ip_index = .i128_type, .legacy = undefined };3356 pub const @"i128": Type = .{ .ip_index = .i128_type };
35843357
3585 pub const @"f16": Type = .{ .ip_index = .f16_type, .legacy = undefined };3358 pub const @"f16": Type = .{ .ip_index = .f16_type };
3586 pub const @"f32": Type = .{ .ip_index = .f32_type, .legacy = undefined };3359 pub const @"f32": Type = .{ .ip_index = .f32_type };
3587 pub const @"f64": Type = .{ .ip_index = .f64_type, .legacy = undefined };3360 pub const @"f64": Type = .{ .ip_index = .f64_type };
3588 pub const @"f80": Type = .{ .ip_index = .f80_type, .legacy = undefined };3361 pub const @"f80": Type = .{ .ip_index = .f80_type };
3589 pub const @"f128": Type = .{ .ip_index = .f128_type, .legacy = undefined };3362 pub const @"f128": Type = .{ .ip_index = .f128_type };
35903363
3591 pub const @"bool": Type = .{ .ip_index = .bool_type, .legacy = undefined };3364 pub const @"bool": Type = .{ .ip_index = .bool_type };
3592 pub const @"usize": Type = .{ .ip_index = .usize_type, .legacy = undefined };3365 pub const @"usize": Type = .{ .ip_index = .usize_type };
3593 pub const @"isize": Type = .{ .ip_index = .isize_type, .legacy = undefined };3366 pub const @"isize": Type = .{ .ip_index = .isize_type };
3594 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type, .legacy = undefined };3367 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type };
3595 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type, .legacy = undefined };3368 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type };
3596 pub const @"void": Type = .{ .ip_index = .void_type, .legacy = undefined };3369 pub const @"void": Type = .{ .ip_index = .void_type };
3597 pub const @"type": Type = .{ .ip_index = .type_type, .legacy = undefined };3370 pub const @"type": Type = .{ .ip_index = .type_type };
3598 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type, .legacy = undefined };3371 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type };
3599 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type, .legacy = undefined };3372 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type };
3600 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type, .legacy = undefined };3373 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type };
3601 pub const @"null": Type = .{ .ip_index = .null_type, .legacy = undefined };3374 pub const @"null": Type = .{ .ip_index = .null_type };
3602 pub const @"undefined": Type = .{ .ip_index = .undefined_type, .legacy = undefined };3375 pub const @"undefined": Type = .{ .ip_index = .undefined_type };
3603 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type, .legacy = undefined };3376 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type };
36043377
3605 pub const @"c_char": Type = .{ .ip_index = .c_char_type, .legacy = undefined };3378 pub const @"c_char": Type = .{ .ip_index = .c_char_type };
3606 pub const @"c_short": Type = .{ .ip_index = .c_short_type, .legacy = undefined };3379 pub const @"c_short": Type = .{ .ip_index = .c_short_type };
3607 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type, .legacy = undefined };3380 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type };
3608 pub const @"c_int": Type = .{ .ip_index = .c_int_type, .legacy = undefined };3381 pub const @"c_int": Type = .{ .ip_index = .c_int_type };
3609 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type, .legacy = undefined };3382 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type };
3610 pub const @"c_long": Type = .{ .ip_index = .c_long_type, .legacy = undefined };3383 pub const @"c_long": Type = .{ .ip_index = .c_long_type };
3611 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type, .legacy = undefined };3384 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type };
3612 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type, .legacy = undefined };3385 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
3613 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type, .legacy = undefined };3386 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
3614 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type, .legacy = undefined };3387 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
36153388
3616 pub const const_slice_u8: Type = .{ .ip_index = .const_slice_u8_type, .legacy = undefined };3389 pub const const_slice_u8: Type = .{ .ip_index = .const_slice_u8_type };
3617 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type, .legacy = undefined };3390 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
3618 pub const single_const_pointer_to_comptime_int: Type = .{3391 pub const single_const_pointer_to_comptime_int: Type = .{
3619 .ip_index = .single_const_pointer_to_comptime_int_type,3392 .ip_index = .single_const_pointer_to_comptime_int_type,
3620 .legacy = undefined,
3621 };
3622 pub const const_slice_u8_sentinel_0: Type = .{
3623 .ip_index = .const_slice_u8_sentinel_0_type,
3624 .legacy = undefined,
3625 };3393 };
3626 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type, .legacy = undefined };3394 pub const const_slice_u8_sentinel_0: Type = .{ .ip_index = .const_slice_u8_sentinel_0_type };
3395 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
36273396
3628 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined };3397 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
36293398
3630 pub const err_int = Type.u16;3399 pub const err_int = Type.u16;
36313400
...@@ -3709,33 +3478,4 @@ pub const Type = struct {...@@ -3709,33 +3478,4 @@ pub const Type = struct {
3709 /// This is only used for comptime asserts. Bump this number when you make a change3478 /// This is only used for comptime asserts. Bump this number when you make a change
3710 /// to packed struct layout to find out all the places in the codebase you need to edit!3479 /// to packed struct layout to find out all the places in the codebase you need to edit!
3711 pub const packed_struct_layout_version = 2;3480 pub const packed_struct_layout_version = 2;
3712
3713 /// This function is used in the debugger pretty formatters in tools/ to fetch the
3714 /// Tag to Payload mapping to facilitate fancy debug printing for this type.
3715 fn dbHelper(self: *Type, tag_to_payload_map: *map: {
3716 const tags = @typeInfo(Tag).Enum.fields;
3717 var fields: [tags.len]std.builtin.Type.StructField = undefined;
3718 for (&fields, tags) |*field, t| field.* = .{
3719 .name = t.name,
3720 .type = *if (t.value < Tag.no_payload_count) void else @field(Tag, t.name).Type(),
3721 .default_value = null,
3722 .is_comptime = false,
3723 .alignment = 0,
3724 };
3725 break :map @Type(.{ .Struct = .{
3726 .layout = .Extern,
3727 .fields = &fields,
3728 .decls = &.{},
3729 .is_tuple = false,
3730 } });
3731 }) void {
3732 _ = self;
3733 _ = tag_to_payload_map;
3734 }
3735
3736 comptime {
3737 if (builtin.mode == .Debug) {
3738 _ = &dbHelper;
3739 }
3740 }
3741};3481};
src/value.zig+2-6
...@@ -2159,9 +2159,7 @@ pub const Value = struct {...@@ -2159,9 +2159,7 @@ pub const Value = struct {
2159 .Null,2159 .Null,
2160 => {},2160 => {},
21612161
2162 .Type => {2162 .Type => unreachable, // handled via ip_index check above
2163 return val.toType().hashWithHasher(hasher, mod);
2164 },
2165 .Float => {2163 .Float => {
2166 // For hash/eql purposes, we treat floats as their IEEE integer representation.2164 // For hash/eql purposes, we treat floats as their IEEE integer representation.
2167 switch (ty.floatBits(mod.getTarget())) {2165 switch (ty.floatBits(mod.getTarget())) {
...@@ -2310,9 +2308,7 @@ pub const Value = struct {...@@ -2310,9 +2308,7 @@ pub const Value = struct {
2310 .Null,2308 .Null,
2311 .Struct, // It sure would be nice to do something clever with structs.2309 .Struct, // It sure would be nice to do something clever with structs.
2312 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),2310 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),
2313 .Type => {2311 .Type => unreachable, // handled above with the ip_index check
2314 val.toType().hashWithHasher(hasher, mod);
2315 },
2316 .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),2312 .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),
2317 .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) {2313 .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) {
2318 .slice => {2314 .slice => {