From 36da8d02b56e06c92279b4df21fbfaa0273e6c7b Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Wed, 12 May 2021 23:06:28 -0700 Subject: [PATCH] translate-c: translate global (file scope) assembly --- src/clang.zig | 5 +++++ src/translate_c.zig | 18 ++++++++++++++++++ src/translate_c/ast.zig | 17 +++++++++++++++++ src/zig_clang.cpp | 5 +++++ src/zig_clang.h | 3 +++ test/translate_c.zig | 14 ++++++++++++++ 6 files changed, 62 insertions(+) diff --git a/src/clang.zig b/src/clang.zig index e00271968b..256dbda1e1 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -905,6 +905,11 @@ pub const TypedefNameDecl = opaque { extern fn ZigClangTypedefNameDecl_getLocation(*const TypedefNameDecl) SourceLocation; }; +pub const FileScopeAsmDecl = opaque { + pub const getAsmString = ZigClangFileScopeAsmDecl_getAsmString; + extern fn ZigClangFileScopeAsmDecl_getAsmString(*const FileScopeAsmDecl) *const StringLiteral; +}; + pub const TypedefType = opaque { pub const getDecl = ZigClangTypedefType_getDecl; extern fn ZigClangTypedefType_getDecl(*const TypedefType) *const TypedefNameDecl; diff --git a/src/translate_c.zig b/src/translate_c.zig index 1f8d818f0b..348e284db3 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -480,6 +480,9 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { .Empty => { // Do nothing }, + .FileScopeAsm => { + try transFileScopeAsm(c, &c.global_scope.base, @ptrCast(*const clang.FileScopeAsmDecl, decl)); + }, else => { const decl_name = try c.str(decl.getDeclKindName()); try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name}); @@ -487,6 +490,21 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { } } +fn transFileScopeAsm(c: *Context, scope: *Scope, file_scope_asm: *const clang.FileScopeAsmDecl) Error!void { + const asm_string = file_scope_asm.getAsmString(); + var len: usize = undefined; + const bytes_ptr = asm_string.getString_bytes_begin_size(&len); + + const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])}); + const str_node = try Tag.string_literal.create(c.arena, str); + + const asm_node = try Tag.asm_simple.create(c.arena, str_node); + const block = try Tag.block_single.create(c.arena, asm_node); + const comptime_node = try Tag.@"comptime".create(c.arena, block); + + try scope.appendNode(comptime_node); +} + fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { const fn_name = try c.str(@ptrCast(*const clang.NamedDecl, fn_decl).getName_bytes_begin()); if (c.global_scope.sym_table.contains(fn_name)) diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 2e75bf1182..1c7e7de1ac 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -161,6 +161,8 @@ pub const Node = extern union { /// @shuffle(type, a, b, mask) shuffle, + asm_simple, + negate, negate_wrap, bit_not, @@ -245,6 +247,7 @@ pub const Node = extern union { .std_mem_zeroes, .@"return", .@"comptime", + .asm_simple, .discard, .std_math_Log2Int, .negate, @@ -1017,6 +1020,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { }, }); }, + .asm_simple => { + const payload = node.castTag(.asm_simple).?.data; + const asm_token = try c.addToken(.keyword_asm, "asm"); + _ = try c.addToken(.l_paren, "("); + return c.addNode(.{ + .tag = .asm_simple, + .main_token = asm_token, + .data = .{ + .lhs = try renderNode(c, payload), + .rhs = try c.addToken(.r_paren, ")"), + }, + }); + }, .type => { const payload = node.castTag(.type).?.data; return c.addNode(.{ @@ -2257,6 +2273,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .@"continue", .@"return", .@"comptime", + .asm_simple, .usingnamespace_builtins, .while_true, .if_not_break, diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index efdef1e26b..bf6e09d8c0 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1820,6 +1820,11 @@ const ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const ZigClangEnumDecl *z return reinterpret_cast(definition); } +const ZigClangStringLiteral *ZigClangFileScopeAsmDecl_getAsmString(const ZigClangFileScopeAsmDecl *self) { + const clang::StringLiteral *result = reinterpret_cast(self)->getAsmString(); + return reinterpret_cast(result); +} + bool ZigClangRecordDecl_isUnion(const ZigClangRecordDecl *record_decl) { return reinterpret_cast(record_decl)->isUnion(); } diff --git a/src/zig_clang.h b/src/zig_clang.h index 4ea8cc731b..b015340c29 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -124,6 +124,7 @@ struct ZigClangEnumType; struct ZigClangExpr; struct ZigClangFieldDecl; struct ZigClangFileID; +struct ZigClangFileScopeAsmDecl; struct ZigClangFloatingLiteral; struct ZigClangForStmt; struct ZigClangFullSourceLoc; @@ -1000,6 +1001,8 @@ ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangV ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx); +ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangFileScopeAsmDecl_getAsmString(const struct ZigClangFileScopeAsmDecl *self); + ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); diff --git a/test/translate_c.zig b/test/translate_c.zig index 4021210b29..5918dbb37b 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3499,4 +3499,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ '\u{1f4af}', \\}; }); + + cases.add("global assembly", + \\__asm__(".globl func\n\t" + \\ ".type func, @function\n\t" + \\ "func:\n\t" + \\ ".cfi_startproc\n\t" + \\ "movl $42, %eax\n\t" + \\ "ret\n\t" + \\ ".cfi_endproc"); + , &[_][]const u8{ + \\comptime { + \\ asm (".globl func\n\t.type func, @function\n\tfunc:\n\t.cfi_startproc\n\tmovl $42, %eax\n\tret\n\t.cfi_endproc"); + \\} + }); }