authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 22:21:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 22:21:26-07:00
log8cf0ef27790a96e784c368d00338229f205c95d9
treed706896341cf35842e23a699adcb106eb8f13ffe
parent0409d433ba7f84885c782decbe06ec285c02c78c

AstGen: implement simple enums and decls for enums


2 files changed, 162 insertions(+), 57 deletions(-)

src/AstGen.zig+105-20
...@@ -2438,12 +2438,11 @@ fn structDeclInner(...@@ -2438,12 +2438,11 @@ fn structDeclInner(
24382438
2439 const decl_inst = try gz.addBlock(tag, node);2439 const decl_inst = try gz.addBlock(tag, node);
2440 try gz.instructions.append(gpa, decl_inst);2440 try gz.instructions.append(gpa, decl_inst);
2441 if (field_index != 0) {2441 if (block_scope.instructions.items.len != 0) {
2442 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);2442 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
2443 }2443 }
24442444
2445 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +2445 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
2446 @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
2447 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +2446 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
2448 block_scope.instructions.items.len +2447 block_scope.instructions.items.len +
2449 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +2448 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
...@@ -2483,6 +2482,7 @@ fn containerDecl(...@@ -2483,6 +2482,7 @@ fn containerDecl(
2483 const tree = &astgen.file.tree;2482 const tree = &astgen.file.tree;
2484 const token_tags = tree.tokens.items(.tag);2483 const token_tags = tree.tokens.items(.tag);
2485 const node_tags = tree.nodes.items(.tag);2484 const node_tags = tree.nodes.items(.tag);
2485 const node_datas = tree.nodes.items(.data);
24862486
2487 // We must not create any types until Sema. Here the goal is only to generate2487 // We must not create any types until Sema. Here the goal is only to generate
2488 // ZIR for all the field types, alignments, and default value expressions.2488 // ZIR for all the field types, alignments, and default value expressions.
...@@ -2594,22 +2594,12 @@ fn containerDecl(...@@ -2594,22 +2594,12 @@ fn containerDecl(
2594 },2594 },
2595 );2595 );
2596 }2596 }
2597 if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {
2598 return astgen.failNode(node, "TODO AstGen simple enums", .{});
2599 }
2600 // In this case we must generate ZIR code for the tag values, similar to2597 // In this case we must generate ZIR code for the tag values, similar to
2601 // how structs are handled above.2598 // how structs are handled above.
2602 const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)2599 const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)
2603 .enum_decl2600 .enum_decl
2604 else2601 else
2605 .enum_decl_nonexhaustive;2602 .enum_decl_nonexhaustive;
2606 if (counts.total_fields == 0) {
2607 return gz.addPlNode(tag, node, Zir.Inst.EnumDecl{
2608 .tag_type = arg_inst,
2609 .fields_len = 0,
2610 .body_len = 0,
2611 });
2612 }
26132603
2614 // The enum_decl instruction introduces a scope in which the decls of the enum2604 // The enum_decl instruction introduces a scope in which the decls of the enum
2615 // are in scope, so that tag values can refer to decls within the enum itself.2605 // are in scope, so that tag values can refer to decls within the enum itself.
...@@ -2621,6 +2611,9 @@ fn containerDecl(...@@ -2621,6 +2611,9 @@ fn containerDecl(
2621 };2611 };
2622 defer block_scope.instructions.deinit(gpa);2612 defer block_scope.instructions.deinit(gpa);
26232613
2614 var wip_decls: WipDecls = .{};
2615 defer wip_decls.deinit(gpa);
2616
2624 var fields_data = ArrayListUnmanaged(u32){};2617 var fields_data = ArrayListUnmanaged(u32){};
2625 defer fields_data.deinit(gpa);2618 defer fields_data.deinit(gpa);
26262619
...@@ -2639,7 +2632,81 @@ fn containerDecl(...@@ -2639,7 +2632,81 @@ fn containerDecl(
2639 .container_field_init => tree.containerFieldInit(member_node),2632 .container_field_init => tree.containerFieldInit(member_node),
2640 .container_field_align => tree.containerFieldAlign(member_node),2633 .container_field_align => tree.containerFieldAlign(member_node),
2641 .container_field => tree.containerField(member_node),2634 .container_field => tree.containerField(member_node),
2642 else => continue,2635
2636 .fn_decl => {
2637 const fn_proto = node_datas[member_node].lhs;
2638 const body = node_datas[member_node].rhs;
2639 switch (node_tags[fn_proto]) {
2640 .fn_proto_simple => {
2641 var params: [1]ast.Node.Index = undefined;
2642 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoSimple(&params, fn_proto));
2643 continue;
2644 },
2645 .fn_proto_multi => {
2646 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoMulti(fn_proto));
2647 continue;
2648 },
2649 .fn_proto_one => {
2650 var params: [1]ast.Node.Index = undefined;
2651 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoOne(&params, fn_proto));
2652 continue;
2653 },
2654 .fn_proto => {
2655 try astgen.fnDecl(gz, &wip_decls, body, tree.fnProto(fn_proto));
2656 continue;
2657 },
2658 else => unreachable,
2659 }
2660 },
2661 .fn_proto_simple => {
2662 var params: [1]ast.Node.Index = undefined;
2663 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoSimple(&params, member_node));
2664 continue;
2665 },
2666 .fn_proto_multi => {
2667 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoMulti(member_node));
2668 continue;
2669 },
2670 .fn_proto_one => {
2671 var params: [1]ast.Node.Index = undefined;
2672 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoOne(&params, member_node));
2673 continue;
2674 },
2675 .fn_proto => {
2676 try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProto(member_node));
2677 continue;
2678 },
2679
2680 .global_var_decl => {
2681 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
2682 continue;
2683 },
2684 .local_var_decl => {
2685 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
2686 continue;
2687 },
2688 .simple_var_decl => {
2689 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
2690 continue;
2691 },
2692 .aligned_var_decl => {
2693 try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
2694 continue;
2695 },
2696
2697 .@"comptime" => {
2698 try astgen.comptimeDecl(gz, scope, member_node);
2699 continue;
2700 },
2701 .@"usingnamespace" => {
2702 try astgen.usingnamespaceDecl(gz, scope, member_node);
2703 continue;
2704 },
2705 .test_decl => {
2706 try astgen.testDecl(gz, scope, member_node);
2707 continue;
2708 },
2709 else => unreachable,
2643 };2710 };
2644 if (field_index % 32 == 0 and field_index != 0) {2711 if (field_index % 32 == 0 and field_index != 0) {
2645 try bit_bag.append(gpa, cur_bit_bag);2712 try bit_bag.append(gpa, cur_bit_bag);
...@@ -2663,27 +2730,45 @@ fn containerDecl(...@@ -2663,27 +2730,45 @@ fn containerDecl(
26632730
2664 field_index += 1;2731 field_index += 1;
2665 }2732 }
2666 const empty_slot_count = 32 - (field_index % 32);2733 {
2667 cur_bit_bag >>= @intCast(u5, empty_slot_count);2734 const empty_slot_count = 32 - (field_index % 32);
2735 cur_bit_bag >>= @intCast(u5, empty_slot_count);
2736 }
2737
2738 if (wip_decls.decl_index != 0) {
2739 const empty_slot_count = 16 - (wip_decls.decl_index % 16);
2740 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
2741 }
26682742
2669 const decl_inst = try gz.addBlock(tag, node);2743 const decl_inst = try gz.addBlock(tag, node);
2670 try gz.instructions.append(gpa, decl_inst);2744 try gz.instructions.append(gpa, decl_inst);
2671 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);2745 if (block_scope.instructions.items.len != 0) {
2746 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
2747 }
26722748
2673 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +2749 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
2674 @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
2675 bit_bag.items.len + 1 + fields_data.items.len +2750 bit_bag.items.len + 1 + fields_data.items.len +
2676 block_scope.instructions.items.len);2751 block_scope.instructions.items.len +
2752 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
2753 wip_decls.name_and_value.items.len);
2677 const zir_datas = astgen.instructions.items(.data);2754 const zir_datas = astgen.instructions.items(.data);
2678 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{2755 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
2679 .tag_type = arg_inst,2756 .tag_type = arg_inst,
2680 .body_len = @intCast(u32, block_scope.instructions.items.len),2757 .body_len = @intCast(u32, block_scope.instructions.items.len),
2681 .fields_len = @intCast(u32, field_index),2758 .fields_len = @intCast(u32, field_index),
2759 .decls_len = @intCast(u32, wip_decls.decl_index),
2682 });2760 });
2683 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);2761 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
2684 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.2762 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
2685 astgen.extra.appendAssumeCapacity(cur_bit_bag);2763 astgen.extra.appendAssumeCapacity(cur_bit_bag);
2686 astgen.extra.appendSliceAssumeCapacity(fields_data.items);2764 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
2765
2766 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
2767 if (wip_decls.decl_index != 0) {
2768 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
2769 }
2770 astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
2771
2687 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);2772 return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
2688 },2773 },
2689 .keyword_opaque => {2774 .keyword_opaque => {
src/Zir.zig+57-37
...@@ -1591,11 +1591,20 @@ pub const Inst = struct {...@@ -1591,11 +1591,20 @@ pub const Inst = struct {
1591 /// field_name: u32,1591 /// field_name: u32,
1592 /// value: Ref, // if corresponding bit is set1592 /// value: Ref, // if corresponding bit is set
1593 /// }1593 /// }
1594 /// 3. decl_bits: u32 // for every 16 decls
1595 /// - sets of 2 bits:
1596 /// 0b0X: whether corresponding decl is pub
1597 /// 0bX0: whether corresponding decl is exported
1598 /// 4. decl: { // for every decls_len
1599 /// name: u32, // null terminated string index
1600 /// value: Index,
1601 /// }
1594 pub const EnumDecl = struct {1602 pub const EnumDecl = struct {
1595 /// Can be `Ref.none`.1603 /// Can be `Ref.none`.
1596 tag_type: Ref,1604 tag_type: Ref,
1597 body_len: u32,1605 body_len: u32,
1598 fields_len: u32,1606 fields_len: u32,
1607 decls_len: u32,
1599 };1608 };
16001609
1601 /// Trailing:1610 /// Trailing:
...@@ -2231,6 +2240,7 @@ const Writer = struct {...@@ -2231,6 +2240,7 @@ const Writer = struct {
2231 const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);2240 const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);
2232 const body = self.code.extra[extra.end..][0..extra.data.body_len];2241 const body = self.code.extra[extra.end..][0..extra.data.body_len];
2233 const fields_len = extra.data.fields_len;2242 const fields_len = extra.data.fields_len;
2243 const decls_len = extra.data.decls_len;
2234 const tag_ty_ref = extra.data.tag_type;2244 const tag_ty_ref = extra.data.tag_type;
22352245
2236 if (tag_ty_ref != .none) {2246 if (tag_ty_ref != .none) {
...@@ -2238,53 +2248,63 @@ const Writer = struct {...@@ -2238,53 +2248,63 @@ const Writer = struct {
2238 try stream.writeAll(", ");2248 try stream.writeAll(", ");
2239 }2249 }
22402250
2251 var extra_index: usize = undefined;
2252
2241 if (fields_len == 0) {2253 if (fields_len == 0) {
2242 assert(body.len == 0);2254 assert(body.len == 0);
2243 try stream.writeAll("{}, {}) ");2255 try stream.writeAll("{}, {}, {");
2244 try self.writeSrc(stream, inst_data.src());2256 extra_index = extra.end;
2245 return;2257 } else {
2246 }2258 try stream.writeAll("{\n");
22472259 self.indent += 2;
2248 try stream.writeAll("{\n");2260 try self.writeBody(stream, body);
2249 self.indent += 2;
2250 try self.writeBody(stream, body);
22512261
2252 try stream.writeByteNTimes(' ', self.indent - 2);2262 try stream.writeByteNTimes(' ', self.indent - 2);
2253 try stream.writeAll("}, {\n");2263 try stream.writeAll("}, {\n");
22542264
2255 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;2265 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
2256 const body_end = extra.end + body.len;2266 const body_end = extra.end + body.len;
2257 var extra_index: usize = body_end + bit_bags_count;2267 extra_index = body_end + bit_bags_count;
2258 var bit_bag_index: usize = body_end;2268 var bit_bag_index: usize = body_end;
2259 var cur_bit_bag: u32 = undefined;2269 var cur_bit_bag: u32 = undefined;
2260 var field_i: u32 = 0;2270 var field_i: u32 = 0;
2261 while (field_i < fields_len) : (field_i += 1) {2271 while (field_i < fields_len) : (field_i += 1) {
2262 if (field_i % 32 == 0) {2272 if (field_i % 32 == 0) {
2263 cur_bit_bag = self.code.extra[bit_bag_index];2273 cur_bit_bag = self.code.extra[bit_bag_index];
2264 bit_bag_index += 1;2274 bit_bag_index += 1;
2265 }2275 }
2266 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;2276 const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
2267 cur_bit_bag >>= 1;2277 cur_bit_bag >>= 1;
22682278
2269 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);2279 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
2270 extra_index += 1;2280 extra_index += 1;
22712281
2272 try stream.writeByteNTimes(' ', self.indent);2282 try stream.writeByteNTimes(' ', self.indent);
2273 try stream.print("{}", .{std.zig.fmtId(field_name)});2283 try stream.print("{}", .{std.zig.fmtId(field_name)});
22742284
2275 if (has_tag_value) {2285 if (has_tag_value) {
2276 const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);2286 const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
2277 extra_index += 1;2287 extra_index += 1;
22782288
2279 try stream.writeAll(" = ");2289 try stream.writeAll(" = ");
2280 try self.writeInstRef(stream, tag_value_ref);2290 try self.writeInstRef(stream, tag_value_ref);
2291 }
2292 try stream.writeAll(",\n");
2281 }2293 }
2282 try stream.writeAll(",\n");2294 self.indent -= 2;
2295 try stream.writeByteNTimes(' ', self.indent);
2296 try stream.writeAll("}, {");
2297 }
2298 if (decls_len == 0) {
2299 try stream.writeAll("}) ");
2300 } else {
2301 try stream.writeAll("\n");
2302 self.indent += 2;
2303 try self.writeDecls(stream, decls_len, extra_index);
2304 self.indent -= 2;
2305 try stream.writeByteNTimes(' ', self.indent);
2306 try stream.writeAll("}) ");
2283 }2307 }
2284
2285 self.indent -= 2;
2286 try stream.writeByteNTimes(' ', self.indent);
2287 try stream.writeAll("}) ");
2288 try self.writeSrc(stream, inst_data.src());2308 try self.writeSrc(stream, inst_data.src());
2289 }2309 }
22902310