@@ -370,6 +370,7 @@ pub const Key = union(enum) {
370
370
layout : std.builtin.Type.ContainerLayout ,
371
371
field_names : NullTerminatedString.Slice ,
372
372
field_types : Index.Slice ,
373
+ field_inits_bodies : InitBody.Slice ,
373
374
field_inits : Index.Slice ,
374
375
field_aligns : Alignment.Slice ,
375
376
runtime_order : RuntimeOrder.Slice ,
@@ -400,6 +401,23 @@ pub const Key = union(enum) {
400
401
}
401
402
};
402
403
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
+
403
421
pub const Offsets = struct {
404
422
start : u32 ,
405
423
len : u32 ,
@@ -463,6 +481,7 @@ pub const Key = union(enum) {
463
481
464
482
pub fn fieldInit (s : @This (), ip : * const InternPool , i : usize ) Index {
465
483
if (s .field_inits .len == 0 ) return .none ;
484
+ assert (s .haveFieldInits (ip ));
466
485
return s .field_inits .get (ip )[i ];
467
486
}
468
487
@@ -497,6 +516,14 @@ pub const Key = union(enum) {
497
516
return @ptrCast (& ip .extra .items [self .extra_index + flags_field_index ]);
498
517
}
499
518
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
+
500
527
pub fn assumeRuntimeBitsIfFieldTypesWip (s : @This (), ip : * InternPool ) bool {
501
528
if (s .layout == .Packed ) return false ;
502
529
const flags_ptr = s .flagsPtr (ip );
@@ -546,6 +573,28 @@ pub const Key = union(enum) {
546
573
s .flagsPtr (ip ).alignment_wip = false ;
547
574
}
548
575
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
+
549
598
pub fn setFullyResolved (s : @This (), ip : * InternPool ) bool {
550
599
if (s .layout == .Packed ) return true ;
551
600
const flags_ptr = s .flagsPtr (ip );
@@ -588,6 +637,20 @@ pub const Key = union(enum) {
588
637
return types .len == 0 or types [0 ] != .none ;
589
638
}
590
639
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
+
591
654
pub fn haveLayout (s : @This (), ip : * InternPool ) bool {
592
655
return switch (s .layout ) {
593
656
.Packed = > s .backingIntType (ip ).* != .none ,
@@ -2985,14 +3048,25 @@ pub const Tag = enum(u8) {
2985
3048
/// Trailing:
2986
3049
/// 0. type: Index for each fields_len
2987
3050
/// 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
2989
3055
pub const TypeStructPacked = struct {
2990
3056
decl : Module.Decl.Index ,
2991
3057
zir_index : Zir.Inst.Index ,
2992
3058
fields_len : u32 ,
2993
3059
namespace : Module.Namespace.OptionalIndex ,
2994
3060
backing_int_ty : Index ,
2995
3061
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
+ };
2996
3070
};
2997
3071
2998
3072
/// At first I thought of storing the denormalized data externally, such as...
@@ -3015,6 +3089,7 @@ pub const Tag = enum(u8) {
3015
3089
/// names_map: MapIndex,
3016
3090
/// name: NullTerminatedString // for each field in declared order
3017
3091
/// 2. if any_default_inits:
3092
+ /// body_indices: Zir.Inst.Index // for each field in declared order, a pair of start index and length.
3018
3093
/// init: Index // for each field in declared order
3019
3094
/// 3. if has_namespace:
3020
3095
/// namespace: Module.Namespace.Index
@@ -3038,6 +3113,7 @@ pub const Tag = enum(u8) {
3038
3113
requires_comptime : RequiresComptime ,
3039
3114
is_tuple : bool ,
3040
3115
assumed_runtime_bits : bool ,
3116
+ assumed_pointer_aligned : bool ,
3041
3117
has_namespace : bool ,
3042
3118
any_comptime_fields : bool ,
3043
3119
any_default_inits : bool ,
@@ -3050,14 +3126,18 @@ pub const Tag = enum(u8) {
3050
3126
field_types_wip : bool ,
3051
3127
/// Dependency loop detection when resolving struct layout.
3052
3128
layout_wip : bool ,
3053
- /// Determines whether `size`, `alignment`, runtime field order, and
3129
+ /// Indicates whether `size`, `alignment`, runtime field order, and
3054
3130
/// field offets are populated.
3055
3131
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 ,
3056
3136
// The types and all its fields have had their layout resolved. Even through pointer,
3057
3137
// which `layout_resolved` does not ensure.
3058
3138
fully_resolved : bool ,
3059
3139
3060
- _ : u11 = 0 ,
3140
+ _ : u8 = 0 ,
3061
3141
};
3062
3142
};
3063
3143
};
@@ -3690,6 +3770,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3690
3770
.layout = .Auto ,
3691
3771
.field_names = .{ .start = 0 , .len = 0 },
3692
3772
.field_types = .{ .start = 0 , .len = 0 },
3773
+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
3693
3774
.field_inits = .{ .start = 0 , .len = 0 },
3694
3775
.field_aligns = .{ .start = 0 , .len = 0 },
3695
3776
.runtime_order = .{ .start = 0 , .len = 0 },
@@ -3706,6 +3787,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3706
3787
.layout = .Auto ,
3707
3788
.field_names = .{ .start = 0 , .len = 0 },
3708
3789
.field_types = .{ .start = 0 , .len = 0 },
3790
+ .field_inits_bodies = .{ .start = 0 , .len = 0 },
3709
3791
.field_inits = .{ .start = 0 , .len = 0 },
3710
3792
.field_aligns = .{ .start = 0 , .len = 0 },
3711
3793
.runtime_order = .{ .start = 0 , .len = 0 },
@@ -4218,6 +4300,12 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
4218
4300
index += fields_len ;
4219
4301
break :t .{ names_map .toOptional (), names };
4220
4302
};
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
+ };
4221
4309
const field_inits : Index.Slice = t : {
4222
4310
if (! s .data .flags .any_default_inits ) break :t .{ .start = 0 , .len = 0 };
4223
4311
const inits : Index.Slice = .{ .start = index , .len = fields_len };
@@ -4261,6 +4349,7 @@ fn extraStructType(ip: *const InternPool, extra_index: u32) Key.StructType {
4261
4349
.field_types = field_types ,
4262
4350
.names_map = names_map ,
4263
4351
.field_names = field_names ,
4352
+ .field_inits_bodies = field_inits_bodies ,
4264
4353
.field_inits = field_inits ,
4265
4354
.namespace = namespace ,
4266
4355
.field_aligns = field_aligns ,
@@ -4287,13 +4376,20 @@ fn extraPackedStructType(ip: *const InternPool, extra_index: u32, inits: bool) K
4287
4376
.start = type_struct_packed .end + fields_len ,
4288
4377
.len = fields_len ,
4289
4378
},
4290
- .field_inits = if (inits ) .{
4379
+ .field_inits_bodies = if (inits ) .{
4291
4380
.start = type_struct_packed .end + fields_len * 2 ,
4292
4381
.len = fields_len ,
4293
4382
} else .{
4294
4383
.start = 0 ,
4295
4384
.len = 0 ,
4296
4385
},
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
+ },
4297
4393
.field_aligns = .{ .start = 0 , .len = 0 },
4298
4394
.runtime_order = .{ .start = 0 , .len = 0 },
4299
4395
.comptime_bits = .{ .start = 0 , .len = 0 },
@@ -5340,6 +5436,7 @@ pub const StructTypeInit = struct {
5340
5436
is_tuple : bool ,
5341
5437
any_comptime_fields : bool ,
5342
5438
any_default_inits : bool ,
5439
+ inits_resolved : bool ,
5343
5440
any_aligned_fields : bool ,
5344
5441
};
5345
5442
@@ -5360,6 +5457,7 @@ pub fn getStructType(
5360
5457
.layout = undefined ,
5361
5458
.field_names = undefined ,
5362
5459
.field_types = undefined ,
5460
+ .field_inits_bodies = undefined ,
5363
5461
.field_inits = undefined ,
5364
5462
.field_aligns = undefined ,
5365
5463
.runtime_order = undefined ,
@@ -5382,6 +5480,7 @@ pub fn getStructType(
5382
5480
try ip .extra .ensureUnusedCapacity (gpa , @typeInfo (Tag .TypeStructPacked ).Struct .fields .len +
5383
5481
ini .fields_len + // types
5384
5482
ini .fields_len + // names
5483
+ ini .fields_len * 2 + // init bodies
5385
5484
ini .fields_len ); // inits
5386
5485
try ip .items .append (gpa , .{
5387
5486
.tag = if (ini .any_default_inits ) .type_struct_packed_inits else .type_struct_packed ,
@@ -5392,11 +5491,16 @@ pub fn getStructType(
5392
5491
.namespace = ini .namespace ,
5393
5492
.backing_int_ty = .none ,
5394
5493
.names_map = names_map ,
5494
+ .flags = .{
5495
+ .field_inits_wip = false ,
5496
+ .inits_resolved = ini .inits_resolved ,
5497
+ },
5395
5498
}),
5396
5499
});
5397
5500
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5398
5501
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
5399
5502
if (ini .any_default_inits ) {
5503
+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
5400
5504
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5401
5505
}
5402
5506
return @enumFromInt (ip .items .len - 1 );
@@ -5408,7 +5512,7 @@ pub fn getStructType(
5408
5512
const comptime_elements_len = if (ini .any_comptime_fields ) (ini .fields_len + 31 ) / 32 else 0 ;
5409
5513
5410
5514
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
5412
5516
align_elements_len + comptime_elements_len +
5413
5517
2 ); // names_map + namespace
5414
5518
try ip .items .append (gpa , .{
@@ -5424,6 +5528,7 @@ pub fn getStructType(
5424
5528
.requires_comptime = ini .requires_comptime ,
5425
5529
.is_tuple = ini .is_tuple ,
5426
5530
.assumed_runtime_bits = false ,
5531
+ .assumed_pointer_aligned = false ,
5427
5532
.has_namespace = ini .namespace != .none ,
5428
5533
.any_comptime_fields = ini .any_comptime_fields ,
5429
5534
.any_default_inits = ini .any_default_inits ,
@@ -5433,6 +5538,8 @@ pub fn getStructType(
5433
5538
.field_types_wip = false ,
5434
5539
.layout_wip = false ,
5435
5540
.layout_resolved = false ,
5541
+ .field_inits_wip = false ,
5542
+ .inits_resolved = ini .inits_resolved ,
5436
5543
.fully_resolved = false ,
5437
5544
},
5438
5545
}),
@@ -5443,6 +5550,7 @@ pub fn getStructType(
5443
5550
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (OptionalNullTerminatedString .none ), ini .fields_len );
5444
5551
}
5445
5552
if (ini .any_default_inits ) {
5553
+ ip .extra .appendNTimesAssumeCapacity (0 , ini .fields_len * 2 );
5446
5554
ip .extra .appendNTimesAssumeCapacity (@intFromEnum (Index .none ), ini .fields_len );
5447
5555
}
5448
5556
if (ini .namespace .unwrap ()) | namespace | {
@@ -6443,6 +6551,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
6443
6551
Tag .TypePointer .PackedOffset ,
6444
6552
Tag .TypeUnion .Flags ,
6445
6553
Tag .TypeStruct .Flags ,
6554
+ Tag .TypeStructPacked .Flags ,
6446
6555
Tag .Variable .Flags ,
6447
6556
= > @bitCast (@field (extra , field .name )),
6448
6557
@@ -6516,6 +6625,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
6516
6625
Tag .TypePointer .PackedOffset ,
6517
6626
Tag .TypeUnion .Flags ,
6518
6627
Tag .TypeStruct .Flags ,
6628
+ Tag .TypeStructPacked .Flags ,
6519
6629
Tag .Variable .Flags ,
6520
6630
FuncAnalysis ,
6521
6631
= > @bitCast (int32 ),
0 commit comments