| author | |
| committer | |
| log | 197509e1ec2d475fe646b3e1cde66a23df2520b3 |
| tree | 06c4d32cd0bab4f9e5d0f424cabaf9d0966e0387 |
| parent | 7bd80f207147167821634e16983edf9e9b115c9f |
| parent | d908ca4823e51e8a9a413a3afac540e9e5295826 |
| signature |
closes #40345 files changed, 148 insertions(+), 7 deletions(-)
src-self-hosted/clang.zig+4| ... | ... | @@ -764,6 +764,9 @@ 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; | |
| 768 | pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint; | |
| 769 | pub extern fn ZigClangVarDecl_getAlignedAttribute(self: *const ZigClangVarDecl, *const ZigClangASTContext) c_uint; | |
| 767 | 770 | pub extern fn ZigClangRecordDecl_getDefinition(self: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl; |
| 768 | 771 | pub extern fn ZigClangEnumDecl_getDefinition(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl; |
| 769 | 772 | pub extern fn ZigClangRecordDecl_getLocation(self: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation; |
| ... | ... | @@ -834,6 +837,7 @@ pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDec |
| 834 | 837 | pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt; |
| 835 | 838 | pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool; |
| 836 | 839 | pub extern fn ZigClangFunctionDecl_isInlineSpecified(self: *const ZigClangFunctionDecl) bool; |
| 840 | pub extern fn ZigClangFunctionDecl_getSectionAttribute(self: *const ZigClangFunctionDecl, len: *usize) ?[*]const u8; | |
| 837 | 841 | |
| 838 | 842 | pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind; |
| 839 | 843 |
src-self-hosted/translate_c.zig+78-6| ... | ... | @@ -581,6 +581,36 @@ 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 | ||
| 600 | const align_expr = blk: { | |
| 601 | const alignment = ZigClangVarDecl_getAlignedAttribute(var_decl, rp.c.clang_context); | |
| 602 | if (alignment != 0) { | |
| 603 | _ = try appendToken(rp.c, .Keyword_linksection, "align"); | |
| 604 | _ = try appendToken(rp.c, .LParen, "("); | |
| 605 | // Clang reports the alignment in bits | |
| 606 | const expr = try transCreateNodeInt(rp.c, alignment / 8); | |
| 607 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 608 | ||
| 609 | break :blk expr; | |
| 610 | } | |
| 611 | break :blk null; | |
| 612 | }; | |
| 613 | ||
| 584 | 614 | const node = try c.a().create(ast.Node.VarDecl); |
| 585 | 615 | node.* = ast.Node.VarDecl{ |
| 586 | 616 | .doc_comments = null, |
| ... | ... | @@ -593,8 +623,8 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 593 | 623 | .extern_export_token = extern_tok, |
| 594 | 624 | .lib_name = null, |
| 595 | 625 | .type_node = type_node, |
| 596 | .align_node = null, | |
| 597 | .section_node = null, | |
| 626 | .align_node = align_expr, | |
| 627 | .section_node = linksection_expr, | |
| 598 | 628 | .init_node = init_node, |
| 599 | 629 | .semicolon_token = try appendToken(c, .Semicolon, ";"), |
| 600 | 630 | }; |
| ... | ... | @@ -3575,6 +3605,14 @@ fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node { |
| 3575 | 3605 | return &node.base; |
| 3576 | 3606 | } |
| 3577 | 3607 | |
| 3608 | fn transCreateNodeStringLiteral(c: *Context, str: []const u8) !*ast.Node { | |
| 3609 | const node = try c.a().create(ast.Node.StringLiteral); | |
| 3610 | node.* = .{ | |
| 3611 | .token = try appendToken(c, .StringLiteral, str), | |
| 3612 | }; | |
| 3613 | return &node.base; | |
| 3614 | } | |
| 3615 | ||
| 3578 | 3616 | fn transCreateNodeIf(c: *Context) !*ast.Node.If { |
| 3579 | 3617 | const if_tok = try appendToken(c, .Keyword_if, "if"); |
| 3580 | 3618 | _ = try appendToken(c, .LParen, "("); |
| ... | ... | @@ -4048,8 +4086,8 @@ fn finishTransFnProto( |
| 4048 | 4086 | const noalias_tok = if (ZigClangQualType_isRestrictQualified(param_qt)) try appendToken(rp.c, .Keyword_noalias, "noalias") else null; |
| 4049 | 4087 | |
| 4050 | 4088 | const param_name_tok: ?ast.TokenIndex = blk: { |
| 4051 | if (fn_decl != null) { | |
| 4052 | const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i)); | |
| 4089 | if (fn_decl) |decl| { | |
| 4090 | const param = ZigClangFunctionDecl_getParamDecl(decl, @intCast(c_uint, i)); | |
| 4053 | 4091 | const param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param))); |
| 4054 | 4092 | if (param_name.len < 1) |
| 4055 | 4093 | break :blk null; |
| ... | ... | @@ -4100,6 +4138,40 @@ fn finishTransFnProto( |
| 4100 | 4138 | |
| 4101 | 4139 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| 4102 | 4140 | |
| 4141 | const linksection_expr = blk: { | |
| 4142 | if (fn_decl) |decl| { | |
| 4143 | var str_len: usize = undefined; | |
| 4144 | if (ZigClangFunctionDecl_getSectionAttribute(decl, &str_len)) |str_ptr| { | |
| 4145 | _ = try appendToken(rp.c, .Keyword_linksection, "linksection"); | |
| 4146 | _ = try appendToken(rp.c, .LParen, "("); | |
| 4147 | const expr = try transCreateNodeStringLiteral( | |
| 4148 | rp.c, | |
| 4149 | try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), | |
| 4150 | ); | |
| 4151 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 4152 | ||
| 4153 | break :blk expr; | |
| 4154 | } | |
| 4155 | } | |
| 4156 | break :blk null; | |
| 4157 | }; | |
| 4158 | ||
| 4159 | const align_expr = blk: { | |
| 4160 | if (fn_decl) |decl| { | |
| 4161 | const alignment = ZigClangFunctionDecl_getAlignedAttribute(decl, rp.c.clang_context); | |
| 4162 | if (alignment != 0) { | |
| 4163 | _ = try appendToken(rp.c, .Keyword_linksection, "align"); | |
| 4164 | _ = try appendToken(rp.c, .LParen, "("); | |
| 4165 | // Clang reports the alignment in bits | |
| 4166 | const expr = try transCreateNodeInt(rp.c, alignment / 8); | |
| 4167 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 4168 | ||
| 4169 | break :blk expr; | |
| 4170 | } | |
| 4171 | } | |
| 4172 | break :blk null; | |
| 4173 | }; | |
| 4174 | ||
| 4103 | 4175 | const return_type_node = blk: { |
| 4104 | 4176 | if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { |
| 4105 | 4177 | break :blk try transCreateNodeIdentifier(rp.c, "noreturn"); |
| ... | ... | @@ -4133,8 +4205,8 @@ fn finishTransFnProto( |
| 4133 | 4205 | .cc_token = cc_tok, |
| 4134 | 4206 | .body_node = null, |
| 4135 | 4207 | .lib_name = null, |
| 4136 | .align_expr = null, | |
| 4137 | .section_expr = null, | |
| 4208 | .align_expr = align_expr, | |
| 4209 | .section_expr = linksection_expr, | |
| 4138 | 4210 | }; |
| 4139 | 4211 | return fn_proto; |
| 4140 | 4212 | } |
src/zig_clang.cpp+40| ... | ... | @@ -1582,6 +1582,36 @@ 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 | ||
| 1595 | unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx) { | |
| 1596 | auto casted_self = reinterpret_cast<const clang::VarDecl *>(self); | |
| 1597 | auto casted_ctx = const_cast<clang::ASTContext *>(reinterpret_cast<const clang::ASTContext *>(ctx)); | |
| 1598 | if (const clang::AlignedAttr *AA = casted_self->getAttr<clang::AlignedAttr>()) { | |
| 1599 | return AA->getAlignment(*casted_ctx); | |
| 1600 | } | |
| 1601 | // Zero means no explicit alignment factor was specified | |
| 1602 | return 0; | |
| 1603 | } | |
| 1604 | ||
| 1605 | unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx) { | |
| 1606 | auto casted_self = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1607 | auto casted_ctx = const_cast<clang::ASTContext *>(reinterpret_cast<const clang::ASTContext *>(ctx)); | |
| 1608 | if (const clang::AlignedAttr *AA = casted_self->getAttr<clang::AlignedAttr>()) { | |
| 1609 | return AA->getAlignment(*casted_ctx); | |
| 1610 | } | |
| 1611 | // Zero means no explicit alignment factor was specified | |
| 1612 | return 0; | |
| 1613 | } | |
| 1614 | ||
| 1585 | 1615 | const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { |
| 1586 | 1616 | const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl); |
| 1587 | 1617 | const clang::RecordDecl *definition = record_decl->getDefinition(); |
| ... | ... | @@ -1696,6 +1726,16 @@ bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *s |
| 1696 | 1726 | return casted->isInlineSpecified(); |
| 1697 | 1727 | } |
| 1698 | 1728 | |
| 1729 | const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *self, size_t *len) { | |
| 1730 | auto casted = reinterpret_cast<const clang::FunctionDecl *>(self); | |
| 1731 | if (const clang::SectionAttr *SA = casted->getAttr<clang::SectionAttr>()) { | |
| 1732 | llvm::StringRef str_ref = SA->getName(); | |
| 1733 | *len = str_ref.size(); | |
| 1734 | return (const char *)str_ref.bytes_begin(); | |
| 1735 | } | |
| 1736 | return nullptr; | |
| 1737 | } | |
| 1738 | ||
| 1699 | 1739 | const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) { |
| 1700 | 1740 | auto casted = reinterpret_cast<const clang::TypedefType *>(self); |
| 1701 | 1741 | const clang::TypedefNameDecl *name_decl = casted->getDecl(); |
src/zig_clang.h+4| ... | ... | @@ -858,6 +858,9 @@ 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); | |
| 862 | ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx); | |
| 863 | ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); | |
| 861 | 864 | |
| 862 | 865 | ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); |
| 863 | 866 | ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); |
| ... | ... | @@ -875,6 +878,7 @@ ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl |
| 875 | 878 | ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *); |
| 876 | 879 | ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *); |
| 877 | 880 | ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *); |
| 881 | ZIG_EXTERN_C const char* ZigClangFunctionDecl_getSectionAttribute(const struct ZigClangFunctionDecl *, size_t *); | |
| 878 | 882 | |
| 879 | 883 | ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl); |
| 880 | 884 | ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl); |
test/translate_c.zig+22-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,28 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 18 | 17 | \\} |
| 19 | 18 | }); |
| 20 | 19 | |
| 20 | cases.add("align() attribute", | |
| 21 | \\__attribute__ ((aligned(128))) | |
| 22 | \\extern char my_array[16]; | |
| 23 | \\__attribute__ ((aligned(128))) | |
| 24 | \\void my_fn(void) { } | |
| 25 | , &[_][]const u8{ | |
| 26 | \\pub extern var my_array: [16]u8 align(128); | |
| 27 | \\pub export fn my_fn() align(128) void {} | |
| 28 | }); | |
| 29 | ||
| 30 | cases.add("linksection() attribute", | |
| 31 | \\// Use the "segment,section" format to make this test pass when | |
| 32 | \\// targeting the mach-o binary format | |
| 33 | \\__attribute__ ((__section__("NEAR,.data"))) | |
| 34 | \\extern char my_array[16]; | |
| 35 | \\__attribute__ ((__section__("NEAR,.data"))) | |
| 36 | \\void my_fn(void) { } | |
| 37 | , &[_][]const u8{ | |
| 38 | \\pub extern var my_array: [16]u8 linksection("NEAR,.data"); | |
| 39 | \\pub export fn my_fn() linksection("NEAR,.data") void {} | |
| 40 | }); | |
| 41 | ||
| 21 | 42 | cases.add("simple function prototypes", |
| 22 | 43 | \\void __attribute__((noreturn)) foo(void); |
| 23 | 44 | \\int bar(void); |