authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 19:27:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 19:27:17-07:00
logc66b48194ff83eb5b1774a1428461f5fc94dcd7d
treec8788e07cf7aca0dc7147d5b40a060e984bcfbd1
parent09000c3f77a85b1b1bf0e19b09aae7deaf9f1faa

stage2: AstGen and ZIR printing for struct decls


4 files changed, 365 insertions(+), 12 deletions(-)

src/AstGen.zig+130-9
...@@ -719,25 +719,25 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -719,25 +719,25 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
719719
720 .container_decl,720 .container_decl,
721 .container_decl_trailing,721 .container_decl_trailing,
722 => return containerDecl(gz, scope, rl, tree.containerDecl(node)),722 => return containerDecl(gz, scope, rl, node, tree.containerDecl(node)),
723 .container_decl_two, .container_decl_two_trailing => {723 .container_decl_two, .container_decl_two_trailing => {
724 var buffer: [2]ast.Node.Index = undefined;724 var buffer: [2]ast.Node.Index = undefined;
725 return containerDecl(gz, scope, rl, tree.containerDeclTwo(&buffer, node));725 return containerDecl(gz, scope, rl, node, tree.containerDeclTwo(&buffer, node));
726 },726 },
727 .container_decl_arg,727 .container_decl_arg,
728 .container_decl_arg_trailing,728 .container_decl_arg_trailing,
729 => return containerDecl(gz, scope, rl, tree.containerDeclArg(node)),729 => return containerDecl(gz, scope, rl, node, tree.containerDeclArg(node)),
730730
731 .tagged_union,731 .tagged_union,
732 .tagged_union_trailing,732 .tagged_union_trailing,
733 => return containerDecl(gz, scope, rl, tree.taggedUnion(node)),733 => return containerDecl(gz, scope, rl, node, tree.taggedUnion(node)),
734 .tagged_union_two, .tagged_union_two_trailing => {734 .tagged_union_two, .tagged_union_two_trailing => {
735 var buffer: [2]ast.Node.Index = undefined;735 var buffer: [2]ast.Node.Index = undefined;
736 return containerDecl(gz, scope, rl, tree.taggedUnionTwo(&buffer, node));736 return containerDecl(gz, scope, rl, node, tree.taggedUnionTwo(&buffer, node));
737 },737 },
738 .tagged_union_enum_tag,738 .tagged_union_enum_tag,
739 .tagged_union_enum_tag_trailing,739 .tagged_union_enum_tag_trailing,
740 => return containerDecl(gz, scope, rl, tree.taggedUnionEnumTag(node)),740 => return containerDecl(gz, scope, rl, node, tree.taggedUnionEnumTag(node)),
741741
742 .@"break" => return breakExpr(gz, scope, node),742 .@"break" => return breakExpr(gz, scope, node),
743 .@"continue" => return continueExpr(gz, scope, node),743 .@"continue" => return continueExpr(gz, scope, node),
...@@ -804,6 +804,16 @@ pub fn structInitExpr(...@@ -804,6 +804,16 @@ pub fn structInitExpr(
804 const astgen = gz.astgen;804 const astgen = gz.astgen;
805 const mod = astgen.mod;805 const mod = astgen.mod;
806 const gpa = mod.gpa;806 const gpa = mod.gpa;
807
808 if (struct_init.ast.fields.len == 0) {
809 if (struct_init.ast.type_expr == 0) {
810 return rvalue(gz, scope, rl, .empty_struct, node);
811 } else {
812 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
813 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
814 return rvalue(gz, scope, rl, result, node);
815 }
816 }
807 switch (rl) {817 switch (rl) {
808 .discard => return mod.failNode(scope, node, "TODO implement structInitExpr discard", .{}),818 .discard => return mod.failNode(scope, node, "TODO implement structInitExpr discard", .{}),
809 .none => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}),819 .none => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}),
...@@ -1310,6 +1320,11 @@ fn blockExprStmts(...@@ -1310,6 +1320,11 @@ fn blockExprStmts(
1310 .switch_capture_multi_ref,1320 .switch_capture_multi_ref,
1311 .switch_capture_else,1321 .switch_capture_else,
1312 .switch_capture_else_ref,1322 .switch_capture_else_ref,
1323 .struct_init_empty,
1324 .struct_decl,
1325 .union_decl,
1326 .enum_decl,
1327 .opaque_decl,
1313 => break :b false,1328 => break :b false,
13141329
1315 // ZIR instructions that are always either `noreturn` or `void`.1330 // ZIR instructions that are always either `noreturn` or `void`.
...@@ -1754,9 +1769,115 @@ fn containerDecl(...@@ -1754,9 +1769,115 @@ fn containerDecl(
1754 gz: *GenZir,1769 gz: *GenZir,
1755 scope: *Scope,1770 scope: *Scope,
1756 rl: ResultLoc,1771 rl: ResultLoc,
1772 node: ast.Node.Index,
1757 container_decl: ast.full.ContainerDecl,1773 container_decl: ast.full.ContainerDecl,
1758) InnerError!zir.Inst.Ref {1774) InnerError!zir.Inst.Ref {
1759 return gz.astgen.mod.failTok(scope, container_decl.ast.main_token, "TODO implement container decls", .{});1775 const astgen = gz.astgen;
1776 const mod = astgen.mod;
1777 const gpa = mod.gpa;
1778 const tree = gz.tree();
1779 const token_tags = tree.tokens.items(.tag);
1780 const node_tags = tree.nodes.items(.tag);
1781
1782 // We must not create any types until Sema. Here the goal is only to generate
1783 // ZIR for all the field types, alignments, and default value expressions.
1784
1785 const arg_inst: zir.Inst.Ref = if (container_decl.ast.arg != 0)
1786 try comptimeExpr(gz, scope, .none, container_decl.ast.arg)
1787 else
1788 .none;
1789
1790 switch (token_tags[container_decl.ast.main_token]) {
1791 .keyword_struct => {
1792 if (container_decl.ast.members.len == 0) {
1793 const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
1794 .fields_len = 0,
1795 });
1796 return rvalue(gz, scope, rl, result, node);
1797 }
1798
1799 assert(arg_inst == .none);
1800 var fields_data = ArrayListUnmanaged(u32){};
1801 defer fields_data.deinit(gpa);
1802
1803 // field_name and field_type are both mandatory
1804 try fields_data.ensureCapacity(gpa, container_decl.ast.members.len * 2);
1805
1806 // We only need this if there are greater than 16 fields.
1807 var bit_bag = ArrayListUnmanaged(u32){};
1808 defer bit_bag.deinit(gpa);
1809
1810 var cur_bit_bag: u32 = 0;
1811 var member_index: usize = 0;
1812 while (true) {
1813 const member_node = container_decl.ast.members[member_index];
1814 const member = switch (node_tags[member_node]) {
1815 .container_field_init => tree.containerFieldInit(member_node),
1816 .container_field_align => tree.containerFieldAlign(member_node),
1817 .container_field => tree.containerField(member_node),
1818 else => unreachable,
1819 };
1820 if (member.comptime_token) |comptime_token| {
1821 return mod.failTok(scope, comptime_token, "TODO implement comptime struct fields", .{});
1822 }
1823 try fields_data.ensureCapacity(gpa, fields_data.items.len + 4);
1824
1825 const field_name = try gz.identAsString(member.ast.name_token);
1826 fields_data.appendAssumeCapacity(field_name);
1827
1828 const field_type = try typeExpr(gz, scope, member.ast.type_expr);
1829 fields_data.appendAssumeCapacity(@enumToInt(field_type));
1830
1831 const have_align = member.ast.align_expr != 0;
1832 const have_value = member.ast.value_expr != 0;
1833 cur_bit_bag = (cur_bit_bag >> 2) |
1834 (@as(u32, @boolToInt(have_align)) << 30) |
1835 (@as(u32, @boolToInt(have_value)) << 31);
1836
1837 if (have_align) {
1838 const align_inst = try comptimeExpr(gz, scope, .{ .ty = .u32_type }, member.ast.align_expr);
1839 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
1840 }
1841 if (have_value) {
1842 const default_inst = try comptimeExpr(gz, scope, .{ .ty = field_type }, member.ast.value_expr);
1843 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
1844 }
1845
1846 member_index += 1;
1847 if (member_index < container_decl.ast.members.len) {
1848 if (member_index % 16 == 0) {
1849 try bit_bag.append(gpa, cur_bit_bag);
1850 cur_bit_bag = 0;
1851 }
1852 } else {
1853 break;
1854 }
1855 }
1856 const empty_slot_count = 16 - ((member_index - 1) % 16);
1857 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
1858
1859 const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
1860 .fields_len = @intCast(u32, container_decl.ast.members.len),
1861 });
1862 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
1863 bit_bag.items.len + 1 + fields_data.items.len);
1864 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
1865 astgen.extra.appendAssumeCapacity(cur_bit_bag);
1866 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
1867 return rvalue(gz, scope, rl, result, node);
1868 },
1869 .keyword_union => {
1870 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for union decl", .{});
1871 },
1872 .keyword_enum => {
1873 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for enum decl", .{});
1874 },
1875 .keyword_opaque => {
1876 const result = try gz.addNode(.opaque_decl, node);
1877 return rvalue(gz, scope, rl, result, node);
1878 },
1879 else => unreachable,
1880 }
1760}1881}
17611882
1762fn errorSetDecl(1883fn errorSetDecl(
...@@ -2809,10 +2930,10 @@ fn switchExpr(...@@ -2809,10 +2930,10 @@ fn switchExpr(
2809 // This is the header as well as the optional else prong body, as well as all the2930 // This is the header as well as the optional else prong body, as well as all the
2810 // scalar cases.2931 // scalar cases.
2811 // At the end we will memcpy this into place.2932 // At the end we will memcpy this into place.
2812 var scalar_cases_payload = std.ArrayListUnmanaged(u32){};2933 var scalar_cases_payload = ArrayListUnmanaged(u32){};
2813 defer scalar_cases_payload.deinit(gpa);2934 defer scalar_cases_payload.deinit(gpa);
2814 // Same deal, but this is only the `extra` data for the multi cases.2935 // Same deal, but this is only the `extra` data for the multi cases.
2815 var multi_cases_payload = std.ArrayListUnmanaged(u32){};2936 var multi_cases_payload = ArrayListUnmanaged(u32){};
2816 defer multi_cases_payload.deinit(gpa);2937 defer multi_cases_payload.deinit(gpa);
28172938
2818 var block_scope: GenZir = .{2939 var block_scope: GenZir = .{
src/Sema.zig+70
...@@ -259,6 +259,12 @@ pub fn analyzeBody(...@@ -259,6 +259,12 @@ pub fn analyzeBody(
259 .typeof_elem => try sema.zirTypeofElem(block, inst),259 .typeof_elem => try sema.zirTypeofElem(block, inst),
260 .typeof_peer => try sema.zirTypeofPeer(block, inst),260 .typeof_peer => try sema.zirTypeofPeer(block, inst),
261 .xor => try sema.zirBitwise(block, inst, .xor),261 .xor => try sema.zirBitwise(block, inst, .xor),
262 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
263
264 .struct_decl => try sema.zirStructDecl(block, inst),
265 .enum_decl => try sema.zirEnumDecl(block, inst),
266 .union_decl => try sema.zirUnionDecl(block, inst),
267 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
262268
263 // Instructions that we know to *always* be noreturn based solely on their tag.269 // Instructions that we know to *always* be noreturn based solely on their tag.
264 // These functions match the return type of analyzeBody so that we can270 // These functions match the return type of analyzeBody so that we can
...@@ -514,6 +520,56 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In...@@ -514,6 +520,56 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
514 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});520 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
515}521}
516522
523fn zirStructDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
524 const tracy = trace(@src());
525 defer tracy.end();
526
527 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
528 const src = inst_data.src();
529 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
530
531 return sema.mod.fail(&block.base, sema.src, "TODO implement zirStructDecl", .{});
532
533 //const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
534 // .ty = decl_ty,
535 // .val = decl_val,
536 //});
537 //return sema.analyzeDeclVal(block, src, new_decl);
538}
539
540fn zirEnumDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
541 const tracy = trace(@src());
542 defer tracy.end();
543
544 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
545 const src = inst_data.src();
546 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
547
548 return sema.mod.fail(&block.base, sema.src, "TODO implement zirEnumDecl", .{});
549}
550
551fn zirUnionDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
552 const tracy = trace(@src());
553 defer tracy.end();
554
555 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
556 const src = inst_data.src();
557 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
558
559 return sema.mod.fail(&block.base, sema.src, "TODO implement zirUnionDecl", .{});
560}
561
562fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
563 const tracy = trace(@src());
564 defer tracy.end();
565
566 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
567 const src = inst_data.src();
568 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
569
570 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
571}
572
517fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {573fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
518 const tracy = trace(@src());574 const tracy = trace(@src());
519 defer tracy.end();575 defer tracy.end();
...@@ -3867,6 +3923,20 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -3867,6 +3923,20 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
3867 return sema.mod.constType(sema.arena, src, ty);3923 return sema.mod.constType(sema.arena, src, ty);
3868}3924}
38693925
3926fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
3927 const tracy = trace(@src());
3928 defer tracy.end();
3929
3930 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3931 const src = inst_data.src();
3932 const struct_type = try sema.resolveType(block, src, inst_data.operand);
3933
3934 return sema.mod.constInst(sema.arena, src, .{
3935 .ty = struct_type,
3936 .val = Value.initTag(.empty_struct_value),
3937 });
3938}
3939
3870fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {3940fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
3871 if (sema.func == null) {3941 if (sema.func == null) {
3872 return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{});3942 return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{});
src/type.zig+32-3
...@@ -93,6 +93,7 @@ pub const Type = extern union {...@@ -93,6 +93,7 @@ pub const Type = extern union {
93 .anyerror_void_error_union, .error_union => return .ErrorUnion,93 .anyerror_void_error_union, .error_union => return .ErrorUnion,
9494
95 .empty_struct => return .Struct,95 .empty_struct => return .Struct,
96 .empty_struct_literal => return .Struct,
9697
97 .var_args_param => unreachable, // can be any type98 .var_args_param => unreachable, // can be any type
98 }99 }
...@@ -530,6 +531,7 @@ pub const Type = extern union {...@@ -530,6 +531,7 @@ pub const Type = extern union {
530 .inferred_alloc_const,531 .inferred_alloc_const,
531 .inferred_alloc_mut,532 .inferred_alloc_mut,
532 .var_args_param,533 .var_args_param,
534 .empty_struct_literal,
533 => unreachable,535 => unreachable,
534536
535 .array_u8,537 .array_u8,
...@@ -672,8 +674,7 @@ pub const Type = extern union {...@@ -672,8 +674,7 @@ pub const Type = extern union {
672 .@"null" => return out_stream.writeAll("@Type(.Null)"),674 .@"null" => return out_stream.writeAll("@Type(.Null)"),
673 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),675 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),
674676
675 // TODO this should print the structs name677 .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"),
676 .empty_struct => return out_stream.writeAll("struct {}"),
677 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),678 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
678 .const_slice_u8 => return out_stream.writeAll("[]const u8"),679 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
679 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),680 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
...@@ -960,6 +961,7 @@ pub const Type = extern union {...@@ -960,6 +961,7 @@ pub const Type = extern union {
960 .@"undefined",961 .@"undefined",
961 .enum_literal,962 .enum_literal,
962 .empty_struct,963 .empty_struct,
964 .empty_struct_literal,
963 .@"opaque",965 .@"opaque",
964 => false,966 => false,
965967
...@@ -1108,6 +1110,7 @@ pub const Type = extern union {...@@ -1108,6 +1110,7 @@ pub const Type = extern union {
1108 .@"undefined",1110 .@"undefined",
1109 .enum_literal,1111 .enum_literal,
1110 .empty_struct,1112 .empty_struct,
1113 .empty_struct_literal,
1111 .inferred_alloc_const,1114 .inferred_alloc_const,
1112 .inferred_alloc_mut,1115 .inferred_alloc_mut,
1113 .@"opaque",1116 .@"opaque",
...@@ -1135,6 +1138,7 @@ pub const Type = extern union {...@@ -1135,6 +1138,7 @@ pub const Type = extern union {
1135 .enum_literal => unreachable,1138 .enum_literal => unreachable,
1136 .single_const_pointer_to_comptime_int => unreachable,1139 .single_const_pointer_to_comptime_int => unreachable,
1137 .empty_struct => unreachable,1140 .empty_struct => unreachable,
1141 .empty_struct_literal => unreachable,
1138 .inferred_alloc_const => unreachable,1142 .inferred_alloc_const => unreachable,
1139 .inferred_alloc_mut => unreachable,1143 .inferred_alloc_mut => unreachable,
1140 .@"opaque" => unreachable,1144 .@"opaque" => unreachable,
...@@ -1313,6 +1317,7 @@ pub const Type = extern union {...@@ -1313,6 +1317,7 @@ pub const Type = extern union {
1313 .error_set,1317 .error_set,
1314 .error_set_single,1318 .error_set_single,
1315 .empty_struct,1319 .empty_struct,
1320 .empty_struct_literal,
1316 .@"opaque",1321 .@"opaque",
1317 .var_args_param,1322 .var_args_param,
1318 => false,1323 => false,
...@@ -1386,6 +1391,7 @@ pub const Type = extern union {...@@ -1386,6 +1391,7 @@ pub const Type = extern union {
1386 .error_set,1391 .error_set,
1387 .error_set_single,1392 .error_set_single,
1388 .empty_struct,1393 .empty_struct,
1394 .empty_struct_literal,
1389 .@"opaque",1395 .@"opaque",
1390 .var_args_param,1396 .var_args_param,
1391 => unreachable,1397 => unreachable,
...@@ -1478,6 +1484,7 @@ pub const Type = extern union {...@@ -1478,6 +1484,7 @@ pub const Type = extern union {
1478 .error_set,1484 .error_set,
1479 .error_set_single,1485 .error_set_single,
1480 .empty_struct,1486 .empty_struct,
1487 .empty_struct_literal,
1481 .inferred_alloc_const,1488 .inferred_alloc_const,
1482 .inferred_alloc_mut,1489 .inferred_alloc_mut,
1483 .@"opaque",1490 .@"opaque",
...@@ -1554,6 +1561,7 @@ pub const Type = extern union {...@@ -1554,6 +1561,7 @@ pub const Type = extern union {
1554 .error_set,1561 .error_set,
1555 .error_set_single,1562 .error_set_single,
1556 .empty_struct,1563 .empty_struct,
1564 .empty_struct_literal,
1557 .inferred_alloc_const,1565 .inferred_alloc_const,
1558 .inferred_alloc_mut,1566 .inferred_alloc_mut,
1559 .@"opaque",1567 .@"opaque",
...@@ -1639,6 +1647,7 @@ pub const Type = extern union {...@@ -1639,6 +1647,7 @@ pub const Type = extern union {
1639 .error_set,1647 .error_set,
1640 .error_set_single,1648 .error_set_single,
1641 .empty_struct,1649 .empty_struct,
1650 .empty_struct_literal,
1642 .inferred_alloc_const,1651 .inferred_alloc_const,
1643 .inferred_alloc_mut,1652 .inferred_alloc_mut,
1644 .@"opaque",1653 .@"opaque",
...@@ -1719,6 +1728,7 @@ pub const Type = extern union {...@@ -1719,6 +1728,7 @@ pub const Type = extern union {
1719 .error_set,1728 .error_set,
1720 .error_set_single,1729 .error_set_single,
1721 .empty_struct,1730 .empty_struct,
1731 .empty_struct_literal,
1722 .inferred_alloc_const,1732 .inferred_alloc_const,
1723 .inferred_alloc_mut,1733 .inferred_alloc_mut,
1724 .@"opaque",1734 .@"opaque",
...@@ -1841,6 +1851,7 @@ pub const Type = extern union {...@@ -1841,6 +1851,7 @@ pub const Type = extern union {
1841 .error_set => unreachable,1851 .error_set => unreachable,
1842 .error_set_single => unreachable,1852 .error_set_single => unreachable,
1843 .empty_struct => unreachable,1853 .empty_struct => unreachable,
1854 .empty_struct_literal => unreachable,
1844 .inferred_alloc_const => unreachable,1855 .inferred_alloc_const => unreachable,
1845 .inferred_alloc_mut => unreachable,1856 .inferred_alloc_mut => unreachable,
1846 .@"opaque" => unreachable,1857 .@"opaque" => unreachable,
...@@ -1989,6 +2000,7 @@ pub const Type = extern union {...@@ -1989,6 +2000,7 @@ pub const Type = extern union {
1989 .error_set,2000 .error_set,
1990 .error_set_single,2001 .error_set_single,
1991 .empty_struct,2002 .empty_struct,
2003 .empty_struct_literal,
1992 .inferred_alloc_const,2004 .inferred_alloc_const,
1993 .inferred_alloc_mut,2005 .inferred_alloc_mut,
1994 .@"opaque",2006 .@"opaque",
...@@ -2059,6 +2071,7 @@ pub const Type = extern union {...@@ -2059,6 +2071,7 @@ pub const Type = extern union {
2059 .error_set,2071 .error_set,
2060 .error_set_single,2072 .error_set_single,
2061 .empty_struct,2073 .empty_struct,
2074 .empty_struct_literal,
2062 .inferred_alloc_const,2075 .inferred_alloc_const,
2063 .inferred_alloc_mut,2076 .inferred_alloc_mut,
2064 .@"opaque",2077 .@"opaque",
...@@ -2144,6 +2157,7 @@ pub const Type = extern union {...@@ -2144,6 +2157,7 @@ pub const Type = extern union {
2144 .error_set,2157 .error_set,
2145 .error_set_single,2158 .error_set_single,
2146 .empty_struct,2159 .empty_struct,
2160 .empty_struct_literal,
2147 .inferred_alloc_const,2161 .inferred_alloc_const,
2148 .inferred_alloc_mut,2162 .inferred_alloc_mut,
2149 .@"opaque",2163 .@"opaque",
...@@ -2225,6 +2239,7 @@ pub const Type = extern union {...@@ -2225,6 +2239,7 @@ pub const Type = extern union {
2225 .error_set,2239 .error_set,
2226 .error_set_single,2240 .error_set_single,
2227 .empty_struct,2241 .empty_struct,
2242 .empty_struct_literal,
2228 .inferred_alloc_const,2243 .inferred_alloc_const,
2229 .inferred_alloc_mut,2244 .inferred_alloc_mut,
2230 .@"opaque",2245 .@"opaque",
...@@ -2292,6 +2307,7 @@ pub const Type = extern union {...@@ -2292,6 +2307,7 @@ pub const Type = extern union {
2292 .error_set,2307 .error_set,
2293 .error_set_single,2308 .error_set_single,
2294 .empty_struct,2309 .empty_struct,
2310 .empty_struct_literal,
2295 .inferred_alloc_const,2311 .inferred_alloc_const,
2296 .inferred_alloc_mut,2312 .inferred_alloc_mut,
2297 .@"opaque",2313 .@"opaque",
...@@ -2387,6 +2403,7 @@ pub const Type = extern union {...@@ -2387,6 +2403,7 @@ pub const Type = extern union {
2387 .error_set,2403 .error_set,
2388 .error_set_single,2404 .error_set_single,
2389 .empty_struct,2405 .empty_struct,
2406 .empty_struct_literal,
2390 .inferred_alloc_const,2407 .inferred_alloc_const,
2391 .inferred_alloc_mut,2408 .inferred_alloc_mut,
2392 .@"opaque",2409 .@"opaque",
...@@ -2503,6 +2520,7 @@ pub const Type = extern union {...@@ -2503,6 +2520,7 @@ pub const Type = extern union {
2503 .error_set,2520 .error_set,
2504 .error_set_single,2521 .error_set_single,
2505 .empty_struct,2522 .empty_struct,
2523 .empty_struct_literal,
2506 .inferred_alloc_const,2524 .inferred_alloc_const,
2507 .inferred_alloc_mut,2525 .inferred_alloc_mut,
2508 .@"opaque",2526 .@"opaque",
...@@ -2585,6 +2603,7 @@ pub const Type = extern union {...@@ -2585,6 +2603,7 @@ pub const Type = extern union {
2585 .error_set,2603 .error_set,
2586 .error_set_single,2604 .error_set_single,
2587 .empty_struct,2605 .empty_struct,
2606 .empty_struct_literal,
2588 .inferred_alloc_const,2607 .inferred_alloc_const,
2589 .inferred_alloc_mut,2608 .inferred_alloc_mut,
2590 .@"opaque",2609 .@"opaque",
...@@ -2666,6 +2685,7 @@ pub const Type = extern union {...@@ -2666,6 +2685,7 @@ pub const Type = extern union {
2666 .error_set,2685 .error_set,
2667 .error_set_single,2686 .error_set_single,
2668 .empty_struct,2687 .empty_struct,
2688 .empty_struct_literal,
2669 .inferred_alloc_const,2689 .inferred_alloc_const,
2670 .inferred_alloc_mut,2690 .inferred_alloc_mut,
2671 .@"opaque",2691 .@"opaque",
...@@ -2747,6 +2767,7 @@ pub const Type = extern union {...@@ -2747,6 +2767,7 @@ pub const Type = extern union {
2747 .error_set,2767 .error_set,
2748 .error_set_single,2768 .error_set_single,
2749 .empty_struct,2769 .empty_struct,
2770 .empty_struct_literal,
2750 .inferred_alloc_const,2771 .inferred_alloc_const,
2751 .inferred_alloc_mut,2772 .inferred_alloc_mut,
2752 .@"opaque",2773 .@"opaque",
...@@ -2825,6 +2846,7 @@ pub const Type = extern union {...@@ -2825,6 +2846,7 @@ pub const Type = extern union {
2825 .error_set,2846 .error_set,
2826 .error_set_single,2847 .error_set_single,
2827 .empty_struct,2848 .empty_struct,
2849 .empty_struct_literal,
2828 .inferred_alloc_const,2850 .inferred_alloc_const,
2829 .inferred_alloc_mut,2851 .inferred_alloc_mut,
2830 .@"opaque",2852 .@"opaque",
...@@ -2903,6 +2925,7 @@ pub const Type = extern union {...@@ -2903,6 +2925,7 @@ pub const Type = extern union {
2903 .error_set,2925 .error_set,
2904 .error_set_single,2926 .error_set_single,
2905 .empty_struct,2927 .empty_struct,
2928 .empty_struct_literal,
2906 .inferred_alloc_const,2929 .inferred_alloc_const,
2907 .inferred_alloc_mut,2930 .inferred_alloc_mut,
2908 .@"opaque",2931 .@"opaque",
...@@ -2981,6 +3004,7 @@ pub const Type = extern union {...@@ -2981,6 +3004,7 @@ pub const Type = extern union {
2981 .error_set,3004 .error_set,
2982 .error_set_single,3005 .error_set_single,
2983 .empty_struct,3006 .empty_struct,
3007 .empty_struct_literal,
2984 .inferred_alloc_const,3008 .inferred_alloc_const,
2985 .inferred_alloc_mut,3009 .inferred_alloc_mut,
2986 .@"opaque",3010 .@"opaque",
...@@ -3046,7 +3070,7 @@ pub const Type = extern union {...@@ -3046,7 +3070,7 @@ pub const Type = extern union {
3046 .var_args_param,3070 .var_args_param,
3047 => return null,3071 => return null,
30483072
3049 .empty_struct => return Value.initTag(.empty_struct_value),3073 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
3050 .void => return Value.initTag(.void_value),3074 .void => return Value.initTag(.void_value),
3051 .noreturn => return Value.initTag(.unreachable_value),3075 .noreturn => return Value.initTag(.unreachable_value),
3052 .@"null" => return Value.initTag(.null_value),3076 .@"null" => return Value.initTag(.null_value),
...@@ -3149,6 +3173,7 @@ pub const Type = extern union {...@@ -3149,6 +3173,7 @@ pub const Type = extern union {
3149 .error_set,3173 .error_set,
3150 .error_set_single,3174 .error_set_single,
3151 .empty_struct,3175 .empty_struct,
3176 .empty_struct_literal,
3152 .inferred_alloc_const,3177 .inferred_alloc_const,
3153 .inferred_alloc_mut,3178 .inferred_alloc_mut,
3154 .@"opaque",3179 .@"opaque",
...@@ -3241,6 +3266,7 @@ pub const Type = extern union {...@@ -3241,6 +3266,7 @@ pub const Type = extern union {
3241 .inferred_alloc_const,3266 .inferred_alloc_const,
3242 .inferred_alloc_mut,3267 .inferred_alloc_mut,
3243 .var_args_param,3268 .var_args_param,
3269 .empty_struct_literal,
3244 => unreachable,3270 => unreachable,
32453271
3246 .empty_struct => self.castTag(.empty_struct).?.data,3272 .empty_struct => self.castTag(.empty_struct).?.data,
...@@ -3361,6 +3387,8 @@ pub const Type = extern union {...@@ -3361,6 +3387,8 @@ pub const Type = extern union {
3361 /// This is a special type for variadic parameters of a function call.3387 /// This is a special type for variadic parameters of a function call.
3362 /// Casts to it will validate that the type can be passed to a c calling convetion function.3388 /// Casts to it will validate that the type can be passed to a c calling convetion function.
3363 var_args_param,3389 var_args_param,
3390 /// Same as `empty_struct` except it has an empty namespace.
3391 empty_struct_literal,
3364 /// This is a special value that tracks a set of types that have been stored3392 /// This is a special value that tracks a set of types that have been stored
3365 /// to an inferred allocation. It does not support most of the normal type queries.3393 /// to an inferred allocation. It does not support most of the normal type queries.
3366 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.3394 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
...@@ -3445,6 +3473,7 @@ pub const Type = extern union {...@@ -3445,6 +3473,7 @@ pub const Type = extern union {
3445 .inferred_alloc_const,3473 .inferred_alloc_const,
3446 .inferred_alloc_mut,3474 .inferred_alloc_mut,
3447 .var_args_param,3475 .var_args_param,
3476 .empty_struct_literal,
3448 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),3477 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
34493478
3450 .array_u8,3479 .array_u8,
src/zir.zig+133
...@@ -270,6 +270,21 @@ pub const Inst = struct {...@@ -270,6 +270,21 @@ pub const Inst = struct {
270 /// A comptime known value.270 /// A comptime known value.
271 /// Uses the `const` union field.271 /// Uses the `const` union field.
272 @"const",272 @"const",
273 /// A struct type definition. Contains references to ZIR instructions for
274 /// the field types, defaults, and alignments.
275 /// Uses the `pl_node` union field. Payload is `StructDecl`.
276 struct_decl,
277 /// A union type definition. Contains references to ZIR instructions for
278 /// the field types and optional type tag expression.
279 /// Uses the `pl_node` union field. Payload is `UnionDecl`.
280 union_decl,
281 /// An enum type definition. Contains references to ZIR instructions for
282 /// the field value expressions and optional type tag expression.
283 /// Uses the `pl_node` union field. Payload is `EnumDecl`.
284 enum_decl,
285 /// An opaque type definition. Provides an AST node only.
286 /// Uses the `node` union field.
287 opaque_decl,
273 /// Declares the beginning of a statement. Used for debug info.288 /// Declares the beginning of a statement. Used for debug info.
274 /// Uses the `node` union field.289 /// Uses the `node` union field.
275 dbg_stmt_node,290 dbg_stmt_node,
...@@ -642,6 +657,9 @@ pub const Inst = struct {...@@ -642,6 +657,9 @@ pub const Inst = struct {
642 /// as well as missing fields, if applicable.657 /// as well as missing fields, if applicable.
643 /// Uses the `pl_node` field. Payload is `Block`.658 /// Uses the `pl_node` field. Payload is `Block`.
644 validate_struct_init_ptr,659 validate_struct_init_ptr,
660 /// A struct literal with a specified type, with no fields.
661 /// Uses the `un_node` field.
662 struct_init_empty,
645663
646 /// Returns whether the instruction is one of the control flow "noreturn" types.664 /// Returns whether the instruction is one of the control flow "noreturn" types.
647 /// Function calls do not count.665 /// Function calls do not count.
...@@ -688,6 +706,10 @@ pub const Inst = struct {...@@ -688,6 +706,10 @@ pub const Inst = struct {
688 .cmp_neq,706 .cmp_neq,
689 .coerce_result_ptr,707 .coerce_result_ptr,
690 .@"const",708 .@"const",
709 .struct_decl,
710 .union_decl,
711 .enum_decl,
712 .opaque_decl,
691 .dbg_stmt_node,713 .dbg_stmt_node,
692 .decl_ref,714 .decl_ref,
693 .decl_val,715 .decl_val,
...@@ -790,6 +812,7 @@ pub const Inst = struct {...@@ -790,6 +812,7 @@ pub const Inst = struct {
790 .switch_block_ref_under,812 .switch_block_ref_under,
791 .switch_block_ref_under_multi,813 .switch_block_ref_under_multi,
792 .validate_struct_init_ptr,814 .validate_struct_init_ptr,
815 .struct_init_empty,
793 => false,816 => false,
794817
795 .@"break",818 .@"break",
...@@ -893,6 +916,8 @@ pub const Inst = struct {...@@ -893,6 +916,8 @@ pub const Inst = struct {
893 bool_true,916 bool_true,
894 /// `false`917 /// `false`
895 bool_false,918 bool_false,
919 /// `.{}` (untyped)
920 empty_struct,
896 /// `0` (usize)921 /// `0` (usize)
897 zero_usize,922 zero_usize,
898 /// `1` (usize)923 /// `1` (usize)
...@@ -1104,6 +1129,10 @@ pub const Inst = struct {...@@ -1104,6 +1129,10 @@ pub const Inst = struct {
1104 .ty = Type.initTag(.bool),1129 .ty = Type.initTag(.bool),
1105 .val = Value.initTag(.bool_false),1130 .val = Value.initTag(.bool_false),
1106 },1131 },
1132 .empty_struct = .{
1133 .ty = Type.initTag(.empty_struct_literal),
1134 .val = Value.initTag(.empty_struct_value),
1135 },
1107 });1136 });
1108 };1137 };
11091138
...@@ -1427,6 +1456,48 @@ pub const Inst = struct {...@@ -1427,6 +1456,48 @@ pub const Inst = struct {
1427 dest_type: Ref,1456 dest_type: Ref,
1428 operand: Ref,1457 operand: Ref,
1429 };1458 };
1459
1460 /// Trailing:
1461 /// 0. has_bits: u32 // for every 16 fields
1462 /// - sets of 2 bits:
1463 /// 0b0X: whether corresponding field has an align expression
1464 /// 0bX0: whether corresponding field has a default expression
1465 /// 1. fields: { // for every fields_len
1466 /// field_name: u32,
1467 /// field_type: Ref,
1468 /// align: Ref, // if corresponding bit is set
1469 /// default_value: Ref, // if corresponding bit is set
1470 /// }
1471 pub const StructDecl = struct {
1472 fields_len: u32,
1473 };
1474
1475 /// Trailing:
1476 /// 0. has_bits: u32 // for every 32 fields
1477 /// - the bit is whether corresponding field has an value expression
1478 /// 1. field_name: u32 // for every field: null terminated string index
1479 /// 2. value: Ref // for every field for which corresponding bit is set
1480 pub const EnumDecl = struct {
1481 /// Can be `Ref.none`.
1482 tag_type: Ref,
1483 fields_len: u32,
1484 };
1485
1486 /// Trailing:
1487 /// 0. has_bits: u32 // for every 10 fields (+1)
1488 /// - first bit is special: set if and only if auto enum tag is enabled.
1489 /// - sets of 3 bits:
1490 /// 0b00X: whether corresponding field has a type expression
1491 /// 0b0X0: whether corresponding field has a align expression
1492 /// 0bX00: whether corresponding field has a tag value expression
1493 /// 1. field_name: u32 // for every field: null terminated string index
1494 /// 2. opt_exprs // Ref for every field for which corresponding bit is set
1495 /// - interleaved. type if present, align if present, tag value if present.
1496 pub const UnionDecl = struct {
1497 /// Can be `Ref.none`.
1498 tag_type: Ref,
1499 fields_len: u32,
1500 };
1430};1501};
14311502
1432pub const SpecialProng = enum { none, @"else", under };1503pub const SpecialProng = enum { none, @"else", under };
...@@ -1500,6 +1571,7 @@ const Writer = struct {...@@ -1500,6 +1571,7 @@ const Writer = struct {
1500 .is_err_ptr,1571 .is_err_ptr,
1501 .typeof,1572 .typeof,
1502 .typeof_elem,1573 .typeof_elem,
1574 .struct_init_empty,
1503 => try self.writeUnNode(stream, inst),1575 => try self.writeUnNode(stream, inst),
15041576
1505 .ref,1577 .ref,
...@@ -1536,6 +1608,8 @@ const Writer = struct {...@@ -1536,6 +1608,8 @@ const Writer = struct {
1536 .slice_start,1608 .slice_start,
1537 .slice_end,1609 .slice_end,
1538 .slice_sentinel,1610 .slice_sentinel,
1611 .union_decl,
1612 .enum_decl,
1539 => try self.writePlNode(stream, inst),1613 => try self.writePlNode(stream, inst),
15401614
1541 .add,1615 .add,
...@@ -1581,6 +1655,8 @@ const Writer = struct {...@@ -1581,6 +1655,8 @@ const Writer = struct {
1581 .condbr_inline,1655 .condbr_inline,
1582 => try self.writePlNodeCondBr(stream, inst),1656 => try self.writePlNodeCondBr(stream, inst),
15831657
1658 .struct_decl => try self.writeStructDecl(stream, inst),
1659
1584 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),1660 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
1585 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),1661 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
1586 .switch_block_under => try self.writePlNodeSwitchBr(stream, inst, .under),1662 .switch_block_under => try self.writePlNodeSwitchBr(stream, inst, .under),
...@@ -1610,6 +1686,7 @@ const Writer = struct {...@@ -1610,6 +1686,7 @@ const Writer = struct {
1610 .as_node => try self.writeAs(stream, inst),1686 .as_node => try self.writeAs(stream, inst),
16111687
1612 .breakpoint,1688 .breakpoint,
1689 .opaque_decl,
1613 .dbg_stmt_node,1690 .dbg_stmt_node,
1614 .ret_ptr,1691 .ret_ptr,
1615 .ret_type,1692 .ret_type,
...@@ -1808,6 +1885,62 @@ const Writer = struct {...@@ -1808,6 +1885,62 @@ const Writer = struct {
1808 try self.writeSrc(stream, inst_data.src());1885 try self.writeSrc(stream, inst_data.src());
1809 }1886 }
18101887
1888 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1889 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1890 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);
1891 const fields_len = extra.data.fields_len;
1892 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
1893
1894 try stream.writeAll("{\n");
1895 self.indent += 2;
1896
1897 var field_index: usize = extra.end + bit_bags_count;
1898 var bit_bag_index: usize = extra.end;
1899 var cur_bit_bag: u32 = undefined;
1900 var field_i: u32 = 0;
1901 while (field_i < fields_len) : (field_i += 1) {
1902 if (field_i % 16 == 0) {
1903 cur_bit_bag = self.code.extra[bit_bag_index];
1904 bit_bag_index += 1;
1905 }
1906 const has_align = @truncate(u1, cur_bit_bag) != 0;
1907 cur_bit_bag >>= 1;
1908 const has_default = @truncate(u1, cur_bit_bag) != 0;
1909 cur_bit_bag >>= 1;
1910
1911 const field_name = self.code.nullTerminatedString(self.code.extra[field_index]);
1912 field_index += 1;
1913 const field_type = @intToEnum(Inst.Ref, self.code.extra[field_index]);
1914 field_index += 1;
1915
1916 try stream.writeByteNTimes(' ', self.indent);
1917 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
1918 try self.writeInstRef(stream, field_type);
1919
1920 if (has_align) {
1921 const align_ref = @intToEnum(Inst.Ref, self.code.extra[field_index]);
1922 field_index += 1;
1923
1924 try stream.writeAll(" align(");
1925 try self.writeInstRef(stream, align_ref);
1926 try stream.writeAll(")");
1927 }
1928 if (has_default) {
1929 const default_ref = @intToEnum(Inst.Ref, self.code.extra[field_index]);
1930 field_index += 1;
1931
1932 try stream.writeAll(" = ");
1933 try self.writeInstRef(stream, default_ref);
1934 }
1935 try stream.writeAll(",\n");
1936 }
1937
1938 self.indent -= 2;
1939 try stream.writeByteNTimes(' ', self.indent);
1940 try stream.writeAll("}) ");
1941 try self.writeSrc(stream, inst_data.src());
1942 }
1943
1811 fn writePlNodeSwitchBr(1944 fn writePlNodeSwitchBr(
1812 self: *Writer,1945 self: *Writer,
1813 stream: anytype,1946 stream: anytype,