authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-13 17:36:18+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-13 17:40:37+02:00
log41a67126a50e3cfab67c749bfc52ac242694774b
treedc07ee07c9ce0e77fc3313a186265ea2baae86a2
parenteb057ef41c8a5482586fc39bab11c280e261ea94
signature Commit is signed but in an unrecognized format.

translate-c-2 typedef


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
735735pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
736736pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
737737pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
738pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
738pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;
739739pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
740740pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
741741pub 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 {
220220 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
221221 },
222222 .Typedef => {
223 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{});
223 try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
224224 },
225225 .Enum => {
226226 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 {
384384 return addTopLevelDecl(c, var_name, &node.base);
385385}
386386
387fn 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
387429const ResultUsed = enum {
388430 used,
389431 unused,
......@@ -1534,6 +1576,13 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
15341576 node.rhs = try transQualType(rp, child_qt, source_loc);
15351577 return &node.base;
15361578 },
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 },
15371586 else => {
15381587 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
15391588 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
15411590 }
15421591}
15431592
1593fn 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
15441602const FnDeclContext = struct {
15451603 fn_name: []const u8,
15461604 has_body: bool,
......@@ -1691,7 +1749,8 @@ fn finishTransFnProto(
16911749 break :blk try appendIdentifier(rp.c, "noreturn");
16921750 } else {
16931751 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)
16951754 break :blk try appendIdentifier(rp.c, "void");
16961755 } else {
16971756 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
17861845 .init_node = &call_node.base,
17871846 .semicolon_token = semi_tok,
17881847 };
1789 try c.tree.root_node.decls.push(&var_decl_node.base);
1848 try addTopLevelDecl(c, name, &var_decl_node.base);
17901849}
17911850
17921851fn 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 {
8484 \\pub fn bar() void {}
8585 });
8686
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
87163 /////////////// Cases that pass for only stage2 ////////////////
88164
89165 cases.add_2("Parameterless function prototypes",
......@@ -144,20 +220,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
144220 \\pub const REDISMODULE_READ = 1 << 0;
145221 });
146222
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
161223 if (builtin.os != builtin.Os.windows) {
162224 // Windows treats this as an enum with type c_int
163225 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 {
330392 \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
331393 });
332394
333 cases.add_both("noreturn attribute",
334 \\void foo(void) __attribute__((noreturn));
335 , &[_][]const u8{
336 \\pub extern fn foo() noreturn;
337 });
338
339395 cases.add("simple function",
340396 \\int abs(int a) {
341397 \\ return a < 0 ? -a : a;
......@@ -512,15 +568,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
512568 \\};
513569 });
514570
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
524571 cases.add("generate inline func for #define global extern fn",
525572 \\extern void (*fn_ptr)(void);
526573 \\#define foo fn_ptr
......@@ -720,42 +767,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
720767 \\}
721768 });
722769
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
759770 cases.add("bitwise binary operators",
760771 \\int max(int a, int b) {
761772 \\ return (a & b) ^ (a | b);
......@@ -1148,17 +1159,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11481159 \\}
11491160 });
11501161
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
11621162 cases.add("post increment/decrement",
11631163 \\void foo(void) {
11641164 \\ int i = 0;