@@ -4148,7 +4148,6 @@ fn structDeclInner(
41484148 .src_node = node ,
41494149 .layout = layout ,
41504150 .fields_len = 0 ,
4151- .body_len = 0 ,
41524151 .decls_len = 0 ,
41534152 .known_non_opv = false ,
41544153 .known_comptime_only = false ,
@@ -4192,6 +4191,19 @@ fn structDeclInner(
41924191 var wip_members = try WipMembers .init (gpa , & astgen .scratch , decl_count , field_count , bits_per_field , max_field_size );
41934192 defer wip_members .deinit ();
41944193
4194+ // We will use the scratch buffer, starting here, for the bodies:
4195+ // bodies: { // for every fields_len
4196+ // field_type_body_inst: Inst, // for each field_type_body_len
4197+ // align_body_inst: Inst, // for each align_body_len
4198+ // init_body_inst: Inst, // for each init_body_len
4199+ // }
4200+ // Note that the scratch buffer is simultaneously being used by WipMembers, however
4201+ // it will not access any elements beyond this point in the ArrayList. It also
4202+ // accesses via the ArrayList items field so it can handle the scratch buffer being
4203+ // reallocated.
4204+ // No defer needed here because it is handled by `wip_members.deinit()` above.
4205+ const bodies_start = astgen .scratch .items .len ;
4206+
41954207 var known_non_opv = false ;
41964208 var known_comptime_only = false ;
41974209 for (container_decl .ast .members ) | member_node | {
@@ -4203,57 +4215,78 @@ fn structDeclInner(
42034215 const field_name = try astgen .identAsString (member .ast .name_token );
42044216 wip_members .appendToField (field_name );
42054217
4218+ const doc_comment_index = try astgen .docCommentAsString (member .firstToken ());
4219+ wip_members .appendToField (doc_comment_index );
4220+
42064221 if (member .ast .type_expr == 0 ) {
42074222 return astgen .failTok (member .ast .name_token , "struct field missing type" , .{});
42084223 }
42094224
42104225 const field_type = try typeExpr (& block_scope , & namespace .base , member .ast .type_expr );
4211- wip_members .appendToField (@enumToInt (field_type ));
4212-
4213- const doc_comment_index = try astgen .docCommentAsString (member .firstToken ());
4214- wip_members .appendToField (doc_comment_index );
4215-
4226+ const have_type_body = ! block_scope .isEmpty ();
42164227 const have_align = member .ast .align_expr != 0 ;
42174228 const have_value = member .ast .value_expr != 0 ;
42184229 const is_comptime = member .comptime_token != null ;
4219- const unused = false ;
42204230
42214231 if (! is_comptime ) {
42224232 known_non_opv = known_non_opv or
42234233 nodeImpliesMoreThanOnePossibleValue (tree , member .ast .type_expr );
42244234 known_comptime_only = known_comptime_only or
42254235 nodeImpliesComptimeOnly (tree , member .ast .type_expr );
42264236 }
4227- wip_members .nextField (bits_per_field , .{ have_align , have_value , is_comptime , unused });
4237+ wip_members .nextField (bits_per_field , .{ have_align , have_value , is_comptime , have_type_body });
4238+
4239+ if (have_type_body ) {
4240+ if (! block_scope .endsWithNoReturn ()) {
4241+ _ = try block_scope .addBreak (.break_inline , decl_inst , field_type );
4242+ }
4243+ const body = block_scope .instructionsSlice ();
4244+ const old_scratch_len = astgen .scratch .items .len ;
4245+ try astgen .scratch .ensureUnusedCapacity (gpa , countBodyLenAfterFixups (astgen , body ));
4246+ appendBodyWithFixupsArrayList (astgen , & astgen .scratch , body );
4247+ wip_members .appendToField (@intCast (u32 , astgen .scratch .items .len - old_scratch_len ));
4248+ block_scope .instructions .items .len = block_scope .instructions_top ;
4249+ } else {
4250+ wip_members .appendToField (@enumToInt (field_type ));
4251+ }
42284252
42294253 if (have_align ) {
42304254 if (layout == .Packed ) {
42314255 try astgen .appendErrorNode (member .ast .align_expr , "unable to override alignment of packed struct fields" , .{});
42324256 }
4233- const align_inst = try expr (& block_scope , & namespace .base , align_rl , member .ast .align_expr );
4234- wip_members .appendToField (@enumToInt (align_inst ));
4257+ const align_ref = try expr (& block_scope , & namespace .base , coerced_align_rl , member .ast .align_expr );
4258+ if (! block_scope .endsWithNoReturn ()) {
4259+ _ = try block_scope .addBreak (.break_inline , decl_inst , align_ref );
4260+ }
4261+ const body = block_scope .instructionsSlice ();
4262+ const old_scratch_len = astgen .scratch .items .len ;
4263+ try astgen .scratch .ensureUnusedCapacity (gpa , countBodyLenAfterFixups (astgen , body ));
4264+ appendBodyWithFixupsArrayList (astgen , & astgen .scratch , body );
4265+ wip_members .appendToField (@intCast (u32 , astgen .scratch .items .len - old_scratch_len ));
4266+ block_scope .instructions .items .len = block_scope .instructions_top ;
42354267 }
4268+
42364269 if (have_value ) {
4237- const rl : ResultLoc = if (field_type == .none ) .none else .{ .ty = field_type };
4270+ const rl : ResultLoc = if (field_type == .none ) .none else .{ .coerced_ty = field_type };
42384271
42394272 const default_inst = try expr (& block_scope , & namespace .base , rl , member .ast .value_expr );
4240- wip_members .appendToField (@enumToInt (default_inst ));
4273+ if (! block_scope .endsWithNoReturn ()) {
4274+ _ = try block_scope .addBreak (.break_inline , decl_inst , default_inst );
4275+ }
4276+ const body = block_scope .instructionsSlice ();
4277+ const old_scratch_len = astgen .scratch .items .len ;
4278+ try astgen .scratch .ensureUnusedCapacity (gpa , countBodyLenAfterFixups (astgen , body ));
4279+ appendBodyWithFixupsArrayList (astgen , & astgen .scratch , body );
4280+ wip_members .appendToField (@intCast (u32 , astgen .scratch .items .len - old_scratch_len ));
4281+ block_scope .instructions .items .len = block_scope .instructions_top ;
42414282 } else if (member .comptime_token ) | comptime_token | {
42424283 return astgen .failTok (comptime_token , "comptime field without default initialization value" , .{});
42434284 }
42444285 }
42454286
4246- if (! block_scope .isEmpty ()) {
4247- _ = try block_scope .addBreak (.break_inline , decl_inst , .void_value );
4248- }
4249-
4250- const body = block_scope .instructionsSlice ();
4251- const body_len = astgen .countBodyLenAfterFixups (body );
4252-
42534287 try gz .setStruct (decl_inst , .{
42544288 .src_node = node ,
42554289 .layout = layout ,
4256- .body_len = body_len ,
42574290 .fields_len = field_count ,
42584291 .decls_len = decl_count ,
42594292 .known_non_opv = known_non_opv ,
@@ -4263,10 +4296,11 @@ fn structDeclInner(
42634296 wip_members .finishBits (bits_per_field );
42644297 const decls_slice = wip_members .declsSlice ();
42654298 const fields_slice = wip_members .fieldsSlice ();
4266- try astgen .extra .ensureUnusedCapacity (gpa , decls_slice .len + body_len + fields_slice .len );
4299+ const bodies_slice = astgen .scratch .items [bodies_start .. ];
4300+ try astgen .extra .ensureUnusedCapacity (gpa , decls_slice .len + fields_slice .len + bodies_slice .len );
42674301 astgen .extra .appendSliceAssumeCapacity (decls_slice );
4268- astgen .appendBodyWithFixups (body );
42694302 astgen .extra .appendSliceAssumeCapacity (fields_slice );
4303+ astgen .extra .appendSliceAssumeCapacity (bodies_slice );
42704304
42714305 block_scope .unstack ();
42724306 try gz .addNamespaceCaptures (& namespace );
@@ -10981,7 +11015,6 @@ const GenZir = struct {
1098111015
1098211016 fn setStruct (gz : * GenZir , inst : Zir.Inst.Index , args : struct {
1098311017 src_node : Ast.Node.Index ,
10984- body_len : u32 ,
1098511018 fields_len : u32 ,
1098611019 decls_len : u32 ,
1098711020 layout : std.builtin.Type.ContainerLayout ,
@@ -10998,9 +11031,6 @@ const GenZir = struct {
1099811031 const node_offset = gz .nodeIndexToRelative (args .src_node );
1099911032 astgen .extra .appendAssumeCapacity (@bitCast (u32 , node_offset ));
1100011033 }
11001- if (args .body_len != 0 ) {
11002- astgen .extra .appendAssumeCapacity (args .body_len );
11003- }
1100411034 if (args .fields_len != 0 ) {
1100511035 astgen .extra .appendAssumeCapacity (args .fields_len );
1100611036 }
@@ -11013,7 +11043,6 @@ const GenZir = struct {
1101311043 .opcode = .struct_decl ,
1101411044 .small = @bitCast (u16 , Zir.Inst.StructDecl.Small {
1101511045 .has_src_node = args .src_node != 0 ,
11016- .has_body_len = args .body_len != 0 ,
1101711046 .has_fields_len = args .fields_len != 0 ,
1101811047 .has_decls_len = args .decls_len != 0 ,
1101911048 .known_non_opv = args .known_non_opv ,
0 commit comments