authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-10 22:04:19+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:05+02:00
logd8b9fca0b1c8929be99b6dff8f961afbe2fe2e3c
treefba3ba67e31c1097373cf0a40f1c37ae73eadc1d
parent5dac3683c9e8819d6ceefb869577e3537d863c41
signature Commit is signed but in an unrecognized format.

translate-c: convert casts and string/array init


2 files changed, 174 insertions(+), 342 deletions(-)

src/translate_c.zig+129-342
...@@ -1084,7 +1084,6 @@ fn transStmt(...@@ -1084,7 +1084,6 @@ fn transStmt(
1084 const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?;1084 const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?;
1085 const expr = try transExpr(c, scope, source_expr, .used, lrvalue);1085 const expr = try transExpr(c, scope, source_expr, .used, lrvalue);
1086 return maybeSuppressResult(c, scope, result_used, expr);1086 return maybeSuppressResult(c, scope, result_used, expr);
1087 const node = try c.arena.create(Node.GroupedExpression);
1088 },1087 },
1089 else => {1088 else => {
1090 return revertAndWarn(1089 return revertAndWarn(
...@@ -1389,62 +1388,56 @@ fn transDeclRefExpr(...@@ -1389,62 +1388,56 @@ fn transDeclRefExpr(
1389}1388}
13901389
1391fn transImplicitCastExpr(1390fn transImplicitCastExpr(
1392 rp: RestorePoint,1391 c: *Context,
1393 scope: *Scope,1392 scope: *Scope,
1394 expr: *const clang.ImplicitCastExpr,1393 expr: *const clang.ImplicitCastExpr,
1395 result_used: ResultUsed,1394 result_used: ResultUsed,
1396) TransError!*ast.Node {1395) TransError!Node {
1397 const c = rp.c;
1398 const sub_expr = expr.getSubExpr();1396 const sub_expr = expr.getSubExpr();
1399 const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr));1397 const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr));
1400 const src_type = getExprQualType(c, sub_expr);1398 const src_type = getExprQualType(c, sub_expr);
1401 switch (expr.getCastKind()) {1399 switch (expr.getCastKind()) {
1402 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {1400 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {
1403 const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value);1401 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
1404 return try transCCast(rp, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node);1402 const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node);
1403 return maybeSuppressResult(c, scope, result_used, casted);
1405 },1404 },
1406 .LValueToRValue, .NoOp, .FunctionToPointerDecay => {1405 .LValueToRValue, .NoOp, .FunctionToPointerDecay => {
1407 const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value);1406 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
1408 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);1407 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
1409 },1408 },
1410 .ArrayToPointerDecay => {1409 .ArrayToPointerDecay => {
1411 if (exprIsNarrowStringLiteral(sub_expr)) {1410 if (exprIsNarrowStringLiteral(sub_expr)) {
1412 const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value);1411 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
1413 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);1412 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
1414 }1413 }
14151414
1416 const prefix_op = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&");1415 const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));
1417 prefix_op.rhs = try transExpr(rp, scope, sub_expr, .used, .r_value);1416 return maybeSuppressResult(c, scope, result_used, addr);
1418
1419 return maybeSuppressResult(rp, scope, result_used, &prefix_op.base);
1420 },1417 },
1421 .NullToPointer => {1418 .NullToPointer => {
1422 return try transCreateNodeNullLiteral(rp.c);1419 return Node.null_literal.init();
1423 },1420 },
1424 .PointerToBoolean => {1421 .PointerToBoolean => {
1425 // @ptrToInt(val) != 01422 // @ptrToInt(val) != 0
1426 const ptr_to_int = try rp.c.createBuiltinCall("@ptrToInt", 1);1423 const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));
1427 ptr_to_int.params()[0] = try transExpr(rp, scope, sub_expr, .used, .r_value);
1428 ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")");
14291424
1430 const op_token = try appendToken(rp.c, .BangEqual, "!=");1425 const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() });
1431 const rhs_node = try transCreateNodeInt(rp.c, 0);1426 return maybeSuppressResult(c, scope, result_used, ne);
1432 return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false);
1433 },1427 },
1434 .IntegralToBoolean => {1428 .IntegralToBoolean => {
1435 const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value);1429 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
14361430
1437 // The expression is already a boolean one, return it as-is1431 // The expression is already a boolean one, return it as-is
1438 if (isBoolRes(sub_expr_node))1432 if (isBoolRes(sub_expr_node))
1439 return sub_expr_node;1433 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
14401434
1441 // val != 01435 // val != 0
1442 const op_token = try appendToken(rp.c, .BangEqual, "!=");1436 const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() });
1443 const rhs_node = try transCreateNodeInt(rp.c, 0);1437 return maybeSuppressResult(c, scope, result_used, ne);
1444 return transCreateNodeInfixOp(rp, scope, sub_expr_node, .BangEqual, op_token, rhs_node, result_used, false);
1445 },1438 },
1446 .BuiltinFnToFnPtr => {1439 .BuiltinFnToFnPtr => {
1447 return transExpr(rp, scope, sub_expr, .used, .r_value);1440 return transExpr(rp, scope, sub_expr, result_used, .r_value);
1448 },1441 },
1449 else => |kind| return revertAndWarn(1442 else => |kind| return revertAndWarn(
1450 rp,1443 rp,
...@@ -1468,12 +1461,12 @@ fn transBoolExpr(...@@ -1468,12 +1461,12 @@ fn transBoolExpr(
1468 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {1461 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
1469 return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});1462 return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
1470 }1463 }
1471 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] };1464 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] };
1472 }1465 }
14731466
1474 var res = try transExpr(c, scope, expr, used, lrvalue);1467 var res = try transExpr(c, scope, expr, used, lrvalue);
1475 if (isBoolRes(res)) {1468 if (isBoolRes(res)) {
1476 return res;1469 return maybeSuppressResult(c, scope, used, res);
1477 }1470 }
14781471
1479 const ty = getExprQualType(c, expr).getTypePtr();1472 const ty = getExprQualType(c, expr).getTypePtr();
...@@ -1563,18 +1556,18 @@ fn finishBoolExpr(...@@ -1563,18 +1556,18 @@ fn finishBoolExpr(
1563 .Float16,1556 .Float16,
1564 => {1557 => {
1565 // node != 01558 // node != 0
1566 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});1559 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
1567 },1560 },
1568 .NullPtr => {1561 .NullPtr => {
1569 // node == null1562 // node == null
1570 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});1563 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });
1571 },1564 },
1572 else => {},1565 else => {},
1573 }1566 }
1574 },1567 },
1575 .Pointer => {1568 .Pointer => {
1576 // node == null1569 // node == null
1577 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});1570 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });
1578 },1571 },
1579 .Typedef => {1572 .Typedef => {
1580 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);1573 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
...@@ -1584,7 +1577,7 @@ fn finishBoolExpr(...@@ -1584,7 +1577,7 @@ fn finishBoolExpr(
1584 },1577 },
1585 .Enum => {1578 .Enum => {
1586 // node != 01579 // node != 0
1587 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});1580 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
1588 const op_token = try appendToken(c, .BangEqual, "!=");1581 const op_token = try appendToken(c, .BangEqual, "!=");
1589 },1582 },
1590 .Elaborated => {1583 .Elaborated => {
...@@ -1653,11 +1646,11 @@ fn transReturnStmt(...@@ -1653,11 +1646,11 @@ fn transReturnStmt(
1653}1646}
16541647
1655fn transStringLiteral(1648fn transStringLiteral(
1656 rp: RestorePoint,1649 c: *Context,
1657 scope: *Scope,1650 scope: *Scope,
1658 stmt: *const clang.StringLiteral,1651 stmt: *const clang.StringLiteral,
1659 result_used: ResultUsed,1652 result_used: ResultUsed,
1660) TransError!*ast.Node {1653) TransError!Node {
1661 const kind = stmt.getKind();1654 const kind = stmt.getKind();
1662 switch (kind) {1655 switch (kind) {
1663 .Ascii, .UTF8 => {1656 .Ascii, .UTF8 => {
...@@ -1665,55 +1658,28 @@ fn transStringLiteral(...@@ -1665,55 +1658,28 @@ fn transStringLiteral(
1665 const bytes_ptr = stmt.getString_bytes_begin_size(&len);1658 const bytes_ptr = stmt.getString_bytes_begin_size(&len);
1666 const str = bytes_ptr[0..len];1659 const str = bytes_ptr[0..len];
16671660
1668 const token = try appendTokenFmt(rp.c, .StringLiteral, "\"{}\"", .{std.zig.fmtEscapes(str)});1661 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)});
1669 const node = try rp.c.arena.create(ast.Node.OneToken);1662 const node = try Node.string_literal.create(c.arena, str);
1670 node.* = .{1663 return maybeSuppressResult(c, scope, result_used, node);
1671 .base = .{ .tag = .StringLiteral },
1672 .token = token,
1673 };
1674 return maybeSuppressResult(rp, scope, result_used, &node.base);
1675 },1664 },
1676 .UTF16, .UTF32, .Wide => {1665 .UTF16, .UTF32, .Wide => {
1677 const node = try transWideStringLiteral(rp, scope, stmt);1666 const str_type = @tagName(stmt.getKind());
1678 return maybeSuppressResult(rp, scope, result_used, node);1667 const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() });
1668 const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1);
1669
1670 const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array });
1671 try scope.appendNode(name, decl);
1672 const node = try Node.identifier.create(c.arena, name);
1673 return maybeSuppressResult(c, scope, result_used, node);
1679 },1674 },
1680 }1675 }
1681}1676}
16821677
1683/// Translates a wide string literal as a global "anonymous" array of the relevant-sized
1684/// integer type + null terminator, and returns an identifier node for it
1685fn transWideStringLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.StringLiteral) TransError!*ast.Node {
1686 const str_type = @tagName(stmt.getKind());
1687 const mangle = rp.c.getMangle();
1688 const name = try std.fmt.allocPrint(rp.c.arena, "zig.{s}_string_{d}", .{ str_type, mangle });
1689
1690 const const_tok = try appendToken(rp.c, .Keyword_const, "const");
1691 const name_tok = try appendIdentifier(rp.c, name);
1692 const eq_tok = try appendToken(rp.c, .Equal, "=");
1693 var semi_tok: ast.TokenIndex = undefined;
1694
1695 const lit_array = try transStringLiteralAsArray(rp, scope, stmt, stmt.getLength() + 1);
1696
1697 semi_tok = try appendToken(rp.c, .Semicolon, ";");
1698 const var_decl_node = try ast.Node.VarDecl.create(rp.c.arena, .{
1699 .name_token = name_tok,
1700 .mut_token = const_tok,
1701 .semicolon_token = semi_tok,
1702 }, .{
1703 .visib_token = null,
1704 .eq_token = eq_tok,
1705 .init_node = lit_array,
1706 });
1707 try addTopLevelDecl(rp.c, name, &var_decl_node.base);
1708 return transCreateNodeIdentifier(rp.c, name);
1709}
1710
1711/// Parse the size of an array back out from an ast Node.1678/// Parse the size of an array back out from an ast Node.
1712fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize {1679fn zigArraySize(c: *Context, node: Node) TransError!usize {
1713 if (node.castTag(.ArrayType)) |array| {1680 if (node.castTag(.array_type)) |array| {
1714 if (array.len_expr.castTag(.IntegerLiteral)) |int_lit| {1681 if (array.data.len.castTag(.int_literal)) |int_lit| {
1715 const tok = tokenSlice(c, int_lit.token);1682 return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation;
1716 return std.fmt.parseUnsigned(usize, tok, 10) catch error.UnsupportedTranslation;
1717 }1683 }
1718 }1684 }
1719 return error.UnsupportedTranslation;1685 return error.UnsupportedTranslation;
...@@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize {...@@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize {
1725/// than the array, truncate the string. If the array is larger than the1691/// than the array, truncate the string. If the array is larger than the
1726/// string literal, pad the array with 0's1692/// string literal, pad the array with 0's
1727fn transStringLiteralAsArray(1693fn transStringLiteralAsArray(
1728 rp: RestorePoint,1694 c: *Context,
1729 scope: *Scope,1695 scope: *Scope,
1730 stmt: *const clang.StringLiteral,1696 stmt: *const clang.StringLiteral,
1731 array_size: usize,1697 array_size: usize,
1732) TransError!*ast.Node {1698) TransError!Node {
1733 if (array_size == 0) return error.UnsupportedType;1699 if (array_size == 0) return error.UnsupportedType;
17341700
1735 const str_length = stmt.getLength();1701 const str_length = stmt.getLength();
...@@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray(...@@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray(
1738 const ty = expr_base.getType().getTypePtr();1704 const ty = expr_base.getType().getTypePtr();
1739 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);1705 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
17401706
1741 const ty_node = try rp.c.arena.create(ast.Node.ArrayType);1707 const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());
1742 const op_token = try appendToken(rp.c, .LBracket, "[");1708 const init_list = try c.arena.alloc(Node, array_size);
1743 const len_expr = try transCreateNodeInt(rp.c, array_size);
1744 _ = try appendToken(rp.c, .RBracket, "]");
1745
1746 ty_node.* = .{
1747 .op_token = op_token,
1748 .rhs = try transQualType(rp, const_arr_ty.getElementType(), expr_base.getBeginLoc()),
1749 .len_expr = len_expr,
1750 };
1751 _ = try appendToken(rp.c, .LBrace, "{");
1752 var init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, array_size);
1753 init_node.* = .{
1754 .lhs = &ty_node.base,
1755 .rtoken = undefined,
1756 .list_len = array_size,
1757 };
1758 const init_list = init_node.list();
17591709
1760 var i: c_uint = 0;1710 var i: c_uint = 0;
1761 const kind = stmt.getKind();1711 const kind = stmt.getKind();
1762 const narrow = kind == .Ascii or kind == .UTF8;1712 const narrow = kind == .Ascii or kind == .UTF8;
1763 while (i < str_length and i < array_size) : (i += 1) {1713 while (i < str_length and i < array_size) : (i += 1) {
1764 const code_unit = stmt.getCodeUnit(i);1714 const code_unit = stmt.getCodeUnit(i);
1765 init_list[i] = try transCreateCharLitNode(rp.c, narrow, code_unit);1715 init_list[i] = try transCreateCharLitNode(c, narrow, code_unit);
1766 _ = try appendToken(rp.c, .Comma, ",");
1767 }1716 }
1768 while (i < array_size) : (i += 1) {1717 while (i < array_size) : (i += 1) {
1769 init_list[i] = try transCreateNodeInt(rp.c, 0);1718 init_list[i] = try transCreateNodeInt(c, 0);
1770 _ = try appendToken(rp.c, .Comma, ",");
1771 }1719 }
1772 init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
17731720
1774 return &init_node.base;1721 return Node.array_init.create(c.arena, init_list);
1775}1722}
17761723
1777fn cIsEnum(qt: clang.QualType) bool {1724fn cIsEnum(qt: clang.QualType) bool {
...@@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType {...@@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType {
1790}1737}
17911738
1792fn transCCast(1739fn transCCast(
1793 rp: RestorePoint,1740 c: *Context,
1794 scope: *Scope,1741 scope: *Scope,
1795 loc: clang.SourceLocation,1742 loc: clang.SourceLocation,
1796 dst_type: clang.QualType,1743 dst_type: clang.QualType,
1797 src_type: clang.QualType,1744 src_type: clang.QualType,
1798 expr: *ast.Node,1745 expr: Node,
1799) !*ast.Node {1746) !Node {
1800 if (qualTypeCanon(dst_type).isVoidType()) return expr;1747 if (qualTypeCanon(dst_type).isVoidType()) return expr;
1801 if (dst_type.eq(src_type)) return expr;1748 if (dst_type.eq(src_type)) return expr;
1802 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))1749 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
1803 return transCPtrCast(rp, loc, dst_type, src_type, expr);1750 return transCPtrCast(c, loc, dst_type, src_type, expr);
1751
1752 const dst_node = try transQualType(c, dst_type, loc);
1804 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {1753 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {
1805 // 1. If src_type is an enum, determine the underlying signed int type1754 // 1. If src_type is an enum, determine the underlying signed int type
1806 // 2. Extend or truncate without changing signed-ness.1755 // 2. Extend or truncate without changing signed-ness.
1807 // 3. Bit-cast to correct signed-ness1756 // 3. Bit-cast to correct signed-ness
1808 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);1757 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
1809 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);1758 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
1810 var src_int_expr = if (cIsInteger(src_type)) expr else try transEnumToInt(rp.c, expr);1759 var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr);
1811
1812 // @bitCast(dest_type, intermediate_value)
1813 const cast_node = try rp.c.createBuiltinCall("@bitCast", 2);
1814 cast_node.params()[0] = try transQualType(rp, dst_type, loc);
1815 _ = try appendToken(rp.c, .Comma, ",");
18161760
1817 if (isBoolRes(src_int_expr)) {1761 if (isBoolRes(src_int_expr)) {
1818 const bool_to_int_node = try rp.c.createBuiltinCall("@boolToInt", 1);1762 src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr);
1819 bool_to_int_node.params()[0] = src_int_expr;
1820 bool_to_int_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1821 src_int_expr = &bool_to_int_node.base;
1822 }1763 }
18231764
1824 switch (cIntTypeCmp(dst_type, src_int_type)) {1765 switch (cIntTypeCmp(dst_type, src_int_type)) {
1825 .lt => {1766 .lt => {
1826 // @truncate(SameSignSmallerInt, src_int_expr)1767 // @truncate(SameSignSmallerInt, src_int_expr)
1827 const trunc_node = try rp.c.createBuiltinCall("@truncate", 2);1768 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
1828 const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed);1769 src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
1829 trunc_node.params()[0] = ty_node;
1830 _ = try appendToken(rp.c, .Comma, ",");
1831 trunc_node.params()[1] = src_int_expr;
1832 trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1833
1834 cast_node.params()[1] = &trunc_node.base;
1835 },1770 },
1836 .gt => {1771 .gt => {
1837 // @as(SameSignBiggerInt, src_int_expr)1772 // @as(SameSignBiggerInt, src_int_expr)
1838 const as_node = try rp.c.createBuiltinCall("@as", 2);1773 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
1839 const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed);1774 src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
1840 as_node.params()[0] = ty_node;
1841 _ = try appendToken(rp.c, .Comma, ",");
1842 as_node.params()[1] = src_int_expr;
1843 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1844
1845 cast_node.params()[1] = &as_node.base;
1846 },1775 },
1847 .eq => {1776 .eq => {
1848 cast_node.params()[1] = src_int_expr;1777 // src_int_expr = src_int_expr
1849 },1778 },
1850 }1779 }
1851 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");1780 // @bitCast(dest_type, intermediate_value)
1852 return &cast_node.base;1781 return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });
1853 }1782 }
1854 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {1783 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
1855 // @intCast(dest_type, @ptrToInt(val))1784 // @intCast(dest_type, @ptrToInt(val))
1856 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);1785 const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);
1857 cast_node.params()[0] = try transQualType(rp, dst_type, loc);1786 return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
1858 _ = try appendToken(rp.c, .Comma, ",");
1859 const builtin_node = try rp.c.createBuiltinCall("@ptrToInt", 1);
1860 builtin_node.params()[0] = expr;
1861 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1862 cast_node.params()[1] = &builtin_node.base;
1863 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1864 return &cast_node.base;
1865 }1787 }
1866 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {1788 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
1867 // @intToPtr(dest_type, val)1789 // @intToPtr(dest_type, val)
1868 const builtin_node = try rp.c.createBuiltinCall("@intToPtr", 2);1790 return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1869 builtin_node.params()[0] = try transQualType(rp, dst_type, loc);
1870 _ = try appendToken(rp.c, .Comma, ",");
1871 builtin_node.params()[1] = expr;
1872 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1873 return &builtin_node.base;
1874 }1791 }
1875 if (cIsFloating(src_type) and cIsFloating(dst_type)) {1792 if (cIsFloating(src_type) and cIsFloating(dst_type)) {
1876 const builtin_node = try rp.c.createBuiltinCall("@floatCast", 2);1793 // @floatCast(dest_type, val)
1877 builtin_node.params()[0] = try transQualType(rp, dst_type, loc);1794 return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1878 _ = try appendToken(rp.c, .Comma, ",");
1879 builtin_node.params()[1] = expr;
1880 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1881 return &builtin_node.base;
1882 }1795 }
1883 if (cIsFloating(src_type) and !cIsFloating(dst_type)) {1796 if (cIsFloating(src_type) and !cIsFloating(dst_type)) {
1884 const builtin_node = try rp.c.createBuiltinCall("@floatToInt", 2);1797 // @floatToInt(dest_type, val)
1885 builtin_node.params()[0] = try transQualType(rp, dst_type, loc);1798 return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1886 _ = try appendToken(rp.c, .Comma, ",");
1887 builtin_node.params()[1] = expr;
1888 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1889 return &builtin_node.base;
1890 }1799 }
1891 if (!cIsFloating(src_type) and cIsFloating(dst_type)) {1800 if (!cIsFloating(src_type) and cIsFloating(dst_type)) {
1892 const builtin_node = try rp.c.createBuiltinCall("@intToFloat", 2);1801 // @intToFloat(dest_type, val)
1893 builtin_node.params()[0] = try transQualType(rp, dst_type, loc);1802 return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1894 _ = try appendToken(rp.c, .Comma, ",");
1895 builtin_node.params()[1] = expr;
1896 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1897 return &builtin_node.base;
1898 }1803 }
1899 if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {1804 if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {
1900 // @boolToInt returns either a comptime_int or a u11805 // @boolToInt returns either a comptime_int or a u1
1901 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast1806 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast
1902 // instead of @as1807 // instead of @as
1903 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);1808 const bool_to_int = Node.bool_to_int.create(c.arena, expr);
1904 builtin_node.params()[0] = expr;1809 return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
1905 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1906
1907 const as_node = try rp.c.createBuiltinCall("@as", 2);
1908 as_node.params()[0] = try transQualType(rp, dst_type, loc);
1909 _ = try appendToken(rp.c, .Comma, ",");
1910 as_node.params()[1] = &builtin_node.base;
1911 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1912
1913 return &as_node.base;
1914 }1810 }
1915 if (cIsEnum(dst_type)) {1811 if (cIsEnum(dst_type)) {
1916 const builtin_node = try rp.c.createBuiltinCall("@intToEnum", 2);1812 // @intToEnum(dest_type, val)
1917 builtin_node.params()[0] = try transQualType(rp, dst_type, loc);1813 return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1918 _ = try appendToken(rp.c, .Comma, ",");
1919 builtin_node.params()[1] = expr;
1920 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1921 return &builtin_node.base;
1922 }1814 }
1923 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {1815 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
1924 return transEnumToInt(rp.c, expr);1816 // @enumToInt(val)
1817 return Node.enum_to_int.create(c.arena, expr);
1925 }1818 }
1926 const cast_node = try rp.c.createBuiltinCall("@as", 2);1819 // @as(dest_type, val)
1927 cast_node.params()[0] = try transQualType(rp, dst_type, loc);1820 return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1928 _ = try appendToken(rp.c, .Comma, ",");
1929 cast_node.params()[1] = expr;
1930 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1931 return &cast_node.base;
1932}
1933
1934fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node {
1935 const builtin_node = try c.createBuiltinCall("@enumToInt", 1);
1936 builtin_node.params()[0] = enum_expr;
1937 builtin_node.rparen_token = try appendToken(c, .RParen, ")");
1938 return &builtin_node.base;
1939}1821}
19401822
1941fn transExpr(1823fn transExpr(
...@@ -1976,13 +1858,12 @@ fn transExprCoercing(...@@ -1976,13 +1858,12 @@ fn transExprCoercing(
1976}1858}
19771859
1978fn transInitListExprRecord(1860fn transInitListExprRecord(
1979 rp: RestorePoint,1861 c: *Context,
1980 scope: *Scope,1862 scope: *Scope,
1981 loc: clang.SourceLocation,1863 loc: clang.SourceLocation,
1982 expr: *const clang.InitListExpr,1864 expr: *const clang.InitListExpr,
1983 ty: *const clang.Type,1865 ty: *const clang.Type,
1984 used: ResultUsed,1866) TransError!Node {
1985) TransError!*ast.Node {
1986 var is_union_type = false;1867 var is_union_type = false;
1987 // Unions and Structs are both represented as RecordDecl1868 // Unions and Structs are both represented as RecordDecl
1988 const record_ty = ty.getAsRecordType() orelse1869 const record_ty = ty.getAsRecordType() orelse
...@@ -1994,13 +1875,11 @@ fn transInitListExprRecord(...@@ -1994,13 +1875,11 @@ fn transInitListExprRecord(
1994 const record_def = record_decl.getDefinition() orelse1875 const record_def = record_decl.getDefinition() orelse
1995 unreachable;1876 unreachable;
19961877
1997 const ty_node = try transType(rp, ty, loc);1878 const ty_node = try transType(c, ty, loc);
1998 const init_count = expr.getNumInits();1879 const init_count = expr.getNumInits();
1999 var field_inits = std.ArrayList(*ast.Node).init(rp.c.gpa);1880 var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa);
2000 defer field_inits.deinit();1881 defer field_inits.deinit();
20011882
2002 _ = try appendToken(rp.c, .LBrace, "{");
2003
2004 var init_i: c_uint = 0;1883 var init_i: c_uint = 0;
2005 var it = record_def.field_begin();1884 var it = record_def.field_begin();
2006 const end_it = record_def.field_end();1885 const end_it = record_def.field_end();
...@@ -2018,76 +1897,28 @@ fn transInitListExprRecord(...@@ -2018,76 +1897,28 @@ fn transInitListExprRecord(
20181897
2019 // Generate the field assignment expression:1898 // Generate the field assignment expression:
2020 // .field_name = expr1899 // .field_name = expr
2021 const period_tok = try appendToken(rp.c, .Period, ".");1900 var raw_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin());
2022
2023 var raw_name = try rp.c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin());
2024 if (field_decl.isAnonymousStructOrUnion()) {1901 if (field_decl.isAnonymousStructOrUnion()) {
2025 const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;1902 const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;
2026 raw_name = try mem.dupe(rp.c.arena, u8, name);1903 raw_name = try mem.dupe(c.arena, u8, name);
2027 }1904 }
2028 const field_name_tok = try appendIdentifier(rp.c, raw_name);
2029
2030 _ = try appendToken(rp.c, .Equal, "=");
2031
2032 const field_init_node = try rp.c.arena.create(ast.Node.FieldInitializer);
2033 field_init_node.* = .{
2034 .period_token = period_tok,
2035 .name_token = field_name_tok,
2036 .expr = try transExpr(rp, scope, elem_expr, .used, .r_value),
2037 };
20381905
2039 try field_inits.append(&field_init_node.base);1906 try field_inits.append(.{
2040 _ = try appendToken(rp.c, .Comma, ",");1907 .name = raw_name,
1908 .value = try transExpr(c, scope, elem_expr, .used, .r_value),
1909 });
2041 }1910 }
20421911
2043 const node = try ast.Node.StructInitializer.alloc(rp.c.arena, field_inits.items.len);1912 return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));
2044 node.* = .{
2045 .lhs = ty_node,
2046 .rtoken = try appendToken(rp.c, .RBrace, "}"),
2047 .list_len = field_inits.items.len,
2048 };
2049 mem.copy(*ast.Node, node.list(), field_inits.items);
2050 return &node.base;
2051}
2052
2053fn transCreateNodeArrayType(
2054 rp: RestorePoint,
2055 source_loc: clang.SourceLocation,
2056 ty: *const clang.Type,
2057 len: anytype,
2058) !*ast.Node {
2059 const node = try rp.c.arena.create(ast.Node.ArrayType);
2060 const op_token = try appendToken(rp.c, .LBracket, "[");
2061 const len_expr = try transCreateNodeInt(rp.c, len);
2062 _ = try appendToken(rp.c, .RBracket, "]");
2063 node.* = .{
2064 .op_token = op_token,
2065 .rhs = try transType(rp, ty, source_loc),
2066 .len_expr = len_expr,
2067 };
2068 return &node.base;
2069}
2070
2071fn transCreateEmptyArray(rp: RestorePoint, loc: clang.SourceLocation, ty: *const clang.Type) TransError!*ast.Node {
2072 const ty_node = try transCreateNodeArrayType(rp, loc, ty, 0);
2073 _ = try appendToken(rp.c, .LBrace, "{");
2074 const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 0);
2075 filler_init_node.* = .{
2076 .lhs = ty_node,
2077 .rtoken = try appendToken(rp.c, .RBrace, "}"),
2078 .list_len = 0,
2079 };
2080 return &filler_init_node.base;
2081}1913}
20821914
2083fn transInitListExprArray(1915fn transInitListExprArray(
2084 rp: RestorePoint,1916 c: *Context,
2085 scope: *Scope,1917 scope: *Scope,
2086 loc: clang.SourceLocation,1918 loc: clang.SourceLocation,
2087 expr: *const clang.InitListExpr,1919 expr: *const clang.InitListExpr,
2088 ty: *const clang.Type,1920 ty: *const clang.Type,
2089 used: ResultUsed,1921) TransError!Node {
2090) TransError!*ast.Node {
2091 const arr_type = ty.getAsArrayTypeUnsafe();1922 const arr_type = ty.getAsArrayTypeUnsafe();
2092 const child_qt = arr_type.getElementType();1923 const child_qt = arr_type.getElementType();
2093 const init_count = expr.getNumInits();1924 const init_count = expr.getNumInits();
...@@ -2098,111 +1929,67 @@ fn transInitListExprArray(...@@ -2098,111 +1929,67 @@ fn transInitListExprArray(
2098 const leftover_count = all_count - init_count;1929 const leftover_count = all_count - init_count;
20991930
2100 if (all_count == 0) {1931 if (all_count == 0) {
2101 return transCreateEmptyArray(rp, loc, child_qt.getTypePtr());1932 return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc));
2102 }1933 }
1934
1935 const ty_node = try transType(ty);
1936 const init_node = if (init_count != 0) blk: {
1937 const init_list = try c.arena.alloc(Node, init_count);
21031938
2104 var init_node: *ast.Node.ArrayInitializer = undefined;1939 for (init_list) |*init, i| {
2105 var cat_tok: ast.TokenIndex = undefined;
2106 if (init_count != 0) {
2107 const ty_node = try transCreateNodeArrayType(
2108 rp,
2109 loc,
2110 child_qt.getTypePtr(),
2111 init_count,
2112 );
2113 _ = try appendToken(rp.c, .LBrace, "{");
2114 init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, init_count);
2115 init_node.* = .{
2116 .lhs = ty_node,
2117 .rtoken = undefined,
2118 .list_len = init_count,
2119 };
2120 const init_list = init_node.list();
2121
2122 var i: c_uint = 0;
2123 while (i < init_count) : (i += 1) {
2124 const elem_expr = expr.getInit(i);1940 const elem_expr = expr.getInit(i);
2125 init_list[i] = try transExpr(rp, scope, elem_expr, .used, .r_value);1941 init.* = try transExpr(c, scope, elem_expr, .used, .r_value);
2126 _ = try appendToken(rp.c, .Comma, ",");
2127 }1942 }
2128 init_node.rtoken = try appendToken(rp.c, .RBrace, "}");1943 const init_node = try Node.array_init.create(c.arena, init_list);
2129 if (leftover_count == 0) {1944 if (leftover_count == 0) {
2130 return &init_node.base;1945 return init_node;
2131 }1946 }
2132 cat_tok = try appendToken(rp.c, .PlusPlus, "++");1947 break :blk init_node;
2133 }1948 } else null;
21341949
2135 const ty_node = try transCreateNodeArrayType(rp, loc, child_qt.getTypePtr(), 1);
2136 _ = try appendToken(rp.c, .LBrace, "{");
2137 const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 1);
2138 filler_init_node.* = .{
2139 .lhs = ty_node,
2140 .rtoken = undefined,
2141 .list_len = 1,
2142 };
2143 const filler_val_expr = expr.getArrayFiller();1950 const filler_val_expr = expr.getArrayFiller();
2144 filler_init_node.list()[0] = try transExpr(rp, scope, filler_val_expr, .used, .r_value);1951 const filler_node = try Node.array_filler.create(c.arena, .{
2145 filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");1952 .type = ty_node,
21461953 .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value),
2147 const rhs_node = if (leftover_count == 1)1954 .count = leftover_count,
2148 &filler_init_node.base1955 });
2149 else blk: {
2150 const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**");
2151 const mul_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
2152 mul_node.* = .{
2153 .base = .{ .tag = .ArrayMult },
2154 .op_token = mul_tok,
2155 .lhs = &filler_init_node.base,
2156 .rhs = try transCreateNodeInt(rp.c, leftover_count),
2157 };
2158 break :blk &mul_node.base;
2159 };
21601956
2161 if (init_count == 0) {1957 if (init_node) |some| {
2162 return rhs_node;1958 return Node.array_cat.create(c.arena, some, filler_node);
1959 } else {
1960 return filler_node;
2163 }1961 }
2164
2165 const cat_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
2166 cat_node.* = .{
2167 .base = .{ .tag = .ArrayCat },
2168 .op_token = cat_tok,
2169 .lhs = &init_node.base,
2170 .rhs = rhs_node,
2171 };
2172 return &cat_node.base;
2173}1962}
21741963
2175fn transInitListExpr(1964fn transInitListExpr(
2176 rp: RestorePoint,1965 c: *Context,
2177 scope: *Scope,1966 scope: *Scope,
2178 expr: *const clang.InitListExpr,1967 expr: *const clang.InitListExpr,
2179 used: ResultUsed,1968 used: ResultUsed,
2180) TransError!*ast.Node {1969) TransError!Node {
2181 const qt = getExprQualType(rp.c, @ptrCast(*const clang.Expr, expr));1970 const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr));
2182 var qual_type = qt.getTypePtr();1971 var qual_type = qt.getTypePtr();
2183 const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc();1972 const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc();
21841973
2185 if (qual_type.isRecordType()) {1974 if (qual_type.isRecordType()) {
2186 return transInitListExprRecord(1975 return maybeSuppressResult(c, scope, used, try transInitListExprRecord(
2187 rp,1976 rp,
2188 scope,1977 scope,
2189 source_loc,1978 source_loc,
2190 expr,1979 expr,
2191 qual_type,1980 qual_type,
2192 used,1981 ));
2193 );
2194 } else if (qual_type.isArrayType()) {1982 } else if (qual_type.isArrayType()) {
2195 return transInitListExprArray(1983 return maybeSuppressResult(c, scope, used, try transInitListExprArray(
2196 rp,1984 rp,
2197 scope,1985 scope,
2198 source_loc,1986 source_loc,
2199 expr,1987 expr,
2200 qual_type,1988 qual_type,
2201 used,1989 ));
2202 );
2203 } else {1990 } else {
2204 const type_name = rp.c.str(qual_type.getTypeClassName());1991 const type_name = c.str(qual_type.getTypeClassName());
2205 return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name});1992 return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name});
2206 }1993 }
2207}1994}
22081995
...@@ -2259,15 +2046,15 @@ fn transZeroInitExpr(...@@ -2259,15 +2046,15 @@ fn transZeroInitExpr(
2259}2046}
22602047
2261fn transImplicitValueInitExpr(2048fn transImplicitValueInitExpr(
2262 rp: RestorePoint,2049 c: *Context,
2263 scope: *Scope,2050 scope: *Scope,
2264 expr: *const clang.Expr,2051 expr: *const clang.Expr,
2265 used: ResultUsed,2052 used: ResultUsed,
2266) TransError!*ast.Node {2053) TransError!Node {
2267 const source_loc = expr.getBeginLoc();2054 const source_loc = expr.getBeginLoc();
2268 const qt = getExprQualType(rp.c, expr);2055 const qt = getExprQualType(c, expr);
2269 const ty = qt.getTypePtr();2056 const ty = qt.getTypePtr();
2270 return transZeroInitExpr(rp, scope, source_loc, ty);2057 return transZeroInitExpr(c, scope, source_loc, ty);
2271}2058}
22722059
2273fn transIfStmt(2060fn transIfStmt(
src/translate_c/ast.zig+45
...@@ -104,6 +104,7 @@ pub const Node = extern union {...@@ -104,6 +104,7 @@ pub const Node = extern union {
104 bit_and,104 bit_and,
105 bit_or,105 bit_or,
106 bit_xor,106 bit_xor,
107 array_cat,
107108
108 log2_int_type,109 log2_int_type,
109 /// @import("std").math.Log2Int(operand)110 /// @import("std").math.Log2Int(operand)
...@@ -118,6 +119,24 @@ pub const Node = extern union {...@@ -118,6 +119,24 @@ pub const Node = extern union {
118 bool_to_int,119 bool_to_int,
119 /// @as(lhs, rhs)120 /// @as(lhs, rhs)
120 as,121 as,
122 /// @truncate(lhs, rhs)
123 truncate,
124 /// @bitCast(lhs, rhs)
125 bit_cast,
126 /// @floatCast(lhs, rhs)
127 float_cast,
128 /// @floatToInt(lhs, rhs)
129 float_to_int,
130 /// @intToFloat(lhs, rhs)
131 int_to_float,
132 /// @intToEnum(lhs, rhs)
133 int_to_enum,
134 /// @enumToInt(operand)
135 enum_to_int,
136 /// @intToPtr(lhs, rhs)
137 int_to_ptr,
138 /// @ptrToInt(operand)
139 ptr_to_int,
121140
122 negate,141 negate,
123 negate_wrap,142 negate_wrap,
...@@ -154,6 +173,11 @@ pub const Node = extern union {...@@ -154,6 +173,11 @@ pub const Node = extern union {
154 /// pub const enum_field_name = @enumToInt(enum_name.field_name);173 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
155 enum_redecl,174 enum_redecl,
156175
176 /// [0]type{}
177 empty_array,
178 /// [1]type{val} ** count
179 array_filler,
180
157 pub const last_no_payload_tag = Tag.usingnamespace_builtins;181 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
158 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;182 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
159183
...@@ -184,6 +208,9 @@ pub const Node = extern union {...@@ -184,6 +208,9 @@ pub const Node = extern union {
184 .optional_type,208 .optional_type,
185 .address_of,209 .address_of,
186 .unwrap_deref,210 .unwrap_deref,
211 .ptr_to_int,
212 .enum_to_int,
213 .empty_array,
187 => Payload.UnOp,214 => Payload.UnOp,
188215
189 .add,216 .add,
...@@ -239,6 +266,14 @@ pub const Node = extern union {...@@ -239,6 +266,14 @@ pub const Node = extern union {
239 .int_cast,266 .int_cast,
240 .bool_to_int,267 .bool_to_int,
241 .as,268 .as,
269 .truncate,
270 .bit_cast,
271 .float_cast,
272 .float_to_int,
273 .int_to_float,
274 .int_to_enum,
275 .int_to_ptr,
276 .array_cat,
242 => Payload.BinOp,277 => Payload.BinOp,
243278
244 .int,279 .int,
...@@ -274,6 +309,7 @@ pub const Node = extern union {...@@ -274,6 +309,7 @@ pub const Node = extern union {
274 .log2_int_type => Payload.Log2IntType,309 .log2_int_type => Payload.Log2IntType,
275 .typedef, .pub_typedef, .pub_var_simple => Payload.SimpleVarDecl,310 .typedef, .pub_typedef, .pub_var_simple => Payload.SimpleVarDecl,
276 .enum_redecl => Payload.EnumRedecl,311 .enum_redecl => Payload.EnumRedecl,
312 .array_filler => Payload.ArrayFiller,
277 };313 };
278 }314 }
279315
...@@ -533,6 +569,15 @@ pub const Payload = struct {...@@ -533,6 +569,15 @@ pub const Payload = struct {
533 enum_name: []const u8,569 enum_name: []const u8,
534 },570 },
535 };571 };
572
573 pub const ArrayFiller = struct {
574 base: Node,
575 data: struct {
576 type: Node,
577 filler: Node,
578 count: usize,
579 },
580 };
536};581};
537582
538/// Converts the nodes into a Zig ast.583/// Converts the nodes into a Zig ast.