diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 850d11afde..194217a600 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -4104,7 +4104,7 @@ fn finishTransFnProto( const rparen_tok = try appendToken(rp.c, .RParen, ")"); - const callconv_expr = if (cc == .C and is_extern) null else blk: { + const callconv_expr = if (extern_export_inline_tok != null) null else blk: { _ = try appendToken(rp.c, .Keyword_callconv, "callconv"); _ = try appendToken(rp.c, .LParen, "("); const expr = try transCreateNodeEnumLiteral(rp.c, @tagName(cc)); diff --git a/test/tests.zig b/test/tests.zig index 4672359802..755b3977cf 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1422,6 +1422,7 @@ pub const TranslateCContext = struct { sources: ArrayList(SourceFile), expected_lines: ArrayList([]const u8), allow_warnings: bool, + target: Target = .Native, const SourceFile = struct { filename: []const u8, @@ -1474,6 +1475,14 @@ pub const TranslateCContext = struct { var zig_args = ArrayList([]const u8).init(b.allocator); zig_args.append(b.zig_exe) catch unreachable; + switch (self.case.target) { + .Native => {}, + .Cross => { + try zig_args.append("-target"); + try zig_args.append(try self.case.target.zigTriple(b.allocator)); + }, + } + const translate_c_cmd = "translate-c"; zig_args.append(translate_c_cmd) catch unreachable; zig_args.append(b.pathFromRoot(root_src)) catch unreachable; @@ -1602,6 +1611,18 @@ pub const TranslateCContext = struct { self.addCase(tc); } + pub fn addWithTarget( + self: *TranslateCContext, + name: []const u8, + target: Target, + source: []const u8, + expected_lines: []const []const u8, + ) void { + const tc = self.create(false, "source.h", name, source, expected_lines); + tc.target = target; + self.addCase(tc); + } + pub fn addAllowWarnings( self: *TranslateCContext, name: []const u8, diff --git a/test/translate_c.zig b/test/translate_c.zig index ab6dcf9f02..78793b01cd 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -106,7 +106,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\static void bar(void) {} , &[_][]const u8{ \\pub export fn foo() void {} - \\pub fn bar() void {} + \\pub fn bar() callconv(.C) void {} }); cases.add("typedef void", @@ -843,6 +843,38 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const fn1 = ?extern fn (u8) void; }); + cases.addWithTarget("Calling convention", tests.Target{ + .Cross = .{ .os = .linux, .arch = .i386, .abi = .none }, + }, + \\void __attribute__((fastcall)) foo1(float *a); + \\void __attribute__((stdcall)) foo2(float *a); + \\void __attribute__((vectorcall)) foo3(float *a); + \\void __attribute__((cdecl)) foo4(float *a); + , &[_][]const u8{ + \\pub fn foo1(a: [*c]f32) callconv(.Fastcall) void; + \\pub fn foo2(a: [*c]f32) callconv(.Stdcall) void; + \\pub fn foo3(a: [*c]f32) callconv(.Vectorcall) void; + \\pub extern fn foo4(a: [*c]f32) void; + }); + + cases.addWithTarget("Calling convention", tests.Target{ + .Cross = .{ .os = .linux, .arch = .{ .arm = .v8_5a }, .abi = .none }, + }, + \\void __attribute__((pcs("aapcs"))) foo1(float *a); + \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); + , &[_][]const u8{ + \\pub fn foo1(a: [*c]f32) callconv(.AAPCS) void; + \\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; + }); + + cases.addWithTarget("Calling convention", tests.Target{ + .Cross = .{ .os = .linux, .arch = .{ .aarch64 = .v8_5a }, .abi = .none }, + }, + \\void __attribute__((aarch64_vector_pcs)) foo1(float *a); + , &[_][]const u8{ + \\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void; + }); + cases.add("Parameterless function prototypes", \\void a() {} \\void b(void) {} @@ -871,7 +903,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ char *arr1[10] ={0}; \\} , &[_][]const u8{ - \\pub fn foo() void { + \\pub fn foo() callconv(.C) void { \\ var arr: [10]u8 = .{ \\ @bitCast(u8, @truncate(i8, @as(c_int, 1))), \\ } ++ .{0} ** 9; @@ -2148,7 +2180,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ baz(); \\} , &[_][]const u8{ - \\pub fn bar() void {} + \\pub fn bar() callconv(.C) void {} \\pub export fn foo(arg_baz: ?extern fn () [*c]c_int) void { \\ var baz = arg_baz; \\ bar();