| author | |
| committer | |
| log | 41a67126a50e3cfab67c749bfc52ac242694774b |
| tree | dc07ee07c9ce0e77fc3313a186265ea2baae86a2 |
| parent | eb057ef41c8a5482586fc39bab11c280e261ea94 |
| signature | Commit is signed but in an unrecognized format. |
3 files changed, 139 insertions(+), 80 deletions(-)
src-self-hosted/clang.zig+1-1| ... | @@ -735,7 +735,7 @@ pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const s | ... | @@ -735,7 +735,7 @@ pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const s |
| 735 | pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType; | 735 | pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType; |
| 736 | pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8; | 736 | pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8; |
| 737 | pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool; | 737 | pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool; |
| 738 | pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl; | 738 | pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl; |
| 739 | pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType; | 739 | pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType; |
| 740 | pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType; | 740 | pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType; |
| 741 | pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass; | 741 | pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass; |
src-self-hosted/translate_c.zig+62-3| ... | @@ -220,7 +220,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { | ... | @@ -220,7 +220,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 220 | return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); | 220 | return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl)); |
| 221 | }, | 221 | }, |
| 222 | .Typedef => { | 222 | .Typedef => { |
| 223 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{}); | 223 | try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl)); |
| 224 | }, | 224 | }, |
| 225 | .Enum => { | 225 | .Enum => { |
| 226 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{}); | 226 | try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{}); |
| ... | @@ -384,6 +384,48 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -384,6 +384,48 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 384 | return addTopLevelDecl(c, var_name, &node.base); | 384 | return addTopLevelDecl(c, var_name, &node.base); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void { | ||
| 388 | if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice | ||
| 389 | const rp = makeRestorePoint(c); | ||
| 390 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | ||
| 391 | const const_tok = try appendToken(c, .Keyword_const, "const"); | ||
| 392 | |||
| 393 | const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); | ||
| 394 | const name_tok = try appendToken(c, .Identifier, typedef_name); | ||
| 395 | const eq_tok = try appendToken(c, .Equal, "="); | ||
| 396 | |||
| 397 | const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); | ||
| 398 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); | ||
| 399 | const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { | ||
| 400 | error.UnsupportedType => { | ||
| 401 | const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{}); | ||
| 402 | _ = try c.decl_table.put(@ptrToInt(typedef_decl), node); | ||
| 403 | return node; | ||
| 404 | }, | ||
| 405 | error.OutOfMemory => |e| return e, | ||
| 406 | }; | ||
| 407 | |||
| 408 | const node = try c.a().create(ast.Node.VarDecl); | ||
| 409 | node.* = ast.Node.VarDecl{ | ||
| 410 | .base = ast.Node{ .id = .VarDecl }, | ||
| 411 | .doc_comments = null, | ||
| 412 | .visib_token = visib_tok, | ||
| 413 | .thread_local_token = null, | ||
| 414 | .name_token = name_tok, | ||
| 415 | .eq_token = eq_tok, | ||
| 416 | .mut_token = const_tok, | ||
| 417 | .comptime_token = null, | ||
| 418 | .extern_export_token = null, | ||
| 419 | .lib_name = null, | ||
| 420 | .type_node = null, | ||
| 421 | .align_node = null, | ||
| 422 | .section_node = null, | ||
| 423 | .init_node = type_node, | ||
| 424 | .semicolon_token = try appendToken(c, .Semicolon, ";"), | ||
| 425 | }; | ||
| 426 | try addTopLevelDecl(c, typedef_name, &node.base); | ||
| 427 | } | ||
| 428 | |||
| 387 | const ResultUsed = enum { | 429 | const ResultUsed = enum { |
| 388 | used, | 430 | used, |
| 389 | unused, | 431 | unused, |
| ... | @@ -1534,6 +1576,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1534,6 +1576,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1534 | node.rhs = try transQualType(rp, child_qt, source_loc); | 1576 | node.rhs = try transQualType(rp, child_qt, source_loc); |
| 1535 | return &node.base; | 1577 | return &node.base; |
| 1536 | }, | 1578 | }, |
| 1579 | .Typedef => { | ||
| 1580 | const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); | ||
| 1581 | |||
| 1582 | const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); | ||
| 1583 | const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); | ||
| 1584 | return appendIdentifier(rp.c, typedef_name); | ||
| 1585 | }, | ||
| 1537 | else => { | 1586 | else => { |
| 1538 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); | 1587 | const type_name = rp.c.str(ZigClangType_getTypeClassName(ty)); |
| 1539 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); | 1588 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name}); |
| ... | @@ -1541,6 +1590,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour | ... | @@ -1541,6 +1590,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour |
| 1541 | } | 1590 | } |
| 1542 | } | 1591 | } |
| 1543 | 1592 | ||
| 1593 | fn isCVoid(qt: ZigClangQualType) bool { | ||
| 1594 | const ty = ZigClangQualType_getTypePtr(qt); | ||
| 1595 | if (ZigClangType_getTypeClass(ty) == .Builtin) { | ||
| 1596 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); | ||
| 1597 | return ZigClangBuiltinType_getKind(builtin_ty) == .Void; | ||
| 1598 | } | ||
| 1599 | return false; | ||
| 1600 | } | ||
| 1601 | |||
| 1544 | const FnDeclContext = struct { | 1602 | const FnDeclContext = struct { |
| 1545 | fn_name: []const u8, | 1603 | fn_name: []const u8, |
| 1546 | has_body: bool, | 1604 | has_body: bool, |
| ... | @@ -1691,7 +1749,8 @@ fn finishTransFnProto( | ... | @@ -1691,7 +1749,8 @@ fn finishTransFnProto( |
| 1691 | break :blk try appendIdentifier(rp.c, "noreturn"); | 1749 | break :blk try appendIdentifier(rp.c, "noreturn"); |
| 1692 | } else { | 1750 | } else { |
| 1693 | const return_qt = ZigClangFunctionType_getReturnType(fn_ty); | 1751 | const return_qt = ZigClangFunctionType_getReturnType(fn_ty); |
| 1694 | if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) { | 1752 | if (isCVoid(return_qt)) { |
| 1753 | // convert primitive c_void to actual void (only for return type) | ||
| 1695 | break :blk try appendIdentifier(rp.c, "void"); | 1754 | break :blk try appendIdentifier(rp.c, "void"); |
| 1696 | } else { | 1755 | } else { |
| 1697 | break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) { | 1756 | break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) { |
| ... | @@ -1786,7 +1845,7 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime | ... | @@ -1786,7 +1845,7 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime |
| 1786 | .init_node = &call_node.base, | 1845 | .init_node = &call_node.base, |
| 1787 | .semicolon_token = semi_tok, | 1846 | .semicolon_token = semi_tok, |
| 1788 | }; | 1847 | }; |
| 1789 | try c.tree.root_node.decls.push(&var_decl_node.base); | 1848 | try addTopLevelDecl(c, name, &var_decl_node.base); |
| 1790 | } | 1849 | } |
| 1791 | 1850 | ||
| 1792 | fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex { | 1851 | fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex { |
test/translate_c.zig+76-76| ... | @@ -84,6 +84,82 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -84,6 +84,82 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 84 | \\pub fn bar() void {} | 84 | \\pub fn bar() void {} |
| 85 | }); | 85 | }); |
| 86 | 86 | ||
| 87 | cases.add_both("typedef void", | ||
| 88 | \\typedef void Foo; | ||
| 89 | \\Foo fun(Foo *a); | ||
| 90 | , &[_][]const u8{ | ||
| 91 | \\pub const Foo = c_void; | ||
| 92 | , | ||
| 93 | \\pub extern fn fun(a: ?*Foo) Foo; | ||
| 94 | }); | ||
| 95 | |||
| 96 | cases.add_both("duplicate typedef", | ||
| 97 | \\typedef long foo; | ||
| 98 | \\typedef int bar; | ||
| 99 | \\typedef long foo; | ||
| 100 | \\typedef int baz; | ||
| 101 | , &[_][]const u8{ | ||
| 102 | \\pub const foo = c_long; | ||
| 103 | \\pub const bar = c_int; | ||
| 104 | \\pub const baz = c_int; | ||
| 105 | }); | ||
| 106 | |||
| 107 | cases.add_both("casting pointers to ints and ints to pointers", | ||
| 108 | \\void foo(void); | ||
| 109 | \\void bar(void) { | ||
| 110 | \\ void *func_ptr = foo; | ||
| 111 | \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr; | ||
| 112 | \\} | ||
| 113 | , &[_][]const u8{ | ||
| 114 | \\pub extern fn foo() void; | ||
| 115 | \\pub export fn bar() void { | ||
| 116 | \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo); | ||
| 117 | \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr))); | ||
| 118 | \\} | ||
| 119 | }); | ||
| 120 | |||
| 121 | cases.add_both("noreturn attribute", | ||
| 122 | \\void foo(void) __attribute__((noreturn)); | ||
| 123 | , &[_][]const u8{ | ||
| 124 | \\pub extern fn foo() noreturn; | ||
| 125 | }); | ||
| 126 | |||
| 127 | cases.add_both("add, sub, mul, div, rem", | ||
| 128 | \\int s(int a, int b) { | ||
| 129 | \\ int c; | ||
| 130 | \\ c = a + b; | ||
| 131 | \\ c = a - b; | ||
| 132 | \\ c = a * b; | ||
| 133 | \\ c = a / b; | ||
| 134 | \\ c = a % b; | ||
| 135 | \\} | ||
| 136 | \\unsigned u(unsigned a, unsigned b) { | ||
| 137 | \\ unsigned c; | ||
| 138 | \\ c = a + b; | ||
| 139 | \\ c = a - b; | ||
| 140 | \\ c = a * b; | ||
| 141 | \\ c = a / b; | ||
| 142 | \\ c = a % b; | ||
| 143 | \\} | ||
| 144 | , &[_][]const u8{ | ||
| 145 | \\pub export fn s(a: c_int, b: c_int) c_int { | ||
| 146 | \\ var c: c_int = undefined; | ||
| 147 | \\ c = (a + b); | ||
| 148 | \\ c = (a - b); | ||
| 149 | \\ c = (a * b); | ||
| 150 | \\ c = @divTrunc(a, b); | ||
| 151 | \\ c = @rem(a, b); | ||
| 152 | \\} | ||
| 153 | \\pub export fn u(a: c_uint, b: c_uint) c_uint { | ||
| 154 | \\ var c: c_uint = undefined; | ||
| 155 | \\ c = (a +% b); | ||
| 156 | \\ c = (a -% b); | ||
| 157 | \\ c = (a *% b); | ||
| 158 | \\ c = (a / b); | ||
| 159 | \\ c = (a % b); | ||
| 160 | \\} | ||
| 161 | }); | ||
| 162 | |||
| 87 | /////////////// Cases that pass for only stage2 //////////////// | 163 | /////////////// Cases that pass for only stage2 //////////////// |
| 88 | 164 | ||
| 89 | cases.add_2("Parameterless function prototypes", | 165 | cases.add_2("Parameterless function prototypes", |
| ... | @@ -144,20 +220,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -144,20 +220,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 144 | \\pub const REDISMODULE_READ = 1 << 0; | 220 | \\pub const REDISMODULE_READ = 1 << 0; |
| 145 | }); | 221 | }); |
| 146 | 222 | ||
| 147 | cases.add_both("casting pointers to ints and ints to pointers", | ||
| 148 | \\void foo(void); | ||
| 149 | \\void bar(void) { | ||
| 150 | \\ void *func_ptr = foo; | ||
| 151 | \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr; | ||
| 152 | \\} | ||
| 153 | , &[_][]const u8{ | ||
| 154 | \\pub extern fn foo() void; | ||
| 155 | \\pub export fn bar() void { | ||
| 156 | \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo); | ||
| 157 | \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr))); | ||
| 158 | \\} | ||
| 159 | }); | ||
| 160 | |||
| 161 | if (builtin.os != builtin.Os.windows) { | 223 | if (builtin.os != builtin.Os.windows) { |
| 162 | // Windows treats this as an enum with type c_int | 224 | // Windows treats this as an enum with type c_int |
| 163 | cases.add("big negative enum init values when C ABI supports long long enums", | 225 | cases.add("big negative enum init values when C ABI supports long long enums", |
| ... | @@ -330,12 +392,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -330,12 +392,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 330 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void; | 392 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void; |
| 331 | }); | 393 | }); |
| 332 | 394 | ||
| 333 | cases.add_both("noreturn attribute", | ||
| 334 | \\void foo(void) __attribute__((noreturn)); | ||
| 335 | , &[_][]const u8{ | ||
| 336 | \\pub extern fn foo() noreturn; | ||
| 337 | }); | ||
| 338 | |||
| 339 | cases.add("simple function", | 395 | cases.add("simple function", |
| 340 | \\int abs(int a) { | 396 | \\int abs(int a) { |
| 341 | \\ return a < 0 ? -a : a; | 397 | \\ return a < 0 ? -a : a; |
| ... | @@ -512,15 +568,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -512,15 +568,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 512 | \\}; | 568 | \\}; |
| 513 | }); | 569 | }); |
| 514 | 570 | ||
| 515 | cases.add("typedef void", | ||
| 516 | \\typedef void Foo; | ||
| 517 | \\Foo fun(Foo *a); | ||
| 518 | , &[_][]const u8{ | ||
| 519 | \\pub const Foo = c_void; | ||
| 520 | , | ||
| 521 | \\pub extern fn fun(a: ?*Foo) Foo; | ||
| 522 | }); | ||
| 523 | |||
| 524 | cases.add("generate inline func for #define global extern fn", | 571 | cases.add("generate inline func for #define global extern fn", |
| 525 | \\extern void (*fn_ptr)(void); | 572 | \\extern void (*fn_ptr)(void); |
| 526 | \\#define foo fn_ptr | 573 | \\#define foo fn_ptr |
| ... | @@ -720,42 +767,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -720,42 +767,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 720 | \\} | 767 | \\} |
| 721 | }); | 768 | }); |
| 722 | 769 | ||
| 723 | cases.add_both("add, sub, mul, div, rem", | ||
| 724 | \\int s(int a, int b) { | ||
| 725 | \\ int c; | ||
| 726 | \\ c = a + b; | ||
| 727 | \\ c = a - b; | ||
| 728 | \\ c = a * b; | ||
| 729 | \\ c = a / b; | ||
| 730 | \\ c = a % b; | ||
| 731 | \\} | ||
| 732 | \\unsigned u(unsigned a, unsigned b) { | ||
| 733 | \\ unsigned c; | ||
| 734 | \\ c = a + b; | ||
| 735 | \\ c = a - b; | ||
| 736 | \\ c = a * b; | ||
| 737 | \\ c = a / b; | ||
| 738 | \\ c = a % b; | ||
| 739 | \\} | ||
| 740 | , &[_][]const u8{ | ||
| 741 | \\pub export fn s(a: c_int, b: c_int) c_int { | ||
| 742 | \\ var c: c_int = undefined; | ||
| 743 | \\ c = (a + b); | ||
| 744 | \\ c = (a - b); | ||
| 745 | \\ c = (a * b); | ||
| 746 | \\ c = @divTrunc(a, b); | ||
| 747 | \\ c = @rem(a, b); | ||
| 748 | \\} | ||
| 749 | \\pub export fn u(a: c_uint, b: c_uint) c_uint { | ||
| 750 | \\ var c: c_uint = undefined; | ||
| 751 | \\ c = (a +% b); | ||
| 752 | \\ c = (a -% b); | ||
| 753 | \\ c = (a *% b); | ||
| 754 | \\ c = (a / b); | ||
| 755 | \\ c = (a % b); | ||
| 756 | \\} | ||
| 757 | }); | ||
| 758 | |||
| 759 | cases.add("bitwise binary operators", | 770 | cases.add("bitwise binary operators", |
| 760 | \\int max(int a, int b) { | 771 | \\int max(int a, int b) { |
| 761 | \\ return (a & b) ^ (a | b); | 772 | \\ return (a & b) ^ (a | b); |
| ... | @@ -1148,17 +1159,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1148,17 +1159,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1148 | \\} | 1159 | \\} |
| 1149 | }); | 1160 | }); |
| 1150 | 1161 | ||
| 1151 | cases.add("duplicate typedef", | ||
| 1152 | \\typedef long foo; | ||
| 1153 | \\typedef int bar; | ||
| 1154 | \\typedef long foo; | ||
| 1155 | \\typedef int baz; | ||
| 1156 | , &[_][]const u8{ | ||
| 1157 | \\pub const foo = c_long; | ||
| 1158 | \\pub const bar = c_int; | ||
| 1159 | \\pub const baz = c_int; | ||
| 1160 | }); | ||
| 1161 | |||
| 1162 | cases.add("post increment/decrement", | 1162 | cases.add("post increment/decrement", |
| 1163 | \\void foo(void) { | 1163 | \\void foo(void) { |
| 1164 | \\ int i = 0; | 1164 | \\ int i = 0; |