authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-11-01 01:42:02-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-11-01 05:41:37-04:00
loge712f87a662e9f2711698bc5a74644a5b3b890f3
treeec2408c3c71dc3c87dda625e82a58227634c5257
parentf0260555d6164642569af9e09f57458a938d5de1

astgen.zig: replace WipDecls with WipMembers, use one allocation to collect container decls, fields, and bits, instead of up to four


1 files changed, 273 insertions(+), 348 deletions(-)

src/AstGen.zig+273-348
...@@ -2995,38 +2995,112 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I...@@ -2995,38 +2995,112 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
2995 return rvalue(gz, rl, result, node);2995 return rvalue(gz, rl, result, node);
2996}2996}
29972997
2998const WipDecls = struct {2998const WipMembers = struct {
2999 decl_index: usize = 0,2999 payload: []u32,
3000 cur_bit_bag: u32 = 0,3000 decls_start: u32,
3001 bit_bag: ArrayListUnmanaged(u32) = .{},3001 field_bits_start: u32,
3002 payload: ArrayListUnmanaged(u32) = .{},3002 fields_start: u32,
3003 decls_end: u32,
3004 fields_end: u32,
3005 decl_index: u32 = 0,
3006 field_index: u32 = 0,
3007
3008 const Self = @This();
3009 /// struct, union, enum, and opaque decls all use same 4 bits per decl
3010 const bits_per_decl = 4;
3011 const decls_per_u32 = 32 / bits_per_decl;
3012 /// struct, union, enum, and opaque decls all have maximum size of 10 u32 slots
3013 /// (4 for src_hash + line + name + value + align + link_section + address_space)
3014 const max_decl_size = 10;
3015
3016 pub fn init(gpa: *Allocator, decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3017 const decls_start = (decl_count + decls_per_u32 - 1) / decls_per_u32;
3018 const field_bits_start = decls_start + decl_count * max_decl_size;
3019 const fields_start = if (bits_per_field > 0) blk: {
3020 const fields_per_u32 = 32 / bits_per_field;
3021 break :blk field_bits_start + (field_count + fields_per_u32 - 1) / fields_per_u32;
3022 } else field_bits_start;
3023 const capacity = fields_start + field_count * max_field_size;
3024 return Self{
3025 .payload = try gpa.alloc(u32, capacity),
3026 .decls_start = decls_start,
3027 .field_bits_start = field_bits_start,
3028 .fields_start = fields_start,
3029 .decls_end = decls_start,
3030 .fields_end = fields_start,
3031 };
3032 }
30033033
3004 const bits_per_field = 4;3034 pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {
3005 const fields_per_u32 = 32 / bits_per_field;3035 const index = self.decl_index / decls_per_u32;
30063036 assert(index < self.decls_start);
3007 fn next(3037 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload[index];
3008 wip_decls: *WipDecls,3038 self.payload[index] = (bit_bag >> bits_per_decl) |
3009 gpa: *Allocator,
3010 is_pub: bool,
3011 is_export: bool,
3012 has_align: bool,
3013 has_section_or_addrspace: bool,
3014 ) Allocator.Error!void {
3015 if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) {
3016 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
3017 wip_decls.cur_bit_bag = 0;
3018 }
3019 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) |
3020 (@as(u32, @boolToInt(is_pub)) << 28) |3039 (@as(u32, @boolToInt(is_pub)) << 28) |
3021 (@as(u32, @boolToInt(is_export)) << 29) |3040 (@as(u32, @boolToInt(is_export)) << 29) |
3022 (@as(u32, @boolToInt(has_align)) << 30) |3041 (@as(u32, @boolToInt(has_align)) << 30) |
3023 (@as(u32, @boolToInt(has_section_or_addrspace)) << 31);3042 (@as(u32, @boolToInt(has_section_or_addrspace)) << 31);
3024 wip_decls.decl_index += 1;3043 self.decl_index += 1;
3044 }
3045
3046 pub fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void {
3047 const fields_per_u32 = 32 / bits_per_field;
3048 const index = self.field_bits_start + self.field_index / fields_per_u32;
3049 assert(index < self.fields_start);
3050 var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload[index];
3051 bit_bag >>= bits_per_field;
3052 comptime var i = 0;
3053 inline while (i < bits_per_field) : (i += 1) {
3054 bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i);
3055 }
3056 self.payload[index] = bit_bag;
3057 self.field_index += 1;
3058 }
3059
3060 pub fn appendToDecl(self: *Self, data: u32) void {
3061 assert(self.decls_end < self.field_bits_start);
3062 self.payload[self.decls_end] = data;
3063 self.decls_end += 1;
3064 }
3065
3066 pub fn appendToDeclSlice(self: *Self, data: []const u32) void {
3067 assert(self.decls_end + data.len <= self.field_bits_start);
3068 mem.copy(u32, self.payload[self.decls_end..], data);
3069 self.decls_end += @intCast(u32, data.len);
3070 }
3071
3072 pub fn appendToField(self: *Self, data: u32) void {
3073 assert(self.fields_end < self.payload.len);
3074 self.payload[self.fields_end] = data;
3075 self.fields_end += 1;
3025 }3076 }
30263077
3027 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {3078 pub fn finishBits(self: *Self, comptime bits_per_field: u32) void {
3028 wip_decls.bit_bag.deinit(gpa);3079 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);
3029 wip_decls.payload.deinit(gpa);3080 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {
3081 const index = self.decl_index / decls_per_u32;
3082 self.payload[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);
3083 }
3084 if (bits_per_field > 0) {
3085 const fields_per_u32 = 32 / bits_per_field;
3086 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
3087 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {
3088 const index = self.field_bits_start + self.field_index / fields_per_u32;
3089 self.payload[index] >>= @intCast(u5, empty_field_slots * bits_per_field);
3090 }
3091 }
3092 }
3093
3094 pub fn declsSlice(self: *Self) []u32 {
3095 return self.payload[0..self.decls_end];
3096 }
3097
3098 pub fn fieldsSlice(self: *Self) []u32 {
3099 return self.payload[self.field_bits_start..self.fields_end];
3100 }
3101
3102 pub fn deinit(self: *Self, gpa: *Allocator) void {
3103 gpa.free(self.payload);
3030 }3104 }
3031};3105};
30323106
...@@ -3034,7 +3108,7 @@ fn fnDecl(...@@ -3034,7 +3108,7 @@ fn fnDecl(
3034 astgen: *AstGen,3108 astgen: *AstGen,
3035 gz: *GenZir,3109 gz: *GenZir,
3036 scope: *Scope,3110 scope: *Scope,
3037 wip_decls: *WipDecls,3111 wip_members: *WipMembers,
3038 decl_node: Ast.Node.Index,3112 decl_node: Ast.Node.Index,
3039 body_node: Ast.Node.Index,3113 body_node: Ast.Node.Index,
3040 fn_proto: Ast.full.FnProto,3114 fn_proto: Ast.full.FnProto,
...@@ -3086,7 +3160,7 @@ fn fnDecl(...@@ -3086,7 +3160,7 @@ fn fnDecl(
3086 break :blk token_tags[maybe_inline_token] == .keyword_inline;3160 break :blk token_tags[maybe_inline_token] == .keyword_inline;
3087 };3161 };
3088 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;3162 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;
3089 try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);3163 wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);
30903164
3091 var params_scope = &fn_gz.base;3165 var params_scope = &fn_gz.base;
3092 const is_var_args = is_var_args: {3166 const is_var_args = is_var_args: {
...@@ -3287,25 +3361,23 @@ fn fnDecl(...@@ -3287,25 +3361,23 @@ fn fnDecl(
3287 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);3361 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
3288 try decl_gz.setBlockBody(block_inst);3362 try decl_gz.setBlockBody(block_inst);
32893363
3290 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
3291 {3364 {
3292 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));3365 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
3293 const casted = @bitCast([4]u32, contents_hash);3366 const casted = @bitCast([4]u32, contents_hash);
3294 wip_decls.payload.appendSliceAssumeCapacity(&casted);3367 wip_members.appendToDeclSlice(&casted);
3295 }3368 }
3296 {3369 {
3297 const line_delta = decl_gz.decl_line - gz.decl_line;3370 const line_delta = decl_gz.decl_line - gz.decl_line;
3298 wip_decls.payload.appendAssumeCapacity(line_delta);3371 wip_members.appendToDecl(line_delta);
3299 }3372 }
3300 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);3373 wip_members.appendToDecl(fn_name_str_index);
3301 wip_decls.payload.appendAssumeCapacity(block_inst);3374 wip_members.appendToDecl(block_inst);
3302 if (align_inst != .none) {3375 if (align_inst != .none) {
3303 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));3376 wip_members.appendToDecl(@enumToInt(align_inst));
3304 }3377 }
3305
3306 if (has_section_or_addrspace) {3378 if (has_section_or_addrspace) {
3307 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));3379 wip_members.appendToDecl(@enumToInt(section_inst));
3308 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));3380 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3309 }3381 }
3310}3382}
33113383
...@@ -3313,7 +3385,7 @@ fn globalVarDecl(...@@ -3313,7 +3385,7 @@ fn globalVarDecl(
3313 astgen: *AstGen,3385 astgen: *AstGen,
3314 gz: *GenZir,3386 gz: *GenZir,
3315 scope: *Scope,3387 scope: *Scope,
3316 wip_decls: *WipDecls,3388 wip_members: *WipMembers,
3317 node: Ast.Node.Index,3389 node: Ast.Node.Index,
3318 var_decl: Ast.full.VarDecl,3390 var_decl: Ast.full.VarDecl,
3319) InnerError!void {3391) InnerError!void {
...@@ -3359,7 +3431,7 @@ fn globalVarDecl(...@@ -3359,7 +3431,7 @@ fn globalVarDecl(
3359 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);3431 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
3360 };3432 };
3361 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;3433 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
3362 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, has_section_or_addrspace);3434 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
33633435
3364 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {3436 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
3365 if (!is_mutable) {3437 if (!is_mutable) {
...@@ -3437,24 +3509,23 @@ fn globalVarDecl(...@@ -3437,24 +3509,23 @@ fn globalVarDecl(
3437 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);3509 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
3438 try block_scope.setBlockBody(block_inst);3510 try block_scope.setBlockBody(block_inst);
34393511
3440 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
3441 {3512 {
3442 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3513 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3443 const casted = @bitCast([4]u32, contents_hash);3514 const casted = @bitCast([4]u32, contents_hash);
3444 wip_decls.payload.appendSliceAssumeCapacity(&casted);3515 wip_members.appendToDeclSlice(&casted);
3445 }3516 }
3446 {3517 {
3447 const line_delta = block_scope.decl_line - gz.decl_line;3518 const line_delta = block_scope.decl_line - gz.decl_line;
3448 wip_decls.payload.appendAssumeCapacity(line_delta);3519 wip_members.appendToDecl(line_delta);
3449 }3520 }
3450 wip_decls.payload.appendAssumeCapacity(name_str_index);3521 wip_members.appendToDecl(name_str_index);
3451 wip_decls.payload.appendAssumeCapacity(block_inst);3522 wip_members.appendToDecl(block_inst);
3452 if (align_inst != .none) {3523 if (align_inst != .none) {
3453 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));3524 wip_members.appendToDecl(@enumToInt(align_inst));
3454 }3525 }
3455 if (has_section_or_addrspace) {3526 if (has_section_or_addrspace) {
3456 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));3527 wip_members.appendToDecl(@enumToInt(section_inst));
3457 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));3528 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3458 }3529 }
3459}3530}
34603531
...@@ -3462,7 +3533,7 @@ fn comptimeDecl(...@@ -3462,7 +3533,7 @@ fn comptimeDecl(
3462 astgen: *AstGen,3533 astgen: *AstGen,
3463 gz: *GenZir,3534 gz: *GenZir,
3464 scope: *Scope,3535 scope: *Scope,
3465 wip_decls: *WipDecls,3536 wip_members: *WipMembers,
3466 node: Ast.Node.Index,3537 node: Ast.Node.Index,
3467) InnerError!void {3538) InnerError!void {
3468 const gpa = astgen.gpa;3539 const gpa = astgen.gpa;
...@@ -3473,7 +3544,7 @@ fn comptimeDecl(...@@ -3473,7 +3544,7 @@ fn comptimeDecl(
3473 // Up top so the ZIR instruction index marks the start range of this3544 // Up top so the ZIR instruction index marks the start range of this
3474 // top-level declaration.3545 // top-level declaration.
3475 const block_inst = try gz.addBlock(.block_inline, node);3546 const block_inst = try gz.addBlock(.block_inline, node);
3476 try wip_decls.next(gpa, false, false, false, false);3547 wip_members.nextDecl(false, false, false, false);
34773548
3478 var decl_block: GenZir = .{3549 var decl_block: GenZir = .{
3479 .force_comptime = true,3550 .force_comptime = true,
...@@ -3491,25 +3562,24 @@ fn comptimeDecl(...@@ -3491,25 +3562,24 @@ fn comptimeDecl(
3491 }3562 }
3492 try decl_block.setBlockBody(block_inst);3563 try decl_block.setBlockBody(block_inst);
34933564
3494 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3495 {3565 {
3496 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3566 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3497 const casted = @bitCast([4]u32, contents_hash);3567 const casted = @bitCast([4]u32, contents_hash);
3498 wip_decls.payload.appendSliceAssumeCapacity(&casted);3568 wip_members.appendToDeclSlice(&casted);
3499 }3569 }
3500 {3570 {
3501 const line_delta = decl_block.decl_line - gz.decl_line;3571 const line_delta = decl_block.decl_line - gz.decl_line;
3502 wip_decls.payload.appendAssumeCapacity(line_delta);3572 wip_members.appendToDecl(line_delta);
3503 }3573 }
3504 wip_decls.payload.appendAssumeCapacity(0);3574 wip_members.appendToDecl(0);
3505 wip_decls.payload.appendAssumeCapacity(block_inst);3575 wip_members.appendToDecl(block_inst);
3506}3576}
35073577
3508fn usingnamespaceDecl(3578fn usingnamespaceDecl(
3509 astgen: *AstGen,3579 astgen: *AstGen,
3510 gz: *GenZir,3580 gz: *GenZir,
3511 scope: *Scope,3581 scope: *Scope,
3512 wip_decls: *WipDecls,3582 wip_members: *WipMembers,
3513 node: Ast.Node.Index,3583 node: Ast.Node.Index,
3514) InnerError!void {3584) InnerError!void {
3515 const gpa = astgen.gpa;3585 const gpa = astgen.gpa;
...@@ -3526,7 +3596,7 @@ fn usingnamespaceDecl(...@@ -3526,7 +3596,7 @@ fn usingnamespaceDecl(
3526 // Up top so the ZIR instruction index marks the start range of this3596 // Up top so the ZIR instruction index marks the start range of this
3527 // top-level declaration.3597 // top-level declaration.
3528 const block_inst = try gz.addBlock(.block_inline, node);3598 const block_inst = try gz.addBlock(.block_inline, node);
3529 try wip_decls.next(gpa, is_pub, true, false, false);3599 wip_members.nextDecl(is_pub, true, false, false);
35303600
3531 var decl_block: GenZir = .{3601 var decl_block: GenZir = .{
3532 .force_comptime = true,3602 .force_comptime = true,
...@@ -3542,25 +3612,24 @@ fn usingnamespaceDecl(...@@ -3542,25 +3612,24 @@ fn usingnamespaceDecl(
3542 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);3612 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
3543 try decl_block.setBlockBody(block_inst);3613 try decl_block.setBlockBody(block_inst);
35443614
3545 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3546 {3615 {
3547 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3616 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3548 const casted = @bitCast([4]u32, contents_hash);3617 const casted = @bitCast([4]u32, contents_hash);
3549 wip_decls.payload.appendSliceAssumeCapacity(&casted);3618 wip_members.appendToDeclSlice(&casted);
3550 }3619 }
3551 {3620 {
3552 const line_delta = decl_block.decl_line - gz.decl_line;3621 const line_delta = decl_block.decl_line - gz.decl_line;
3553 wip_decls.payload.appendAssumeCapacity(line_delta);3622 wip_members.appendToDecl(line_delta);
3554 }3623 }
3555 wip_decls.payload.appendAssumeCapacity(0);3624 wip_members.appendToDecl(0);
3556 wip_decls.payload.appendAssumeCapacity(block_inst);3625 wip_members.appendToDecl(block_inst);
3557}3626}
35583627
3559fn testDecl(3628fn testDecl(
3560 astgen: *AstGen,3629 astgen: *AstGen,
3561 gz: *GenZir,3630 gz: *GenZir,
3562 scope: *Scope,3631 scope: *Scope,
3563 wip_decls: *WipDecls,3632 wip_members: *WipMembers,
3564 node: Ast.Node.Index,3633 node: Ast.Node.Index,
3565) InnerError!void {3634) InnerError!void {
3566 const gpa = astgen.gpa;3635 const gpa = astgen.gpa;
...@@ -3572,7 +3641,7 @@ fn testDecl(...@@ -3572,7 +3641,7 @@ fn testDecl(
3572 // top-level declaration.3641 // top-level declaration.
3573 const block_inst = try gz.addBlock(.block_inline, node);3642 const block_inst = try gz.addBlock(.block_inline, node);
35743643
3575 try wip_decls.next(gpa, false, false, false, false);3644 wip_members.nextDecl(false, false, false, false);
35763645
3577 var decl_block: GenZir = .{3646 var decl_block: GenZir = .{
3578 .force_comptime = true,3647 .force_comptime = true,
...@@ -3643,18 +3712,17 @@ fn testDecl(...@@ -3643,18 +3712,17 @@ fn testDecl(
3643 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);3712 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
3644 try decl_block.setBlockBody(block_inst);3713 try decl_block.setBlockBody(block_inst);
36453714
3646 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3647 {3715 {
3648 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3716 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3649 const casted = @bitCast([4]u32, contents_hash);3717 const casted = @bitCast([4]u32, contents_hash);
3650 wip_decls.payload.appendSliceAssumeCapacity(&casted);3718 wip_members.appendToDeclSlice(&casted);
3651 }3719 }
3652 {3720 {
3653 const line_delta = decl_block.decl_line - gz.decl_line;3721 const line_delta = decl_block.decl_line - gz.decl_line;
3654 wip_decls.payload.appendAssumeCapacity(line_delta);3722 wip_members.appendToDecl(line_delta);
3655 }3723 }
3656 wip_decls.payload.appendAssumeCapacity(test_name);3724 wip_members.appendToDecl(test_name);
3657 wip_decls.payload.appendAssumeCapacity(block_inst);3725 wip_members.appendToDecl(block_inst);
3658}3726}
36593727
3660fn structDeclInner(3728fn structDeclInner(
...@@ -3705,25 +3773,15 @@ fn structDeclInner(...@@ -3705,25 +3773,15 @@ fn structDeclInner(
3705 };3773 };
3706 defer block_scope.instructions.deinit(gpa);3774 defer block_scope.instructions.deinit(gpa);
37073775
3708 try astgen.scanDecls(&namespace, container_decl.ast.members);3776 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
37093777 const field_count = @intCast(u32, container_decl.ast.members.len - decl_count);
3710 var wip_decls: WipDecls = .{};
3711 defer wip_decls.deinit(gpa);
3712
3713 // We don't know which members are fields until we iterate, so cannot do
3714 // an accurate ensureTotalCapacity yet.
3715 var fields_data = ArrayListUnmanaged(u32){};
3716 defer fields_data.deinit(gpa);
37173778
3718 const bits_per_field = 4;3779 const bits_per_field = 4;
3719 const fields_per_u32 = 32 / bits_per_field;3780 const max_field_size = 4;
3720 // We only need this if there are greater than fields_per_u32 fields.3781 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);
3721 var bit_bag = ArrayListUnmanaged(u32){};3782 defer wip_members.deinit(gpa);
3722 defer bit_bag.deinit(gpa);
37233783
3724 var known_has_bits = false;3784 var known_has_bits = false;
3725 var cur_bit_bag: u32 = 0;
3726 var field_index: usize = 0;
3727 for (container_decl.ast.members) |member_node| {3785 for (container_decl.ast.members) |member_node| {
3728 const member = switch (node_tags[member_node]) {3786 const member = switch (node_tags[member_node]) {
3729 .container_field_init => tree.containerFieldInit(member_node),3787 .container_field_init => tree.containerFieldInit(member_node),
...@@ -3736,14 +3794,14 @@ fn structDeclInner(...@@ -3736,14 +3794,14 @@ fn structDeclInner(
3736 switch (node_tags[fn_proto]) {3794 switch (node_tags[fn_proto]) {
3737 .fn_proto_simple => {3795 .fn_proto_simple => {
3738 var params: [1]Ast.Node.Index = undefined;3796 var params: [1]Ast.Node.Index = undefined;
3739 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {3797 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3740 error.OutOfMemory => return error.OutOfMemory,3798 error.OutOfMemory => return error.OutOfMemory,
3741 error.AnalysisFail => {},3799 error.AnalysisFail => {},
3742 };3800 };
3743 continue;3801 continue;
3744 },3802 },
3745 .fn_proto_multi => {3803 .fn_proto_multi => {
3746 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {3804 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
3747 error.OutOfMemory => return error.OutOfMemory,3805 error.OutOfMemory => return error.OutOfMemory,
3748 error.AnalysisFail => {},3806 error.AnalysisFail => {},
3749 };3807 };
...@@ -3751,14 +3809,14 @@ fn structDeclInner(...@@ -3751,14 +3809,14 @@ fn structDeclInner(
3751 },3809 },
3752 .fn_proto_one => {3810 .fn_proto_one => {
3753 var params: [1]Ast.Node.Index = undefined;3811 var params: [1]Ast.Node.Index = undefined;
3754 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {3812 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
3755 error.OutOfMemory => return error.OutOfMemory,3813 error.OutOfMemory => return error.OutOfMemory,
3756 error.AnalysisFail => {},3814 error.AnalysisFail => {},
3757 };3815 };
3758 continue;3816 continue;
3759 },3817 },
3760 .fn_proto => {3818 .fn_proto => {
3761 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {3819 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
3762 error.OutOfMemory => return error.OutOfMemory,3820 error.OutOfMemory => return error.OutOfMemory,
3763 error.AnalysisFail => {},3821 error.AnalysisFail => {},
3764 };3822 };
...@@ -3769,14 +3827,14 @@ fn structDeclInner(...@@ -3769,14 +3827,14 @@ fn structDeclInner(
3769 },3827 },
3770 .fn_proto_simple => {3828 .fn_proto_simple => {
3771 var params: [1]Ast.Node.Index = undefined;3829 var params: [1]Ast.Node.Index = undefined;
3772 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {3830 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
3773 error.OutOfMemory => return error.OutOfMemory,3831 error.OutOfMemory => return error.OutOfMemory,
3774 error.AnalysisFail => {},3832 error.AnalysisFail => {},
3775 };3833 };
3776 continue;3834 continue;
3777 },3835 },
3778 .fn_proto_multi => {3836 .fn_proto_multi => {
3779 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {3837 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
3780 error.OutOfMemory => return error.OutOfMemory,3838 error.OutOfMemory => return error.OutOfMemory,
3781 error.AnalysisFail => {},3839 error.AnalysisFail => {},
3782 };3840 };
...@@ -3784,14 +3842,14 @@ fn structDeclInner(...@@ -3784,14 +3842,14 @@ fn structDeclInner(
3784 },3842 },
3785 .fn_proto_one => {3843 .fn_proto_one => {
3786 var params: [1]Ast.Node.Index = undefined;3844 var params: [1]Ast.Node.Index = undefined;
3787 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {3845 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
3788 error.OutOfMemory => return error.OutOfMemory,3846 error.OutOfMemory => return error.OutOfMemory,
3789 error.AnalysisFail => {},3847 error.AnalysisFail => {},
3790 };3848 };
3791 continue;3849 continue;
3792 },3850 },
3793 .fn_proto => {3851 .fn_proto => {
3794 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {3852 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
3795 error.OutOfMemory => return error.OutOfMemory,3853 error.OutOfMemory => return error.OutOfMemory,
3796 error.AnalysisFail => {},3854 error.AnalysisFail => {},
3797 };3855 };
...@@ -3799,28 +3857,28 @@ fn structDeclInner(...@@ -3799,28 +3857,28 @@ fn structDeclInner(
3799 },3857 },
38003858
3801 .global_var_decl => {3859 .global_var_decl => {
3802 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {3860 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3803 error.OutOfMemory => return error.OutOfMemory,3861 error.OutOfMemory => return error.OutOfMemory,
3804 error.AnalysisFail => {},3862 error.AnalysisFail => {},
3805 };3863 };
3806 continue;3864 continue;
3807 },3865 },
3808 .local_var_decl => {3866 .local_var_decl => {
3809 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {3867 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
3810 error.OutOfMemory => return error.OutOfMemory,3868 error.OutOfMemory => return error.OutOfMemory,
3811 error.AnalysisFail => {},3869 error.AnalysisFail => {},
3812 };3870 };
3813 continue;3871 continue;
3814 },3872 },
3815 .simple_var_decl => {3873 .simple_var_decl => {
3816 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {3874 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
3817 error.OutOfMemory => return error.OutOfMemory,3875 error.OutOfMemory => return error.OutOfMemory,
3818 error.AnalysisFail => {},3876 error.AnalysisFail => {},
3819 };3877 };
3820 continue;3878 continue;
3821 },3879 },
3822 .aligned_var_decl => {3880 .aligned_var_decl => {
3823 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {3881 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
3824 error.OutOfMemory => return error.OutOfMemory,3882 error.OutOfMemory => return error.OutOfMemory,
3825 error.AnalysisFail => {},3883 error.AnalysisFail => {},
3826 };3884 };
...@@ -3828,21 +3886,21 @@ fn structDeclInner(...@@ -3828,21 +3886,21 @@ fn structDeclInner(
3828 },3886 },
38293887
3830 .@"comptime" => {3888 .@"comptime" => {
3831 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {3889 astgen.comptimeDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
3832 error.OutOfMemory => return error.OutOfMemory,3890 error.OutOfMemory => return error.OutOfMemory,
3833 error.AnalysisFail => {},3891 error.AnalysisFail => {},
3834 };3892 };
3835 continue;3893 continue;
3836 },3894 },
3837 .@"usingnamespace" => {3895 .@"usingnamespace" => {
3838 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {3896 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
3839 error.OutOfMemory => return error.OutOfMemory,3897 error.OutOfMemory => return error.OutOfMemory,
3840 error.AnalysisFail => {},3898 error.AnalysisFail => {},
3841 };3899 };
3842 continue;3900 continue;
3843 },3901 },
3844 .test_decl => {3902 .test_decl => {
3845 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {3903 astgen.testDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
3846 error.OutOfMemory => return error.OutOfMemory,3904 error.OutOfMemory => return error.OutOfMemory,
3847 error.AnalysisFail => {},3905 error.AnalysisFail => {},
3848 };3906 };
...@@ -3850,14 +3908,9 @@ fn structDeclInner(...@@ -3850,14 +3908,9 @@ fn structDeclInner(
3850 },3908 },
3851 else => unreachable,3909 else => unreachable,
3852 };3910 };
3853 if (field_index % fields_per_u32 == 0 and field_index != 0) {
3854 try bit_bag.append(gpa, cur_bit_bag);
3855 cur_bit_bag = 0;
3856 }
3857 try fields_data.ensureUnusedCapacity(gpa, 4);
38583911
3859 const field_name = try astgen.identAsString(member.ast.name_token);3912 const field_name = try astgen.identAsString(member.ast.name_token);
3860 fields_data.appendAssumeCapacity(field_name);3913 wip_members.appendToField(field_name);
38613914
3862 if (member.ast.type_expr == 0) {3915 if (member.ast.type_expr == 0) {
3863 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});3916 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
...@@ -3867,7 +3920,7 @@ fn structDeclInner(...@@ -3867,7 +3920,7 @@ fn structDeclInner(
3867 .none3920 .none
3868 else3921 else
3869 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);3922 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
3870 fields_data.appendAssumeCapacity(@enumToInt(field_type));3923 wip_members.appendToField(@enumToInt(field_type));
38713924
3872 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);3925 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
38733926
...@@ -3875,39 +3928,22 @@ fn structDeclInner(...@@ -3875,39 +3928,22 @@ fn structDeclInner(
3875 const have_value = member.ast.value_expr != 0;3928 const have_value = member.ast.value_expr != 0;
3876 const is_comptime = member.comptime_token != null;3929 const is_comptime = member.comptime_token != null;
3877 const unused = false;3930 const unused = false;
3878 cur_bit_bag = (cur_bit_bag >> bits_per_field) |3931 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });
3879 (@as(u32, @boolToInt(have_align)) << 28) |
3880 (@as(u32, @boolToInt(have_value)) << 29) |
3881 (@as(u32, @boolToInt(is_comptime)) << 30) |
3882 (@as(u32, @boolToInt(unused)) << 31);
38833932
3884 if (have_align) {3933 if (have_align) {
3885 const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);3934 const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);
3886 fields_data.appendAssumeCapacity(@enumToInt(align_inst));3935 wip_members.appendToField(@enumToInt(align_inst));
3887 }3936 }
3888 if (have_value) {3937 if (have_value) {
3889 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };3938 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
38903939
3891 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);3940 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);
3892 fields_data.appendAssumeCapacity(@enumToInt(default_inst));3941 wip_members.appendToField(@enumToInt(default_inst));
3893 } else if (member.comptime_token) |comptime_token| {3942 } else if (member.comptime_token) |comptime_token| {
3894 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});3943 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
3895 }3944 }
3896
3897 field_index += 1;
3898 }
3899 {
3900 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
3901 if (empty_slot_count < fields_per_u32) {
3902 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
3903 }
3904 }
3905 {
3906 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3907 if (empty_slot_count < WipDecls.fields_per_u32) {
3908 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3909 }
3910 }3945 }
3946 assert(wip_members.decl_index == decl_count and wip_members.field_index == field_count);
39113947
3912 if (block_scope.instructions.items.len != 0) {3948 if (block_scope.instructions.items.len != 0) {
3913 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);3949 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
...@@ -3917,36 +3953,18 @@ fn structDeclInner(...@@ -3917,36 +3953,18 @@ fn structDeclInner(
3917 .src_node = node,3953 .src_node = node,
3918 .layout = layout,3954 .layout = layout,
3919 .body_len = @intCast(u32, block_scope.instructions.items.len),3955 .body_len = @intCast(u32, block_scope.instructions.items.len),
3920 .fields_len = @intCast(u32, field_index),3956 .fields_len = field_count,
3921 .decls_len = @intCast(u32, wip_decls.decl_index),3957 .decls_len = decl_count,
3922 .known_has_bits = known_has_bits,3958 .known_has_bits = known_has_bits,
3923 });3959 });
39243960
3925 // zig fmt: off3961 wip_members.finishBits(bits_per_field);
3926 try astgen.extra.ensureUnusedCapacity(gpa,3962 const decls_slice = wip_members.declsSlice();
3927 bit_bag.items.len +3963 const fields_slice = wip_members.fieldsSlice();
3928 @boolToInt(wip_decls.decl_index != 0) +3964 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len);
3929 wip_decls.payload.items.len +3965 astgen.extra.appendSliceAssumeCapacity(decls_slice);
3930 block_scope.instructions.items.len +
3931 wip_decls.bit_bag.items.len +
3932 @boolToInt(field_index != 0) +
3933 fields_data.items.len
3934 );
3935 // zig fmt: on
3936
3937 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3938 if (wip_decls.decl_index != 0) {
3939 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3940 }
3941 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
3942
3943 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);3966 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
39443967 astgen.extra.appendSliceAssumeCapacity(fields_slice);
3945 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
3946 if (field_index != 0) {
3947 astgen.extra.appendAssumeCapacity(cur_bit_bag);
3948 }
3949 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
39503968
3951 return indexToRef(decl_inst);3969 return indexToRef(decl_inst);
3952}3970}
...@@ -3989,29 +4007,19 @@ fn unionDeclInner(...@@ -3989,29 +4007,19 @@ fn unionDeclInner(
3989 };4007 };
3990 defer block_scope.instructions.deinit(gpa);4008 defer block_scope.instructions.deinit(gpa);
39914009
3992 try astgen.scanDecls(&namespace, members);4010 const decl_count = try astgen.scanDecls(&namespace, members);
4011 const field_count = @intCast(u32, members.len - decl_count);
39934012
3994 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)4013 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
3995 try typeExpr(&block_scope, &namespace.base, arg_node)4014 try typeExpr(&block_scope, &namespace.base, arg_node)
3996 else4015 else
3997 .none;4016 .none;
39984017
3999 var wip_decls: WipDecls = .{};
4000 defer wip_decls.deinit(gpa);
4001
4002 // We don't know which members are fields until we iterate, so cannot do
4003 // an accurate ensureTotalCapacity yet.
4004 var fields_data = ArrayListUnmanaged(u32){};
4005 defer fields_data.deinit(gpa);
4006
4007 const bits_per_field = 4;4018 const bits_per_field = 4;
4008 const fields_per_u32 = 32 / bits_per_field;4019 const max_field_size = 4;
4009 // We only need this if there are greater than fields_per_u32 fields.4020 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);
4010 var bit_bag = ArrayListUnmanaged(u32){};4021 defer wip_members.deinit(gpa);
4011 defer bit_bag.deinit(gpa);
40124022
4013 var cur_bit_bag: u32 = 0;
4014 var field_index: usize = 0;
4015 for (members) |member_node| {4023 for (members) |member_node| {
4016 const member = switch (node_tags[member_node]) {4024 const member = switch (node_tags[member_node]) {
4017 .container_field_init => tree.containerFieldInit(member_node),4025 .container_field_init => tree.containerFieldInit(member_node),
...@@ -4024,14 +4032,14 @@ fn unionDeclInner(...@@ -4024,14 +4032,14 @@ fn unionDeclInner(
4024 switch (node_tags[fn_proto]) {4032 switch (node_tags[fn_proto]) {
4025 .fn_proto_simple => {4033 .fn_proto_simple => {
4026 var params: [1]Ast.Node.Index = undefined;4034 var params: [1]Ast.Node.Index = undefined;
4027 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {4035 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4028 error.OutOfMemory => return error.OutOfMemory,4036 error.OutOfMemory => return error.OutOfMemory,
4029 error.AnalysisFail => {},4037 error.AnalysisFail => {},
4030 };4038 };
4031 continue;4039 continue;
4032 },4040 },
4033 .fn_proto_multi => {4041 .fn_proto_multi => {
4034 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {4042 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4035 error.OutOfMemory => return error.OutOfMemory,4043 error.OutOfMemory => return error.OutOfMemory,
4036 error.AnalysisFail => {},4044 error.AnalysisFail => {},
4037 };4045 };
...@@ -4039,14 +4047,14 @@ fn unionDeclInner(...@@ -4039,14 +4047,14 @@ fn unionDeclInner(
4039 },4047 },
4040 .fn_proto_one => {4048 .fn_proto_one => {
4041 var params: [1]Ast.Node.Index = undefined;4049 var params: [1]Ast.Node.Index = undefined;
4042 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {4050 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4043 error.OutOfMemory => return error.OutOfMemory,4051 error.OutOfMemory => return error.OutOfMemory,
4044 error.AnalysisFail => {},4052 error.AnalysisFail => {},
4045 };4053 };
4046 continue;4054 continue;
4047 },4055 },
4048 .fn_proto => {4056 .fn_proto => {
4049 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {4057 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4050 error.OutOfMemory => return error.OutOfMemory,4058 error.OutOfMemory => return error.OutOfMemory,
4051 error.AnalysisFail => {},4059 error.AnalysisFail => {},
4052 };4060 };
...@@ -4057,14 +4065,14 @@ fn unionDeclInner(...@@ -4057,14 +4065,14 @@ fn unionDeclInner(
4057 },4065 },
4058 .fn_proto_simple => {4066 .fn_proto_simple => {
4059 var params: [1]Ast.Node.Index = undefined;4067 var params: [1]Ast.Node.Index = undefined;
4060 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {4068 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4061 error.OutOfMemory => return error.OutOfMemory,4069 error.OutOfMemory => return error.OutOfMemory,
4062 error.AnalysisFail => {},4070 error.AnalysisFail => {},
4063 };4071 };
4064 continue;4072 continue;
4065 },4073 },
4066 .fn_proto_multi => {4074 .fn_proto_multi => {
4067 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {4075 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4068 error.OutOfMemory => return error.OutOfMemory,4076 error.OutOfMemory => return error.OutOfMemory,
4069 error.AnalysisFail => {},4077 error.AnalysisFail => {},
4070 };4078 };
...@@ -4072,14 +4080,14 @@ fn unionDeclInner(...@@ -4072,14 +4080,14 @@ fn unionDeclInner(
4072 },4080 },
4073 .fn_proto_one => {4081 .fn_proto_one => {
4074 var params: [1]Ast.Node.Index = undefined;4082 var params: [1]Ast.Node.Index = undefined;
4075 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {4083 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4076 error.OutOfMemory => return error.OutOfMemory,4084 error.OutOfMemory => return error.OutOfMemory,
4077 error.AnalysisFail => {},4085 error.AnalysisFail => {},
4078 };4086 };
4079 continue;4087 continue;
4080 },4088 },
4081 .fn_proto => {4089 .fn_proto => {
4082 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {4090 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4083 error.OutOfMemory => return error.OutOfMemory,4091 error.OutOfMemory => return error.OutOfMemory,
4084 error.AnalysisFail => {},4092 error.AnalysisFail => {},
4085 };4093 };
...@@ -4087,28 +4095,28 @@ fn unionDeclInner(...@@ -4087,28 +4095,28 @@ fn unionDeclInner(
4087 },4095 },
40884096
4089 .global_var_decl => {4097 .global_var_decl => {
4090 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {4098 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4091 error.OutOfMemory => return error.OutOfMemory,4099 error.OutOfMemory => return error.OutOfMemory,
4092 error.AnalysisFail => {},4100 error.AnalysisFail => {},
4093 };4101 };
4094 continue;4102 continue;
4095 },4103 },
4096 .local_var_decl => {4104 .local_var_decl => {
4097 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {4105 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4098 error.OutOfMemory => return error.OutOfMemory,4106 error.OutOfMemory => return error.OutOfMemory,
4099 error.AnalysisFail => {},4107 error.AnalysisFail => {},
4100 };4108 };
4101 continue;4109 continue;
4102 },4110 },
4103 .simple_var_decl => {4111 .simple_var_decl => {
4104 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {4112 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4105 error.OutOfMemory => return error.OutOfMemory,4113 error.OutOfMemory => return error.OutOfMemory,
4106 error.AnalysisFail => {},4114 error.AnalysisFail => {},
4107 };4115 };
4108 continue;4116 continue;
4109 },4117 },
4110 .aligned_var_decl => {4118 .aligned_var_decl => {
4111 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {4119 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4112 error.OutOfMemory => return error.OutOfMemory,4120 error.OutOfMemory => return error.OutOfMemory,
4113 error.AnalysisFail => {},4121 error.AnalysisFail => {},
4114 };4122 };
...@@ -4116,21 +4124,21 @@ fn unionDeclInner(...@@ -4116,21 +4124,21 @@ fn unionDeclInner(
4116 },4124 },
41174125
4118 .@"comptime" => {4126 .@"comptime" => {
4119 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4127 astgen.comptimeDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4120 error.OutOfMemory => return error.OutOfMemory,4128 error.OutOfMemory => return error.OutOfMemory,
4121 error.AnalysisFail => {},4129 error.AnalysisFail => {},
4122 };4130 };
4123 continue;4131 continue;
4124 },4132 },
4125 .@"usingnamespace" => {4133 .@"usingnamespace" => {
4126 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4134 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4127 error.OutOfMemory => return error.OutOfMemory,4135 error.OutOfMemory => return error.OutOfMemory,
4128 error.AnalysisFail => {},4136 error.AnalysisFail => {},
4129 };4137 };
4130 continue;4138 continue;
4131 },4139 },
4132 .test_decl => {4140 .test_decl => {
4133 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4141 astgen.testDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4134 error.OutOfMemory => return error.OutOfMemory,4142 error.OutOfMemory => return error.OutOfMemory,
4135 error.AnalysisFail => {},4143 error.AnalysisFail => {},
4136 };4144 };
...@@ -4138,40 +4146,31 @@ fn unionDeclInner(...@@ -4138,40 +4146,31 @@ fn unionDeclInner(
4138 },4146 },
4139 else => unreachable,4147 else => unreachable,
4140 };4148 };
4141 if (field_index % fields_per_u32 == 0 and field_index != 0) {
4142 try bit_bag.append(gpa, cur_bit_bag);
4143 cur_bit_bag = 0;
4144 }
4145 if (member.comptime_token) |comptime_token| {4149 if (member.comptime_token) |comptime_token| {
4146 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});4150 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
4147 }4151 }
4148 try fields_data.ensureUnusedCapacity(gpa, 4);
41494152
4150 const field_name = try astgen.identAsString(member.ast.name_token);4153 const field_name = try astgen.identAsString(member.ast.name_token);
4151 fields_data.appendAssumeCapacity(field_name);4154 wip_members.appendToField(field_name);
41524155
4153 const have_type = member.ast.type_expr != 0;4156 const have_type = member.ast.type_expr != 0;
4154 const have_align = member.ast.align_expr != 0;4157 const have_align = member.ast.align_expr != 0;
4155 const have_value = member.ast.value_expr != 0;4158 const have_value = member.ast.value_expr != 0;
4156 const unused = false;4159 const unused = false;
4157 cur_bit_bag = (cur_bit_bag >> bits_per_field) |4160 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
4158 (@as(u32, @boolToInt(have_type)) << 28) |
4159 (@as(u32, @boolToInt(have_align)) << 29) |
4160 (@as(u32, @boolToInt(have_value)) << 30) |
4161 (@as(u32, @boolToInt(unused)) << 31);
41624161
4163 if (have_type) {4162 if (have_type) {
4164 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")4163 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
4165 .none4164 .none
4166 else4165 else
4167 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);4166 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
4168 fields_data.appendAssumeCapacity(@enumToInt(field_type));4167 wip_members.appendToField(@enumToInt(field_type));
4169 } else if (arg_inst == .none and !have_auto_enum) {4168 } else if (arg_inst == .none and !have_auto_enum) {
4170 return astgen.failNode(member_node, "union field missing type", .{});4169 return astgen.failNode(member_node, "union field missing type", .{});
4171 }4170 }
4172 if (have_align) {4171 if (have_align) {
4173 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);4172 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
4174 fields_data.appendAssumeCapacity(@enumToInt(align_inst));4173 wip_members.appendToField(@enumToInt(align_inst));
4175 }4174 }
4176 if (have_value) {4175 if (have_value) {
4177 if (arg_inst == .none) {4176 if (arg_inst == .none) {
...@@ -4203,26 +4202,13 @@ fn unionDeclInner(...@@ -4203,26 +4202,13 @@ fn unionDeclInner(
4203 );4202 );
4204 }4203 }
4205 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);4204 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
4206 fields_data.appendAssumeCapacity(@enumToInt(tag_value));4205 wip_members.appendToField(@enumToInt(tag_value));
4207 }4206 }
4208
4209 field_index += 1;
4210 }4207 }
4211 if (field_index == 0) {4208 assert(wip_members.decl_index == decl_count and wip_members.field_index == field_count);
4209 if (field_count == 0) {
4212 return astgen.failNode(node, "union declarations must have at least one tag", .{});4210 return astgen.failNode(node, "union declarations must have at least one tag", .{});
4213 }4211 }
4214 {
4215 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
4216 if (empty_slot_count < fields_per_u32) {
4217 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
4218 }
4219 }
4220 {
4221 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4222 if (empty_slot_count < WipDecls.fields_per_u32) {
4223 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4224 }
4225 }
42264212
4227 if (block_scope.instructions.items.len != 0) {4213 if (block_scope.instructions.items.len != 0) {
4228 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);4214 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
...@@ -4233,34 +4219,18 @@ fn unionDeclInner(...@@ -4233,34 +4219,18 @@ fn unionDeclInner(
4233 .layout = layout,4219 .layout = layout,
4234 .tag_type = arg_inst,4220 .tag_type = arg_inst,
4235 .body_len = @intCast(u32, block_scope.instructions.items.len),4221 .body_len = @intCast(u32, block_scope.instructions.items.len),
4236 .fields_len = @intCast(u32, field_index),4222 .fields_len = field_count,
4237 .decls_len = @intCast(u32, wip_decls.decl_index),4223 .decls_len = decl_count,
4238 .auto_enum_tag = have_auto_enum,4224 .auto_enum_tag = have_auto_enum,
4239 });4225 });
42404226
4241 // zig fmt: off4227 wip_members.finishBits(bits_per_field);
4242 try astgen.extra.ensureUnusedCapacity(gpa,4228 const decls_slice = wip_members.declsSlice();
4243 bit_bag.items.len +4229 const fields_slice = wip_members.fieldsSlice();
4244 @boolToInt(wip_decls.decl_index != 0) +4230 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len);
4245 wip_decls.payload.items.len +4231 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4246 block_scope.instructions.items.len +
4247 wip_decls.bit_bag.items.len +
4248 1 + // cur_bit_bag
4249 fields_data.items.len
4250 );
4251 // zig fmt: on
4252
4253 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4254 if (wip_decls.decl_index != 0) {
4255 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4256 }
4257 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4258
4259 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);4232 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
42604233 astgen.extra.appendSliceAssumeCapacity(fields_slice);
4261 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
4262 astgen.extra.appendAssumeCapacity(cur_bit_bag);
4263 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
42644234
4265 return indexToRef(decl_inst);4235 return indexToRef(decl_inst);
4266}4236}
...@@ -4434,27 +4404,18 @@ fn containerDecl(...@@ -4434,27 +4404,18 @@ fn containerDecl(
4434 };4404 };
4435 defer block_scope.instructions.deinit(gpa);4405 defer block_scope.instructions.deinit(gpa);
44364406
4437 try astgen.scanDecls(&namespace, container_decl.ast.members);4407 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
44384408
4439 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)4409 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4440 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)4410 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
4441 else4411 else
4442 .none;4412 .none;
44434413
4444 var wip_decls: WipDecls = .{};4414 const bits_per_field = 1;
4445 defer wip_decls.deinit(gpa);4415 const max_field_size = 2;
44464416 var wip_members = try WipMembers.init(gpa, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4447 var fields_data = ArrayListUnmanaged(u32){};4417 defer wip_members.deinit(gpa);
4448 defer fields_data.deinit(gpa);
4449
4450 try fields_data.ensureTotalCapacity(gpa, counts.total_fields + counts.values);
4451
4452 // We only need this if there are greater than 32 fields.
4453 var bit_bag = ArrayListUnmanaged(u32){};
4454 defer bit_bag.deinit(gpa);
44554418
4456 var cur_bit_bag: u32 = 0;
4457 var field_index: usize = 0;
4458 for (container_decl.ast.members) |member_node| {4419 for (container_decl.ast.members) |member_node| {
4459 if (member_node == counts.nonexhaustive_node)4420 if (member_node == counts.nonexhaustive_node)
4460 continue;4421 continue;
...@@ -4469,14 +4430,14 @@ fn containerDecl(...@@ -4469,14 +4430,14 @@ fn containerDecl(
4469 switch (node_tags[fn_proto]) {4430 switch (node_tags[fn_proto]) {
4470 .fn_proto_simple => {4431 .fn_proto_simple => {
4471 var params: [1]Ast.Node.Index = undefined;4432 var params: [1]Ast.Node.Index = undefined;
4472 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {4433 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4473 error.OutOfMemory => return error.OutOfMemory,4434 error.OutOfMemory => return error.OutOfMemory,
4474 error.AnalysisFail => {},4435 error.AnalysisFail => {},
4475 };4436 };
4476 continue;4437 continue;
4477 },4438 },
4478 .fn_proto_multi => {4439 .fn_proto_multi => {
4479 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {4440 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4480 error.OutOfMemory => return error.OutOfMemory,4441 error.OutOfMemory => return error.OutOfMemory,
4481 error.AnalysisFail => {},4442 error.AnalysisFail => {},
4482 };4443 };
...@@ -4484,14 +4445,14 @@ fn containerDecl(...@@ -4484,14 +4445,14 @@ fn containerDecl(
4484 },4445 },
4485 .fn_proto_one => {4446 .fn_proto_one => {
4486 var params: [1]Ast.Node.Index = undefined;4447 var params: [1]Ast.Node.Index = undefined;
4487 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {4448 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4488 error.OutOfMemory => return error.OutOfMemory,4449 error.OutOfMemory => return error.OutOfMemory,
4489 error.AnalysisFail => {},4450 error.AnalysisFail => {},
4490 };4451 };
4491 continue;4452 continue;
4492 },4453 },
4493 .fn_proto => {4454 .fn_proto => {
4494 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {4455 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4495 error.OutOfMemory => return error.OutOfMemory,4456 error.OutOfMemory => return error.OutOfMemory,
4496 error.AnalysisFail => {},4457 error.AnalysisFail => {},
4497 };4458 };
...@@ -4502,14 +4463,14 @@ fn containerDecl(...@@ -4502,14 +4463,14 @@ fn containerDecl(
4502 },4463 },
4503 .fn_proto_simple => {4464 .fn_proto_simple => {
4504 var params: [1]Ast.Node.Index = undefined;4465 var params: [1]Ast.Node.Index = undefined;
4505 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {4466 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4506 error.OutOfMemory => return error.OutOfMemory,4467 error.OutOfMemory => return error.OutOfMemory,
4507 error.AnalysisFail => {},4468 error.AnalysisFail => {},
4508 };4469 };
4509 continue;4470 continue;
4510 },4471 },
4511 .fn_proto_multi => {4472 .fn_proto_multi => {
4512 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {4473 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4513 error.OutOfMemory => return error.OutOfMemory,4474 error.OutOfMemory => return error.OutOfMemory,
4514 error.AnalysisFail => {},4475 error.AnalysisFail => {},
4515 };4476 };
...@@ -4517,14 +4478,14 @@ fn containerDecl(...@@ -4517,14 +4478,14 @@ fn containerDecl(
4517 },4478 },
4518 .fn_proto_one => {4479 .fn_proto_one => {
4519 var params: [1]Ast.Node.Index = undefined;4480 var params: [1]Ast.Node.Index = undefined;
4520 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {4481 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4521 error.OutOfMemory => return error.OutOfMemory,4482 error.OutOfMemory => return error.OutOfMemory,
4522 error.AnalysisFail => {},4483 error.AnalysisFail => {},
4523 };4484 };
4524 continue;4485 continue;
4525 },4486 },
4526 .fn_proto => {4487 .fn_proto => {
4527 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {4488 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4528 error.OutOfMemory => return error.OutOfMemory,4489 error.OutOfMemory => return error.OutOfMemory,
4529 error.AnalysisFail => {},4490 error.AnalysisFail => {},
4530 };4491 };
...@@ -4532,28 +4493,28 @@ fn containerDecl(...@@ -4532,28 +4493,28 @@ fn containerDecl(
4532 },4493 },
45334494
4534 .global_var_decl => {4495 .global_var_decl => {
4535 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {4496 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4536 error.OutOfMemory => return error.OutOfMemory,4497 error.OutOfMemory => return error.OutOfMemory,
4537 error.AnalysisFail => {},4498 error.AnalysisFail => {},
4538 };4499 };
4539 continue;4500 continue;
4540 },4501 },
4541 .local_var_decl => {4502 .local_var_decl => {
4542 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {4503 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4543 error.OutOfMemory => return error.OutOfMemory,4504 error.OutOfMemory => return error.OutOfMemory,
4544 error.AnalysisFail => {},4505 error.AnalysisFail => {},
4545 };4506 };
4546 continue;4507 continue;
4547 },4508 },
4548 .simple_var_decl => {4509 .simple_var_decl => {
4549 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {4510 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4550 error.OutOfMemory => return error.OutOfMemory,4511 error.OutOfMemory => return error.OutOfMemory,
4551 error.AnalysisFail => {},4512 error.AnalysisFail => {},
4552 };4513 };
4553 continue;4514 continue;
4554 },4515 },
4555 .aligned_var_decl => {4516 .aligned_var_decl => {
4556 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {4517 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4557 error.OutOfMemory => return error.OutOfMemory,4518 error.OutOfMemory => return error.OutOfMemory,
4558 error.AnalysisFail => {},4519 error.AnalysisFail => {},
4559 };4520 };
...@@ -4561,21 +4522,21 @@ fn containerDecl(...@@ -4561,21 +4522,21 @@ fn containerDecl(
4561 },4522 },
45624523
4563 .@"comptime" => {4524 .@"comptime" => {
4564 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4525 astgen.comptimeDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4565 error.OutOfMemory => return error.OutOfMemory,4526 error.OutOfMemory => return error.OutOfMemory,
4566 error.AnalysisFail => {},4527 error.AnalysisFail => {},
4567 };4528 };
4568 continue;4529 continue;
4569 },4530 },
4570 .@"usingnamespace" => {4531 .@"usingnamespace" => {
4571 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4532 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4572 error.OutOfMemory => return error.OutOfMemory,4533 error.OutOfMemory => return error.OutOfMemory,
4573 error.AnalysisFail => {},4534 error.AnalysisFail => {},
4574 };4535 };
4575 continue;4536 continue;
4576 },4537 },
4577 .test_decl => {4538 .test_decl => {
4578 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4539 astgen.testDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4579 error.OutOfMemory => return error.OutOfMemory,4540 error.OutOfMemory => return error.OutOfMemory,
4580 error.AnalysisFail => {},4541 error.AnalysisFail => {},
4581 };4542 };
...@@ -4583,20 +4544,15 @@ fn containerDecl(...@@ -4583,20 +4544,15 @@ fn containerDecl(
4583 },4544 },
4584 else => unreachable,4545 else => unreachable,
4585 };4546 };
4586 if (field_index % 32 == 0 and field_index != 0) {
4587 try bit_bag.append(gpa, cur_bit_bag);
4588 cur_bit_bag = 0;
4589 }
4590 assert(member.comptime_token == null);4547 assert(member.comptime_token == null);
4591 assert(member.ast.type_expr == 0);4548 assert(member.ast.type_expr == 0);
4592 assert(member.ast.align_expr == 0);4549 assert(member.ast.align_expr == 0);
45934550
4594 const field_name = try astgen.identAsString(member.ast.name_token);4551 const field_name = try astgen.identAsString(member.ast.name_token);
4595 fields_data.appendAssumeCapacity(field_name);4552 wip_members.appendToField(field_name);
45964553
4597 const have_value = member.ast.value_expr != 0;4554 const have_value = member.ast.value_expr != 0;
4598 cur_bit_bag = (cur_bit_bag >> 1) |4555 wip_members.nextField(bits_per_field, .{have_value});
4599 (@as(u32, @boolToInt(have_value)) << 31);
46004556
4601 if (have_value) {4557 if (have_value) {
4602 if (arg_inst == .none) {4558 if (arg_inst == .none) {
...@@ -4614,23 +4570,10 @@ fn containerDecl(...@@ -4614,23 +4570,10 @@ fn containerDecl(
4614 );4570 );
4615 }4571 }
4616 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);4572 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);
4617 fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));4573 wip_members.appendToField(@enumToInt(tag_value_inst));
4618 }
4619
4620 field_index += 1;
4621 }
4622 {
4623 const empty_slot_count = 32 - (field_index % 32);
4624 if (empty_slot_count < 32) {
4625 cur_bit_bag >>= @intCast(u5, empty_slot_count);
4626 }
4627 }
4628 {
4629 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4630 if (empty_slot_count < WipDecls.fields_per_u32) {
4631 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4632 }4574 }
4633 }4575 }
4576 assert(wip_members.decl_index == counts.decls and wip_members.field_index == counts.total_fields);
46344577
4635 if (block_scope.instructions.items.len != 0) {4578 if (block_scope.instructions.items.len != 0) {
4636 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);4579 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
...@@ -4641,32 +4584,17 @@ fn containerDecl(...@@ -4641,32 +4584,17 @@ fn containerDecl(
4641 .nonexhaustive = nonexhaustive,4584 .nonexhaustive = nonexhaustive,
4642 .tag_type = arg_inst,4585 .tag_type = arg_inst,
4643 .body_len = @intCast(u32, block_scope.instructions.items.len),4586 .body_len = @intCast(u32, block_scope.instructions.items.len),
4644 .fields_len = @intCast(u32, field_index),4587 .fields_len = @intCast(u32, counts.total_fields),
4645 .decls_len = @intCast(u32, wip_decls.decl_index),4588 .decls_len = @intCast(u32, counts.decls),
4646 });4589 });
46474590
4648 // zig fmt: off4591 wip_members.finishBits(bits_per_field);
4649 try astgen.extra.ensureUnusedCapacity(gpa,4592 const decls_slice = wip_members.declsSlice();
4650 bit_bag.items.len +4593 const fields_slice = wip_members.fieldsSlice();
4651 @boolToInt(wip_decls.decl_index != 0) +4594 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + block_scope.instructions.items.len + fields_slice.len);
4652 wip_decls.payload.items.len +4595 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4653 block_scope.instructions.items.len +
4654 wip_decls.bit_bag.items.len +
4655 1 + // cur_bit_bag
4656 fields_data.items.len
4657 );
4658 // zig fmt: on
4659
4660 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4661 if (wip_decls.decl_index != 0) {
4662 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4663 }
4664 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4665
4666 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);4596 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
4667 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.4597 astgen.extra.appendSliceAssumeCapacity(fields_slice);
4668 astgen.extra.appendAssumeCapacity(cur_bit_bag);
4669 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
46704598
4671 return rvalue(gz, rl, indexToRef(decl_inst), node);4599 return rvalue(gz, rl, indexToRef(decl_inst), node);
4672 },4600 },
...@@ -4683,10 +4611,10 @@ fn containerDecl(...@@ -4683,10 +4611,10 @@ fn containerDecl(
4683 };4611 };
4684 defer namespace.deinit(gpa);4612 defer namespace.deinit(gpa);
46854613
4686 try astgen.scanDecls(&namespace, container_decl.ast.members);4614 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
46874615
4688 var wip_decls: WipDecls = .{};4616 var wip_members = try WipMembers.init(gpa, decl_count, 0, 0, 0);
4689 defer wip_decls.deinit(gpa);4617 defer wip_members.deinit(gpa);
46904618
4691 for (container_decl.ast.members) |member_node| {4619 for (container_decl.ast.members) |member_node| {
4692 switch (node_tags[member_node]) {4620 switch (node_tags[member_node]) {
...@@ -4698,14 +4626,14 @@ fn containerDecl(...@@ -4698,14 +4626,14 @@ fn containerDecl(
4698 switch (node_tags[fn_proto]) {4626 switch (node_tags[fn_proto]) {
4699 .fn_proto_simple => {4627 .fn_proto_simple => {
4700 var params: [1]Ast.Node.Index = undefined;4628 var params: [1]Ast.Node.Index = undefined;
4701 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {4629 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4702 error.OutOfMemory => return error.OutOfMemory,4630 error.OutOfMemory => return error.OutOfMemory,
4703 error.AnalysisFail => {},4631 error.AnalysisFail => {},
4704 };4632 };
4705 continue;4633 continue;
4706 },4634 },
4707 .fn_proto_multi => {4635 .fn_proto_multi => {
4708 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {4636 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4709 error.OutOfMemory => return error.OutOfMemory,4637 error.OutOfMemory => return error.OutOfMemory,
4710 error.AnalysisFail => {},4638 error.AnalysisFail => {},
4711 };4639 };
...@@ -4713,14 +4641,14 @@ fn containerDecl(...@@ -4713,14 +4641,14 @@ fn containerDecl(
4713 },4641 },
4714 .fn_proto_one => {4642 .fn_proto_one => {
4715 var params: [1]Ast.Node.Index = undefined;4643 var params: [1]Ast.Node.Index = undefined;
4716 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {4644 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4717 error.OutOfMemory => return error.OutOfMemory,4645 error.OutOfMemory => return error.OutOfMemory,
4718 error.AnalysisFail => {},4646 error.AnalysisFail => {},
4719 };4647 };
4720 continue;4648 continue;
4721 },4649 },
4722 .fn_proto => {4650 .fn_proto => {
4723 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {4651 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4724 error.OutOfMemory => return error.OutOfMemory,4652 error.OutOfMemory => return error.OutOfMemory,
4725 error.AnalysisFail => {},4653 error.AnalysisFail => {},
4726 };4654 };
...@@ -4731,14 +4659,14 @@ fn containerDecl(...@@ -4731,14 +4659,14 @@ fn containerDecl(
4731 },4659 },
4732 .fn_proto_simple => {4660 .fn_proto_simple => {
4733 var params: [1]Ast.Node.Index = undefined;4661 var params: [1]Ast.Node.Index = undefined;
4734 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {4662 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4735 error.OutOfMemory => return error.OutOfMemory,4663 error.OutOfMemory => return error.OutOfMemory,
4736 error.AnalysisFail => {},4664 error.AnalysisFail => {},
4737 };4665 };
4738 continue;4666 continue;
4739 },4667 },
4740 .fn_proto_multi => {4668 .fn_proto_multi => {
4741 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {4669 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4742 error.OutOfMemory => return error.OutOfMemory,4670 error.OutOfMemory => return error.OutOfMemory,
4743 error.AnalysisFail => {},4671 error.AnalysisFail => {},
4744 };4672 };
...@@ -4746,14 +4674,14 @@ fn containerDecl(...@@ -4746,14 +4674,14 @@ fn containerDecl(
4746 },4674 },
4747 .fn_proto_one => {4675 .fn_proto_one => {
4748 var params: [1]Ast.Node.Index = undefined;4676 var params: [1]Ast.Node.Index = undefined;
4749 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {4677 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4750 error.OutOfMemory => return error.OutOfMemory,4678 error.OutOfMemory => return error.OutOfMemory,
4751 error.AnalysisFail => {},4679 error.AnalysisFail => {},
4752 };4680 };
4753 continue;4681 continue;
4754 },4682 },
4755 .fn_proto => {4683 .fn_proto => {
4756 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {4684 astgen.fnDecl(gz, &namespace.base, &wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4757 error.OutOfMemory => return error.OutOfMemory,4685 error.OutOfMemory => return error.OutOfMemory,
4758 error.AnalysisFail => {},4686 error.AnalysisFail => {},
4759 };4687 };
...@@ -4761,28 +4689,28 @@ fn containerDecl(...@@ -4761,28 +4689,28 @@ fn containerDecl(
4761 },4689 },
47624690
4763 .global_var_decl => {4691 .global_var_decl => {
4764 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {4692 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4765 error.OutOfMemory => return error.OutOfMemory,4693 error.OutOfMemory => return error.OutOfMemory,
4766 error.AnalysisFail => {},4694 error.AnalysisFail => {},
4767 };4695 };
4768 continue;4696 continue;
4769 },4697 },
4770 .local_var_decl => {4698 .local_var_decl => {
4771 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {4699 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4772 error.OutOfMemory => return error.OutOfMemory,4700 error.OutOfMemory => return error.OutOfMemory,
4773 error.AnalysisFail => {},4701 error.AnalysisFail => {},
4774 };4702 };
4775 continue;4703 continue;
4776 },4704 },
4777 .simple_var_decl => {4705 .simple_var_decl => {
4778 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {4706 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4779 error.OutOfMemory => return error.OutOfMemory,4707 error.OutOfMemory => return error.OutOfMemory,
4780 error.AnalysisFail => {},4708 error.AnalysisFail => {},
4781 };4709 };
4782 continue;4710 continue;
4783 },4711 },
4784 .aligned_var_decl => {4712 .aligned_var_decl => {
4785 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {4713 astgen.globalVarDecl(gz, &namespace.base, &wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4786 error.OutOfMemory => return error.OutOfMemory,4714 error.OutOfMemory => return error.OutOfMemory,
4787 error.AnalysisFail => {},4715 error.AnalysisFail => {},
4788 };4716 };
...@@ -4790,21 +4718,21 @@ fn containerDecl(...@@ -4790,21 +4718,21 @@ fn containerDecl(
4790 },4718 },
47914719
4792 .@"comptime" => {4720 .@"comptime" => {
4793 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4721 astgen.comptimeDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4794 error.OutOfMemory => return error.OutOfMemory,4722 error.OutOfMemory => return error.OutOfMemory,
4795 error.AnalysisFail => {},4723 error.AnalysisFail => {},
4796 };4724 };
4797 continue;4725 continue;
4798 },4726 },
4799 .@"usingnamespace" => {4727 .@"usingnamespace" => {
4800 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4728 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4801 error.OutOfMemory => return error.OutOfMemory,4729 error.OutOfMemory => return error.OutOfMemory,
4802 error.AnalysisFail => {},4730 error.AnalysisFail => {},
4803 };4731 };
4804 continue;4732 continue;
4805 },4733 },
4806 .test_decl => {4734 .test_decl => {
4807 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {4735 astgen.testDecl(gz, &namespace.base, &wip_members, member_node) catch |err| switch (err) {
4808 error.OutOfMemory => return error.OutOfMemory,4736 error.OutOfMemory => return error.OutOfMemory,
4809 error.AnalysisFail => {},4737 error.AnalysisFail => {},
4810 };4738 };
...@@ -4813,31 +4741,17 @@ fn containerDecl(...@@ -4813,31 +4741,17 @@ fn containerDecl(
4813 else => unreachable,4741 else => unreachable,
4814 }4742 }
4815 }4743 }
4816 {4744 assert(wip_members.decl_index == decl_count);
4817 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4818 if (empty_slot_count < WipDecls.fields_per_u32) {
4819 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4820 }
4821 }
48224745
4823 try gz.setOpaque(decl_inst, .{4746 try gz.setOpaque(decl_inst, .{
4824 .src_node = node,4747 .src_node = node,
4825 .decls_len = @intCast(u32, wip_decls.decl_index),4748 .decls_len = decl_count,
4826 });4749 });
48274750
4828 // zig fmt: off4751 wip_members.finishBits(0);
4829 try astgen.extra.ensureUnusedCapacity(gpa,4752 const decls_slice = wip_members.declsSlice();
4830 wip_decls.bit_bag.items.len +4753 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len);
4831 @boolToInt(wip_decls.decl_index != 0) +4754 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4832 wip_decls.payload.items.len
4833 );
4834 // zig fmt: on
4835
4836 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4837 if (wip_decls.decl_index != 0) {
4838 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4839 }
4840 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
48414755
4842 return rvalue(gz, rl, indexToRef(decl_inst), node);4756 return rvalue(gz, rl, indexToRef(decl_inst), node);
4843 },4757 },
...@@ -10436,12 +10350,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {...@@ -10436,12 +10350,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
10436 astgen.source_column = column;10350 astgen.source_column = column;
10437}10351}
1043810352
10439fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !void {10353fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !u32 {
10440 const gpa = astgen.gpa;10354 const gpa = astgen.gpa;
10441 const tree = astgen.tree;10355 const tree = astgen.tree;
10442 const node_tags = tree.nodes.items(.tag);10356 const node_tags = tree.nodes.items(.tag);
10443 const main_tokens = tree.nodes.items(.main_token);10357 const main_tokens = tree.nodes.items(.main_token);
10444 const token_tags = tree.tokens.items(.tag);10358 const token_tags = tree.tokens.items(.tag);
10359 var decl_count: u32 = 0;
10445 for (members) |member_node| {10360 for (members) |member_node| {
10446 const name_token = switch (node_tags[member_node]) {10361 const name_token = switch (node_tags[member_node]) {
10447 .fn_proto_simple,10362 .fn_proto_simple,
...@@ -10452,9 +10367,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10452,9 +10367,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10452 .local_var_decl,10367 .local_var_decl,
10453 .simple_var_decl,10368 .simple_var_decl,
10454 .aligned_var_decl,10369 .aligned_var_decl,
10455 => main_tokens[member_node] + 1,10370 => blk: {
10371 decl_count += 1;
10372 break :blk main_tokens[member_node] + 1;
10373 },
1045610374
10457 .fn_decl => blk: {10375 .fn_decl => blk: {
10376 decl_count += 1;
10458 const ident = main_tokens[member_node] + 1;10377 const ident = main_tokens[member_node] + 1;
10459 if (token_tags[ident] != .identifier) {10378 if (token_tags[ident] != .identifier) {
10460 switch (astgen.failNode(member_node, "missing function name", .{})) {10379 switch (astgen.failNode(member_node, "missing function name", .{})) {
...@@ -10465,6 +10384,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10465,6 +10384,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10465 break :blk ident;10384 break :blk ident;
10466 },10385 },
1046710386
10387 .@"comptime", .@"usingnamespace", .test_decl => {
10388 decl_count += 1;
10389 continue;
10390 },
10391
10468 else => continue,10392 else => continue,
10469 };10393 };
1047010394
...@@ -10498,4 +10422,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10498,4 +10422,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10498 }10422 }
10499 gop.value_ptr.* = member_node;10423 gop.value_ptr.* = member_node;
10500 }10424 }
10425 return decl_count;
10501}10426}