diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 2336ab2963..5a702b182a 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -765,6 +765,8 @@ pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigC pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl; pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8; +pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint; +pub extern fn ZigClangVarDecl_getAlignedAttribute(self: *const ZigClangVarDecl, *const ZigClangASTContext) c_uint; pub extern fn ZigClangRecordDecl_getDefinition(self: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl; pub extern fn ZigClangEnumDecl_getDefinition(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl; pub extern fn ZigClangRecordDecl_getLocation(self: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index e4f24e4cf6..579367a3f2 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -597,6 +597,20 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { break :blk null; }; + const align_expr = blk: { + const alignment = ZigClangVarDecl_getAlignedAttribute(var_decl, rp.c.clang_context); + if (alignment != 0) { + _ = try appendToken(rp.c, .Keyword_linksection, "align"); + _ = try appendToken(rp.c, .LParen, "("); + // Clang reports the alignment in bits + const expr = try transCreateNodeInt(rp.c, alignment / 8); + _ = try appendToken(rp.c, .RParen, ")"); + + break :blk expr; + } + break :blk null; + }; + const node = try c.a().create(ast.Node.VarDecl); node.* = ast.Node.VarDecl{ .doc_comments = null, @@ -609,7 +623,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { .extern_export_token = extern_tok, .lib_name = null, .type_node = type_node, - .align_node = null, + .align_node = align_expr, .section_node = linksection_expr, .init_node = init_node, .semicolon_token = try appendToken(c, .Semicolon, ";"), @@ -4142,6 +4156,22 @@ fn finishTransFnProto( break :blk null; }; + const align_expr = blk: { + if (fn_decl) |decl| { + const alignment = ZigClangFunctionDecl_getAlignedAttribute(decl, rp.c.clang_context); + if (alignment != 0) { + _ = try appendToken(rp.c, .Keyword_linksection, "align"); + _ = try appendToken(rp.c, .LParen, "("); + // Clang reports the alignment in bits + const expr = try transCreateNodeInt(rp.c, alignment / 8); + _ = try appendToken(rp.c, .RParen, ")"); + + break :blk expr; + } + } + break :blk null; + }; + const return_type_node = blk: { if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) { break :blk try transCreateNodeIdentifier(rp.c, "noreturn"); @@ -4175,7 +4205,7 @@ fn finishTransFnProto( .cc_token = cc_tok, .body_node = null, .lib_name = null, - .align_expr = null, + .align_expr = align_expr, .section_expr = linksection_expr, }; return fn_proto; diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index cf839d16c8..c8dec14bfe 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1592,6 +1592,26 @@ const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *se return nullptr; } +unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx) { + auto casted_self = reinterpret_cast(self); + auto casted_ctx = const_cast(reinterpret_cast(ctx)); + if (const clang::AlignedAttr *AA = casted_self->getAttr()) { + return AA->getAlignment(*casted_ctx); + } + // Zero means no explicit alignment factor was specified + return 0; +} + +unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx) { + auto casted_self = reinterpret_cast(self); + auto casted_ctx = const_cast(reinterpret_cast(ctx)); + if (const clang::AlignedAttr *AA = casted_self->getAttr()) { + return AA->getAlignment(*casted_ctx); + } + // Zero means no explicit alignment factor was specified + return 0; +} + const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { const clang::RecordDecl *record_decl = reinterpret_cast(zig_record_decl); const clang::RecordDecl *definition = record_decl->getDefinition(); diff --git a/src/zig_clang.h b/src/zig_clang.h index d5bd3e4d5b..8f00ff2155 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -859,6 +859,8 @@ ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefNameDecl_getCa ZIG_EXTERN_C const struct ZigClangFunctionDecl *ZigClangFunctionDecl_getCanonicalDecl(const ZigClangFunctionDecl *self); ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(const ZigClangVarDecl *self); ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len); +ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx); +ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); diff --git a/test/translate_c.zig b/test/translate_c.zig index e9e0bb83ba..c38eb3ad78 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -17,14 +17,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.add("linksection() attribute", - \\__attribute__ ((__section__(".data"))) + cases.add("align() attribute", + \\__attribute__ ((aligned(128))) \\extern char my_array[16]; - \\__attribute__ ((__section__(".data"))) + \\__attribute__ ((aligned(128))) \\void my_fn(void) { } , &[_][]const u8{ - \\pub extern var my_array: [16]u8 linksection(".data"); - \\pub export fn my_fn() linksection(".data") void {} + \\pub extern var my_array: [16]u8 align(128); + \\pub export fn my_fn() align(128) void {} + }); + + cases.add("linksection() attribute", + \\// Use the "segment,section" format to make this test pass when + \\// targeting the mach-o binary format + \\__attribute__ ((__section__("NEAR,.data"))) + \\extern char my_array[16]; + \\__attribute__ ((__section__("NEAR,.data"))) + \\void my_fn(void) { } + , &[_][]const u8{ + \\pub extern var my_array: [16]u8 linksection("NEAR,.data"); + \\pub export fn my_fn() linksection("NEAR,.data") void {} }); cases.add("simple function prototypes",