authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-14 15:35:51+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:42+02:00
logc4dfabf4dcfc29f48356e3c5f762f1ca2c21f088
tree4a24c653e0e25bf882c8f38ecc9728bd8adec1f2
parentf191251ddb424eba7384d31fa2d50e50586f3993
signature Commit is signed but in an unrecognized format.

translate-c: render macro functions, use cast type as return type

Closes #8004

2 files changed, 191 insertions(+), 97 deletions(-)

src/translate_c.zig+6-2
......@@ -4099,14 +4099,18 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
40994099 const br = blk_last.castTag(.break_val).?;
41004100 break :blk br.data.val;
41014101 } else expr;
4102 const typeof = try Tag.typeof.create(c.arena, typeof_arg);
4102 const return_type = if (typeof_arg.castTag(.std_meta_cast)) |some|
4103 some.data.lhs
4104 else
4105 try Tag.typeof.create(c.arena, typeof_arg);
4106
41034107 const return_expr = try Tag.@"return".create(c.arena, expr);
41044108 try block_scope.statements.append(return_expr);
41054109
41064110 const fn_decl = try Tag.pub_inline_fn.create(c.arena, .{
41074111 .name = m.name,
41084112 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
4109 .return_type = typeof,
4113 .return_type = return_type,
41104114 .body = try block_scope.complete(c),
41114115 });
41124116 _ = try c.global_scope.macro_table.put(m.name, fn_decl);
src/translate_c/ast.zig+185-95
......@@ -615,9 +615,15 @@ pub fn render(gpa: *Allocator, nodes: []const Node) !std.zig.ast.Tree {
615615 defer ctx.extra_data.deinit(gpa);
616616 defer ctx.tokens.deinit(gpa);
617617
618 // Estimate that each top level node has 25 child nodes.
619 const estimated_node_count = nodes.len * 25;
618 // Estimate that each top level node has 10 child nodes.
619 const estimated_node_count = nodes.len * 10;
620620 try ctx.nodes.ensureCapacity(gpa, estimated_node_count);
621 // Estimate that each each node has 2 tokens.
622 const estimated_tokens_count = estimated_node_count * 2;
623 try ctx.tokens.ensureCapacity(gpa, estimated_tokens_count);
624 // Estimate that each each token is 3 bytes long.
625 const estimated_buf_len = estimated_tokens_count * 3;
626 try ctx.buf.ensureCapacity(estimated_buf_len);
621627
622628 ctx.nodes.appendAssumeCapacity(.{
623629 .tag = .root,
......@@ -776,74 +782,47 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
776782 .null_literal => return c.addNode(.{
777783 .tag = .null_literal,
778784 .main_token = try c.addToken(.keyword_null, "null"),
779 .data = .{
780 .lhs = undefined,
781 .rhs = undefined,
782 },
785 .data = undefined,
783786 }),
784787 .undefined_literal => return c.addNode(.{
785788 .tag = .undefined_literal,
786789 .main_token = try c.addToken(.keyword_undefined, "undefined"),
787 .data = .{
788 .lhs = undefined,
789 .rhs = undefined,
790 },
790 .data = undefined,
791791 }),
792792 .true_literal => return c.addNode(.{
793793 .tag = .true_literal,
794794 .main_token = try c.addToken(.keyword_true, "true"),
795 .data = .{
796 .lhs = undefined,
797 .rhs = undefined,
798 },
795 .data = undefined,
799796 }),
800797 .false_literal => return c.addNode(.{
801798 .tag = .false_literal,
802799 .main_token = try c.addToken(.keyword_false, "false"),
803 .data = .{
804 .lhs = undefined,
805 .rhs = undefined,
806 },
800 .data = undefined,
807801 }),
808802 .zero_literal => return c.addNode(.{
809803 .tag = .integer_literal,
810804 .main_token = try c.addToken(.integer_literal, "0"),
811 .data = .{
812 .lhs = undefined,
813 .rhs = undefined,
814 },
805 .data = undefined,
815806 }),
816807 .one_literal => return c.addNode(.{
817808 .tag = .integer_literal,
818809 .main_token = try c.addToken(.integer_literal, "1"),
819 .data = .{
820 .lhs = undefined,
821 .rhs = undefined,
822 },
810 .data = undefined,
823811 }),
824812 .void_type => return c.addNode(.{
825813 .tag = .identifier,
826814 .main_token = try c.addToken(.identifier, "void"),
827 .data = .{
828 .lhs = undefined,
829 .rhs = undefined,
830 },
815 .data = undefined,
831816 }),
832817 .@"anytype" => return c.addNode(.{
833818 .tag = .@"anytype",
834819 .main_token = try c.addToken(.keyword_anytype, "anytype"),
835 .data = .{
836 .lhs = undefined,
837 .rhs = undefined,
838 },
820 .data = undefined,
839821 }),
840822 .noreturn_type => return c.addNode(.{
841823 .tag = .identifier,
842824 .main_token = try c.addToken(.identifier, "noreturn"),
843 .data = .{
844 .lhs = undefined,
845 .rhs = undefined,
846 },
825 .data = undefined,
847826 }),
848827 .@"continue" => return c.addNode(.{
849828 .tag = .@"continue",
......@@ -853,6 +832,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
853832 .rhs = undefined,
854833 },
855834 }),
835 .return_void => return c.addNode(.{
836 .tag = .@"return",
837 .main_token = try c.addToken(.keyword_return, "return"),
838 .data = .{
839 .lhs = 0,
840 .rhs = undefined,
841 },
842 }),
856843 .@"break" => {
857844 const payload = node.castTag(.@"break").?.data;
858845 const tok = try c.addToken(.keyword_break, "break");
......@@ -885,15 +872,23 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
885872 },
886873 });
887874 },
875 .@"return" => {
876 const payload = node.castTag(.@"return").?.data;
877 return c.addNode(.{
878 .tag = .@"return",
879 .main_token = try c.addToken(.keyword_return, "return"),
880 .data = .{
881 .lhs = try renderNode(c, payload),
882 .rhs = undefined,
883 },
884 });
885 },
888886 .type => {
889887 const payload = node.castTag(.type).?.data;
890888 return c.addNode(.{
891889 .tag = .identifier,
892890 .main_token = try c.addToken(.identifier, payload),
893 .data = .{
894 .lhs = undefined,
895 .rhs = undefined,
896 },
891 .data = undefined,
897892 });
898893 },
899894 .log2_int_type => {
......@@ -901,10 +896,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
901896 return c.addNode(.{
902897 .tag = .identifier,
903898 .main_token = try c.addTokenFmt(.identifier, "u{d}", .{payload}),
904 .data = .{
905 .lhs = undefined,
906 .rhs = undefined,
907 },
899 .data = undefined,
908900 });
909901 },
910902 .identifier => {
......@@ -912,10 +904,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
912904 return c.addNode(.{
913905 .tag = .identifier,
914906 .main_token = try c.addIdentifier(payload),
915 .data = .{
916 .lhs = undefined,
917 .rhs = undefined,
918 },
907 .data = undefined,
919908 });
920909 },
921910 .float_literal => {
......@@ -923,10 +912,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
923912 return c.addNode(.{
924913 .tag = .float_literal,
925914 .main_token = try c.addToken(.float_literal, payload),
926 .data = .{
927 .lhs = undefined,
928 .rhs = undefined,
929 },
915 .data = undefined,
930916 });
931917 },
932918 .integer_literal => {
......@@ -934,10 +920,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
934920 return c.addNode(.{
935921 .tag = .integer_literal,
936922 .main_token = try c.addToken(.integer_literal, payload),
937 .data = .{
938 .lhs = undefined,
939 .rhs = undefined,
940 },
923 .data = undefined,
941924 });
942925 },
943926 .string_literal => {
......@@ -945,10 +928,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
945928 return c.addNode(.{
946929 .tag = .identifier,
947930 .main_token = try c.addToken(.string_literal, payload),
948 .data = .{
949 .lhs = undefined,
950 .rhs = undefined,
951 },
931 .data = undefined,
952932 });
953933 },
954934 .char_literal => {
......@@ -956,10 +936,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
956936 return c.addNode(.{
957937 .tag = .identifier,
958938 .main_token = try c.addToken(.string_literal, payload),
959 .data = .{
960 .lhs = undefined,
961 .rhs = undefined,
962 },
939 .data = undefined,
963940 });
964941 },
965942 .fail_decl => {
......@@ -976,10 +953,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
976953 const err_msg = try c.addNode(.{
977954 .tag = .string_literal,
978955 .main_token = err_msg_tok,
979 .data = .{
980 .lhs = undefined,
981 .rhs = undefined,
982 },
956 .data = undefined,
983957 });
984958 _ = try c.addToken(.r_paren, ")");
985959 const compile_error = try c.addNode(.{
......@@ -1130,6 +1104,31 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
11301104 },
11311105 });
11321106 },
1107 .c_pointer, .single_pointer => {
1108 const payload = @fieldParentPtr(Payload.Pointer, "base", node.ptr_otherwise).data;
1109
1110 const asterisk = if (node.tag() == .single_pointer)
1111 try c.addToken(.asterisk, "*")
1112 else blk: {
1113 _ = try c.addToken(.l_bracket, "[");
1114 const res = try c.addToken(.asterisk, "*");
1115 _ = try c.addIdentifier("c");
1116 _ = try c.addToken(.r_bracket, "]");
1117 break :blk res;
1118 };
1119 if (payload.is_const) _ = try c.addToken(.keyword_const, "const");
1120 if (payload.is_volatile) _ = try c.addToken(.keyword_volatile, "volatile");
1121 const elem_type = try renderNode(c, payload.elem_type);
1122
1123 return c.addNode(.{
1124 .tag = .ptr_type_aligned,
1125 .main_token = asterisk,
1126 .data = .{
1127 .lhs = 0,
1128 .rhs = elem_type,
1129 },
1130 });
1131 },
11331132 .add => return renderBinOp(c, node, .add, .plus, "+"),
11341133 .add_assign => return renderBinOp(c, node, .assign_add, .plus_equal, "+="),
11351134 .add_wrap => return renderBinOp(c, node, .add_wrap, .plus_percent, "+%"),
......@@ -1229,6 +1228,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12291228 });
12301229 },
12311230 .func => return renderFunc(c, node),
1231 .pub_inline_fn => return renderMacroFunc(c, node),
12321232 .discard => {
12331233 const payload = node.castTag(.discard).?.data;
12341234 const lhs = try c.addNode(.{
......@@ -1300,6 +1300,9 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
13001300 .type,
13011301 .array_access,
13021302 .align_cast,
1303 .optional_type,
1304 .c_pointer,
1305 .single_pointer,
13031306 => {
13041307 // no grouping needed
13051308 return renderNode(c, node);
......@@ -1310,7 +1313,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
13101313 .bit_not,
13111314 .opaque_literal,
13121315 .not,
1313 .optional_type,
13141316 .address_of,
13151317 .unwrap,
13161318 .deref,
......@@ -1350,8 +1352,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
13501352 .tuple,
13511353 .container_init,
13521354 .block,
1353 .c_pointer,
1354 .single_pointer,
13551355 .array_type,
13561356 => return c.addNode(.{
13571357 .tag = .grouped_expression,
......@@ -1439,10 +1439,7 @@ fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeInde
14391439 const std_node = try c.addNode(.{
14401440 .tag = .string_literal,
14411441 .main_token = std_tok,
1442 .data = .{
1443 .lhs = undefined,
1444 .rhs = undefined,
1445 },
1442 .data = undefined,
14461443 });
14471444 _ = try c.addToken(.r_paren, ")");
14481445
......@@ -1498,21 +1495,23 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
14981495 });
14991496 },
15001497 else => blk: {
1501 const start = @intCast(u32, c.extra_data.items.len);
1502 const end = @intCast(u32, start + args.len);
1503 try c.extra_data.ensureCapacity(c.gpa, end + 2); // + 2 for span start + end
1498 var rendered = try c.gpa.alloc(NodeIndex, args.len);
1499 defer c.gpa.free(rendered);
1500
15041501 for (args) |arg, i| {
15051502 if (i != 0) _ = try c.addToken(.comma, ",");
1506 c.extra_data.appendAssumeCapacity(try renderNode(c, arg));
1503 rendered[i] = try renderNode(c, arg);
15071504 }
1508 c.extra_data.appendAssumeCapacity(start);
1509 c.extra_data.appendAssumeCapacity(end);
1505 const span = try c.listToSpan(rendered);
15101506 break :blk try c.addNode(.{
1511 .tag = .call_comma,
1507 .tag = .call,
15121508 .main_token = lparen,
15131509 .data = .{
15141510 .lhs = lhs,
1515 .rhs = end + 2,
1511 .rhs = try c.addExtra(std.zig.ast.Node.SubRange{
1512 .start = span.start,
1513 .end = span.end,
1514 }),
15161515 },
15171516 });
15181517 },
......@@ -1653,20 +1652,20 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
16531652
16541653 var span: NodeSubRange = undefined;
16551654 if (payload.params.len > 1) {
1656 var params = std.ArrayList(NodeIndex).init(c.gpa);
1657 defer params.deinit();
1655 var params = try c.gpa.alloc(NodeIndex, payload.params.len);
1656 defer c.gpa.free(params);
16581657
1659 try params.append(first);
1660 for (payload.params[1..]) |param| {
1658 params[0] = first;
1659 for (payload.params[1..]) |param, i| {
16611660 _ = try c.addToken(.comma, ",");
16621661 if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
16631662 if (param.name) |some| {
16641663 _ = try c.addIdentifier(some);
16651664 _ = try c.addToken(.colon, ":");
16661665 }
1667 try params.append(try renderNode(c, param.type));
1666 params[i + 1] = try renderNode(c, param.type);
16681667 }
1669 span = try c.listToSpan(params.items);
1668 span = try c.listToSpan(params);
16701669 }
16711670 if (payload.is_var_args) {
16721671 if (payload.params.len != 0) _ = try c.addToken(.comma, ",");
......@@ -1674,8 +1673,6 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
16741673 }
16751674 _ = try c.addToken(.r_paren, ")");
16761675
1677 const return_type_expr = try renderNode(c, payload.return_type);
1678
16791676 const align_expr = if (payload.alignment) |some| blk: {
16801677 _ = try c.addToken(.keyword_align, "align");
16811678 _ = try c.addToken(.l_paren, "(");
......@@ -1701,18 +1698,20 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
17011698 } else 0;
17021699
17031700 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
1704 _ = try c.addToken(.keyword_linksection, "callconv");
1701 _ = try c.addToken(.keyword_callconv, "callconv");
17051702 _ = try c.addToken(.l_paren, "(");
17061703 _ = try c.addToken(.period, ".");
17071704 const res = try c.addNode(.{
17081705 .tag = .enum_literal,
1709 .main_token = try c.addTokenFmt(.string_literal, "{}", .{some}),
1706 .main_token = try c.addTokenFmt(.identifier, "{}", .{some}),
17101707 .data = .{ .lhs = undefined, .rhs = undefined },
17111708 });
17121709 _ = try c.addToken(.r_paren, ")");
17131710 break :blk res;
17141711 } else 0;
17151712
1713 const return_type_expr = try renderNode(c, payload.return_type);
1714
17161715 const fn_proto = try blk: {
17171716 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
17181717 if (payload.params.len < 2)
......@@ -1784,3 +1783,94 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
17841783 },
17851784 });
17861785}
1786
1787fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
1788 const payload = node.castTag(.pub_inline_fn).?.data;
1789 _ = try c.addToken(.keyword_pub, "pub");
1790 const fn_token = try c.addToken(.keyword_fn, "fn");
1791 _ = try c.addIdentifier(payload.name);
1792
1793 _ = try c.addToken(.l_paren, "(");
1794 const first = if (payload.params.len != 0) blk: {
1795 const param = payload.params[0];
1796 if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
1797 if (param.name) |some| {
1798 _ = try c.addIdentifier(some);
1799 _ = try c.addToken(.colon, ":");
1800 }
1801 break :blk try renderNode(c, param.type);
1802 } else 0;
1803
1804 var span: NodeSubRange = undefined;
1805 if (payload.params.len > 1) {
1806 var params = try c.gpa.alloc(NodeIndex, payload.params.len);
1807 defer c.gpa.free(params);
1808
1809 params[0] = first;
1810 for (payload.params[1..]) |param, i| {
1811 _ = try c.addToken(.comma, ",");
1812 if (param.is_noalias) _ = try c.addToken(.keyword_noalias, "noalias");
1813 if (param.name) |some| {
1814 _ = try c.addIdentifier(some);
1815 _ = try c.addToken(.colon, ":");
1816 }
1817 params[i + 1] = try renderNode(c, param.type);
1818 }
1819 span = try c.listToSpan(params);
1820 }
1821 _ = try c.addToken(.r_paren, ")");
1822
1823 const callconv_expr = blk: {
1824 _ = try c.addToken(.keyword_callconv, "callconv");
1825 _ = try c.addToken(.l_paren, "(");
1826 _ = try c.addToken(.period, ".");
1827 const res = try c.addNode(.{
1828 .tag = .enum_literal,
1829 .main_token = try c.addToken(.identifier, "Inline"),
1830 .data = .{ .lhs = undefined, .rhs = undefined },
1831 });
1832 _ = try c.addToken(.r_paren, ")");
1833 break :blk res;
1834 };
1835 const return_type_expr = try renderNode(c, payload.return_type);
1836
1837 const fn_proto = try blk: {
1838 if (payload.params.len < 2)
1839 break :blk c.addNode(.{
1840 .tag = .fn_proto_one,
1841 .main_token = fn_token,
1842 .data = .{
1843 .lhs = try c.addExtra(std.zig.ast.Node.FnProtoOne{
1844 .param = first,
1845 .align_expr = 0,
1846 .section_expr = 0,
1847 .callconv_expr = callconv_expr,
1848 }),
1849 .rhs = return_type_expr,
1850 },
1851 })
1852 else
1853 break :blk c.addNode(.{
1854 .tag = .fn_proto,
1855 .main_token = fn_token,
1856 .data = .{
1857 .lhs = try c.addExtra(std.zig.ast.Node.FnProto{
1858 .params_start = span.start,
1859 .params_end = span.end,
1860 .align_expr = 0,
1861 .section_expr = 0,
1862 .callconv_expr = callconv_expr,
1863 }),
1864 .rhs = return_type_expr,
1865 },
1866 });
1867 };
1868 return c.addNode(.{
1869 .tag = .fn_decl,
1870 .main_token = fn_token,
1871 .data = .{
1872 .lhs = fn_proto,
1873 .rhs = try renderNode(c, payload.body),
1874 },
1875 });
1876}