authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-14 18:06:15+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:43+02:00
logc0540967e974b59bf85f71be9f085b5852d20ef6
treeea3027ece32cc67ddd1a2aa14ec878cca3e6c126
parent62162a07171ccbdb753650205880c3745a599366
signature Commit is signed but in an unrecognized format.

translate-c: render array stuff


3 files changed, 227 insertions(+), 59 deletions(-)

src/Compilation.zig+1-1
......@@ -1334,7 +1334,7 @@ pub fn update(self: *Compilation) !void {
13341334 self.c_object_work_queue.writeItemAssumeCapacity(entry.key);
13351335 }
13361336
1337 const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_llvm;
1337 const use_stage1 = build_options.omit_stage2 or build_options.is_stage1 and self.bin_file.options.use_llvm;
13381338 if (!use_stage1) {
13391339 if (self.bin_file.options.module) |module| {
13401340 module.compile_log_text.shrinkAndFree(module.gpa, 0);
src/translate_c.zig+32-32
......@@ -1689,7 +1689,10 @@ fn transStringLiteralAsArray(
16891689 init_list[i] = try transCreateNodeNumber(c, 0, .int);
16901690 }
16911691
1692 return Tag.array_init.create(c.arena, init_list);
1692 return Tag.array_init.create(c.arena, .{
1693 .cond = arr_type,
1694 .cases = init_list,
1695 });
16931696}
16941697
16951698fn cIsEnum(qt: clang.QualType) bool {
......@@ -1880,6 +1883,7 @@ fn transInitListExprArray(
18801883) TransError!Node {
18811884 const arr_type = ty.getAsArrayTypeUnsafe();
18821885 const child_qt = arr_type.getElementType();
1886 const child_type = try transQualType(c, child_qt, loc);
18831887 const init_count = expr.getNumInits();
18841888 assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType());
18851889 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type);
......@@ -1888,18 +1892,20 @@ fn transInitListExprArray(
18881892 const leftover_count = all_count - init_count;
18891893
18901894 if (all_count == 0) {
1891 return Tag.empty_array.create(c.arena, try transQualType(c, child_qt, loc));
1895 return Tag.empty_array.create(c.arena, child_type);
18921896 }
18931897
1894 const ty_node = try transType(c, ty, loc);
18951898 const init_node = if (init_count != 0) blk: {
18961899 const init_list = try c.arena.alloc(Node, init_count);
18971900
18981901 for (init_list) |*init, i| {
18991902 const elem_expr = expr.getInit(@intCast(c_uint, i));
1900 init.* = try transExpr(c, scope, elem_expr, .used);
1903 init.* = try transExprCoercing(c, scope, elem_expr, .used);
19011904 }
1902 const init_node = try Tag.array_init.create(c.arena, init_list);
1905 const init_node = try Tag.array_init.create(c.arena, .{
1906 .cond = try Tag.array_type.create(c.arena, .{ .len = init_count, .elem_type = child_type }),
1907 .cases = init_list,
1908 });
19031909 if (leftover_count == 0) {
19041910 return init_node;
19051911 }
......@@ -1908,8 +1914,8 @@ fn transInitListExprArray(
19081914
19091915 const filler_val_expr = expr.getArrayFiller();
19101916 const filler_node = try Tag.array_filler.create(c.arena, .{
1911 .type = ty_node,
1912 .filler = try transExpr(c, scope, filler_val_expr, .used),
1917 .type = child_type,
1918 .filler = try transExprCoercing(c, scope, filler_val_expr, .used),
19131919 .count = leftover_count,
19141920 });
19151921
......@@ -2422,9 +2428,7 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re
24222428 const decl = @ptrCast(*const clang.NamedDecl, member_decl);
24232429 break :blk try c.str(decl.getName_bytes_begin());
24242430 };
2425 const ident = try Tag.identifier.create(c.arena, name);
2426
2427 const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident });
2431 const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .field_name = name });
24282432 return maybeSuppressResult(c, scope, result_used, node);
24292433}
24302434
......@@ -2698,14 +2702,14 @@ fn transCreatePreCrement(
26982702 defer block_scope.deinit();
26992703 const ref = try block_scope.makeMangledName(c, "ref");
27002704
2701 const expr = try transExpr(c, scope, op_expr, .used);
2705 const expr = try transExpr(c, &block_scope.base, op_expr, .used);
27022706 const addr_of = try Tag.address_of.create(c.arena, expr);
27032707 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
27042708 try block_scope.statements.append(ref_decl);
27052709
27062710 const lhs_node = try Tag.identifier.create(c.arena, ref);
27072711 const ref_node = try Tag.deref.create(c.arena, lhs_node);
2708 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used);
2712 const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used);
27092713 try block_scope.statements.append(node);
27102714
27112715 const break_node = try Tag.break_val.create(c.arena, .{
......@@ -2745,7 +2749,7 @@ fn transCreatePostCrement(
27452749 defer block_scope.deinit();
27462750 const ref = try block_scope.makeMangledName(c, "ref");
27472751
2748 const expr = try transExpr(c, scope, op_expr, .used);
2752 const expr = try transExpr(c, &block_scope.base, op_expr, .used);
27492753 const addr_of = try Tag.address_of.create(c.arena, expr);
27502754 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
27512755 try block_scope.statements.append(ref_decl);
......@@ -2757,7 +2761,7 @@ fn transCreatePostCrement(
27572761 const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node });
27582762 try block_scope.statements.append(tmp_decl);
27592763
2760 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used);
2764 const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used);
27612765 try block_scope.statements.append(node);
27622766
27632767 const break_node = try Tag.break_val.create(c.arena, .{
......@@ -2864,7 +2868,7 @@ fn transCreateCompoundAssign(
28642868 defer block_scope.deinit();
28652869 const ref = try block_scope.makeMangledName(c, "ref");
28662870
2867 const expr = try transExpr(c, scope, lhs, .used);
2871 const expr = try transExpr(c, &block_scope.base, lhs, .used);
28682872 const addr_of = try Tag.address_of.create(c.arena, expr);
28692873 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
28702874 try block_scope.statements.append(ref_decl);
......@@ -2873,16 +2877,16 @@ fn transCreateCompoundAssign(
28732877 const ref_node = try Tag.deref.create(c.arena, lhs_node);
28742878
28752879 if ((is_mod or is_div) and is_signed) {
2876 const rhs_node = try transExpr(c, scope, rhs, .used);
2880 const rhs_node = try transExpr(c, &block_scope.base, rhs, .used);
28772881 const builtin = if (is_mod)
28782882 try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
28792883 else
28802884 try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
28812885
2882 const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
2886 const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, builtin, .used);
28832887 try block_scope.statements.append(assign);
28842888 } else {
2885 var rhs_node = try transExpr(c, scope, rhs, .used);
2889 var rhs_node = try transExpr(c, &block_scope.base, rhs, .used);
28862890
28872891 if (is_shift or requires_int_cast) {
28882892 // @intCast(rhs)
......@@ -2894,7 +2898,7 @@ fn transCreateCompoundAssign(
28942898 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
28952899 }
28962900
2897 const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used);
2901 const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used);
28982902 try block_scope.statements.append(assign);
28992903 }
29002904
......@@ -3395,7 +3399,7 @@ fn transCreateNodeAssign(
33953399 defer block_scope.deinit();
33963400
33973401 const tmp = try block_scope.makeMangledName(c, "tmp");
3398 const rhs_node = try transExpr(c, scope, rhs, .used);
3402 const rhs_node = try transExpr(c, &block_scope.base, rhs, .used);
33993403 const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = rhs_node });
34003404 try block_scope.statements.append(tmp_decl);
34013405
......@@ -4756,8 +4760,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
47564760 return error.ParseError;
47574761 }
47584762
4759 const ident = try Tag.identifier.create(c.arena, m.slice());
4760 node = try Tag.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
4763 node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() });
47614764 },
47624765 .Arrow => {
47634766 if (m.next().? != .Identifier) {
......@@ -4766,8 +4769,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
47664769 }
47674770
47684771 const deref = try Tag.deref.create(c.arena, node);
4769 const ident = try Tag.identifier.create(c.arena, m.slice());
4770 node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
4772 node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() });
47714773 },
47724774 .LBracket => {
47734775 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
......@@ -4914,13 +4916,12 @@ fn getContainer(c: *Context, node: Node) ?Node {
49144916 },
49154917
49164918 .field_access => {
4917 const infix = node.castTag(.field_access).?;
4919 const field_access = node.castTag(.field_access).?;
49184920
4919 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
4921 if (getContainerTypeOf(c, field_access.data.lhs)) |ty_node| {
49204922 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
49214923 for (container.data.fields) |field| {
4922 const ident = infix.data.rhs.castTag(.identifier).?;
4923 if (mem.eql(u8, field.name, ident.data)) {
4924 if (mem.eql(u8, field.name, field_access.data.field_name)) {
49244925 return getContainer(c, field.type);
49254926 }
49264927 }
......@@ -4940,12 +4941,11 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
49404941 return getContainer(c, var_decl.data.type);
49414942 }
49424943 }
4943 } else if (ref.castTag(.field_access)) |infix| {
4944 if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| {
4944 } else if (ref.castTag(.field_access)) |field_access| {
4945 if (getContainerTypeOf(c, field_access.data.lhs)) |ty_node| {
49454946 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
49464947 for (container.data.fields) |field| {
4947 const ident = infix.data.rhs.castTag(.identifier).?;
4948 if (mem.eql(u8, field.name, ident.data)) {
4948 if (mem.eql(u8, field.name, field_access.data.field_name)) {
49494949 return getContainer(c, field.type);
49504950 }
49514951 }
src/translate_c/ast.zig+194-26
......@@ -291,7 +291,6 @@ pub const Node = extern union {
291291 .array_cat,
292292 .ellipsis3,
293293 .switch_prong,
294 .field_access,
295294 .assign,
296295 .align_cast,
297296 .array_access,
......@@ -309,7 +308,7 @@ pub const Node = extern union {
309308 => Payload.Value,
310309 .@"if" => Payload.If,
311310 .@"while" => Payload.While,
312 .@"switch" => Payload.Switch,
311 .@"switch", .array_init => Payload.Switch,
313312 .@"break" => Payload.Break,
314313 .break_val => Payload.BreakVal,
315314 .call => Payload.Call,
......@@ -317,7 +316,7 @@ pub const Node = extern union {
317316 .func => Payload.Func,
318317 .@"enum" => Payload.Enum,
319318 .@"struct", .@"union" => Payload.Record,
320 .array_init, .tuple => Payload.ArrayInit,
319 .tuple => Payload.TupleInit,
321320 .container_init => Payload.ContainerInit,
322321 .std_meta_cast => Payload.Infix,
323322 .block => Payload.Block,
......@@ -329,6 +328,7 @@ pub const Node = extern union {
329328 .enum_redecl => Payload.EnumRedecl,
330329 .array_filler => Payload.ArrayFiller,
331330 .pub_inline_fn => Payload.PubInlineFn,
331 .field_access => Payload.FieldAccess,
332332 };
333333 }
334334
......@@ -513,7 +513,7 @@ pub const Payload = struct {
513513 };
514514 };
515515
516 pub const ArrayInit = struct {
516 pub const TupleInit = struct {
517517 base: Payload,
518518 data: []Node,
519519 };
......@@ -601,6 +601,14 @@ pub const Payload = struct {
601601 body: Node,
602602 },
603603 };
604
605 pub const FieldAccess = struct {
606 base: Payload,
607 data: struct {
608 lhs: Node,
609 field_name: []const u8,
610 },
611 };
604612};
605613
606614/// Converts the nodes into a Zig ast.
......@@ -995,6 +1003,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
9951003 });
9961004 },
9971005 .var_decl => return renderVar(c, node),
1006 .arg_redecl, .alias => {
1007 const payload = @fieldParentPtr(Payload.ArgRedecl, "base", node.ptr_otherwise).data;
1008 if (node.tag() == .alias) _ = try c.addToken(.keyword_pub, "pub");
1009 const mut_tok = if (node.tag() == .alias)
1010 try c.addToken(.keyword_const, "const")
1011 else
1012 try c.addToken(.keyword_var, "var");
1013 _ = try c.addIdentifier(payload.actual);
1014 _ = try c.addToken(.equal, "=");
1015
1016 const init = try c.addNode(.{
1017 .tag = .identifier,
1018 .main_token = try c.addIdentifier(payload.mangled),
1019 .data = undefined,
1020 });
1021 _ = try c.addToken(.semicolon, ";");
1022
1023 return c.addNode(.{
1024 .tag = .simple_var_decl,
1025 .main_token = mut_tok,
1026 .data = .{
1027 .lhs = 0,
1028 .rhs = init,
1029 },
1030 });
1031 },
9981032 .int_cast => {
9991033 const payload = node.castTag(.int_cast).?.data;
10001034 return renderBuiltinCall(c, "@intCast", &.{ payload.lhs, payload.rhs });
......@@ -1339,7 +1373,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13391373 _ = try c.addToken(.l_paren, "(");
13401374 const cond = try c.addNode(.{
13411375 .tag = .bool_not,
1342 .main_token = try c.addToken(.bang, "!"),
1376 .main_token = try c.addToken(.bang, "!"),
13431377 .data = .{
13441378 .lhs = try renderNodeGrouped(c, payload),
13451379 .rhs = undefined,
......@@ -1430,7 +1464,77 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
14301464 },
14311465 });
14321466 },
1433 else => return c.addNode(.{
1467 .array_access => {
1468 const payload = node.castTag(.array_access).?.data;
1469 const lhs = try renderNode(c, payload.lhs);
1470 const l_bracket = try c.addToken(.l_bracket, "[");
1471 const index_expr = try renderNode(c, payload.rhs);
1472 _ = try c.addToken(.r_bracket, "]");
1473 return c.addNode(.{
1474 .tag = .array_access,
1475 .main_token = l_bracket,
1476 .data = .{
1477 .lhs = lhs,
1478 .rhs = index_expr,
1479 },
1480 });
1481 },
1482 .array_type => {
1483 const payload = node.castTag(.array_type).?.data;
1484 return renderArrayType(c, payload.len, payload.elem_type);
1485 },
1486 .array_filler => {
1487 const payload = node.castTag(.array_filler).?.data;
1488
1489 const type_expr = try renderArrayType(c, 1, payload.type);
1490 const l_brace = try c.addToken(.l_brace, "{");
1491 const val = try renderNode(c, payload.filler);
1492 _ = try c.addToken(.r_brace, "}");
1493
1494 const init = try c.addNode(.{
1495 .tag = .array_init_one,
1496 .main_token = l_brace,
1497 .data = .{
1498 .lhs = type_expr,
1499 .rhs = val,
1500 },
1501 });
1502 return c.addNode(.{
1503 .tag = .array_cat,
1504 .main_token = try c.addToken(.asterisk_asterisk, "**"),
1505 .data = .{
1506 .lhs = init,
1507 .rhs = try c.addNode(.{
1508 .tag = .integer_literal,
1509 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.count}),
1510 .data = .{ .lhs = undefined, .rhs = undefined },
1511 }),
1512 },
1513 });
1514 },
1515 .empty_array => {
1516 const payload = node.castTag(.empty_array).?.data;
1517
1518 const type_expr = try renderArrayType(c, 0, payload);
1519 return renderArrayInit(c, 0, &.{});
1520 },
1521 .array_init => {
1522 const payload = node.castTag(.array_init).?.data;
1523 const type_expr = try renderNode(c, payload.cond);
1524 return renderArrayInit(c, type_expr, payload.cases);
1525 },
1526 .field_access => {
1527 const payload = node.castTag(.field_access).?.data;
1528 const lhs = try renderNode(c, payload.lhs);
1529 return renderFieldAccess(c, lhs, payload.field_name);
1530 },
1531 .tuple,
1532 .@"enum",
1533 .@"struct",
1534 .@"union",
1535 .container_init,
1536 .enum_redecl,
1537 => return c.addNode(.{
14341538 .tag = .identifier,
14351539 .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}),
14361540 .data = .{
......@@ -1441,10 +1545,88 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
14411545 }
14421546}
14431547
1548fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeIndex {
1549 return c.addNode(.{
1550 .tag = .field_access,
1551 .main_token = try c.addToken(.period, "."),
1552 .data = .{
1553 .lhs = lhs,
1554 .rhs = try c.addIdentifier(field_name),
1555 },
1556 });
1557}
1558
1559fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
1560 const l_brace = try c.addToken(.l_brace, "{");
1561 const res = switch (inits.len) {
1562 0 => try c.addNode(.{
1563 .tag = .struct_init_one,
1564 .main_token = l_brace,
1565 .data = .{
1566 .lhs = lhs,
1567 .rhs = 0,
1568 },
1569 }),
1570 1 => blk: {
1571 const init = try renderNode(c, inits[0]);
1572 break :blk try c.addNode(.{
1573 .tag = .array_init_one,
1574 .main_token = l_brace,
1575 .data = .{
1576 .lhs = lhs,
1577 .rhs = init,
1578 },
1579 });
1580 },
1581 else => blk: {
1582 var rendered = try c.gpa.alloc(NodeIndex, inits.len);
1583 defer c.gpa.free(rendered);
1584
1585 for (inits) |init, i| {
1586 if (i != 0) _ = try c.addToken(.comma, ",");
1587 rendered[i] = try renderNode(c, init);
1588 }
1589 const span = try c.listToSpan(rendered);
1590 break :blk try c.addNode(.{
1591 .tag = .array_init,
1592 .main_token = l_brace,
1593 .data = .{
1594 .lhs = lhs,
1595 .rhs = try c.addExtra(NodeSubRange{
1596 .start = span.start,
1597 .end = span.end,
1598 }),
1599 },
1600 });
1601 },
1602 };
1603 _ = try c.addToken(.r_brace, "}");
1604 return res;
1605}
1606
1607fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
1608 const l_bracket = try c.addToken(.l_bracket, "[");
1609 const len_expr = try c.addNode(.{
1610 .tag = .integer_literal,
1611 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}),
1612 .data = .{ .lhs = undefined, .rhs = undefined },
1613 });
1614 _ = try c.addToken(.r_bracket, "]");
1615 const elem_type_expr = try renderNode(c, elem_type);
1616 return c.addNode(.{
1617 .tag = .array_type,
1618 .main_token = l_bracket,
1619 .data = .{
1620 .lhs = len_expr,
1621 .rhs = elem_type_expr,
1622 },
1623 });
1624}
1625
14441626fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
14451627 switch (node.tag()) {
14461628 .warning => unreachable,
1447 .var_decl, .var_simple, .block, .empty_block, .@"switch" => {},
1629 .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .@"switch" => {},
14481630 .while_true => {
14491631 const payload = node.castTag(.while_true).?.data;
14501632 return addSemicolonIfNeeded(c, payload);
......@@ -1517,6 +1699,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
15171699 .negate,
15181700 .negate_wrap,
15191701 .bit_not,
1702 .func,
15201703 => {
15211704 // no grouping needed
15221705 return renderNode(c, node);
......@@ -1572,7 +1755,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
15721755 .switch_prong,
15731756 .warning,
15741757 .var_decl,
1575 .func,
15761758 .fail_decl,
15771759 .arg_redecl,
15781760 .alias,
......@@ -1658,22 +1840,8 @@ fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeInde
16581840 });
16591841
16601842 var access_chain = import_node;
1661 access_chain = try c.addNode(.{
1662 .tag = .field_access,
1663 .main_token = try c.addToken(.period, "."),
1664 .data = .{
1665 .lhs = access_chain,
1666 .rhs = try c.addIdentifier(first),
1667 },
1668 });
1669 access_chain = try c.addNode(.{
1670 .tag = .field_access,
1671 .main_token = try c.addToken(.period, "."),
1672 .data = .{
1673 .lhs = access_chain,
1674 .rhs = try c.addIdentifier(second),
1675 },
1676 });
1843 access_chain = try renderFieldAccess(c, access_chain, first);
1844 access_chain = try renderFieldAccess(c, access_chain, second);
16771845 return access_chain;
16781846}
16791847
......@@ -1974,10 +2142,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
19742142
19752143 const body = if (payload.body) |some|
19762144 try renderNode(c, some)
1977 else blk: {
2145 else if (payload.is_extern) blk: {
19782146 _ = try c.addToken(.semicolon, ";");
19792147 break :blk 0;
1980 };
2148 } else return fn_proto;
19812149
19822150 return c.addNode(.{
19832151 .tag = .fn_decl,