@@ -371,6 +371,7 @@ pub const Key = union(enum) {
371
371
layout : std.builtin.Type.ContainerLayout ,
372
372
field_names : NullTerminatedString.Slice ,
373
373
field_types : Index.Slice ,
374
+ field_inits_bodies : InitBody.Slice ,
374
375
field_inits : Index.Slice ,
375
376
field_aligns : Alignment.Slice ,
376
377
runtime_order : RuntimeOrder.Slice ,
@@ -401,6 +402,23 @@ pub const Key = union(enum) {
401
402
}
402
403
};
403
404
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
+
404
422
pub const Offsets = struct {
405
423
start : u32 ,
406
424
len : u32 ,
@@ -464,6 +482,7 @@ pub const Key = union(enum) {
464
482
465
483
pub fn fieldInit (s : @This (), ip : * const InternPool , i : usize ) Index {
466
484
if (s .field_inits .len == 0 ) return .none ;
485
+ assert (s .haveFieldInits (ip ));
467
486
return s .field_inits .get (ip )[i ];
468
487
}
469
488
@@ -498,6 +517,14 @@ pub const Key = union(enum) {
498
517
return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
499
518
}
500
519
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
+
501
528
pub fn assumeRuntimeBitsIfFieldTypesWip (s : @This (), ip : * InternPool ) bool {
502
529
if (s .layout == .Packed ) return false ;
503
530
const flags_ptr = s .flagsPtr (ip );
@@ -547,6 +574,28 @@ pub const Key = union(enum) {
547
574
s .flagsPtr (ip ).alignment_wip = false ;
548
575
}
549
576
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
+
550
599
pub fn setFullyResolved (s : @This (), ip : * InternPool ) bool {
551
600
if (s .layout == .Packed ) return true ;
552
601
const flags_ptr = s .flagsPtr (ip );
@@ -589,6 +638,20 @@ pub const Key = union(enum) {
589
638
return types .len == 0 or types [0 ] != .none ;
590
639
}
591
640
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
+
592
655
pub fn haveLayout (s : @This (), ip : * InternPool ) bool {
593
656
return switch (s .layout ) {
594
657
.Packed = > s .backingIntType (ip ).* != .none ,
@@ -2999,14 +3062,25 @@ pub const Tag = enum(u8) {
2999
3062
/// Trailing:
3000
3063
/// 0. type: Index for each fields_len
3001
3064
/// 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
3003
3069
pub const TypeStructPacked = struct {
3004
3070
decl : Module.Decl.Index ,
3005
3071
zir_index : Zir.Inst.Index ,
3006
3072
fields_len : u32 ,
3007
3073
namespace : Module.Namespace.OptionalIndex ,
3008
3074
backing_int_ty : Index ,
3009
3075
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
+ };
3010
3084
};
3011
3085
3012
3086
/// At first I thought of storing the denormalized data externally, such as...
@@ -3029,6 +3103,7 @@ pub const Tag = enum(u8) {
3029
3103
/// names_map: MapIndex,
3030
3104
/// name: NullTerminatedString // for each field in declared order
3031
3105
/// 2. if any_default_inits:
3106
+ /// body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
3032
3107
/// init: Index // for each field in declared order
3033
3108
/// 3. if has_namespace:
3034
3109
/// namespace: Module.Namespace.Index
@@ -3052,6 +3127,7 @@ pub const Tag = enum(u8) {
3052
3127
requires_comptime : RequiresComptime ,
3053
3128
is_tuple : bool ,
3054
3129
assumed_runtime_bits : bool ,
3130
+ assumed_pointer_aligned : bool ,
3055
3131
has_namespace : bool ,
3056
3132
any_comptime_fields : bool ,
3057
3133
any_default_inits : bool ,
@@ -3064,14 +3140,18 @@ pub const Tag = enum(u8) {
3064
3140
field_types_wip : bool ,
3065
3141
/// Dependency loop detection when resolving struct layout.
3066
3142
layout_wip : bool ,
3067
- /// Determines whether `size`, `alignment`, runtime field order, and
3143
+ /// Indicates whether `size`, `alignment`, runtime field order, and
3068
3144
/// field offets are populated.
3069
3145
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 ,
3070
3150
// The types and all its fields have had their layout resolved. Even through pointer,
3071
3151
// which `layout_resolved` does not ensure.
3072
3152
fully_resolved : bool ,
3073
3153
3074
- _ : u11 = 0 ,
3154
+ _ : u8 = 0 ,
3075
3155
};
3076
3156
};
3077
3157
};
@@ -3704,6 +3784,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3704
3784
.layout = .Auto ,
3705
3785
.field_names = .{ .start = 0 , .len = 0 },
3706
3786
.field_types = .{ .start = 0 , .len = 0 },
3787
+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
3707
3788
.field_inits = .{ .start = 0 , .len = 0 },
3708
3789
.field_aligns = .{ .start = 0 , .len = 0 },
3709
3790
.runtime_order = .{ .start = 0 , .len = 0 },
@@ -3720,6 +3801,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3720
3801
.layout = .Auto ,
3721
3802
.field_names = .{ .start = 0 , .len = 0 },
3722
3803
.field_types = .{ .start = 0 , .len = 0 },
3804
+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
3723
3805
.field_inits = .{ .start = 0 , .len = 0 },
3724
3806
.field_aligns = .{ .start = 0 , .len = 0 },
3725
3807
.runtime_order = .{ .start = 0 , .len = 0 },
@@ -4233,6 +4315,12 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
4233
4315
index += fields_len ;
4234
4316
break :t .{ names_map .toOptional (), names };
4235
4317
};
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
+ };
4236
4324
const field_inits : Index.Slice = t : {
4237
4325
if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
4238
4326
const inits : Index.Slice = .{ .start = index , .len = fields_len };
@@ -4276,6 +4364,7 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
4276
4364
.field_types = field_types ,
4277
4365
.names_map = names_map ,
4278
4366
.field_names = field_names ,
4367
+ .field_inits_bodies = field_inits_bodies ,
4279
4368
.field_inits = field_inits ,
4280
4369
.namespace = namespace ,
4281
4370
.field_aligns = field_aligns ,
@@ -4302,13 +4391,20 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
4302
4391
.start = type_struct_packed .end + fields_len ,
4303
4392
.len = fields_len ,
4304
4393
},
4305
- .field_inits = if (inits ) .{
4394
+ .field_inits_bodies = if (inits ) .{
4306
4395
.start = type_struct_packed .end + fields_len * 2 ,
4307
4396
.len = fields_len ,
4308
4397
} else .{
4309
4398
.start = 0 ,
4310
4399
.len = 0 ,
4311
4400
},
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
+ },
4312
4408
.field_aligns = .{ .start = 0 , .len = 0 },
4313
4409
.runtime_order = .{ .start = 0 , .len = 0 },
4314
4410
.comptime_bits = .{ .start = 0 , .len = 0 },
@@ -5362,6 +5458,7 @@ pub const StructTypeInit = struct {
5362
5458
is_tuple : bool ,
5363
5459
any_comptime_fields : bool ,
5364
5460
any_default_inits : bool ,
5461
+ inits_resolved : bool ,
5365
5462
any_aligned_fields : bool ,
5366
5463
};
5367
5464
@@ -5382,6 +5479,7 @@ pub fn getStructType(
5382
5479
.layout = undefined ,
5383
5480
.field_names = undefined ,
5384
5481
.field_types = undefined ,
5482
+ .field_inits_bodies = undefined ,
5385
5483
.field_inits = undefined ,
5386
5484
.field_aligns = undefined ,
5387
5485
.runtime_order = undefined ,
@@ -5404,6 +5502,7 @@ pub fn getStructType(
5404
5502
try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStructPacked ).Struct .fields .len +
5405
5503
ini .fields_len + // types
5406
5504
ini .fields_len + // names
5505
+ ini .fields_len * 2 + // init bodies
5407
5506
ini .fields_len ); // inits
5408
5507
try ip .items .append (gpa , .{
5409
5508
.tag = if (ini .any_default_inits ) .type_struct_packed_inits else .type_struct_packed ,
@@ -5414,11 +5513,16 @@ pub fn getStructType(
5414
5513
.namespace = ini .namespace ,
5415
5514
.backing_int_ty = .none ,
5416
5515
.names_map = names_map ,
5516
+ .flags = .{
5517
+ .field_inits_wip = false ,
5518
+ .inits_resolved = ini .inits_resolved ,
5519
+ },
5417
5520
}),
5418
5521
});
5419
5522
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5420
5523
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
5421
5524
if (ini .any_default_inits ) {
5525
+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
5422
5526
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5423
5527
}
5424
5528
return @enumFromInt (ip .items .len - 1 );
@@ -5430,7 +5534,7 @@ pub fn getStructType(
5430
5534
const comptime_elements_len = if (ini .any_comptime_fields ) (ini .fields_len + 31 ) / 32 else 0 ;
5431
5535
5432
5536
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
5434
5538
align_elements_len + comptime_elements_len +
5435
5539
2 ); // names_map + namespace
5436
5540
try ip .items .append (gpa , .{
@@ -5446,6 +5550,7 @@ pub fn getStructType(
5446
5550
.requires_comptime = ini .requires_comptime ,
5447
5551
.is_tuple = ini .is_tuple ,
5448
5552
.assumed_runtime_bits = false ,
5553
+ .assumed_pointer_aligned = false ,
5449
5554
.has_namespace = ini .namespace != .none ,
5450
5555
.any_comptime_fields = ini .any_comptime_fields ,
5451
5556
.any_default_inits = ini .any_default_inits ,
@@ -5455,6 +5560,8 @@ pub fn getStructType(
5455
5560
.field_types_wip = false ,
5456
5561
.layout_wip = false ,
5457
5562
.layout_resolved = false ,
5563
+ .field_inits_wip = false ,
5564
+ .inits_resolved = ini .inits_resolved ,
5458
5565
.fully_resolved = false ,
5459
5566
},
5460
5567
}),
@@ -5465,6 +5572,7 @@ pub fn getStructType(
5465
5572
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
5466
5573
}
5467
5574
if (ini .any_default_inits ) {
5575
+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
5468
5576
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5469
5577
}
5470
5578
if (ini .namespace .unwrap ()) | namespace | {
@@ -6465,6 +6573,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
6465
6573
Tag .TypePointer .PackedOffset ,
6466
6574
Tag .TypeUnion .Flags ,
6467
6575
Tag .TypeStruct .Flags ,
6576
+ Tag .TypeStructPacked .Flags ,
6468
6577
Tag .Variable .Flags ,
6469
6578
= > @bitCast (@field (extra , field .name )),
6470
6579
@@ -6538,6 +6647,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
6538
6647
Tag .TypePointer .PackedOffset ,
6539
6648
Tag .TypeUnion .Flags ,
6540
6649
Tag .TypeStruct .Flags ,
6650
+ Tag .TypeStructPacked .Flags ,
6541
6651
Tag .Variable .Flags ,
6542
6652
FuncAnalysis ,
6543
6653
= > @bitCast (int32 ),
0 commit comments