| author | |
| committer | |
| log | 8e89bdfe991ebf643c6f35064a2e72de18feff9b |
| tree | 817be8192b4bea3127b6956490303ccbae1237e5 |
| parent | 7bd80f207147167821634e16983edf9e9b115c9f |
| signature |
5 files changed, 80 insertions(+), 5 deletions(-)
src-self-hosted/clang.zig+2| ... | ... | @@ -764,6 +764,7 @@ pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnu |
| 764 | 764 | pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl; |
| 765 | 765 | pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; |
| 766 | 766 | pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl; |
| 767 | pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8; | |
| 767 | 768 | pub extern fn ZigClangRecordDecl_getDefinition(self: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl; |
| 768 | 769 | pub extern fn ZigClangEnumDecl_getDefinition(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl; |
| 769 | 770 | pub extern fn ZigClangRecordDecl_getLocation(self: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation; |
| ... | ... | @@ -834,6 +835,7 @@ pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDec |
| 834 | 835 | pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; |
| 835 | 836 | pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool; |
| 836 | 837 | pub extern fn ZigClangFunctionDecl_isInlineSpecified(self: *const ZigClangFunctionDecl) bool; |
| 838 | pub extern fn ZigClangFunctionDecl_getSectionAttribute(self: *const ZigClangFunctionDecl, len: *usize) ?[*]const u8; | |
| 837 | 839 | |
| 838 | 840 | pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; |
| 839 | 841 |
src-self-hosted/translate_c.zig+46-4| ... | ... | @@ -581,6 +581,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 581 | 581 | return failDecl(c, var_decl_loc, checked_name, "non-extern variable has no initializer", .{}); |
| 582 | 582 | } |
| 583 | 583 | |
| 584 | const linksection_expr = blk: { | |
| 585 | var str_len: usize = undefined; | |
| 586 | if (ZigClangVarDecl_getSectionAttribute(var_decl, &str_len)) |str_ptr| { | |
| 587 | _ = try appendToken(rp.c, .Keyword_linksection, "linksection"); | |
| 588 | _ = try appendToken(rp.c, .LParen, "("); | |
| 589 | const expr = try transCreateNodeStringLiteral( | |
| 590 | rp.c, | |
| 591 | try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), | |
| 592 | ); | |
| 593 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 594 | ||
| 595 | break :blk expr; | |
| 596 | } | |
| 597 | break :blk null; | |
| 598 | }; | |
| 599 | ||
| 584 | 600 | const node = try c.a().create(ast.Node.VarDecl); |
| 585 | 601 | node.* = ast.Node.VarDecl{ |
| 586 | 602 | .doc_comments = null, |
| ... | ... | @@ -594,7 +610,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 594 | 610 | .lib_name = null, |
| 595 | 611 | .type_node = type_node, |
| 596 | 612 | .align_node = null, |
| 597 | .section_node = null, | |
| 613 | .section_node = linksection_expr, | |
| 598 | 614 | .init_node = init_node, |
| 599 | 615 | .semicolon_token = try appendToken(c, .Semicolon, ";"), |
| 600 | 616 | }; |
| ... | ... | @@ -3575,6 +3591,14 @@ fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node { |
| 3575 | 3591 | return &node.base; |
| 3576 | 3592 | } |
| 3577 | 3593 | |
| 3594 | fn transCreateNodeStringLiteral(c: *Context, str: []const u8) !*ast.Node { | |
| 3595 | const node = try c.a().create(ast.Node.StringLiteral); | |
| 3596 | node.* = .{ | |
| 3597 | .token = try appendToken(c, .StringLiteral, str), | |
| 3598 | }; | |
| 3599 | return &node.base; | |
| 3600 | } | |
| 3601 | ||
| 3578 | 3602 | fn transCreateNodeIf(c: *Context) !*ast.Node.If { |
| 3579 | 3603 | const if_tok = try appendToken(c, .Keyword_if, "if"); |
| 3580 | 3604 | _ = try appendToken(c, .LParen, "("); |
| ... | ... | @@ -4048,8 +4072,8 @@ fn finishTransFnProto( |
| 4048 | 4072 | const noalias_tok = if (ZigClangQualType_isRestrictQualified(param_qt)) try appendToken(rp.c, .Keyword_noalias, "noalias") else null; |
| 4049 | 4073 | |
| 4050 | 4074 | const param_name_tok: ?ast.TokenIndex = blk: { |
| 4051 | if (fn_decl != null) { | |
| 4052 | const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i)); | |
| 4075 | if (fn_decl) |decl| { | |
| 4076 | const param = ZigClangFunctionDecl_getParamDecl(decl, @intCast(c_uint, i)); | |
| 4053 | 4077 | const param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param))); |
| 4054 | 4078 | if (param_name.len < 1) |
| 4055 | 4079 | break :blk null; |
| ... | ... | @@ -4100,6 +4124,24 @@ fn finishTransFnProto( |
| 4100 | 4124 | |
| 4101 | 4125 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| 4102 | 4126 | |
| 4127 | const linksection_expr = blk: { | |
| 4128 | if (fn_decl) |decl| { | |
| 4129 | var str_len: usize = undefined; | |
| 4130 | if (ZigClangFunctionDecl_getSectionAttribute(decl, &str_len)) |str_ptr| { | |
| 4131 | _ = try appendToken(rp.c, .Keyword_linksection, "linksection"); | |
| 4132 | _ = try appendToken(rp.c, .LParen, "("); | |
| 4133 | const expr = try transCreateNodeStringLiteral( | |
| 4134 | rp.c, | |
| 4135 | try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), | |
| 4136 | ); | |
| 4137 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 4138 | ||
| 4139 | break :blk expr; | |
| 4140 | } | |
| 4141 | } | |
| 4142 | break :blk null; | |
| 4143 | }; | |
| 4144 | ||
| 4103 | 4145 | const return_type_node = blk: { |
| 4104 | 4146 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { |
| 4105 | 4147 | break :blk try transCreateNodeIdentifier(rp.c, "noreturn"); |
| ... | ... | @@ -4134,7 +4176,7 @@ fn finishTransFnProto( |
| 4134 | 4176 | .body_node = null, |
| 4135 | 4177 | .lib_name = null, |
| 4136 | 4178 | .align_expr = null, |
| 4137 | .section_expr = null, | |
| 4179 | .section_expr = linksection_expr, | |
| 4138 | 4180 | }; |
| 4139 | 4181 | return fn_proto; |
| 4140 | 4182 | } |
src/zig_clang.cpp+20| ... | ... | @@ -1582,6 +1582,16 @@ const ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *s |
| 1582 | 1582 | return reinterpret_cast<const ZigClangVarDecl *>(decl); |
| 1583 | 1583 | } |
| 1584 | 1584 | |
| 1585 | const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len) { | |
| 1586 | auto casted = reinterpret_cast<const clang::VarDecl *>(self); | |
| 1587 | if (const clang::SectionAttr *SA = casted->getAttr<clang::SectionAttr>()) { | |
| 1588 | llvm::StringRef str_ref = SA->getName(); | |
| 1589 | *len = str_ref.size(); | |
| 1590 | return (const char *)str_ref.bytes_begin(); | |
| 1591 | } | |
| 1592 | return nullptr; | |
| 1593 | } | |
| 1594 | ||
| 1585 | 1595 | const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { |
| 1586 | 1596 | const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl); |
| 1587 | 1597 | const clang::RecordDecl *definition = record_decl->getDefinition(); |
| ... | ... | @@ -1696,6 +1706,16 @@ bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *s |
| 1696 | 1706 | return casted->isInlineSpecified(); |
| 1697 | 1707 | } |
| 1698 | 1708 | |
| 1709 | const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *self, size_t *len) { | |
| 1710 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1711 | if (const clang::SectionAttr *SA = casted->getAttr<clang::SectionAttr>()) { | |
| 1712 | llvm::StringRef str_ref = SA->getName(); | |
| 1713 | *len = str_ref.size(); | |
| 1714 | return (const char *)str_ref.bytes_begin(); | |
| 1715 | } | |
| 1716 | return nullptr; | |
| 1717 | } | |
| 1718 | ||
| 1699 | 1719 | const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) { |
| 1700 | 1720 | auto casted = reinterpret_cast<const clang::TypedefType *>(self); |
| 1701 | 1721 | const clang::TypedefNameDecl *name_decl = casted->getDecl(); |
src/zig_clang.h+2| ... | ... | @@ -858,6 +858,7 @@ ZIG_EXTERN_C const struct ZigClangTagDecl *ZigClangEnumDecl_getCanonicalDecl(con |
| 858 | 858 | ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCanonicalDecl(const struct ZigClangTypedefNameDecl *); |
| 859 | 859 | ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangFunctionDecl_getCanonicalDecl(const ZigClangFunctionDecl *self); |
| 860 | 860 | ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *self); |
| 861 | ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len); | |
| 861 | 862 | |
| 862 | 863 | ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); |
| 863 | 864 | ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); |
| ... | ... | @@ -875,6 +876,7 @@ ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl |
| 875 | 876 | ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *); |
| 876 | 877 | ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *); |
| 877 | 878 | ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *); |
| 879 | ZIG_EXTERN_C const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *, size_t *); | |
| 878 | 880 | |
| 879 | 881 | ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl); |
| 880 | 882 | ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl); |
test/translate_c.zig+10-1| ... | ... | @@ -2,7 +2,6 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 5 | /////////////// Cases that pass for both stage1/stage2 //////////////// | |
| 6 | 5 | cases.add("simple ptrCast for casts between opaque types", |
| 7 | 6 | \\struct opaque; |
| 8 | 7 | \\struct opaque_2; |
| ... | ... | @@ -18,6 +17,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 18 | 17 | \\} |
| 19 | 18 | }); |
| 20 | 19 | |
| 20 | cases.add("linksection() attribute", | |
| 21 | \\__attribute__ ((__section__(".data"))) | |
| 22 | \\extern char my_array[16]; | |
| 23 | \\__attribute__ ((__section__(".data"))) | |
| 24 | \\void my_fn(void) { } | |
| 25 | , &[_][]const u8{ | |
| 26 | \\pub extern var my_array: [16]u8 linksection(".data"); | |
| 27 | \\pub export fn my_fn() linksection(".data") void {} | |
| 28 | }); | |
| 29 | ||
| 21 | 30 | cases.add("simple function prototypes", |
| 22 | 31 | \\void __attribute__((noreturn)) foo(void); |
| 23 | 32 | \\int bar(void); |