authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-08 11:07:44+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:02+02:00
logbb867b071a9e2fa69f39a45532dffa0f51ffdbfd
tree493ab077cfcf1501a2fa17692b83178f74eb6489
parentf36849fed24b54476ecadacb52d9a1b55ae14274
signature Commit is signed but in an unrecognized format.

translate-c: convert vardecl and typedef


3 files changed, 233 insertions(+), 308 deletions(-)

src/astgen.zig+32-38
...@@ -2664,8 +2664,11 @@ fn identifier(...@@ -2664,8 +2664,11 @@ fn identifier(
2664 return mod.failNode(scope, ident, "TODO implement '_' identifier", .{});2664 return mod.failNode(scope, ident, "TODO implement '_' identifier", .{});
2665 }2665 }
26662666
2667 if (getSimplePrimitiveValue(ident_name)) |typed_value| {2667 if (simple_types.get(ident_name)) |val_tag| {
2668 const result = try addZIRInstConst(mod, scope, src, typed_value);2668 const result = try addZIRInstConst(mod, scope, src, TypedValue{
2669 .ty = Type.initTag(.type),
2670 .val = Value.initTag(val_tag),
2671 });
2669 return rvalue(mod, scope, rl, result);2672 return rvalue(mod, scope, rl, result);
2670 }2673 }
26712674
...@@ -3325,42 +3328,33 @@ fn callExpr(...@@ -3325,42 +3328,33 @@ fn callExpr(
3325 return rvalue(mod, scope, rl, result);3328 return rvalue(mod, scope, rl, result);
3326}3329}
33273330
3328fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {3331pub const simple_types = std.ComptimeStringMap(Value.Tag, .{
3329 const simple_types = std.ComptimeStringMap(Value.Tag, .{3332 .{ "u8", .u8_type },
3330 .{ "u8", .u8_type },3333 .{ "i8", .i8_type },
3331 .{ "i8", .i8_type },3334 .{ "isize", .isize_type },
3332 .{ "isize", .isize_type },3335 .{ "usize", .usize_type },
3333 .{ "usize", .usize_type },3336 .{ "c_short", .c_short_type },
3334 .{ "c_short", .c_short_type },3337 .{ "c_ushort", .c_ushort_type },
3335 .{ "c_ushort", .c_ushort_type },3338 .{ "c_int", .c_int_type },
3336 .{ "c_int", .c_int_type },3339 .{ "c_uint", .c_uint_type },
3337 .{ "c_uint", .c_uint_type },3340 .{ "c_long", .c_long_type },
3338 .{ "c_long", .c_long_type },3341 .{ "c_ulong", .c_ulong_type },
3339 .{ "c_ulong", .c_ulong_type },3342 .{ "c_longlong", .c_longlong_type },
3340 .{ "c_longlong", .c_longlong_type },3343 .{ "c_ulonglong", .c_ulonglong_type },
3341 .{ "c_ulonglong", .c_ulonglong_type },3344 .{ "c_longdouble", .c_longdouble_type },
3342 .{ "c_longdouble", .c_longdouble_type },3345 .{ "f16", .f16_type },
3343 .{ "f16", .f16_type },3346 .{ "f32", .f32_type },
3344 .{ "f32", .f32_type },3347 .{ "f64", .f64_type },
3345 .{ "f64", .f64_type },3348 .{ "f128", .f128_type },
3346 .{ "f128", .f128_type },3349 .{ "c_void", .c_void_type },
3347 .{ "c_void", .c_void_type },3350 .{ "bool", .bool_type },
3348 .{ "bool", .bool_type },3351 .{ "void", .void_type },
3349 .{ "void", .void_type },3352 .{ "type", .type_type },
3350 .{ "type", .type_type },3353 .{ "anyerror", .anyerror_type },
3351 .{ "anyerror", .anyerror_type },3354 .{ "comptime_int", .comptime_int_type },
3352 .{ "comptime_int", .comptime_int_type },3355 .{ "comptime_float", .comptime_float_type },
3353 .{ "comptime_float", .comptime_float_type },3356 .{ "noreturn", .noreturn_type },
3354 .{ "noreturn", .noreturn_type },3357});
3355 });
3356 if (simple_types.get(name)) |tag| {
3357 return TypedValue{
3358 .ty = Type.initTag(.type),
3359 .val = Value.initTag(tag),
3360 };
3361 }
3362 return null;
3363}
33643358
3365fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {3359fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
3366 var node = start_node;3360 var node = start_node;
src/translate_c.zig+170-259
...@@ -614,25 +614,21 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -614,25 +614,21 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
614 return addTopLevelDecl(c, fn_name, &proto_node.base);614 return addTopLevelDecl(c, fn_name, &proto_node.base);
615}615}
616616
617fn transQualTypeMaybeInitialized(rp: RestorePoint, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!*ast.Node {617fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {
618 return if (decl_init) |init_expr|618 return if (decl_init) |init_expr|
619 transQualTypeInitialized(rp, qt, init_expr, loc)619 transQualTypeInitialized(c, qt, init_expr, loc)
620 else620 else
621 transQualType(rp, qt, loc);621 transQualType(c, qt, loc);
622}622}
623
623/// if mangled_name is not null, this var decl was declared in a block scope.624/// if mangled_name is not null, this var decl was declared in a block scope.
624fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]const u8) Error!void {625fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]const u8) Error!void {
625 const var_name = mangled_name orelse try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());626 const var_name = mangled_name orelse try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());
626 if (c.global_scope.sym_table.contains(var_name))627 if (c.global_scope.sym_table.contains(var_name))
627 return; // Avoid processing this decl twice628 return; // Avoid processing this decl twice
628 const rp = makeRestorePoint(c);
629 const visib_tok = if (mangled_name) |_| null else try appendToken(c, .Keyword_pub, "pub");
630
631 const thread_local_token = if (var_decl.getTLSKind() == .None)
632 null
633 else
634 try appendToken(c, .Keyword_threadlocal, "threadlocal");
635629
630 const is_pub = mangled_name == null;
631 const is_thread_local = var_decl.getTLSKind() != .None;
636 const scope = &c.global_scope.base;632 const scope = &c.global_scope.base;
637633
638 // TODO https://github.com/ziglang/zig/issues/3756634 // TODO https://github.com/ziglang/zig/issues/3756
...@@ -651,42 +647,27 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -651,42 +647,27 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
651 // does the same as:647 // does the same as:
652 // extern int foo;648 // extern int foo;
653 // int foo = 2;649 // int foo = 2;
654 const extern_tok = if (storage_class == .Extern and !has_init)650 const is_extern = storage_class == .Extern and !has_init;
655 try appendToken(c, .Keyword_extern, "extern")651 const is_export = !is_extern and storage_class != .Static;
656 else if (storage_class != .Static)
657 try appendToken(c, .Keyword_export, "export")
658 else
659 null;
660
661 const mut_tok = if (is_const)
662 try appendToken(c, .Keyword_const, "const")
663 else
664 try appendToken(c, .Keyword_var, "var");
665652
666 const name_tok = try appendIdentifier(c, checked_name);653 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
667
668 _ = try appendToken(c, .Colon, ":");
669
670 const type_node = transQualTypeMaybeInitialized(rp, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
671 error.UnsupportedTranslation, error.UnsupportedType => {654 error.UnsupportedTranslation, error.UnsupportedType => {
672 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});655 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
673 },656 },
674 error.OutOfMemory => |e| return e,657 error.OutOfMemory => |e| return e,
675 };658 };
676659
677 var eq_tok: ast.TokenIndex = undefined;660 var init_node: ?Node = null;
678 var init_node: ?*ast.Node = null;
679661
680 // If the initialization expression is not present, initialize with undefined.662 // If the initialization expression is not present, initialize with undefined.
681 // If it is an integer literal, we can skip the @as since it will be redundant663 // If it is an integer literal, we can skip the @as since it will be redundant
682 // with the variable type.664 // with the variable type.
683 if (has_init) {665 if (has_init) {
684 eq_tok = try appendToken(c, .Equal, "=");
685 if (decl_init) |expr| {666 if (decl_init) |expr| {
686 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)667 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)
687 transStringLiteralAsArray(rp, &c.global_scope.base, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(rp.c, type_node) catch 0)668 transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)
688 else669 else
689 transExprCoercing(rp, scope, expr, .used, .r_value);670 transExprCoercing(c, scope, expr, .used, .r_value);
690 init_node = node_or_error catch |err| switch (err) {671 init_node = node_or_error catch |err| switch (err) {
691 error.UnsupportedTranslation,672 error.UnsupportedTranslation,
692 error.UnsupportedType,673 error.UnsupportedType,
...@@ -695,118 +676,83 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -695,118 +676,83 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
695 },676 },
696 error.OutOfMemory => |e| return e,677 error.OutOfMemory => |e| return e,
697 };678 };
679 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
680 init_node = try Node.bool_to_int.create(c.arena, init_node);
681 }
698 } else {682 } else {
699 init_node = try transCreateNodeUndefinedLiteral(c);683 init_node = Node.undefined_literal.init();
700 }684 }
701 } else if (storage_class != .Extern) {685 } else if (storage_class != .Extern) {
702 eq_tok = try appendToken(c, .Equal, "=");
703 // The C language specification states that variables with static or threadlocal686 // The C language specification states that variables with static or threadlocal
704 // storage without an initializer are initialized to a zero value.687 // storage without an initializer are initialized to a zero value.
705688
706 // @import("std").mem.zeroes(T)689 // @import("std").mem.zeroes(T)
707 const import_fn_call = try c.createBuiltinCall("@import", 1);690 init_node = try Node.std_mem_zeroes.create(c.arena, type_node);
708 const std_node = try transCreateNodeStringLiteral(c, "\"std\"");
709 import_fn_call.params()[0] = std_node;
710 import_fn_call.rparen_token = try appendToken(c, .RParen, ")");
711 const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem");
712 const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroes");
713
714 const zero_init_call = try c.createCall(outer_field_access, 1);
715 zero_init_call.params()[0] = type_node;
716 zero_init_call.rtoken = try appendToken(c, .RParen, ")");
717
718 init_node = &zero_init_call.base;
719 }691 }
720692
721 const linksection_expr = blk: {693 const linksection_string = blk: {
722 var str_len: usize = undefined;694 var str_len: usize = undefined;
723 if (var_decl.getSectionAttribute(&str_len)) |str_ptr| {695 if (var_decl.getSectionAttribute(&str_len)) |str_ptr| {
724 _ = try appendToken(rp.c, .Keyword_linksection, "linksection");696 break :blk str_ptr[0..str_len];
725 _ = try appendToken(rp.c, .LParen, "(");
726 const expr = try transCreateNodeStringLiteral(
727 rp.c,
728 try std.fmt.allocPrint(rp.c.arena, "\"{s}\"", .{str_ptr[0..str_len]}),
729 );
730 _ = try appendToken(rp.c, .RParen, ")");
731
732 break :blk expr;
733 }697 }
734 break :blk null;698 break :blk null;
735 };699 };
736700
737 const align_expr = blk: {701 const alignment = blk: {
738 const alignment = var_decl.getAlignedAttribute(rp.c.clang_context);702 const alignment = var_decl.getAlignedAttribute(c.clang_context);
739 if (alignment != 0) {703 if (alignment != 0) {
740 _ = try appendToken(rp.c, .Keyword_align, "align");
741 _ = try appendToken(rp.c, .LParen, "(");
742 // Clang reports the alignment in bits704 // Clang reports the alignment in bits
743 const expr = try transCreateNodeInt(rp.c, alignment / 8);705 break :blk alignment / 8;
744 _ = try appendToken(rp.c, .RParen, ")");
745
746 break :blk expr;
747 }706 }
748 break :blk null;707 break :blk null;
749 };708 };
750709
751 const node = try ast.Node.VarDecl.create(c.arena, .{710 const node = try Node.var_decl.create(c.arena, .{
752 .name_token = name_tok,711 .is_pub = is_pub,
753 .mut_token = mut_tok,712 .is_const = is_const,
754 .semicolon_token = try appendToken(c, .Semicolon, ";"),713 .is_extern = is_extern,
755 }, .{714 .is_export = is_export,
756 .visib_token = visib_tok,715 .linksection_string = linksection_string,
757 .thread_local_token = thread_local_token,716 .alignment = alignment,
758 .eq_token = eq_tok,717 .name = checked_name,
759 .extern_export_token = extern_tok,718 .type = type_node,
760 .type_node = type_node,719 .init = init_node,
761 .align_node = align_expr,
762 .section_node = linksection_expr,
763 .init_node = init_node,
764 });720 });
765 return addTopLevelDecl(c, checked_name, &node.base);721 return addTopLevelDecl(c, checked_name, &node.base);
766}722}
767723
768fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !*ast.Node {724fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {
769 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);725 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
770 return transCreateNodeIdentifier(c, builtin_name);726 return Node.identifier.create(c.arena, builtin_name);
771}727}
772728
773fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 {729const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
774 const table = [_][2][]const u8{730 .{ "uint8_t", "u8" },
775 .{ "uint8_t", "u8" },731 .{ "int8_t", "i8" },
776 .{ "int8_t", "i8" },732 .{ "uint16_t", "u16" },
777 .{ "uint16_t", "u16" },733 .{ "int16_t", "i16" },
778 .{ "int16_t", "i16" },734 .{ "uint32_t", "u32" },
779 .{ "uint32_t", "u32" },735 .{ "int32_t", "i32" },
780 .{ "int32_t", "i32" },736 .{ "uint64_t", "u64" },
781 .{ "uint64_t", "u64" },737 .{ "int64_t", "i64" },
782 .{ "int64_t", "i64" },738 .{ "intptr_t", "isize" },
783 .{ "intptr_t", "isize" },739 .{ "uintptr_t", "usize" },
784 .{ "uintptr_t", "usize" },740 .{ "ssize_t", "isize" },
785 .{ "ssize_t", "isize" },741 .{ "size_t", "usize" },
786 .{ "size_t", "usize" },742});
787 };
788
789 for (table) |entry| {
790 if (mem.eql(u8, checked_name, entry[0])) {
791 return entry[1];
792 }
793 }
794
795 return null;
796}
797743
798fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?*ast.Node {744fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {
799 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|745 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
800 return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice746 return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
801 const rp = makeRestorePoint(c);
802747
803 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());748 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
804749
805 // TODO https://github.com/ziglang/zig/issues/3756750 // TODO https://github.com/ziglang/zig/issues/3756
806 // TODO https://github.com/ziglang/zig/issues/1802751 // TODO https://github.com/ziglang/zig/issues/1802
807 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;752 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;
808 if (checkForBuiltinTypedef(checked_name)) |builtin| {753 if (builtin_typedef_map.get(checked_name)) |builtin| {
809 return transTypeDefAsBuiltin(c, typedef_decl, builtin);754 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
755 return Node.identifier.create(c.arena, builtin);
810 }756 }
811757
812 if (!top_level_visit) {758 if (!top_level_visit) {
...@@ -814,42 +760,36 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev...@@ -814,42 +760,36 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev
814 }760 }
815761
816 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);762 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);
817 const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null;763 const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;
818 try addTopLevelDecl(c, checked_name, node);764 try addTopLevelDecl(c, checked_name, node);
819 return transCreateNodeIdentifier(c, checked_name);765 return transCreateNodeIdentifier(c, checked_name);
820}766}
821767
822fn transCreateNodeTypedef(768fn transCreateNodeTypedef(
823 rp: RestorePoint,769 c: *Context,
824 typedef_decl: *const clang.TypedefNameDecl,770 typedef_decl: *const clang.TypedefNameDecl,
825 toplevel: bool,771 toplevel: bool,
826 checked_name: []const u8,772 checked_name: []const u8,
827) Error!?*ast.Node {773) Error!?Node {
828 const visib_tok = if (toplevel) try appendToken(rp.c, .Keyword_pub, "pub") else null;
829 const mut_tok = try appendToken(rp.c, .Keyword_const, "const");
830 const name_tok = try appendIdentifier(rp.c, checked_name);
831 const eq_token = try appendToken(rp.c, .Equal, "=");
832 const child_qt = typedef_decl.getUnderlyingType();774 const child_qt = typedef_decl.getUnderlyingType();
833 const typedef_loc = typedef_decl.getLocation();775 const typedef_loc = typedef_decl.getLocation();
834 const init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {776 const init_node = transQualType(c, child_qt, typedef_loc) catch |err| switch (err) {
835 error.UnsupportedType => {777 error.UnsupportedType => {
836 try failDecl(rp.c, typedef_loc, checked_name, "unable to resolve typedef child type", .{});778 try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{});
837 return null;779 return null;
838 },780 },
839 error.OutOfMemory => |e| return e,781 error.OutOfMemory => |e| return e,
840 };782 };
841 const semicolon_token = try appendToken(rp.c, .Semicolon, ";");
842783
843 const node = try ast.Node.VarDecl.create(rp.c.arena, .{784 const payload = try c.arena.create(ast.Payload.Typedef);
844 .name_token = name_tok,785 payload.* = .{
845 .mut_token = mut_tok,786 .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[toplevel] },
846 .semicolon_token = semicolon_token,787 .data = .{
847 }, .{788 .name = checked_name,
848 .visib_token = visib_tok,789 .init = init_node,
849 .eq_token = eq_token,790 },
850 .init_node = init_node,791 };
851 });792 return Node.initPayload(&payload.base);
852 return &node.base;
853}793}
854794
855fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*ast.Node {795fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*ast.Node {
...@@ -1399,13 +1339,15 @@ fn transBinaryOperator(...@@ -1399,13 +1339,15 @@ fn transBinaryOperator(
1399 const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);1339 const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
1400 const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);1340 const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
14011341
1402 const lhs = if (isBoolRes(lhs_uncasted)) 1342 const lhs = if (isBoolRes(lhs_uncasted))
1403 try Node.bool_to_int.create(c.arena, lhs_uncasted)1343 try Node.bool_to_int.create(c.arena, lhs_uncasted)
1404 else lhs_uncasted;1344 else
1345 lhs_uncasted;
14051346
1406 const rhs = if (isBoolRes(rhs_uncasted)) 1347 const rhs = if (isBoolRes(rhs_uncasted))
1407 try Node.bool_to_int.create(c.arena, rhs_uncasted)1348 try Node.bool_to_int.create(c.arena, rhs_uncasted)
1408 else rhs_uncasted;1349 else
1350 rhs_uncasted;
14091351
1410 const payload = try c.arena.create(ast.Payload.BinOp);1352 const payload = try c.arena.create(ast.Payload.BinOp);
1411 payload.* = .{1353 payload.* = .{
...@@ -1415,7 +1357,7 @@ fn transBinaryOperator(...@@ -1415,7 +1357,7 @@ fn transBinaryOperator(
1415 .rhs = rhs,1357 .rhs = rhs,
1416 },1358 },
1417 };1359 };
1418 return maybeSuppressResult(c, scope, used, &payload.base);1360 return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base));
1419}1361}
14201362
1421fn transCompoundStmtInline(1363fn transCompoundStmtInline(
...@@ -1459,13 +1401,11 @@ fn transCStyleCastExprClass(...@@ -1459,13 +1401,11 @@ fn transCStyleCastExprClass(
1459}1401}
14601402
1461fn transDeclStmtOne(1403fn transDeclStmtOne(
1462 rp: RestorePoint,1404 c: *Context,
1463 scope: *Scope,1405 scope: *Scope,
1464 decl: *const clang.Decl,1406 decl: *const clang.Decl,
1465 block_scope: *Scope.Block,1407 block_scope: *Scope.Block,
1466) TransError!*ast.Node {1408) TransError!Node {
1467 const c = rp.c;
1468
1469 switch (decl.getKind()) {1409 switch (decl.getKind()) {
1470 .Var => {1410 .Var => {
1471 const var_decl = @ptrCast(*const clang.VarDecl, decl);1411 const var_decl = @ptrCast(*const clang.VarDecl, decl);
...@@ -1479,47 +1419,38 @@ fn transDeclStmtOne(...@@ -1479,47 +1419,38 @@ fn transDeclStmtOne(
1479 .Extern, .Static => {1419 .Extern, .Static => {
1480 // This is actually a global variable, put it in the global scope and reference it.1420 // This is actually a global variable, put it in the global scope and reference it.
1481 // `_ = mangled_name;`1421 // `_ = mangled_name;`
1482 try visitVarDecl(rp.c, var_decl, mangled_name);1422 try visitVarDecl(c, var_decl, mangled_name);
1483 return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name));1423 return try maybeSuppressResult(c, scope, .unused, try Node.identifier.create(c.arena, mangled_name));
1484 },1424 },
1485 else => {},1425 else => {},
1486 }1426 }
14871427
1488 const mut_tok = if (qual_type.isConstQualified())1428 const is_const = qual_type.isConstQualified();
1489 try appendToken(c, .Keyword_const, "const")
1490 else
1491 try appendToken(c, .Keyword_var, "var");
1492 const name_tok = try appendIdentifier(c, mangled_name);
14931429
1494 _ = try appendToken(c, .Colon, ":");
1495 const loc = decl.getLocation();1430 const loc = decl.getLocation();
1496 const type_node = try transQualTypeMaybeInitialized(rp, qual_type, decl_init, loc);1431 const type_node = try transQualTypeMaybeInitialized(c, qual_type, decl_init, loc);
14971432
1498 const eq_token = try appendToken(c, .Equal, "=");
1499 var init_node = if (decl_init) |expr|1433 var init_node = if (decl_init) |expr|
1500 if (expr.getStmtClass() == .StringLiteralClass)1434 if (expr.getStmtClass() == .StringLiteralClass)
1501 try transStringLiteralAsArray(rp, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(rp.c, type_node))1435 try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node))
1502 else1436 else
1503 try transExprCoercing(rp, scope, expr, .used, .r_value)1437 try transExprCoercing(c, scope, expr, .used, .r_value)
1504 else1438 else
1505 try transCreateNodeUndefinedLiteral(c);1439 try transCreateNodeUndefinedLiteral(c);
1506 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {1440 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1507 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);1441 init_node = try Node.bool_to_int.create(c.arena, init_node);
1508 builtin_node.params()[0] = init_node;
1509 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1510 init_node = &builtin_node.base;
1511 }1442 }
1512 const semicolon_token = try appendToken(c, .Semicolon, ";");1443 return Node.var_decl.create(c.arena, .{
1513 const node = try ast.Node.VarDecl.create(c.arena, .{1444 .is_pub = false,
1514 .name_token = name_tok,1445 .is_const = is_const,
1515 .mut_token = mut_tok,1446 .is_extern = false,
1516 .semicolon_token = semicolon_token,1447 .is_export = false,
1517 }, .{1448 .linksection_string = null,
1518 .eq_token = eq_token,1449 .alignment = null,
1519 .type_node = type_node,1450 .name = mangled_name,
1520 .init_node = init_node,1451 .type = type_node,
1452 .init = init_node,
1521 });1453 });
1522 return &node.base;
1523 },1454 },
1524 .Typedef => {1455 .Typedef => {
1525 const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl);1456 const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl);
...@@ -1529,7 +1460,7 @@ fn transDeclStmtOne(...@@ -1529,7 +1460,7 @@ fn transDeclStmtOne(
1529 const underlying_type = underlying_qual.getTypePtr();1460 const underlying_type = underlying_qual.getTypePtr();
15301461
1531 const mangled_name = try block_scope.makeMangledName(c, name);1462 const mangled_name = try block_scope.makeMangledName(c, name);
1532 const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse1463 const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse
1533 return error.UnsupportedTranslation;1464 return error.UnsupportedTranslation;
1534 return node;1465 return node;
1535 },1466 },
...@@ -1543,14 +1474,14 @@ fn transDeclStmtOne(...@@ -1543,14 +1474,14 @@ fn transDeclStmtOne(
1543 }1474 }
1544}1475}
15451476
1546fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) TransError!*ast.Node {1477fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node {
1547 const block_scope = scope.findBlockScope(rp.c) catch unreachable;1478 const block_scope = scope.findBlockScope(c) catch unreachable;
15481479
1549 var it = stmt.decl_begin();1480 var it = stmt.decl_begin();
1550 const end_it = stmt.decl_end();1481 const end_it = stmt.decl_end();
1551 assert(it != end_it);1482 assert(it != end_it);
1552 while (true) : (it += 1) {1483 while (true) : (it += 1) {
1553 const node = try transDeclStmtOne(rp, scope, it[0], block_scope);1484 const node = try transDeclStmtOne(c, scope, it[0], block_scope);
15541485
1555 if (it + 1 == end_it) {1486 if (it + 1 == end_it) {
1556 return node;1487 return node;
...@@ -1562,15 +1493,15 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) T...@@ -1562,15 +1493,15 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) T
1562}1493}
15631494
1564fn transDeclRefExpr(1495fn transDeclRefExpr(
1565 rp: RestorePoint,1496 c: *Context,
1566 scope: *Scope,1497 scope: *Scope,
1567 expr: *const clang.DeclRefExpr,1498 expr: *const clang.DeclRefExpr,
1568 lrvalue: LRValue,1499 lrvalue: LRValue,
1569) TransError!*ast.Node {1500) TransError!Node {
1570 const value_decl = expr.getDecl();1501 const value_decl = expr.getDecl();
1571 const name = try rp.c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin());1502 const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin());
1572 const mangled_name = scope.getAlias(name);1503 const mangled_name = scope.getAlias(name);
1573 return transCreateNodeIdentifier(rp.c, mangled_name);1504 return Node.identifier.create(c.arena, mangled_name);
1574}1505}
15751506
1576fn transImplicitCastExpr(1507fn transImplicitCastExpr(
...@@ -1642,52 +1573,29 @@ fn transImplicitCastExpr(...@@ -1642,52 +1573,29 @@ fn transImplicitCastExpr(
1642}1573}
16431574
1644fn transBoolExpr(1575fn transBoolExpr(
1645 rp: RestorePoint,1576 c: *Context,
1646 scope: *Scope,1577 scope: *Scope,
1647 expr: *const clang.Expr,1578 expr: *const clang.Expr,
1648 used: ResultUsed,1579 used: ResultUsed,
1649 lrvalue: LRValue,1580 lrvalue: LRValue,
1650 grouped: bool,1581) TransError!Node {
1651) TransError!*ast.Node {
1652 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {1582 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
1653 var is_zero: bool = undefined;1583 var is_zero: bool = undefined;
1654 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, rp.c.clang_context))) {1584 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
1655 return revertAndWarn(rp, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});1585 return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
1656 }1586 }
1657 return try transCreateNodeBoolLiteral(rp.c, !is_zero);1587 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] };
1658 }1588 }
16591589
1660 const lparen = if (grouped)1590 var res = try transExpr(c, scope, expr, used, lrvalue);
1661 try appendToken(rp.c, .LParen, "(")
1662 else
1663 undefined;
1664 var res = try transExpr(rp, scope, expr, used, lrvalue);
1665
1666 if (isBoolRes(res)) {1591 if (isBoolRes(res)) {
1667 if (!grouped and res.tag == .GroupedExpression) {
1668 const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res);
1669 res = group.expr;
1670 // get zig fmt to work properly
1671 tokenSlice(rp.c, group.lparen)[0] = ')';
1672 }
1673 return res;1592 return res;
1674 }1593 }
16751594
1676 const ty = getExprQualType(rp.c, expr).getTypePtr();1595 const ty = getExprQualType(c, expr).getTypePtr();
1677 const node = try finishBoolExpr(rp, scope, expr.getBeginLoc(), ty, res, used);1596 const node = try finishBoolExpr(c, scope, expr.getBeginLoc(), ty, res, used);
16781597
1679 if (grouped) {1598 return maybeSuppressResult(c, scope, used, node);
1680 const rparen = try appendToken(rp.c, .RParen, ")");
1681 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
1682 grouped_expr.* = .{
1683 .lparen = lparen,
1684 .expr = node,
1685 .rparen = rparen,
1686 };
1687 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
1688 } else {
1689 return maybeSuppressResult(rp, scope, used, node);
1690 }
1691}1599}
16921600
1693fn exprIsBooleanType(expr: *const clang.Expr) bool {1601fn exprIsBooleanType(expr: *const clang.Expr) bool {
...@@ -1713,34 +1621,32 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool {...@@ -1713,34 +1621,32 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool {
1713 }1621 }
1714}1622}
17151623
1716fn isBoolRes(res: *ast.Node) bool {1624fn isBoolRes(res: Node) bool {
1717 switch (res.tag) {1625 switch (res.tag()) {
1718 .BoolOr,1626 .@"or",
1719 .BoolAnd,1627 .@"and",
1720 .EqualEqual,1628 .equal,
1721 .BangEqual,1629 .note_equal,
1722 .LessThan,1630 .less_than,
1723 .GreaterThan,1631 .less_than_equal,
1724 .LessOrEqual,1632 .greater_than,
1725 .GreaterOrEqual,1633 .greater_than_equal,
1726 .BoolNot,1634 .not,
1727 .BoolLiteral,1635 .false_literal,
1636 .true_literal,
1728 => return true,1637 => return true,
1729
1730 .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
1731
1732 else => return false,1638 else => return false,
1733 }1639 }
1734}1640}
17351641
1736fn finishBoolExpr(1642fn finishBoolExpr(
1737 rp: RestorePoint,1643 c: *Context,
1738 scope: *Scope,1644 scope: *Scope,
1739 loc: clang.SourceLocation,1645 loc: clang.SourceLocation,
1740 ty: *const clang.Type,1646 ty: *const clang.Type,
1741 node: *ast.Node,1647 node: Node,
1742 used: ResultUsed,1648 used: ResultUsed,
1743) TransError!*ast.Node {1649) TransError!Node {
1744 switch (ty.getTypeClass()) {1650 switch (ty.getTypeClass()) {
1745 .Builtin => {1651 .Builtin => {
1746 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);1652 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
...@@ -1772,42 +1678,39 @@ fn finishBoolExpr(...@@ -1772,42 +1678,39 @@ fn finishBoolExpr(
1772 .WChar_S,1678 .WChar_S,
1773 .Float16,1679 .Float16,
1774 => {1680 => {
1775 const op_token = try appendToken(rp.c, .BangEqual, "!=");1681 // node != 0
1776 const rhs_node = try transCreateNodeInt(rp.c, 0);1682 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});
1777 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1778 },1683 },
1779 .NullPtr => {1684 .NullPtr => {
1780 const op_token = try appendToken(rp.c, .EqualEqual, "==");1685 // node == null
1781 const rhs_node = try transCreateNodeNullLiteral(rp.c);1686 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});
1782 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false);
1783 },1687 },
1784 else => {},1688 else => {},
1785 }1689 }
1786 },1690 },
1787 .Pointer => {1691 .Pointer => {
1788 const op_token = try appendToken(rp.c, .BangEqual, "!=");1692 // node == null
1789 const rhs_node = try transCreateNodeNullLiteral(rp.c);1693 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});
1790 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1791 },1694 },
1792 .Typedef => {1695 .Typedef => {
1793 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);1696 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
1794 const typedef_decl = typedef_ty.getDecl();1697 const typedef_decl = typedef_ty.getDecl();
1795 const underlying_type = typedef_decl.getUnderlyingType();1698 const underlying_type = typedef_decl.getUnderlyingType();
1796 return finishBoolExpr(rp, scope, loc, underlying_type.getTypePtr(), node, used);1699 return finishBoolExpr(c, scope, loc, underlying_type.getTypePtr(), node, used);
1797 },1700 },
1798 .Enum => {1701 .Enum => {
1799 const op_token = try appendToken(rp.c, .BangEqual, "!=");1702 // node != 0
1800 const rhs_node = try transCreateNodeInt(rp.c, 0);1703 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});
1801 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);1704 const op_token = try appendToken(c, .BangEqual, "!=");
1802 },1705 },
1803 .Elaborated => {1706 .Elaborated => {
1804 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);1707 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
1805 const named_type = elaborated_ty.getNamedType();1708 const named_type = elaborated_ty.getNamedType();
1806 return finishBoolExpr(rp, scope, loc, named_type.getTypePtr(), node, used);1709 return finishBoolExpr(c, scope, loc, named_type.getTypePtr(), node, used);
1807 },1710 },
1808 else => {},1711 else => {},
1809 }1712 }
1810 return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{});1713 return fail(c, error.UnsupportedType, loc, "unsupported bool expression type", .{});
1811}1714}
18121715
1813const SuppressCast = enum {1716const SuppressCast = enum {
...@@ -4242,7 +4145,7 @@ fn transCreateNodeBoolInfixOp(...@@ -4242,7 +4145,7 @@ fn transCreateNodeBoolInfixOp(
4242 .rhs = rhs,4145 .rhs = rhs,
4243 },4146 },
4244 };4147 };
4245 return maybeSuppressResult(c, scope, used, &payload.base);4148 return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base));
4246}4149}
42474150
4248fn transCreateNodePtrType(4151fn transCreateNodePtrType(
...@@ -4654,7 +4557,7 @@ fn transCreateNodeShiftOp(...@@ -4654,7 +4557,7 @@ fn transCreateNodeShiftOp(
4654 const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value);4557 const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value);
46554558
4656 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);4559 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
4657 const rhs = try transExpr(c, scope, rhs_expr, .used, .r_value);4560 const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value);
4658 const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });4561 const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
46594562
4660 const payload = try c.arena.create(ast.Payload.BinOp);4563 const payload = try c.arena.create(ast.Payload.BinOp);
...@@ -4663,9 +4566,9 @@ fn transCreateNodeShiftOp(...@@ -4663,9 +4566,9 @@ fn transCreateNodeShiftOp(
4663 .data = .{4566 .data = .{
4664 .lhs = lhs,4567 .lhs = lhs,
4665 .rhs = rhs_casted,4568 .rhs = rhs_casted,
4666 }4569 },
4667 };4570 };
4668 return &payload.base;4571 return Node.initPayload(&payload.base);
4669}4572}
46704573
4671fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {4574fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
...@@ -4961,7 +4864,7 @@ fn finishTransFnProto(...@@ -4961,7 +4864,7 @@ fn finishTransFnProto(
4961 };4864 };
4962 }4865 }
49634866
4964 const link_section_string: ?[]const u8 = blk: {4867 const linksection_string = blk: {
4965 if (fn_decl) |decl| {4868 if (fn_decl) |decl| {
4966 var str_len: usize = undefined;4869 var str_len: usize = undefined;
4967 if (decl.getSectionAttribute(&str_len)) |str_ptr| {4870 if (decl.getSectionAttribute(&str_len)) |str_ptr| {
...@@ -5004,24 +4907,19 @@ fn finishTransFnProto(...@@ -5004,24 +4907,19 @@ fn finishTransFnProto(
5004 }4907 }
5005 };4908 };
50064909
5007 const fn_proto = try c.arena.create(ast.Payload.Func);4910 return Node.func.create(c.arena, .{
5008 fn_proto.* = .{4911 .is_pub = is_pub,
5009 .base = .{ .tag = .func },4912 .is_extern = is_extern,
5010 .data = .{4913 .is_export = is_export,
5011 .is_pub = is_pub,4914 .is_var_args = is_var_args,
5012 .is_extern = is_extern,4915 .name = name,
5013 .is_export = is_export,4916 .linksection_string = linksection_string,
5014 .is_var_args = is_var_args,4917 .explicit_callconv = explicit_callconv,
5015 .name = name,4918 .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items),
5016 .link_section_string = link_section_string,4919 .return_type = return_node,
5017 .explicit_callconv = explicit_callconv,4920 .body = null,
5018 .params = c.arena.dupe(ast.Payload.Func.Param, fn_params.items),4921 .alignment = alignment,
5019 .return_type = return_node,4922 });
5020 .body = null,
5021 .alignment = alignment,
5022 },
5023 };
5024 return fn_proto;
5025}4923}
50264924
5027fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {4925fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
...@@ -5054,6 +4952,19 @@ pub fn freeErrors(errors: []ClangErrMsg) void {...@@ -5054,6 +4952,19 @@ pub fn freeErrors(errors: []ClangErrMsg) void {
5054 errors.ptr.delete(errors.len);4952 errors.ptr.delete(errors.len);
5055}4953}
50564954
4955fn isZigPrimitiveType(name: []const u8) bool {
4956 if (name.len > 1 and (name[0] == 'u' or name[0] == 'i')) {
4957 for (name[1..]) |c| {
4958 switch (c) {
4959 '0'...'9' => {},
4960 else => return false,
4961 }
4962 }
4963 return true;
4964 }
4965 return @import("astgen.zig").simple_types.has(name);
4966}
4967
5057const MacroCtx = struct {4968const MacroCtx = struct {
5058 source: []const u8,4969 source: []const u8,
5059 list: []const CToken,4970 list: []const CToken,
src/translate_c/ast.zig+31-11
...@@ -137,11 +137,16 @@ pub const Node = extern union {...@@ -137,11 +137,16 @@ pub const Node = extern union {
137 single_pointer,137 single_pointer,
138 array_type,138 array_type,
139139
140140 /// @import("std").mem.zeroes(T)
141 std_mem_zeroes,
141 // pub const name = @compileError(msg);142 // pub const name = @compileError(msg);
142 fail_decl,143 fail_decl,
143 // var actual = mangled;144 // var actual = mangled;
144 arg_redecl,145 arg_redecl,
146 /// const name = init;
147 typedef,
148 /// pub const name = init;
149 pub_typedef,
145150
146 pub const last_no_payload_tag = Tag.usingnamespace_builtins;151 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
147 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;152 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -257,11 +262,11 @@ pub const Node = extern union {...@@ -257,11 +262,11 @@ pub const Node = extern union {
257 .container_init => Payload.ContainerInit,262 .container_init => Payload.ContainerInit,
258 .std_meta_cast => Payload.Infix,263 .std_meta_cast => Payload.Infix,
259 .block => Payload.Block,264 .block => Payload.Block,
260 .c_pointer => Payload.Pointer,265 .c_pointer, .single_pointer => Payload.Pointer,
261 .single_pointer => Payload.Pointer,
262 .array_type => Payload.Array,266 .array_type => Payload.Array,
263 .arg_redecl => Payload.ArgRedecl,267 .arg_redecl => Payload.ArgRedecl,
264 .log2_int_type => Payload.Log2IntType,268 .log2_int_type => Payload.Log2IntType,
269 .typedef, .pub_typedef => Payload.Typedef,
265 };270 };
266 }271 }
267272
...@@ -301,6 +306,11 @@ pub const Node = extern union {...@@ -301,6 +306,11 @@ pub const Node = extern union {
301306
302 return null;307 return null;
303 }308 }
309
310 pub fn initPayload(payload: *Payload) Node {
311 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
312 return .{ .ptr_otherwise = payload };
313 }
304};314};
305315
306pub const Payload = struct {316pub const Payload = struct {
...@@ -383,13 +393,15 @@ pub const Payload = struct {...@@ -383,13 +393,15 @@ pub const Payload = struct {
383 pub const VarDecl = struct {393 pub const VarDecl = struct {
384 base: Node = .{ .tag = .var_decl },394 base: Node = .{ .tag = .var_decl },
385 data: struct {395 data: struct {
386 @"pub": bool,396 is_pub: bool,
387 @"const": bool,397 is_const: bool,
388 @"extern": bool,398 is_extern: bool,
389 @"export": bool,399 is_export: bool,
400 alignment: ?c_uint,
401 linksection_string: ?[]const u8,
390 name: []const u8,402 name: []const u8,
391 type: Type,403 type: Node,
392 init: Node,404 init: ?Node,
393 },405 },
394 };406 };
395407
...@@ -401,12 +413,12 @@ pub const Payload = struct {...@@ -401,12 +413,12 @@ pub const Payload = struct {
401 is_export: bool,413 is_export: bool,
402 is_var_args: bool,414 is_var_args: bool,
403 name: []const u8,415 name: []const u8,
404 link_section_string: ?[]const u8,416 linksection_string: ?[]const u8,
405 explicit_callconv: ?std.builtin.CallingConvention,417 explicit_callconv: ?std.builtin.CallingConvention,
406 params: []Param,418 params: []Param,
407 return_type: Node,419 return_type: Node,
408 body: ?Node,420 body: ?Node,
409 alignment: c_uint,421 alignment: ?c_uint,
410422
411 pub const Param = struct {423 pub const Param = struct {
412 is_noalias: bool,424 is_noalias: bool,
...@@ -501,6 +513,14 @@ pub const Payload = struct {...@@ -501,6 +513,14 @@ pub const Payload = struct {
501 base: Node,513 base: Node,
502 data: std.math.Log2Int(u64),514 data: std.math.Log2Int(u64),
503 };515 };
516
517 pub const Typedef = struct {
518 base: Node,
519 data: struct {
520 name: []const u8,
521 init: Node,
522 },
523 };
504};524};
505525
506/// Converts the nodes into a Zig ast.526/// Converts the nodes into a Zig ast.