| ... | @@ -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 | } |
| 2997 | | 2997 | |
| 2998 | const WipDecls = struct { | 2998 | const 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 | } |
| 3003 | | 3033 | |
| 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; |
| 3006 | | 3036 | 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 | } |
| 3026 | | 3077 | |
| 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 | }; |
| 3032 | | 3106 | |
| ... | @@ -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); |
| 3090 | | 3164 | |
| 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); |
| 3289 | | 3363 | |
| 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 | } |
| 3311 | | 3383 | |
| ... | @@ -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); |
| 3363 | | 3435 | |
| 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); |
| 3439 | | 3511 | |
| 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 | } |
| 3460 | | 3531 | |
| ... | @@ -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 this | 3544 | // 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); |
| 3477 | | 3548 | |
| 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); |
| 3493 | | 3564 | |
| 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 | } |
| 3507 | | 3577 | |
| 3508 | fn usingnamespaceDecl( | 3578 | fn 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 this | 3596 | // 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); |
| 3530 | | 3600 | |
| 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); |
| 3544 | | 3614 | |
| 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 | } |
| 3558 | | 3627 | |
| 3559 | fn testDecl( | 3628 | fn 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); |
| 3574 | | 3643 | |
| 3575 | try wip_decls.next(gpa, false, false, false, false); | 3644 | wip_members.nextDecl(false, false, false, false); |
| 3576 | | 3645 | |
| 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); |
| 3645 | | 3714 | |
| 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 | } |
| 3659 | | 3727 | |
| 3660 | fn structDeclInner( | 3728 | fn 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); |
| 3707 | | 3775 | |
| 3708 | try astgen.scanDecls(&namespace, container_decl.ast.members); | 3776 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3709 | | 3777 | 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); | | |
| 3717 | | 3778 | |
| 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); | | |
| 3723 | | 3783 | |
| 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 | }, |
| 3800 | | 3858 | |
| 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 | }, |
| 3829 | | 3887 | |
| 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); | | |
| 3858 | | 3911 | |
| 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); |
| 3861 | | 3914 | |
| 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 | .none | 3920 | .none |
| 3868 | else | 3921 | 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)); |
| 3871 | | 3924 | |
| 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); |
| 3873 | | 3926 | |
| ... | @@ -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); | | |
| 3883 | | 3932 | |
| 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 }; |
| 3890 | | 3939 | |
| 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); |
| 3911 | | 3947 | |
| 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 | }); |
| 3924 | | 3960 | |
| 3925 | // zig fmt: off | 3961 | 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); |
| 3944 | | 3967 | 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); | | |
| 3950 | | 3968 | |
| 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); |
| 3991 | | 4009 | |
| 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); |
| 3993 | | 4012 | |
| 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 | else | 4015 | else |
| 3997 | .none; | 4016 | .none; |
| 3998 | | 4017 | |
| 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); | | |
| 4012 | | 4022 | |
| 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 | }, |
| 4088 | | 4096 | |
| 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 | }, |
| 4117 | | 4125 | |
| 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); | | |
| 4149 | | 4152 | |
| 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); |
| 4152 | | 4155 | |
| 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); | | |
| 4162 | | 4161 | |
| 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 | .none | 4164 | .none |
| 4166 | else | 4165 | 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 | } | | |
| 4226 | | 4212 | |
| 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 | }); |
| 4240 | | 4226 | |
| 4241 | // zig fmt: off | 4227 | 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); |
| 4260 | | 4233 | 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); | | |
| 4264 | | 4234 | |
| 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); |
| 4436 | | 4406 | |
| 4437 | try astgen.scanDecls(&namespace, container_decl.ast.members); | 4407 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4438 | | 4408 | |
| 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 | else | 4411 | else |
| 4442 | .none; | 4412 | .none; |
| 4443 | | 4413 | |
| 4444 | var wip_decls: WipDecls = .{}; | 4414 | const bits_per_field = 1; |
| 4445 | defer wip_decls.deinit(gpa); | 4415 | const max_field_size = 2; |
| 4446 | | 4416 | 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); | | |
| 4455 | | 4418 | |
| 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 | }, |
| 4533 | | 4494 | |
| 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 | }, |
| 4562 | | 4523 | |
| 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); |
| 4593 | | 4550 | |
| 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); |
| 4596 | | 4553 | |
| 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); | | |
| 4600 | | 4556 | |
| 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); |
| 4634 | | 4577 | |
| 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 | }); |
| 4647 | | 4590 | |
| 4648 | // zig fmt: off | 4591 | 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); | | |
| 4670 | | 4598 | |
| 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); |
| 4685 | | 4613 | |
| 4686 | try astgen.scanDecls(&namespace, container_decl.ast.members); | 4614 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4687 | | 4615 | |
| 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); |
| 4690 | | 4618 | |
| 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 | }, |
| 4762 | | 4690 | |
| 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 | }, |
| 4791 | | 4719 | |
| 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 | } | | |
| 4822 | | 4745 | |
| 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 | }); |
| 4827 | | 4750 | |
| 4828 | // zig fmt: off | 4751 | 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); | | |
| 4841 | | 4755 | |
| 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 | } |
| 10438 | | 10352 | |
| 10439 | fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !void { | 10353 | fn 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 | }, |
| 10456 | | 10374 | |
| 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 | }, |
| 10467 | | 10386 | |
| | 10387 | .@"comptime", .@"usingnamespace", .test_decl => { |
| | 10388 | decl_count += 1; |
| | 10389 | continue; |
| | 10390 | }, |
| | 10391 | |
| 10468 | else => continue, | 10392 | else => continue, |
| 10469 | }; | 10393 | }; |
| 10470 | | 10394 | |
| ... | @@ -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 | } |