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(
26642664 return mod.failNode(scope, ident, "TODO implement '_' identifier", .{});
26652665 }
26662666
2667 if (getSimplePrimitiveValue(ident_name)) |typed_value| {
2668 const result = try addZIRInstConst(mod, scope, src, typed_value);
2667 if (simple_types.get(ident_name)) |val_tag| {
2668 const result = try addZIRInstConst(mod, scope, src, TypedValue{
2669 .ty = Type.initTag(.type),
2670 .val = Value.initTag(val_tag),
2671 });
26692672 return rvalue(mod, scope, rl, result);
26702673 }
26712674
......@@ -3325,42 +3328,33 @@ fn callExpr(
33253328 return rvalue(mod, scope, rl, result);
33263329}
33273330
3328fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
3329 const simple_types = std.ComptimeStringMap(Value.Tag, .{
3330 .{ "u8", .u8_type },
3331 .{ "i8", .i8_type },
3332 .{ "isize", .isize_type },
3333 .{ "usize", .usize_type },
3334 .{ "c_short", .c_short_type },
3335 .{ "c_ushort", .c_ushort_type },
3336 .{ "c_int", .c_int_type },
3337 .{ "c_uint", .c_uint_type },
3338 .{ "c_long", .c_long_type },
3339 .{ "c_ulong", .c_ulong_type },
3340 .{ "c_longlong", .c_longlong_type },
3341 .{ "c_ulonglong", .c_ulonglong_type },
3342 .{ "c_longdouble", .c_longdouble_type },
3343 .{ "f16", .f16_type },
3344 .{ "f32", .f32_type },
3345 .{ "f64", .f64_type },
3346 .{ "f128", .f128_type },
3347 .{ "c_void", .c_void_type },
3348 .{ "bool", .bool_type },
3349 .{ "void", .void_type },
3350 .{ "type", .type_type },
3351 .{ "anyerror", .anyerror_type },
3352 .{ "comptime_int", .comptime_int_type },
3353 .{ "comptime_float", .comptime_float_type },
3354 .{ "noreturn", .noreturn_type },
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}
3331pub const simple_types = std.ComptimeStringMap(Value.Tag, .{
3332 .{ "u8", .u8_type },
3333 .{ "i8", .i8_type },
3334 .{ "isize", .isize_type },
3335 .{ "usize", .usize_type },
3336 .{ "c_short", .c_short_type },
3337 .{ "c_ushort", .c_ushort_type },
3338 .{ "c_int", .c_int_type },
3339 .{ "c_uint", .c_uint_type },
3340 .{ "c_long", .c_long_type },
3341 .{ "c_ulong", .c_ulong_type },
3342 .{ "c_longlong", .c_longlong_type },
3343 .{ "c_ulonglong", .c_ulonglong_type },
3344 .{ "c_longdouble", .c_longdouble_type },
3345 .{ "f16", .f16_type },
3346 .{ "f32", .f32_type },
3347 .{ "f64", .f64_type },
3348 .{ "f128", .f128_type },
3349 .{ "c_void", .c_void_type },
3350 .{ "bool", .bool_type },
3351 .{ "void", .void_type },
3352 .{ "type", .type_type },
3353 .{ "anyerror", .anyerror_type },
3354 .{ "comptime_int", .comptime_int_type },
3355 .{ "comptime_float", .comptime_float_type },
3356 .{ "noreturn", .noreturn_type },
3357});
33643358
33653359fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
33663360 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 {
614614 return addTopLevelDecl(c, fn_name, &proto_node.base);
615615}
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 {
618618 return if (decl_init) |init_expr|
619 transQualTypeInitialized(rp, qt, init_expr, loc)
619 transQualTypeInitialized(c, qt, init_expr, loc)
620620 else
621 transQualType(rp, qt, loc);
621 transQualType(c, qt, loc);
622622}
623
623624/// if mangled_name is not null, this var decl was declared in a block scope.
624625fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]const u8) Error!void {
625626 const var_name = mangled_name orelse try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin());
626627 if (c.global_scope.sym_table.contains(var_name))
627628 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;
636632 const scope = &c.global_scope.base;
637633
638634 // TODO https://github.com/ziglang/zig/issues/3756
......@@ -651,42 +647,27 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
651647 // does the same as:
652648 // extern int foo;
653649 // int foo = 2;
654 const extern_tok = if (storage_class == .Extern and !has_init)
655 try appendToken(c, .Keyword_extern, "extern")
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");
650 const is_extern = storage_class == .Extern and !has_init;
651 const is_export = !is_extern and storage_class != .Static;
665652
666 const name_tok = try appendIdentifier(c, checked_name);
667
668 _ = try appendToken(c, .Colon, ":");
669
670 const type_node = transQualTypeMaybeInitialized(rp, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
653 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
671654 error.UnsupportedTranslation, error.UnsupportedType => {
672655 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
673656 },
674657 error.OutOfMemory => |e| return e,
675658 };
676659
677 var eq_tok: ast.TokenIndex = undefined;
678 var init_node: ?*ast.Node = null;
660 var init_node: ?Node = null;
679661
680662 // If the initialization expression is not present, initialize with undefined.
681663 // If it is an integer literal, we can skip the @as since it will be redundant
682664 // with the variable type.
683665 if (has_init) {
684 eq_tok = try appendToken(c, .Equal, "=");
685666 if (decl_init) |expr| {
686667 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)
688669 else
689 transExprCoercing(rp, scope, expr, .used, .r_value);
670 transExprCoercing(c, scope, expr, .used, .r_value);
690671 init_node = node_or_error catch |err| switch (err) {
691672 error.UnsupportedTranslation,
692673 error.UnsupportedType,
......@@ -695,118 +676,83 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
695676 },
696677 error.OutOfMemory => |e| return e,
697678 };
679 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
680 init_node = try Node.bool_to_int.create(c.arena, init_node);
681 }
698682 } else {
699 init_node = try transCreateNodeUndefinedLiteral(c);
683 init_node = Node.undefined_literal.init();
700684 }
701685 } else if (storage_class != .Extern) {
702 eq_tok = try appendToken(c, .Equal, "=");
703686 // The C language specification states that variables with static or threadlocal
704687 // storage without an initializer are initialized to a zero value.
705688
706689 // @import("std").mem.zeroes(T)
707 const import_fn_call = try c.createBuiltinCall("@import", 1);
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;
690 init_node = try Node.std_mem_zeroes.create(c.arena, type_node);
719691 }
720692
721 const linksection_expr = blk: {
693 const linksection_string = blk: {
722694 var str_len: usize = undefined;
723695 if (var_decl.getSectionAttribute(&str_len)) |str_ptr| {
724 _ = try appendToken(rp.c, .Keyword_linksection, "linksection");
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;
696 break :blk str_ptr[0..str_len];
733697 }
734698 break :blk null;
735699 };
736700
737 const align_expr = blk: {
738 const alignment = var_decl.getAlignedAttribute(rp.c.clang_context);
701 const alignment = blk: {
702 const alignment = var_decl.getAlignedAttribute(c.clang_context);
739703 if (alignment != 0) {
740 _ = try appendToken(rp.c, .Keyword_align, "align");
741 _ = try appendToken(rp.c, .LParen, "(");
742704 // Clang reports the alignment in bits
743 const expr = try transCreateNodeInt(rp.c, alignment / 8);
744 _ = try appendToken(rp.c, .RParen, ")");
745
746 break :blk expr;
705 break :blk alignment / 8;
747706 }
748707 break :blk null;
749708 };
750709
751 const node = try ast.Node.VarDecl.create(c.arena, .{
752 .name_token = name_tok,
753 .mut_token = mut_tok,
754 .semicolon_token = try appendToken(c, .Semicolon, ";"),
755 }, .{
756 .visib_token = visib_tok,
757 .thread_local_token = thread_local_token,
758 .eq_token = eq_tok,
759 .extern_export_token = extern_tok,
760 .type_node = type_node,
761 .align_node = align_expr,
762 .section_node = linksection_expr,
763 .init_node = init_node,
710 const node = try Node.var_decl.create(c.arena, .{
711 .is_pub = is_pub,
712 .is_const = is_const,
713 .is_extern = is_extern,
714 .is_export = is_export,
715 .linksection_string = linksection_string,
716 .alignment = alignment,
717 .name = checked_name,
718 .type = type_node,
719 .init = init_node,
764720 });
765721 return addTopLevelDecl(c, checked_name, &node.base);
766722}
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 {
769725 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
770 return transCreateNodeIdentifier(c, builtin_name);
771}
772
773fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 {
774 const table = [_][2][]const u8{
775 .{ "uint8_t", "u8" },
776 .{ "int8_t", "i8" },
777 .{ "uint16_t", "u16" },
778 .{ "int16_t", "i16" },
779 .{ "uint32_t", "u32" },
780 .{ "int32_t", "i32" },
781 .{ "uint64_t", "u64" },
782 .{ "int64_t", "i64" },
783 .{ "intptr_t", "isize" },
784 .{ "uintptr_t", "usize" },
785 .{ "ssize_t", "isize" },
786 .{ "size_t", "usize" },
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}
726 return Node.identifier.create(c.arena, builtin_name);
727}
728
729const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
730 .{ "uint8_t", "u8" },
731 .{ "int8_t", "i8" },
732 .{ "uint16_t", "u16" },
733 .{ "int16_t", "i16" },
734 .{ "uint32_t", "u32" },
735 .{ "int32_t", "i32" },
736 .{ "uint64_t", "u64" },
737 .{ "int64_t", "i64" },
738 .{ "intptr_t", "isize" },
739 .{ "uintptr_t", "usize" },
740 .{ "ssize_t", "isize" },
741 .{ "size_t", "usize" },
742});
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 {
799745 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
800746 return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
801 const rp = makeRestorePoint(c);
802747
803748 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
804749
805750 // TODO https://github.com/ziglang/zig/issues/3756
806751 // TODO https://github.com/ziglang/zig/issues/1802
807752 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| {
809 return transTypeDefAsBuiltin(c, typedef_decl, builtin);
753 if (builtin_typedef_map.get(checked_name)) |builtin| {
754 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
755 return Node.identifier.create(c.arena, builtin);
810756 }
811757
812758 if (!top_level_visit) {
......@@ -814,42 +760,36 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev
814760 }
815761
816762 _ = 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;
818764 try addTopLevelDecl(c, checked_name, node);
819765 return transCreateNodeIdentifier(c, checked_name);
820766}
821767
822768fn transCreateNodeTypedef(
823 rp: RestorePoint,
769 c: *Context,
824770 typedef_decl: *const clang.TypedefNameDecl,
825771 toplevel: bool,
826772 checked_name: []const u8,
827) Error!?*ast.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, "=");
773) Error!?Node {
832774 const child_qt = typedef_decl.getUnderlyingType();
833775 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) {
835777 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", .{});
837779 return null;
838780 },
839781 error.OutOfMemory => |e| return e,
840782 };
841 const semicolon_token = try appendToken(rp.c, .Semicolon, ";");
842783
843 const node = try ast.Node.VarDecl.create(rp.c.arena, .{
844 .name_token = name_tok,
845 .mut_token = mut_tok,
846 .semicolon_token = semicolon_token,
847 }, .{
848 .visib_token = visib_tok,
849 .eq_token = eq_token,
850 .init_node = init_node,
851 });
852 return &node.base;
784 const payload = try c.arena.create(ast.Payload.Typedef);
785 payload.* = .{
786 .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[toplevel] },
787 .data = .{
788 .name = checked_name,
789 .init = init_node,
790 },
791 };
792 return Node.initPayload(&payload.base);
853793}
854794
855795fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*ast.Node {
......@@ -1399,13 +1339,15 @@ fn transBinaryOperator(
13991339 const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
14001340 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))
14031343 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))
14071348 try Node.bool_to_int.create(c.arena, rhs_uncasted)
1408 else rhs_uncasted;
1349 else
1350 rhs_uncasted;
14091351
14101352 const payload = try c.arena.create(ast.Payload.BinOp);
14111353 payload.* = .{
......@@ -1415,7 +1357,7 @@ fn transBinaryOperator(
14151357 .rhs = rhs,
14161358 },
14171359 };
1418 return maybeSuppressResult(c, scope, used, &payload.base);
1360 return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base));
14191361}
14201362
14211363fn transCompoundStmtInline(
......@@ -1459,13 +1401,11 @@ fn transCStyleCastExprClass(
14591401}
14601402
14611403fn transDeclStmtOne(
1462 rp: RestorePoint,
1404 c: *Context,
14631405 scope: *Scope,
14641406 decl: *const clang.Decl,
14651407 block_scope: *Scope.Block,
1466) TransError!*ast.Node {
1467 const c = rp.c;
1468
1408) TransError!Node {
14691409 switch (decl.getKind()) {
14701410 .Var => {
14711411 const var_decl = @ptrCast(*const clang.VarDecl, decl);
......@@ -1479,47 +1419,38 @@ fn transDeclStmtOne(
14791419 .Extern, .Static => {
14801420 // This is actually a global variable, put it in the global scope and reference it.
14811421 // `_ = mangled_name;`
1482 try visitVarDecl(rp.c, var_decl, mangled_name);
1483 return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name));
1422 try visitVarDecl(c, var_decl, mangled_name);
1423 return try maybeSuppressResult(c, scope, .unused, try Node.identifier.create(c.arena, mangled_name));
14841424 },
14851425 else => {},
14861426 }
14871427
1488 const mut_tok = if (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);
1428 const is_const = qual_type.isConstQualified();
14931429
1494 _ = try appendToken(c, .Colon, ":");
14951430 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, "=");
14991433 var init_node = if (decl_init) |expr|
15001434 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))
15021436 else
1503 try transExprCoercing(rp, scope, expr, .used, .r_value)
1437 try transExprCoercing(c, scope, expr, .used, .r_value)
15041438 else
15051439 try transCreateNodeUndefinedLiteral(c);
15061440 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1507 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);
1508 builtin_node.params()[0] = init_node;
1509 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1510 init_node = &builtin_node.base;
1441 init_node = try Node.bool_to_int.create(c.arena, init_node);
15111442 }
1512 const semicolon_token = try appendToken(c, .Semicolon, ";");
1513 const node = try ast.Node.VarDecl.create(c.arena, .{
1514 .name_token = name_tok,
1515 .mut_token = mut_tok,
1516 .semicolon_token = semicolon_token,
1517 }, .{
1518 .eq_token = eq_token,
1519 .type_node = type_node,
1520 .init_node = init_node,
1443 return Node.var_decl.create(c.arena, .{
1444 .is_pub = false,
1445 .is_const = is_const,
1446 .is_extern = false,
1447 .is_export = false,
1448 .linksection_string = null,
1449 .alignment = null,
1450 .name = mangled_name,
1451 .type = type_node,
1452 .init = init_node,
15211453 });
1522 return &node.base;
15231454 },
15241455 .Typedef => {
15251456 const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl);
......@@ -1529,7 +1460,7 @@ fn transDeclStmtOne(
15291460 const underlying_type = underlying_qual.getTypePtr();
15301461
15311462 const mangled_name = try block_scope.makeMangledName(c, name);
1532 const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse
1463 const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse
15331464 return error.UnsupportedTranslation;
15341465 return node;
15351466 },
......@@ -1543,14 +1474,14 @@ fn transDeclStmtOne(
15431474 }
15441475}
15451476
1546fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) TransError!*ast.Node {
1547 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
1477fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node {
1478 const block_scope = scope.findBlockScope(c) catch unreachable;
15481479
15491480 var it = stmt.decl_begin();
15501481 const end_it = stmt.decl_end();
15511482 assert(it != end_it);
15521483 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
15551486 if (it + 1 == end_it) {
15561487 return node;
......@@ -1562,15 +1493,15 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const clang.DeclStmt) T
15621493}
15631494
15641495fn transDeclRefExpr(
1565 rp: RestorePoint,
1496 c: *Context,
15661497 scope: *Scope,
15671498 expr: *const clang.DeclRefExpr,
15681499 lrvalue: LRValue,
1569) TransError!*ast.Node {
1500) TransError!Node {
15701501 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());
15721503 const mangled_name = scope.getAlias(name);
1573 return transCreateNodeIdentifier(rp.c, mangled_name);
1504 return Node.identifier.create(c.arena, mangled_name);
15741505}
15751506
15761507fn transImplicitCastExpr(
......@@ -1642,52 +1573,29 @@ fn transImplicitCastExpr(
16421573}
16431574
16441575fn transBoolExpr(
1645 rp: RestorePoint,
1576 c: *Context,
16461577 scope: *Scope,
16471578 expr: *const clang.Expr,
16481579 used: ResultUsed,
16491580 lrvalue: LRValue,
1650 grouped: bool,
1651) TransError!*ast.Node {
1581) TransError!Node {
16521582 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
16531583 var is_zero: bool = undefined;
1654 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, rp.c.clang_context))) {
1655 return revertAndWarn(rp, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
1584 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
1585 return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
16561586 }
1657 return try transCreateNodeBoolLiteral(rp.c, !is_zero);
1587 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] };
16581588 }
16591589
1660 const lparen = if (grouped)
1661 try appendToken(rp.c, .LParen, "(")
1662 else
1663 undefined;
1664 var res = try transExpr(rp, scope, expr, used, lrvalue);
1665
1590 var res = try transExpr(c, scope, expr, used, lrvalue);
16661591 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 }
16731592 return res;
16741593 }
16751594
1676 const ty = getExprQualType(rp.c, expr).getTypePtr();
1677 const node = try finishBoolExpr(rp, scope, expr.getBeginLoc(), ty, res, used);
1595 const ty = getExprQualType(c, expr).getTypePtr();
1596 const node = try finishBoolExpr(c, scope, expr.getBeginLoc(), ty, res, used);
16781597
1679 if (grouped) {
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 }
1598 return maybeSuppressResult(c, scope, used, node);
16911599}
16921600
16931601fn exprIsBooleanType(expr: *const clang.Expr) bool {
......@@ -1713,34 +1621,32 @@ fn exprIsNarrowStringLiteral(expr: *const clang.Expr) bool {
17131621 }
17141622}
17151623
1716fn isBoolRes(res: *ast.Node) bool {
1717 switch (res.tag) {
1718 .BoolOr,
1719 .BoolAnd,
1720 .EqualEqual,
1721 .BangEqual,
1722 .LessThan,
1723 .GreaterThan,
1724 .LessOrEqual,
1725 .GreaterOrEqual,
1726 .BoolNot,
1727 .BoolLiteral,
1624fn isBoolRes(res: Node) bool {
1625 switch (res.tag()) {
1626 .@"or",
1627 .@"and",
1628 .equal,
1629 .note_equal,
1630 .less_than,
1631 .less_than_equal,
1632 .greater_than,
1633 .greater_than_equal,
1634 .not,
1635 .false_literal,
1636 .true_literal,
17281637 => return true,
1729
1730 .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
1731
17321638 else => return false,
17331639 }
17341640}
17351641
17361642fn finishBoolExpr(
1737 rp: RestorePoint,
1643 c: *Context,
17381644 scope: *Scope,
17391645 loc: clang.SourceLocation,
17401646 ty: *const clang.Type,
1741 node: *ast.Node,
1647 node: Node,
17421648 used: ResultUsed,
1743) TransError!*ast.Node {
1649) TransError!Node {
17441650 switch (ty.getTypeClass()) {
17451651 .Builtin => {
17461652 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
......@@ -1772,42 +1678,39 @@ fn finishBoolExpr(
17721678 .WChar_S,
17731679 .Float16,
17741680 => {
1775 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1776 const rhs_node = try transCreateNodeInt(rp.c, 0);
1777 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1681 // node != 0
1682 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});
17781683 },
17791684 .NullPtr => {
1780 const op_token = try appendToken(rp.c, .EqualEqual, "==");
1781 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1782 return transCreateNodeInfixOp(rp, scope, node, .EqualEqual, op_token, rhs_node, used, false);
1685 // node == null
1686 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});
17831687 },
17841688 else => {},
17851689 }
17861690 },
17871691 .Pointer => {
1788 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1789 const rhs_node = try transCreateNodeNullLiteral(rp.c);
1790 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1692 // node == null
1693 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()});
17911694 },
17921695 .Typedef => {
17931696 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
17941697 const typedef_decl = typedef_ty.getDecl();
17951698 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);
17971700 },
17981701 .Enum => {
1799 const op_token = try appendToken(rp.c, .BangEqual, "!=");
1800 const rhs_node = try transCreateNodeInt(rp.c, 0);
1801 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, used, false);
1702 // node != 0
1703 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()});
1704 const op_token = try appendToken(c, .BangEqual, "!=");
18021705 },
18031706 .Elaborated => {
18041707 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
18051708 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);
18071710 },
18081711 else => {},
18091712 }
1810 return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{});
1713 return fail(c, error.UnsupportedType, loc, "unsupported bool expression type", .{});
18111714}
18121715
18131716const SuppressCast = enum {
......@@ -4242,7 +4145,7 @@ fn transCreateNodeBoolInfixOp(
42424145 .rhs = rhs,
42434146 },
42444147 };
4245 return maybeSuppressResult(c, scope, used, &payload.base);
4148 return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base));
42464149}
42474150
42484151fn transCreateNodePtrType(
......@@ -4654,7 +4557,7 @@ fn transCreateNodeShiftOp(
46544557 const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value);
46554558
46564559 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);
46584561 const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
46594562
46604563 const payload = try c.arena.create(ast.Payload.BinOp);
......@@ -4663,9 +4566,9 @@ fn transCreateNodeShiftOp(
46634566 .data = .{
46644567 .lhs = lhs,
46654568 .rhs = rhs_casted,
4666 }
4569 },
46674570 };
4668 return &payload.base;
4571 return Node.initPayload(&payload.base);
46694572}
46704573
46714574fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
......@@ -4961,7 +4864,7 @@ fn finishTransFnProto(
49614864 };
49624865 }
49634866
4964 const link_section_string: ?[]const u8 = blk: {
4867 const linksection_string = blk: {
49654868 if (fn_decl) |decl| {
49664869 var str_len: usize = undefined;
49674870 if (decl.getSectionAttribute(&str_len)) |str_ptr| {
......@@ -5004,24 +4907,19 @@ fn finishTransFnProto(
50044907 }
50054908 };
50064909
5007 const fn_proto = try c.arena.create(ast.Payload.Func);
5008 fn_proto.* = .{
5009 .base = .{ .tag = .func },
5010 .data = .{
5011 .is_pub = is_pub,
5012 .is_extern = is_extern,
5013 .is_export = is_export,
5014 .is_var_args = is_var_args,
5015 .name = name,
5016 .link_section_string = link_section_string,
5017 .explicit_callconv = explicit_callconv,
5018 .params = c.arena.dupe(ast.Payload.Func.Param, fn_params.items),
5019 .return_type = return_node,
5020 .body = null,
5021 .alignment = alignment,
5022 },
5023 };
5024 return fn_proto;
4910 return Node.func.create(c.arena, .{
4911 .is_pub = is_pub,
4912 .is_extern = is_extern,
4913 .is_export = is_export,
4914 .is_var_args = is_var_args,
4915 .name = name,
4916 .linksection_string = linksection_string,
4917 .explicit_callconv = explicit_callconv,
4918 .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items),
4919 .return_type = return_node,
4920 .body = null,
4921 .alignment = alignment,
4922 });
50254923}
50264924
50274925fn 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 {
50544952 errors.ptr.delete(errors.len);
50554953}
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
50574968const MacroCtx = struct {
50584969 source: []const u8,
50594970 list: []const CToken,
src/translate_c/ast.zig+31-11
......@@ -137,11 +137,16 @@ pub const Node = extern union {
137137 single_pointer,
138138 array_type,
139139
140
140 /// @import("std").mem.zeroes(T)
141 std_mem_zeroes,
141142 // pub const name = @compileError(msg);
142143 fail_decl,
143144 // var actual = mangled;
144145 arg_redecl,
146 /// const name = init;
147 typedef,
148 /// pub const name = init;
149 pub_typedef,
145150
146151 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
147152 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -257,11 +262,11 @@ pub const Node = extern union {
257262 .container_init => Payload.ContainerInit,
258263 .std_meta_cast => Payload.Infix,
259264 .block => Payload.Block,
260 .c_pointer => Payload.Pointer,
261 .single_pointer => Payload.Pointer,
265 .c_pointer, .single_pointer => Payload.Pointer,
262266 .array_type => Payload.Array,
263267 .arg_redecl => Payload.ArgRedecl,
264268 .log2_int_type => Payload.Log2IntType,
269 .typedef, .pub_typedef => Payload.Typedef,
265270 };
266271 }
267272
......@@ -301,6 +306,11 @@ pub const Node = extern union {
301306
302307 return null;
303308 }
309
310 pub fn initPayload(payload: *Payload) Node {
311 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
312 return .{ .ptr_otherwise = payload };
313 }
304314};
305315
306316pub const Payload = struct {
......@@ -383,13 +393,15 @@ pub const Payload = struct {
383393 pub const VarDecl = struct {
384394 base: Node = .{ .tag = .var_decl },
385395 data: struct {
386 @"pub": bool,
387 @"const": bool,
388 @"extern": bool,
389 @"export": bool,
396 is_pub: bool,
397 is_const: bool,
398 is_extern: bool,
399 is_export: bool,
400 alignment: ?c_uint,
401 linksection_string: ?[]const u8,
390402 name: []const u8,
391 type: Type,
392 init: Node,
403 type: Node,
404 init: ?Node,
393405 },
394406 };
395407
......@@ -401,12 +413,12 @@ pub const Payload = struct {
401413 is_export: bool,
402414 is_var_args: bool,
403415 name: []const u8,
404 link_section_string: ?[]const u8,
416 linksection_string: ?[]const u8,
405417 explicit_callconv: ?std.builtin.CallingConvention,
406418 params: []Param,
407419 return_type: Node,
408420 body: ?Node,
409 alignment: c_uint,
421 alignment: ?c_uint,
410422
411423 pub const Param = struct {
412424 is_noalias: bool,
......@@ -501,6 +513,14 @@ pub const Payload = struct {
501513 base: Node,
502514 data: std.math.Log2Int(u64),
503515 };
516
517 pub const Typedef = struct {
518 base: Node,
519 data: struct {
520 name: []const u8,
521 init: Node,
522 },
523 };
504524};
505525
506526/// Converts the nodes into a Zig ast.