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 {
24822482 decl_index: usize = 0,
24832483 cur_bit_bag: u32 = 0,
24842484 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
24872490 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {
24882491 wip_decls.bit_bag.deinit(gpa);
2489 wip_decls.name_and_value.deinit(gpa);
2492 wip_decls.payload.deinit(gpa);
24902493 }
24912494};
24922495
......@@ -2501,6 +2504,15 @@ fn fnDecl(
25012504 const tree = &astgen.file.tree;
25022505 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
25042516 const is_pub = fn_proto.visib_token != null;
25052517 const is_export = blk: {
25062518 const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;
......@@ -2510,13 +2522,22 @@ fn fnDecl(
25102522 const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
25112523 break :blk token_tags[maybe_extern_token] == .keyword_extern;
25122524 };
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) {
25142533 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
25152534 wip_decls.cur_bit_bag = 0;
25162535 }
2517 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) |
2518 (@as(u32, @boolToInt(is_pub)) << 30) |
2519 (@as(u32, @boolToInt(is_export)) << 31);
2536 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2537 (@as(u32, @boolToInt(is_pub)) << 28) |
2538 (@as(u32, @boolToInt(is_export)) << 29) |
2539 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2540 (@as(u32, @boolToInt(section_inst != .none)) << 31);
25202541 wip_decls.decl_index += 1;
25212542
25222543 // The AST params array does not contain anytype and ... parameters.
......@@ -2537,15 +2558,6 @@ fn fnDecl(
25372558 const param_types = try gpa.alloc(Zir.Inst.Ref, param_count);
25382559 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
25492561 var is_var_args = false;
25502562 {
25512563 var param_type_i: usize = 0;
......@@ -2577,21 +2589,6 @@ fn fnDecl(
25772589 break :blk lib_name_str.index;
25782590 } 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
25952592 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
25962593 const is_inferred_error = token_tags[maybe_bang] == .bang;
25972594
......@@ -2713,9 +2710,15 @@ fn fnDecl(
27132710 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
27142711 try decl_gz.setBlockBody(block_inst);
27152712
2716 try wip_decls.name_and_value.ensureCapacity(gpa, wip_decls.name_and_value.items.len + 2);
2717 wip_decls.name_and_value.appendAssumeCapacity(fn_name_str_index);
2718 wip_decls.name_and_value.appendAssumeCapacity(block_inst);
2713 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);
2714 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
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 }
27192722}
27202723
27212724fn globalVarDecl(
......@@ -2730,6 +2733,14 @@ fn globalVarDecl(
27302733 const tree = &astgen.file.tree;
27312734 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
27332744 const is_pub = var_decl.visib_token != null;
27342745 const is_export = blk: {
27352746 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
......@@ -2739,13 +2750,21 @@ fn globalVarDecl(
27392750 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
27402751 break :blk token_tags[maybe_extern_token] == .keyword_extern;
27412752 };
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) {
27432760 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
27442761 wip_decls.cur_bit_bag = 0;
27452762 }
2746 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) |
2747 (@as(u32, @boolToInt(is_pub)) << 30) |
2748 (@as(u32, @boolToInt(is_export)) << 31);
2763 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> WipDecls.bits_per_field) |
2764 (@as(u32, @boolToInt(is_pub)) << 28) |
2765 (@as(u32, @boolToInt(is_export)) << 29) |
2766 (@as(u32, @boolToInt(align_inst != .none)) << 30) |
2767 (@as(u32, @boolToInt(section_inst != .none)) << 31);
27492768 wip_decls.decl_index += 1;
27502769
27512770 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
......@@ -2762,12 +2781,6 @@ fn globalVarDecl(
27622781 } else 0;
27632782
27642783 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
27722785 const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: {
27732786 if (is_extern) {
......@@ -2778,14 +2791,6 @@ fn globalVarDecl(
27782791 );
27792792 }
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
27892794 const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{
27902795 .ty = try expr(
27912796 &block_scope,
......@@ -2812,7 +2817,7 @@ fn globalVarDecl(
28122817 } else if (var_decl.ast.type_node != 0) {
28132818 // 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
28172822 return astgen.failNode(node, "TODO AstGen extern global variable", .{});
28182823 } else {
......@@ -2822,9 +2827,15 @@ fn globalVarDecl(
28222827 const name_token = var_decl.ast.mut_token + 1;
28232828 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);
2826 wip_decls.name_and_value.appendAssumeCapacity(name_str_index);
2827 wip_decls.name_and_value.appendAssumeCapacity(var_inst);
2830 try wip_decls.payload.ensureUnusedCapacity(gpa, 4);
2831 wip_decls.payload.appendAssumeCapacity(name_str_index);
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 }
28282839}
28292840
28302841fn comptimeDecl(
......@@ -3080,7 +3091,7 @@ fn structDeclInner(
30803091 (@as(u32, @boolToInt(have_value)) << 31);
30813092
30823093 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);
30843095 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
30853096 }
30863097 if (have_value) {
......@@ -3097,9 +3108,9 @@ fn structDeclInner(
30973108 }
30983109 }
30993110 {
3100 const empty_slot_count = 16 - (wip_decls.decl_index % 16);
3101 if (empty_slot_count < 16) {
3102 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
3111 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3112 if (empty_slot_count < WipDecls.fields_per_u32) {
3113 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
31033114 }
31043115 }
31053116
......@@ -3113,7 +3124,7 @@ fn structDeclInner(
31133124 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
31143125 block_scope.instructions.items.len +
31153126 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);
31173128 const zir_datas = astgen.instructions.items(.data);
31183129 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{
31193130 .body_len = @intCast(u32, block_scope.instructions.items.len),
......@@ -3132,7 +3143,7 @@ fn structDeclInner(
31323143 if (wip_decls.decl_index != 0) {
31333144 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
31343145 }
3135 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
3146 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
31363147
31373148 return gz.indexToRef(decl_inst);
31383149}
......@@ -3321,9 +3332,9 @@ fn unionDeclInner(
33213332 }
33223333 }
33233334 {
3324 const empty_slot_count = 16 - (wip_decls.decl_index % 16);
3325 if (empty_slot_count < 16) {
3326 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
3335 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3336 if (empty_slot_count < WipDecls.fields_per_u32) {
3337 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
33273338 }
33283339 }
33293340
......@@ -3337,7 +3348,7 @@ fn unionDeclInner(
33373348 bit_bag.items.len + 1 + fields_data.items.len +
33383349 block_scope.instructions.items.len +
33393350 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);
33413352 const zir_datas = astgen.instructions.items(.data);
33423353 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{
33433354 .tag_type = arg_inst,
......@@ -3355,7 +3366,7 @@ fn unionDeclInner(
33553366 if (wip_decls.decl_index != 0) {
33563367 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
33573368 }
3358 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
3369 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
33593370
33603371 return gz.indexToRef(decl_inst);
33613372}
......@@ -3653,9 +3664,9 @@ fn containerDecl(
36533664 }
36543665 }
36553666 {
3656 const empty_slot_count = 16 - (wip_decls.decl_index % 16);
3657 if (empty_slot_count < 16) {
3658 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
3667 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3668 if (empty_slot_count < WipDecls.fields_per_u32) {
3669 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
36593670 }
36603671 }
36613672
......@@ -3669,7 +3680,7 @@ fn containerDecl(
36693680 bit_bag.items.len + 1 + fields_data.items.len +
36703681 block_scope.instructions.items.len +
36713682 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);
36733684 const zir_datas = astgen.instructions.items(.data);
36743685 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
36753686 .tag_type = arg_inst,
......@@ -3686,7 +3697,7 @@ fn containerDecl(
36863697 if (wip_decls.decl_index != 0) {
36873698 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
36883699 }
3689 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
3700 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
36903701
36913702 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
36923703 },
src/Zir.zig+53-16
......@@ -2021,13 +2021,17 @@ pub const Inst = struct {
20212021 /// align: Ref, // if corresponding bit is set
20222022 /// default_value: Ref, // if corresponding bit is set
20232023 /// }
2024 /// 3. decl_bits: u32 // for every 16 decls
2025 /// - sets of 2 bits:
2026 /// 0b0X: whether corresponding decl is pub
2027 /// 0bX0: whether corresponding decl is exported
2024 /// 3. decl_bits: u32 // for every 8 decls
2025 /// - sets of 4 bits:
2026 /// 0b000X: whether corresponding decl is pub
2027 /// 0b00X0: whether corresponding decl is exported
2028 /// 0b0X00: whether corresponding decl has an align expression
2029 /// 0bX000: whether corresponding decl has a linksection expression
20282030 /// 4. decl: { // for every decls_len
20292031 /// name: u32, // null terminated string index
20302032 /// value: Index,
2033 /// align: Ref, // if corresponding bit is set
2034 /// link_section: Ref, // if corresponding bit is set
20312035 /// }
20322036 pub const StructDecl = struct {
20332037 body_len: u32,
......@@ -2043,13 +2047,17 @@ pub const Inst = struct {
20432047 /// field_name: u32,
20442048 /// value: Ref, // if corresponding bit is set
20452049 /// }
2046 /// 3. decl_bits: u32 // for every 16 decls
2047 /// - sets of 2 bits:
2048 /// 0b0X: whether corresponding decl is pub
2049 /// 0bX0: whether corresponding decl is exported
2050 /// 3. decl_bits: u32 // for every 8 decls
2051 /// - sets of 4 bits:
2052 /// 0b000X: whether corresponding decl is pub
2053 /// 0b00X0: whether corresponding decl is exported
2054 /// 0b0X00: whether corresponding decl has an align expression
2055 /// 0bX000: whether corresponding decl has a linksection expression
20502056 /// 4. decl: { // for every decls_len
20512057 /// name: u32, // null terminated string index
20522058 /// value: Index,
2059 /// align: Ref, // if corresponding bit is set
2060 /// link_section: Ref, // if corresponding bit is set
20532061 /// }
20542062 pub const EnumDecl = struct {
20552063 /// Can be `Ref.none`.
......@@ -2077,13 +2085,17 @@ pub const Inst = struct {
20772085 /// align: Ref, // if corresponding bit is set
20782086 /// tag_value: Ref, // if corresponding bit is set
20792087 /// }
2080 /// 3. decl_bits: u32 // for every 16 decls
2081 /// - sets of 2 bits:
2082 /// 0b0X: whether corresponding decl is pub
2083 /// 0bX0: whether corresponding decl is exported
2088 /// 3. decl_bits: u32 // for every 8 decls
2089 /// - sets of 4 bits:
2090 /// 0b000X: whether corresponding decl is pub
2091 /// 0b00X0: whether corresponding decl is exported
2092 /// 0b0X00: whether corresponding decl has an align expression
2093 /// 0bX000: whether corresponding decl has a linksection expression
20842094 /// 4. decl: { // for every decls_len
20852095 /// name: u32, // null terminated string index
20862096 /// value: Index,
2097 /// align: Ref, // if corresponding bit is set
2098 /// link_section: Ref, // if corresponding bit is set
20872099 /// }
20882100 pub const UnionDecl = struct {
20892101 /// Can be `Ref.none`.
......@@ -3072,13 +3084,13 @@ const Writer = struct {
30723084
30733085 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !void {
30743086 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;
30763088 var extra_index = extra_start + bit_bags_count;
30773089 var bit_bag_index: usize = extra_start;
30783090 var cur_bit_bag: u32 = undefined;
30793091 var decl_i: u32 = 0;
30803092 while (decl_i < decls_len) : (decl_i += 1) {
3081 if (decl_i % 16 == 0) {
3093 if (decl_i % 8 == 0) {
30823094 cur_bit_bag = self.code.extra[bit_bag_index];
30833095 bit_bag_index += 1;
30843096 }
......@@ -3086,19 +3098,44 @@ const Writer = struct {
30863098 cur_bit_bag >>= 1;
30873099 const is_exported = @truncate(u1, cur_bit_bag) != 0;
30883100 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
30903106 const decl_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
30913107 extra_index += 1;
30923108 const decl_index = self.code.extra[extra_index];
30933109 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
30953121 const tag = self.code.instructions.items(.tag)[decl_index];
30963122 const pub_str = if (is_pub) "pub " else "";
30973123 const export_str = if (is_exported) "export " else "";
30983124 try stream.writeByteNTimes(' ', self.indent);
3099 try stream.print("{s}{s}{}: %{d} = {s}(", .{
3100 pub_str, export_str, std.zig.fmtId(decl_name), decl_index, @tagName(tag),
3125 try stream.print("{s}{s}{}", .{
3126 pub_str, export_str, std.zig.fmtId(decl_name),
31013127 });
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
31033140 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;
31043141 const sub_decl_node_off = decl_block_inst_data.src_node;