@@ -371,6 +371,7 @@ pub const Key = union(enum) {
371371 layout : std.builtin.Type.ContainerLayout ,
372372 field_names : NullTerminatedString.Slice ,
373373 field_types : Index.Slice ,
374+ field_inits_bodies : InitBody.Slice ,
374375 field_inits : Index.Slice ,
375376 field_aligns : Alignment.Slice ,
376377 runtime_order : RuntimeOrder.Slice ,
@@ -401,6 +402,23 @@ pub const Key = union(enum) {
401402 }
402403 };
403404
405+ pub const InitBody = struct {
406+ start : Zir.Inst.Index ,
407+ len : u32 ,
408+
409+ pub const Slice = struct {
410+ start : u32 ,
411+ len : u32 ,
412+
413+ pub fn get (this : @This (), ip : * const InternPool ) []InitBody {
414+ // Workaround for not being able to case between slices of different lengths
415+ assert (ip .extra .items .len >= this .start + this .len * 2 );
416+ const bodies_ptr : [* ]InitBody = @ptrCast (ip .extra .items [this .start .. ].ptr );
417+ return bodies_ptr [0.. this .len ];
418+ }
419+ };
420+ };
421+
404422 pub const Offsets = struct {
405423 start : u32 ,
406424 len : u32 ,
@@ -464,6 +482,7 @@ pub const Key = union(enum) {
464482
465483 pub fn fieldInit (s : @This (), ip : * const InternPool , i : usize ) Index {
466484 if (s .field_inits .len == 0 ) return .none ;
485+ assert (s .haveFieldInits (ip ));
467486 return s .field_inits .get (ip )[i ];
468487 }
469488
@@ -498,6 +517,14 @@ pub const Key = union(enum) {
498517 return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
499518 }
500519
520+ /// The returned pointer expires with any addition to the `InternPool`.
521+ /// Asserts the is not packed.
522+ pub fn packedFlagsPtr (self : @This (), ip : * const InternPool ) * Tag.TypeStructPacked.Flags {
523+ assert (self .layout == .Packed );
524+ const flags_field_index = std .meta .fieldIndex (Tag .TypeStructPacked , "flags" ).? ;
525+ return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
526+ }
527+
501528 pub fn assumeRuntimeBitsIfFieldTypesWip (s : @This (), ip : * InternPool ) bool {
502529 if (s .layout == .Packed ) return false ;
503530 const flags_ptr = s .flagsPtr (ip );
@@ -547,6 +574,28 @@ pub const Key = union(enum) {
547574 s .flagsPtr (ip ).alignment_wip = false ;
548575 }
549576
577+ pub fn setInitsWip (s : @This (), ip : * InternPool ) bool {
578+ switch (s .layout ) {
579+ inline else = > | layout | {
580+ const flag = if (layout == .Packed )
581+ & s .packedFlagsPtr (ip ).field_inits_wip
582+ else
583+ & s .flagsPtr (ip ).field_inits_wip ;
584+
585+ if (flag .* ) return true ;
586+ flag .* = true ;
587+ return false ;
588+ },
589+ }
590+ }
591+
592+ pub fn clearInitsWip (s : @This (), ip : * InternPool ) void {
593+ switch (s .layout ) {
594+ .Packed = > s .packedFlagsPtr (ip ).field_inits_wip = false ,
595+ .Auto , .Extern = > s .flagsPtr (ip ).field_inits_wip = false ,
596+ }
597+ }
598+
550599 pub fn setFullyResolved (s : @This (), ip : * InternPool ) bool {
551600 if (s .layout == .Packed ) return true ;
552601 const flags_ptr = s .flagsPtr (ip );
@@ -589,6 +638,20 @@ pub const Key = union(enum) {
589638 return types .len == 0 or types [0 ] != .none ;
590639 }
591640
641+ pub fn haveFieldInits (s : @This (), ip : * const InternPool ) bool {
642+ return switch (s .layout ) {
643+ .Packed = > s .packedFlagsPtr (ip ).inits_resolved ,
644+ .Auto , .Extern = > s .flagsPtr (ip ).inits_resolved ,
645+ };
646+ }
647+
648+ pub fn setHaveFieldInits (s : @This (), ip : * InternPool ) void {
649+ return switch (s .layout ) {
650+ .Packed = > s .packedFlagsPtr (ip ).inits_resolved = true ,
651+ .Auto , .Extern = > s .flagsPtr (ip ).inits_resolved = true ,
652+ };
653+ }
654+
592655 pub fn haveLayout (s : @This (), ip : * InternPool ) bool {
593656 return switch (s .layout ) {
594657 .Packed = > s .backingIntType (ip ).* != .none ,
@@ -2999,14 +3062,25 @@ pub const Tag = enum(u8) {
29993062 /// Trailing:
30003063 /// 0. type: Index for each fields_len
30013064 /// 1. name: NullTerminatedString for each fields_len
3002- /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
3065+ ///
3066+ /// if tag is type_struct_packed_inits:
3067+ /// 2. body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
3068+ /// 3. init: Index for each fields_len
30033069 pub const TypeStructPacked = struct {
30043070 decl : Module.Decl.Index ,
30053071 zir_index : Zir.Inst.Index ,
30063072 fields_len : u32 ,
30073073 namespace : Module.Namespace.OptionalIndex ,
30083074 backing_int_ty : Index ,
30093075 names_map : MapIndex ,
3076+ flags : Flags ,
3077+
3078+ pub const Flags = packed struct (u32 ) {
3079+ /// Dependency loop detection when resolving field inits.
3080+ field_inits_wip : bool ,
3081+ inits_resolved : bool ,
3082+ _ : u30 = 0 ,
3083+ };
30103084 };
30113085
30123086 /// At first I thought of storing the denormalized data externally, such as...
@@ -3029,6 +3103,7 @@ pub const Tag = enum(u8) {
30293103 /// names_map: MapIndex,
30303104 /// name: NullTerminatedString // for each field in declared order
30313105 /// 2. if any_default_inits:
3106+ /// body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
30323107 /// init: Index // for each field in declared order
30333108 /// 3. if has_namespace:
30343109 /// namespace: Module.Namespace.Index
@@ -3052,6 +3127,7 @@ pub const Tag = enum(u8) {
30523127 requires_comptime : RequiresComptime ,
30533128 is_tuple : bool ,
30543129 assumed_runtime_bits : bool ,
3130+ assumed_pointer_aligned : bool ,
30553131 has_namespace : bool ,
30563132 any_comptime_fields : bool ,
30573133 any_default_inits : bool ,
@@ -3064,14 +3140,18 @@ pub const Tag = enum(u8) {
30643140 field_types_wip : bool ,
30653141 /// Dependency loop detection when resolving struct layout.
30663142 layout_wip : bool ,
3067- /// Determines whether `size`, `alignment`, runtime field order, and
3143+ /// Indicates whether `size`, `alignment`, runtime field order, and
30683144 /// field offets are populated.
30693145 layout_resolved : bool ,
3146+ /// Dependency loop detection when resolving field inits.
3147+ field_inits_wip : bool ,
3148+ /// Indicates whether `field_inits` has been resolved.
3149+ inits_resolved : bool ,
30703150 // The types and all its fields have had their layout resolved. Even through pointer,
30713151 // which `layout_resolved` does not ensure.
30723152 fully_resolved : bool ,
30733153
3074- _ : u11 = 0 ,
3154+ _ : u8 = 0 ,
30753155 };
30763156 };
30773157};
@@ -3704,6 +3784,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
37043784 .layout = .Auto ,
37053785 .field_names = .{ .start = 0 , .len = 0 },
37063786 .field_types = .{ .start = 0 , .len = 0 },
3787+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
37073788 .field_inits = .{ .start = 0 , .len = 0 },
37083789 .field_aligns = .{ .start = 0 , .len = 0 },
37093790 .runtime_order = .{ .start = 0 , .len = 0 },
@@ -3720,6 +3801,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
37203801 .layout = .Auto ,
37213802 .field_names = .{ .start = 0 , .len = 0 },
37223803 .field_types = .{ .start = 0 , .len = 0 },
3804+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
37233805 .field_inits = .{ .start = 0 , .len = 0 },
37243806 .field_aligns = .{ .start = 0 , .len = 0 },
37253807 .runtime_order = .{ .start = 0 , .len = 0 },
@@ -4233,6 +4315,12 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
42334315 index += fields_len ;
42344316 break :t .{ names_map .toOptional (), names };
42354317 };
4318+ const field_inits_bodies : Key.StructType.InitBody.Slice = t : {
4319+ if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
4320+ const offsets : Key.StructType.InitBody.Slice = .{ .start = index , .len = fields_len };
4321+ index += fields_len * 2 ;
4322+ break :t offsets ;
4323+ };
42364324 const field_inits : Index.Slice = t : {
42374325 if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
42384326 const inits : Index.Slice = .{ .start = index , .len = fields_len };
@@ -4276,6 +4364,7 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
42764364 .field_types = field_types ,
42774365 .names_map = names_map ,
42784366 .field_names = field_names ,
4367+ .field_inits_bodies = field_inits_bodies ,
42794368 .field_inits = field_inits ,
42804369 .namespace = namespace ,
42814370 .field_aligns = field_aligns ,
@@ -4302,13 +4391,20 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
43024391 .start = type_struct_packed .end + fields_len ,
43034392 .len = fields_len ,
43044393 },
4305- .field_inits = if (inits ) .{
4394+ .field_inits_bodies = if (inits ) .{
43064395 .start = type_struct_packed .end + fields_len * 2 ,
43074396 .len = fields_len ,
43084397 } else .{
43094398 .start = 0 ,
43104399 .len = 0 ,
43114400 },
4401+ .field_inits = if (inits ) .{
4402+ .start = type_struct_packed .end + fields_len * 4 ,
4403+ .len = fields_len ,
4404+ } else .{
4405+ .start = 0 ,
4406+ .len = 0 ,
4407+ },
43124408 .field_aligns = .{ .start = 0 , .len = 0 },
43134409 .runtime_order = .{ .start = 0 , .len = 0 },
43144410 .comptime_bits = .{ .start = 0 , .len = 0 },
@@ -5362,6 +5458,7 @@ pub const StructTypeInit = struct {
53625458 is_tuple : bool ,
53635459 any_comptime_fields : bool ,
53645460 any_default_inits : bool ,
5461+ inits_resolved : bool ,
53655462 any_aligned_fields : bool ,
53665463};
53675464
@@ -5382,6 +5479,7 @@ pub fn getStructType(
53825479 .layout = undefined ,
53835480 .field_names = undefined ,
53845481 .field_types = undefined ,
5482+ .field_inits_bodies = undefined ,
53855483 .field_inits = undefined ,
53865484 .field_aligns = undefined ,
53875485 .runtime_order = undefined ,
@@ -5404,6 +5502,7 @@ pub fn getStructType(
54045502 try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStructPacked ).Struct .fields .len +
54055503 ini .fields_len + // types
54065504 ini .fields_len + // names
5505+ ini .fields_len * 2 + // init bodies
54075506 ini .fields_len ); // inits
54085507 try ip .items .append (gpa , .{
54095508 .tag = if (ini .any_default_inits ) .type_struct_packed_inits else .type_struct_packed ,
@@ -5414,11 +5513,16 @@ pub fn getStructType(
54145513 .namespace = ini .namespace ,
54155514 .backing_int_ty = .none ,
54165515 .names_map = names_map ,
5516+ .flags = .{
5517+ .field_inits_wip = false ,
5518+ .inits_resolved = ini .inits_resolved ,
5519+ },
54175520 }),
54185521 });
54195522 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
54205523 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
54215524 if (ini .any_default_inits ) {
5525+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
54225526 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
54235527 }
54245528 return @enumFromInt (ip .items .len - 1 );
@@ -5430,7 +5534,7 @@ pub fn getStructType(
54305534 const comptime_elements_len = if (ini .any_comptime_fields ) (ini .fields_len + 31 ) / 32 else 0 ;
54315535
54325536 try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStruct ).Struct .fields .len +
5433- (ini .fields_len * 5 ) + // types, names, inits, runtime order, offsets
5537+ (ini .fields_len * 7 ) + // types, names, init bodies , inits, runtime order, offsets
54345538 align_elements_len + comptime_elements_len +
54355539 2 ); // names_map + namespace
54365540 try ip .items .append (gpa , .{
@@ -5446,6 +5550,7 @@ pub fn getStructType(
54465550 .requires_comptime = ini .requires_comptime ,
54475551 .is_tuple = ini .is_tuple ,
54485552 .assumed_runtime_bits = false ,
5553+ .assumed_pointer_aligned = false ,
54495554 .has_namespace = ini .namespace != .none ,
54505555 .any_comptime_fields = ini .any_comptime_fields ,
54515556 .any_default_inits = ini .any_default_inits ,
@@ -5455,6 +5560,8 @@ pub fn getStructType(
54555560 .field_types_wip = false ,
54565561 .layout_wip = false ,
54575562 .layout_resolved = false ,
5563+ .field_inits_wip = false ,
5564+ .inits_resolved = ini .inits_resolved ,
54585565 .fully_resolved = false ,
54595566 },
54605567 }),
@@ -5465,6 +5572,7 @@ pub fn getStructType(
54655572 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
54665573 }
54675574 if (ini .any_default_inits ) {
5575+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
54685576 ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
54695577 }
54705578 if (ini .namespace .unwrap ()) | namespace | {
@@ -6465,6 +6573,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
64656573 Tag .TypePointer .PackedOffset ,
64666574 Tag .TypeUnion .Flags ,
64676575 Tag .TypeStruct .Flags ,
6576+ Tag .TypeStructPacked .Flags ,
64686577 Tag .Variable .Flags ,
64696578 = > @bitCast (@field (extra , field .name )),
64706579
@@ -6538,6 +6647,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
65386647 Tag .TypePointer .PackedOffset ,
65396648 Tag .TypeUnion .Flags ,
65406649 Tag .TypeStruct .Flags ,
6650+ Tag .TypeStructPacked .Flags ,
65416651 Tag .Variable .Flags ,
65426652 FuncAnalysis ,
65436653 = > @bitCast (int32 ),
0 commit comments