authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-22 19:21:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-22 19:21:33-07:00
log329a359974c29d62931c32ca85aa42aa9e4847f7
tree395c0097d7706af6bcaf04003edbc9a9311af4ab
parent507a8096d2f9624bafaf963c3e189a477ef6b7bf

AstGen: implement align and linksection on globals


2 files changed, 135 insertions(+), 87 deletions(-)

src/AstGen.zig+82-71
...@@ -2482,11 +2482,14 @@ const WipDecls = struct {...@@ -2482,11 +2482,14 @@ const WipDecls = struct {
2482 decl_index: usize = 0,2482 decl_index: usize = 0,
2483 cur_bit_bag: u32 = 0,2483 cur_bit_bag: u32 = 0,
2484 bit_bag: ArrayListUnmanaged(u32) = .{},2484 bit_bag: ArrayListUnmanaged(u32) = .{},
2485 name_and_value: ArrayListUnmanaged(u32) = .{},2485 payload: ArrayListUnmanaged(u32) = .{},
2486
2487 const bits_per_field = 4;
2488 const fields_per_u32 = 32 / bits_per_field;
24862489
2487 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {2490 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {
2488 wip_decls.bit_bag.deinit(gpa);2491 wip_decls.bit_bag.deinit(gpa);
2489 wip_decls.name_and_value.deinit(gpa);2492 wip_decls.payload.deinit(gpa);
2490 }2493 }
2491};2494};
24922495
...@@ -2501,6 +2504,15 @@ fn fnDecl(...@@ -2501,6 +2504,15 @@ fn fnDecl(
2501 const tree = &astgen.file.tree;2504 const tree = &astgen.file.tree;
2502 const token_tags = tree.tokens.items(.tag);2505 const token_tags = tree.tokens.items(.tag);
25032506
2507 var decl_gz: GenZir = .{
2508 .force_comptime = true,
2509 .decl_node_index = fn_proto.ast.proto_node,
2510 .parent = &gz.base,
2511 .astgen = astgen,
2512 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len),
2513 };
2514 defer decl_gz.instructions.deinit(gpa);
2515
2504 const is_pub = fn_proto.visib_token != null;2516 const is_pub = fn_proto.visib_token != null;
2505 const is_export = blk: {2517 const is_export = blk: {
2506 const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;2518 const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;
...@@ -2510,13 +2522,22 @@ fn fnDecl(...@@ -2510,13 +2522,22 @@ fn fnDecl(
2510 const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;2522 const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
2511 break :blk token_tags[maybe_extern_token] == .keyword_extern;2523 break :blk token_tags[maybe_extern_token] == .keyword_extern;
2512 };2524 };
2513 if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) {2525 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
2526 break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr);
2527 };
2528 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
2529 break :inst try comptimeExpr(&decl_gz, &decl_gz.base, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
2530 };
2531
2532 if (wip_decls.decl_index % WipDecls.fields_per_u32 == 0 and wip_decls.decl_index != 0) {
2514 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);2533 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2515 wip_decls.cur_bit_bag = 0;2534 wip_decls.cur_bit_bag = 0;
2516 }2535 }
2517 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) |2536 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2518 (@as(u32, @boolToInt(is_pub)) << 30) |2537 (@as(u32, @boolToInt(is_pub)) << 28) |
2519 (@as(u32, @boolToInt(is_export)) << 31);2538 (@as(u32, @boolToInt(is_export)) << 29) |
2539 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2540 (@as(u32, @boolToInt(section_inst != .none)) << 31);
2520 wip_decls.decl_index += 1;2541 wip_decls.decl_index += 1;
25212542
2522 // The AST params array does not contain anytype and ... parameters.2543 // The AST params array does not contain anytype and ... parameters.
...@@ -2537,15 +2558,6 @@ fn fnDecl(...@@ -2537,15 +2558,6 @@ fn fnDecl(
2537 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);2558 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
2538 defer gpa.free(param_types);2559 defer gpa.free(param_types);
25392560
2540 var decl_gz: GenZir = .{
2541 .force_comptime = true,
2542 .decl_node_index = fn_proto.ast.proto_node,
2543 .parent = &gz.base,
2544 .astgen = astgen,
2545 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len),
2546 };
2547 defer decl_gz.instructions.deinit(gpa);
2548
2549 var is_var_args = false;2561 var is_var_args = false;
2550 {2562 {
2551 var param_type_i: usize = 0;2563 var param_type_i: usize = 0;
...@@ -2577,21 +2589,6 @@ fn fnDecl(...@@ -2577,21 +2589,6 @@ fn fnDecl(
2577 break :blk lib_name_str.index;2589 break :blk lib_name_str.index;
2578 } else 0;2590 } else 0;
25792591
2580 if (fn_proto.ast.align_expr != 0) {
2581 return astgen.failNode(
2582 fn_proto.ast.align_expr,
2583 "TODO implement function align expression",
2584 .{},
2585 );
2586 }
2587 if (fn_proto.ast.section_expr != 0) {
2588 return astgen.failNode(
2589 fn_proto.ast.section_expr,
2590 "TODO implement function section expression",
2591 .{},
2592 );
2593 }
2594
2595 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;2592 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
2596 const is_inferred_error = token_tags[maybe_bang] == .bang;2593 const is_inferred_error = token_tags[maybe_bang] == .bang;
25972594
...@@ -2713,9 +2710,15 @@ fn fnDecl(...@@ -2713,9 +2710,15 @@ fn fnDecl(
2713 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);2710 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
2714 try decl_gz.setBlockBody(block_inst);2711 try decl_gz.setBlockBody(block_inst);
27152712
2716 try wip_decls.name_and_value.ensureCapacity(gpa, wip_decls.name_and_value.items.len + 2);2713 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);
2717 wip_decls.name_and_value.appendAssumeCapacity(fn_name_str_index);2714 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
2718 wip_decls.name_and_value.appendAssumeCapacity(block_inst);2715 wip_decls.payload.appendAssumeCapacity(block_inst);
2716 if (align_inst != .none) {
2717 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
2718 }
2719 if (section_inst != .none) {
2720 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
2721 }
2719}2722}
27202723
2721fn globalVarDecl(2724fn globalVarDecl(
...@@ -2730,6 +2733,14 @@ fn globalVarDecl(...@@ -2730,6 +2733,14 @@ fn globalVarDecl(
2730 const tree = &astgen.file.tree;2733 const tree = &astgen.file.tree;
2731 const token_tags = tree.tokens.items(.tag);2734 const token_tags = tree.tokens.items(.tag);
27322735
2736 var block_scope: GenZir = .{
2737 .parent = scope,
2738 .decl_node_index = node,
2739 .astgen = astgen,
2740 .force_comptime = true,
2741 };
2742 defer block_scope.instructions.deinit(gpa);
2743
2733 const is_pub = var_decl.visib_token != null;2744 const is_pub = var_decl.visib_token != null;
2734 const is_export = blk: {2745 const is_export = blk: {
2735 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;2746 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
...@@ -2739,13 +2750,21 @@ fn globalVarDecl(...@@ -2739,13 +2750,21 @@ fn globalVarDecl(
2739 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;2750 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
2740 break :blk token_tags[maybe_extern_token] == .keyword_extern;2751 break :blk token_tags[maybe_extern_token] == .keyword_extern;
2741 };2752 };
2742 if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) {2753 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {
2754 break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node);
2755 };
2756 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
2757 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
2758 };
2759 if (wip_decls.decl_index % WipDecls.fields_per_u32 == 0 and wip_decls.decl_index != 0) {
2743 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);2760 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
2744 wip_decls.cur_bit_bag = 0;2761 wip_decls.cur_bit_bag = 0;
2745 }2762 }
2746 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) |2763 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2747 (@as(u32, @boolToInt(is_pub)) << 30) |2764 (@as(u32, @boolToInt(is_pub)) << 28) |
2748 (@as(u32, @boolToInt(is_export)) << 31);2765 (@as(u32, @boolToInt(is_export)) << 29) |
2766 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2767 (@as(u32, @boolToInt(section_inst != .none)) << 31);
2749 wip_decls.decl_index += 1;2768 wip_decls.decl_index += 1;
27502769
2751 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;2770 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
...@@ -2762,12 +2781,6 @@ fn globalVarDecl(...@@ -2762,12 +2781,6 @@ fn globalVarDecl(
2762 } else 0;2781 } else 0;
27632782
2764 assert(var_decl.comptime_token == null); // handled by parser2783 assert(var_decl.comptime_token == null); // handled by parser
2765 if (var_decl.ast.align_node != 0) {
2766 return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on globals", .{});
2767 }
2768 if (var_decl.ast.section_node != 0) {
2769 return astgen.failNode(var_decl.ast.section_node, "TODO linksection on globals", .{});
2770 }
27712784
2772 const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: {2785 const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: {
2773 if (is_extern) {2786 if (is_extern) {
...@@ -2778,14 +2791,6 @@ fn globalVarDecl(...@@ -2778,14 +2791,6 @@ fn globalVarDecl(
2778 );2791 );
2779 }2792 }
27802793
2781 var block_scope: GenZir = .{
2782 .parent = scope,
2783 .decl_node_index = node,
2784 .astgen = astgen,
2785 .force_comptime = true,
2786 };
2787 defer block_scope.instructions.deinit(gpa);
2788
2789 const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{2794 const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{
2790 .ty = try expr(2795 .ty = try expr(
2791 &block_scope,2796 &block_scope,
...@@ -2812,7 +2817,7 @@ fn globalVarDecl(...@@ -2812,7 +2817,7 @@ fn globalVarDecl(
2812 } else if (var_decl.ast.type_node != 0) {2817 } else if (var_decl.ast.type_node != 0) {
2813 // Extern variable which has an explicit type.2818 // Extern variable which has an explicit type.
28142819
2815 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);2820 const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
28162821
2817 return astgen.failNode(node, "TODO AstGen extern global variable", .{});2822 return astgen.failNode(node, "TODO AstGen extern global variable", .{});
2818 } else {2823 } else {
...@@ -2822,9 +2827,15 @@ fn globalVarDecl(...@@ -2822,9 +2827,15 @@ fn globalVarDecl(
2822 const name_token = var_decl.ast.mut_token + 1;2827 const name_token = var_decl.ast.mut_token + 1;
2823 const name_str_index = try gz.identAsString(name_token);2828 const name_str_index = try gz.identAsString(name_token);
28242829
2825 try wip_decls.name_and_value.ensureCapacity(gpa, wip_decls.name_and_value.items.len + 2);2830 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);
2826 wip_decls.name_and_value.appendAssumeCapacity(name_str_index);2831 wip_decls.payload.appendAssumeCapacity(name_str_index);
2827 wip_decls.name_and_value.appendAssumeCapacity(var_inst);2832 wip_decls.payload.appendAssumeCapacity(var_inst);
2833 if (align_inst != .none) {
2834 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
2835 }
2836 if (section_inst != .none) {
2837 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
2838 }
2828}2839}
28292840
2830fn comptimeDecl(2841fn comptimeDecl(
...@@ -3080,7 +3091,7 @@ fn structDeclInner(...@@ -3080,7 +3091,7 @@ fn structDeclInner(
3080 (@as(u32, @boolToInt(have_value)) << 31);3091 (@as(u32, @boolToInt(have_value)) << 31);
30813092
3082 if (have_align) {3093 if (have_align) {
3083 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);3094 const align_inst = try expr(&block_scope, &block_scope.base, align_rl, member.ast.align_expr);
3084 fields_data.appendAssumeCapacity(@enumToInt(align_inst));3095 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3085 }3096 }
3086 if (have_value) {3097 if (have_value) {
...@@ -3097,9 +3108,9 @@ fn structDeclInner(...@@ -3097,9 +3108,9 @@ fn structDeclInner(
3097 }3108 }
3098 }3109 }
3099 {3110 {
3100 const empty_slot_count = 16 - (wip_decls.decl_index % 16);3111 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3101 if (empty_slot_count < 16) {3112 if (empty_slot_count < WipDecls.fields_per_u32) {
3102 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);3113 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3103 }3114 }
3104 }3115 }
31053116
...@@ -3113,7 +3124,7 @@ fn structDeclInner(...@@ -3113,7 +3124,7 @@ fn structDeclInner(
3113 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +3124 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
3114 block_scope.instructions.items.len +3125 block_scope.instructions.items.len +
3115 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +3126 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3116 wip_decls.name_and_value.items.len);3127 wip_decls.payload.items.len);
3117 const zir_datas = astgen.instructions.items(.data);3128 const zir_datas = astgen.instructions.items(.data);
3118 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{3129 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{
3119 .body_len = @intCast(u32, block_scope.instructions.items.len),3130 .body_len = @intCast(u32, block_scope.instructions.items.len),
...@@ -3132,7 +3143,7 @@ fn structDeclInner(...@@ -3132,7 +3143,7 @@ fn structDeclInner(
3132 if (wip_decls.decl_index != 0) {3143 if (wip_decls.decl_index != 0) {
3133 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);3144 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3134 }3145 }
3135 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);3146 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
31363147
3137 return gz.indexToRef(decl_inst);3148 return gz.indexToRef(decl_inst);
3138}3149}
...@@ -3321,9 +3332,9 @@ fn unionDeclInner(...@@ -3321,9 +3332,9 @@ fn unionDeclInner(
3321 }3332 }
3322 }3333 }
3323 {3334 {
3324 const empty_slot_count = 16 - (wip_decls.decl_index % 16);3335 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3325 if (empty_slot_count < 16) {3336 if (empty_slot_count < WipDecls.fields_per_u32) {
3326 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);3337 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3327 }3338 }
3328 }3339 }
33293340
...@@ -3337,7 +3348,7 @@ fn unionDeclInner(...@@ -3337,7 +3348,7 @@ fn unionDeclInner(
3337 bit_bag.items.len + 1 + fields_data.items.len +3348 bit_bag.items.len + 1 + fields_data.items.len +
3338 block_scope.instructions.items.len +3349 block_scope.instructions.items.len +
3339 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +3350 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3340 wip_decls.name_and_value.items.len);3351 wip_decls.payload.items.len);
3341 const zir_datas = astgen.instructions.items(.data);3352 const zir_datas = astgen.instructions.items(.data);
3342 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{3353 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{
3343 .tag_type = arg_inst,3354 .tag_type = arg_inst,
...@@ -3355,7 +3366,7 @@ fn unionDeclInner(...@@ -3355,7 +3366,7 @@ fn unionDeclInner(
3355 if (wip_decls.decl_index != 0) {3366 if (wip_decls.decl_index != 0) {
3356 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);3367 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3357 }3368 }
3358 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);3369 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
33593370
3360 return gz.indexToRef(decl_inst);3371 return gz.indexToRef(decl_inst);
3361}3372}
...@@ -3653,9 +3664,9 @@ fn containerDecl(...@@ -3653,9 +3664,9 @@ fn containerDecl(
3653 }3664 }
3654 }3665 }
3655 {3666 {
3656 const empty_slot_count = 16 - (wip_decls.decl_index % 16);3667 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3657 if (empty_slot_count < 16) {3668 if (empty_slot_count < WipDecls.fields_per_u32) {
3658 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);3669 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3659 }3670 }
3660 }3671 }
36613672
...@@ -3669,7 +3680,7 @@ fn containerDecl(...@@ -3669,7 +3680,7 @@ fn containerDecl(
3669 bit_bag.items.len + 1 + fields_data.items.len +3680 bit_bag.items.len + 1 + fields_data.items.len +
3670 block_scope.instructions.items.len +3681 block_scope.instructions.items.len +
3671 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +3682 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3672 wip_decls.name_and_value.items.len);3683 wip_decls.payload.items.len);
3673 const zir_datas = astgen.instructions.items(.data);3684 const zir_datas = astgen.instructions.items(.data);
3674 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{3685 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
3675 .tag_type = arg_inst,3686 .tag_type = arg_inst,
...@@ -3686,7 +3697,7 @@ fn containerDecl(...@@ -3686,7 +3697,7 @@ fn containerDecl(
3686 if (wip_decls.decl_index != 0) {3697 if (wip_decls.decl_index != 0) {
3687 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);3698 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3688 }3699 }
3689 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);3700 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
36903701
3691 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);3702 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
3692 },3703 },
src/Zir.zig+53-16
...@@ -2021,13 +2021,17 @@ pub const Inst = struct {...@@ -2021,13 +2021,17 @@ pub const Inst = struct {
2021 /// align: Ref, // if corresponding bit is set2021 /// align: Ref, // if corresponding bit is set
2022 /// default_value: Ref, // if corresponding bit is set2022 /// default_value: Ref, // if corresponding bit is set
2023 /// }2023 /// }
2024 /// 3. decl_bits: u32 // for every 16 decls2024 /// 3. decl_bits: u32 // for every 8 decls
2025 /// - sets of 2 bits:2025 /// - sets of 4 bits:
2026 /// 0b0X: whether corresponding decl is pub2026 /// 0b000X: whether corresponding decl is pub
2027 /// 0bX0: whether corresponding decl is exported2027 /// 0b00X0: whether corresponding decl is exported
2028 /// 0b0X00: whether corresponding decl has an align expression
2029 /// 0bX000: whether corresponding decl has a linksection expression
2028 /// 4. decl: { // for every decls_len2030 /// 4. decl: { // for every decls_len
2029 /// name: u32, // null terminated string index2031 /// name: u32, // null terminated string index
2030 /// value: Index,2032 /// value: Index,
2033 /// align: Ref, // if corresponding bit is set
2034 /// link_section: Ref, // if corresponding bit is set
2031 /// }2035 /// }
2032 pub const StructDecl = struct {2036 pub const StructDecl = struct {
2033 body_len: u32,2037 body_len: u32,
...@@ -2043,13 +2047,17 @@ pub const Inst = struct {...@@ -2043,13 +2047,17 @@ pub const Inst = struct {
2043 /// field_name: u32,2047 /// field_name: u32,
2044 /// value: Ref, // if corresponding bit is set2048 /// value: Ref, // if corresponding bit is set
2045 /// }2049 /// }
2046 /// 3. decl_bits: u32 // for every 16 decls2050 /// 3. decl_bits: u32 // for every 8 decls
2047 /// - sets of 2 bits:2051 /// - sets of 4 bits:
2048 /// 0b0X: whether corresponding decl is pub2052 /// 0b000X: whether corresponding decl is pub
2049 /// 0bX0: whether corresponding decl is exported2053 /// 0b00X0: whether corresponding decl is exported
2054 /// 0b0X00: whether corresponding decl has an align expression
2055 /// 0bX000: whether corresponding decl has a linksection expression
2050 /// 4. decl: { // for every decls_len2056 /// 4. decl: { // for every decls_len
2051 /// name: u32, // null terminated string index2057 /// name: u32, // null terminated string index
2052 /// value: Index,2058 /// value: Index,
2059 /// align: Ref, // if corresponding bit is set
2060 /// link_section: Ref, // if corresponding bit is set
2053 /// }2061 /// }
2054 pub const EnumDecl = struct {2062 pub const EnumDecl = struct {
2055 /// Can be `Ref.none`.2063 /// Can be `Ref.none`.
...@@ -2077,13 +2085,17 @@ pub const Inst = struct {...@@ -2077,13 +2085,17 @@ pub const Inst = struct {
2077 /// align: Ref, // if corresponding bit is set2085 /// align: Ref, // if corresponding bit is set
2078 /// tag_value: Ref, // if corresponding bit is set2086 /// tag_value: Ref, // if corresponding bit is set
2079 /// }2087 /// }
2080 /// 3. decl_bits: u32 // for every 16 decls2088 /// 3. decl_bits: u32 // for every 8 decls
2081 /// - sets of 2 bits:2089 /// - sets of 4 bits:
2082 /// 0b0X: whether corresponding decl is pub2090 /// 0b000X: whether corresponding decl is pub
2083 /// 0bX0: whether corresponding decl is exported2091 /// 0b00X0: whether corresponding decl is exported
2092 /// 0b0X00: whether corresponding decl has an align expression
2093 /// 0bX000: whether corresponding decl has a linksection expression
2084 /// 4. decl: { // for every decls_len2094 /// 4. decl: { // for every decls_len
2085 /// name: u32, // null terminated string index2095 /// name: u32, // null terminated string index
2086 /// value: Index,2096 /// value: Index,
2097 /// align: Ref, // if corresponding bit is set
2098 /// link_section: Ref, // if corresponding bit is set
2087 /// }2099 /// }
2088 pub const UnionDecl = struct {2100 pub const UnionDecl = struct {
2089 /// Can be `Ref.none`.2101 /// Can be `Ref.none`.
...@@ -3072,13 +3084,13 @@ const Writer = struct {...@@ -3072,13 +3084,13 @@ const Writer = struct {
30723084
3073 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !void {3085 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !void {
3074 const parent_decl_node = self.parent_decl_node;3086 const parent_decl_node = self.parent_decl_node;
3075 const bit_bags_count = std.math.divCeil(usize, decls_len, 16) catch unreachable;3087 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
3076 var extra_index = extra_start + bit_bags_count;3088 var extra_index = extra_start + bit_bags_count;
3077 var bit_bag_index: usize = extra_start;3089 var bit_bag_index: usize = extra_start;
3078 var cur_bit_bag: u32 = undefined;3090 var cur_bit_bag: u32 = undefined;
3079 var decl_i: u32 = 0;3091 var decl_i: u32 = 0;
3080 while (decl_i < decls_len) : (decl_i += 1) {3092 while (decl_i < decls_len) : (decl_i += 1) {
3081 if (decl_i % 16 == 0) {3093 if (decl_i % 8 == 0) {
3082 cur_bit_bag = self.code.extra[bit_bag_index];3094 cur_bit_bag = self.code.extra[bit_bag_index];
3083 bit_bag_index += 1;3095 bit_bag_index += 1;
3084 }3096 }
...@@ -3086,19 +3098,44 @@ const Writer = struct {...@@ -3086,19 +3098,44 @@ const Writer = struct {
3086 cur_bit_bag >>= 1;3098 cur_bit_bag >>= 1;
3087 const is_exported = @truncate(u1, cur_bit_bag) != 0;3099 const is_exported = @truncate(u1, cur_bit_bag) != 0;
3088 cur_bit_bag >>= 1;3100 cur_bit_bag >>= 1;
3101 const has_align = @truncate(u1, cur_bit_bag) != 0;
3102 cur_bit_bag >>= 1;
3103 const has_section = @truncate(u1, cur_bit_bag) != 0;
3104 cur_bit_bag >>= 1;
30893105
3090 const decl_name = self.code.nullTerminatedString(self.code.extra[extra_index]);3106 const decl_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
3091 extra_index += 1;3107 extra_index += 1;
3092 const decl_index = self.code.extra[extra_index];3108 const decl_index = self.code.extra[extra_index];
3093 extra_index += 1;3109 extra_index += 1;
3110 const align_inst: Inst.Ref = if (!has_align) .none else inst: {
3111 const inst = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3112 extra_index += 1;
3113 break :inst inst;
3114 };
3115 const section_inst: Inst.Ref = if (!has_section) .none else inst: {
3116 const inst = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
3117 extra_index += 1;
3118 break :inst inst;
3119 };
30943120
3095 const tag = self.code.instructions.items(.tag)[decl_index];3121 const tag = self.code.instructions.items(.tag)[decl_index];
3096 const pub_str = if (is_pub) "pub " else "";3122 const pub_str = if (is_pub) "pub " else "";
3097 const export_str = if (is_exported) "export " else "";3123 const export_str = if (is_exported) "export " else "";
3098 try stream.writeByteNTimes(' ', self.indent);3124 try stream.writeByteNTimes(' ', self.indent);
3099 try stream.print("{s}{s}{}: %{d} = {s}(", .{3125 try stream.print("{s}{s}{}", .{
3100 pub_str, export_str, std.zig.fmtId(decl_name), decl_index, @tagName(tag),3126 pub_str, export_str, std.zig.fmtId(decl_name),
3101 });3127 });
3128 if (align_inst != .none) {
3129 try stream.writeAll(" align(");
3130 try self.writeInstRef(stream, align_inst);
3131 try stream.writeAll(")");
3132 }
3133 if (section_inst != .none) {
3134 try stream.writeAll(" linksection(");
3135 try self.writeInstRef(stream, section_inst);
3136 try stream.writeAll(")");
3137 }
3138 try stream.print(": %{d} = {s}(", .{ decl_index, @tagName(tag) });
31023139
3103 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;3140 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;
3104 const sub_decl_node_off = decl_block_inst_data.src_node;3141 const sub_decl_node_off = decl_block_inst_data.src_node;