@@ -370,6 +370,7 @@ pub const Key = union(enum) {
370370 layout : std.builtin.Type.ContainerLayout ,
371371 field_names : NullTerminatedString.Slice ,
372372 field_types : Index.Slice ,
373+ field_inits_bodies : InitBody.Slice ,
373374 field_inits : Index.Slice ,
374375 field_aligns : Alignment.Slice ,
375376 runtime_order : RuntimeOrder.Slice ,
@@ -400,6 +401,23 @@ pub const Key = union(enum) {
400401 }
401402 };
402403
404+ pub const InitBody = struct {
405+ start : Zir.Inst.Index ,
406+ len : u32 ,
407+
408+ pub const Slice = struct {
409+ start : u32 ,
410+ len : u32 ,
411+
412+ pub fn get (this : @This (), ip : * const InternPool ) []InitBody {
413+ // Workaround for not being able to case between slices of different lengths
414+ assert (ip .extra .items .len >= this .start + this .len * 2 );
415+ const bodies_ptr : [* ]InitBody = @ptrCast (ip .extra .items [this .start .. ].ptr );
416+ return bodies_ptr [0.. this .len ];
417+ }
418+ };
419+ };
420+
403421 pub const Offsets = struct {
404422 start : u32 ,
405423 len : u32 ,
@@ -463,6 +481,7 @@ pub const Key = union(enum) {
463481
464482 pub fn fieldInit (s : @This (), ip : * const InternPool , i : usize ) Index {
465483 if (s .field_inits .len == 0 ) return .none ;
484+ assert (s .haveFieldInits (ip ));
466485 return s .field_inits .get (ip )[i ];
467486 }
468487
@@ -497,6 +516,14 @@ pub const Key = union(enum) {
497516 return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
498517 }
499518
519+ /// The returned pointer expires with any addition to the `InternPool`.
520+ /// Asserts the is not packed.
521+ pub fn packedFlagsPtr (self : @This (), ip : * const InternPool ) * Tag.TypeStructPacked.Flags {
522+ assert (self .layout == .Packed );
523+ const flags_field_index = std .meta .fieldIndex (Tag .TypeStructPacked , "flags" ).? ;
524+ return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
525+ }
526+
500527 pub fn assumeRuntimeBitsIfFieldTypesWip (s : @This (), ip : * InternPool ) bool {
501528 if (s .layout == .Packed ) return false ;
502529 const flags_ptr = s .flagsPtr (ip );
@@ -546,6 +573,28 @@ pub const Key = union(enum) {
546573 s .flagsPtr (ip ).alignment_wip = false ;
547574 }
548575
576+ pub fn setInitsWip (s : @This (), ip : * InternPool ) bool {
577+ switch (s .layout ) {
578+ inline else = > | layout | {
579+ const flag = if (layout == .Packed )
580+ & s .packedFlagsPtr (ip ).field_inits_wip
581+ else
582+ & s .flagsPtr (ip ).field_inits_wip ;
583+
584+ if (flag .* ) return true ;
585+ flag .* = true ;
586+ return false ;
587+ },
588+ }
589+ }
590+
591+ pub fn clearInitsWip (s : @This (), ip : * InternPool ) void {
592+ switch (s .layout ) {
593+ .Packed = > s .packedFlagsPtr (ip ).field_inits_wip = false ,
594+ .Auto , .Extern = > s .flagsPtr (ip ).field_inits_wip = false ,
595+ }
596+ }
597+
549598 pub fn setFullyResolved (s : @This (), ip : * InternPool ) bool {
550599 if (s .layout == .Packed ) return true ;
551600 const flags_ptr = s .flagsPtr (ip );
@@ -588,6 +637,20 @@ pub const Key = union(enum) {
588637 return types .len == 0 or types [0 ] != .none ;
589638 }
590639
640+ pub fn haveFieldInits (s : @This (), ip : * const InternPool ) bool {
641+ return switch (s .layout ) {
642+ .Packed = > s .packedFlagsPtr (ip ).inits_resolved ,
643+ .Auto , .Extern = > s .flagsPtr (ip ).inits_resolved ,
644+ };
645+ }
646+
647+ pub fn setHaveFieldInits (s : @This (), ip : * InternPool ) void {
648+ return switch (s .layout ) {
649+ .Packed = > s .packedFlagsPtr (ip ).inits_resolved = true ,
650+ .Auto , .Extern = > s .flagsPtr (ip ).inits_resolved = true ,
651+ };
652+ }
653+
591654 pub fn haveLayout (s : @This (), ip : * InternPool ) bool {
592655 return switch (s .layout ) {
593656 .Packed = > s .backingIntType (ip ).* != .none ,
@@ -2985,14 +3048,25 @@ pub const Tag = enum(u8) {
29853048 /// Trailing:
29863049 /// 0. type: Index for each fields_len
29873050 /// 1. name: NullTerminatedString for each fields_len
2988- /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
3051+ ///
3052+ /// if tag is type_struct_packed_inits:
3053+ /// 2. body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
3054+ /// 3. init: Index for each fields_len
29893055 pub const TypeStructPacked = struct {
29903056 decl : Module.Decl.Index ,
29913057 zir_index : Zir.Inst.Index ,
29923058 fields_len : u32 ,
29933059 namespace : Module.Namespace.OptionalIndex ,
29943060 backing_int_ty : Index ,
29953061 names_map : MapIndex ,
3062+ flags : Flags ,
3063+
3064+ pub const Flags = packed struct (u32 ) {
3065+ /// Dependency loop detection when resolving field inits.
3066+ field_inits_wip : bool ,
3067+ inits_resolved : bool ,
3068+ _ : u30 = 0 ,
3069+ };
29963070 };
29973071
29983072 /// At first I thought of storing the denormalized data externally, such as...
@@ -3015,6 +3089,7 @@ pub const Tag = enum(u8) {
30153089 /// names_map: MapIndex,
30163090 /// name: NullTerminatedString // for each field in declared order
30173091 /// 2. if any_default_inits:
3092+ /// body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
30183093 /// init: Index // for each field in declared order
30193094 /// 3. if has_namespace:
30203095 /// namespace: Module.Namespace.Index
@@ -3038,6 +3113,7 @@ pub const Tag = enum(u8) {
30383113 requires_comptime : RequiresComptime ,
30393114 is_tuple : bool ,
30403115 assumed_runtime_bits : bool ,
3116+ assumed_pointer_aligned : bool ,
30413117 has_namespace : bool ,
30423118 any_comptime_fields : bool ,
30433119 any_default_inits : bool ,
@@ -3050,14 +3126,18 @@ pub const Tag = enum(u8) {
30503126 field_types_wip : bool ,
30513127 /// Dependency loop detection when resolving struct layout.
30523128 layout_wip : bool ,
3053- /// Determines whether `size`, `alignment`, runtime field order, and
3129+ /// Indicates whether `size`, `alignment`, runtime field order, and
30543130 /// field offets are populated.
30553131 layout_resolved : bool ,
3132+ /// Dependency loop detection when resolving field inits.
3133+ field_inits_wip : bool ,
3134+ /// Indicates whether `field_inits` has been resolved.
3135+ inits_resolved : bool ,
30563136 // The types and all its fields have had their layout resolved. Even through pointer,
30573137 // which `layout_resolved` does not ensure.
30583138 fully_resolved : bool ,
30593139
3060- _ : u11 = 0 ,
3140+ _ : u8 = 0 ,
30613141 };
30623142 };
30633143};
@@ -3690,6 +3770,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
36903770 .layout = .Auto ,
36913771 .field_names = .{ .start = 0 , .len = 0 },
36923772 .field_types = .{ .start = 0 , .len = 0 },
3773+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
36933774 .field_inits = .{ .start = 0 , .len = 0 },
36943775 .field_aligns = .{ .start = 0 , .len = 0 },
36953776 .runtime_order = .{ .start = 0 , .len = 0 },
@@ -3706,6 +3787,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
37063787 .layout = .Auto ,
37073788 .field_names = .{ .start = 0 , .len = 0 },
37083789 .field_types = .{ .start = 0 , .len = 0 },
3790+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
37093791 .field_inits = .{ .start = 0 , .len = 0 },
37103792 .field_aligns = .{ .start = 0 , .len = 0 },
37113793 .runtime_order = .{ .start = 0 , .len = 0 },
@@ -4218,6 +4300,12 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
42184300 index += fields_len ;
42194301 break :t .{ names_map .toOptional (), names };
42204302 };
4303+ const field_inits_bodies : Key.StructType.InitBody.Slice = t : {
4304+ if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
4305+ const offsets : Key.StructType.InitBody.Slice = .{ .start = index , .len = fields_len };
4306+ index += fields_len * 2 ;
4307+ break :t offsets ;
4308+ };
42214309 const field_inits : Index.Slice = t : {
42224310 if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
42234311 const inits : Index.Slice = .{ .start = index , .len = fields_len };
@@ -4261,6 +4349,7 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
42614349 .field_types = field_types ,
42624350 .names_map = names_map ,
42634351 .field_names = field_names ,
4352+ .field_inits_bodies = field_inits_bodies ,
42644353 .field_inits = field_inits ,
42654354 .namespace = namespace ,
42664355 .field_aligns = field_aligns ,
@@ -4287,13 +4376,20 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
42874376 .start = type_struct_packed .end + fields_len ,
42884377 .len = fields_len ,
42894378 },
4290- .field_inits = if (inits ) .{
4379+ .field_inits_bodies = if (inits ) .{
42914380 .start = type_struct_packed .end + fields_len * 2 ,
42924381 .len = fields_len ,
42934382 } else .{
42944383 .start = 0 ,
42954384 .len = 0 ,
42964385 },
4386+ .field_inits = if (inits ) .{
4387+ .start = type_struct_packed .end + fields_len * 4 ,
4388+ .len = fields_len ,
4389+ } else .{
4390+ .start = 0 ,
4391+ .len = 0 ,
4392+ },
42974393 .field_aligns = .{ .start = 0 , .len = 0 },
42984394 .runtime_order = .{ .start = 0 , .len = 0 },
42994395 .comptime_bits = .{ .start = 0 , .len = 0 },
@@ -5340,6 +5436,7 @@ pub const StructTypeInit = struct {
53405436 is_tuple : bool ,
53415437 any_comptime_fields : bool ,
53425438 any_default_inits : bool ,
5439+ inits_resolved : bool ,
53435440 any_aligned_fields : bool ,
53445441};
53455442
@@ -5360,6 +5457,7 @@ pub fn getStructType(
53605457 .layout = undefined ,
53615458 .field_names = undefined ,
53625459 .field_types = undefined ,
5460+ .field_inits_bodies = undefined ,
53635461 .field_inits = undefined ,
53645462 .field_aligns = undefined ,
53655463 .runtime_order = undefined ,
@@ -5382,6 +5480,7 @@ pub fn getStructType(
53825480 try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStructPacked ).Struct .fields .len +
53835481 ini .fields_len + // types
53845482 ini .fields_len + // names
5483+ ini .fields_len * 2 + // init bodies
53855484 ini .fields_len ); // inits
53865485 try ip .items .append (gpa , .{
53875486 .tag = if (ini .any_default_inits ) .type_struct_packed_inits else .type_struct_packed ,
@@ -5392,11 +5491,16 @@ pub fn getStructType(
53925491 .namespace = ini .namespace ,
53935492 .backing_int_ty = .none ,
53945493 .names_map = names_map ,
5494+ .flags = .{
5495+ .field_inits_wip = false ,
5496+ .inits_resolved = ini .inits_resolved ,
5497+ },
53955498 }),
53965499 });
53975500 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
53985501 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
53995502 if (ini .any_default_inits ) {
5503+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
54005504 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
54015505 }
54025506 return @enumFromInt (ip .items .len - 1 );
@@ -5408,7 +5512,7 @@ pub fn getStructType(
54085512 const comptime_elements_len = if (ini .any_comptime_fields ) (ini .fields_len + 31 ) / 32 else 0 ;
54095513
54105514 try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStruct ).Struct .fields .len +
5411- (ini .fields_len * 5 ) + // types, names, inits, runtime order, offsets
5515+ (ini .fields_len * 7 ) + // types, names, init bodies , inits, runtime order, offsets
54125516 align_elements_len + comptime_elements_len +
54135517 2 ); // names_map + namespace
54145518 try ip .items .append (gpa , .{
@@ -5424,6 +5528,7 @@ pub fn getStructType(
54245528 .requires_comptime = ini .requires_comptime ,
54255529 .is_tuple = ini .is_tuple ,
54265530 .assumed_runtime_bits = false ,
5531+ .assumed_pointer_aligned = false ,
54275532 .has_namespace = ini .namespace != .none ,
54285533 .any_comptime_fields = ini .any_comptime_fields ,
54295534 .any_default_inits = ini .any_default_inits ,
@@ -5433,6 +5538,8 @@ pub fn getStructType(
54335538 .field_types_wip = false ,
54345539 .layout_wip = false ,
54355540 .layout_resolved = false ,
5541+ .field_inits_wip = false ,
5542+ .inits_resolved = ini .inits_resolved ,
54365543 .fully_resolved = false ,
54375544 },
54385545 }),
@@ -5443,6 +5550,7 @@ pub fn getStructType(
54435550 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
54445551 }
54455552 if (ini .any_default_inits ) {
5553+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
54465554 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
54475555 }
54485556 if (ini .namespace .unwrap ()) | namespace | {
@@ -6443,6 +6551,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
64436551 Tag .TypePointer .PackedOffset ,
64446552 Tag .TypeUnion .Flags ,
64456553 Tag .TypeStruct .Flags ,
6554+ Tag .TypeStructPacked .Flags ,
64466555 Tag .Variable .Flags ,
64476556 = > @bitCast (@field (extra , field .name )),
64486557
@@ -6516,6 +6625,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
65166625 Tag .TypePointer .PackedOffset ,
65176626 Tag .TypeUnion .Flags ,
65186627 Tag .TypeStruct .Flags ,
6628+ Tag .TypeStructPacked .Flags ,
65196629 Tag .Variable .Flags ,
65206630 FuncAnalysis ,
65216631 = > @bitCast (int32 ),
0 commit comments