authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-17 15:44:14-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 14:44:41-04:00
loge03056d45a864c8176cdd897d771457005ead592
tree2831c341924bf2b9c5c07825cecb96e1a687fa67
parent6c003e84338bc1f8ceaf7ca869cb343b31be9fc7

cbe: various calling convention fixes

- Annotate function pointers with calling convention. - Support `incoming_stack_alignment`. - Fix noreturn attribute position.

6 files changed, 239 insertions(+), 149 deletions(-)

lib/zig.h+6-13
...@@ -199,10 +199,8 @@...@@ -199,10 +199,8 @@
199#endif199#endif
200200
201#if defined(zig_msvc)201#if defined(zig_msvc)
202#define zig_const_arr
203#define zig_callconv(c) __##c202#define zig_callconv(c) __##c
204#else203#else
205#define zig_const_arr static const
206#define zig_callconv(c) __attribute__((c))204#define zig_callconv(c) __attribute__((c))
207#endif205#endif
208206
...@@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80;...@@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80;
5841#define zig_init_special_f80(sign, name, arg, repr) repr5839#define zig_init_special_f80(sign, name, arg, repr) repr
5842#endif5840#endif
58435841
5844#if defined(zig_gcc) && defined(zig_x86)
5845#define zig_f128_has_miscompilations 1
5846#else
5847#define zig_f128_has_miscompilations 0
5848#endif
5849#define zig_has_f128 15842#define zig_has_f128 1
5850#define zig_libc_name_f128(name) name##f1285843#define zig_libc_name_f128(name) name##f128
5851#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)5844#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
...@@ -5859,22 +5852,22 @@ typedef struct { uint64_t hi, lo; } zig_f128;...@@ -5859,22 +5852,22 @@ typedef struct { uint64_t hi, lo; } zig_f128;
5859#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }5852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
5860#define zig_lo_repr_f128(arg) (arg).lo5853#define zig_lo_repr_f128(arg) (arg).lo
5861#define zig_hi_repr_f128(arg) (arg).hi5854#define zig_hi_repr_f128(arg) (arg).hi
5862#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 1135855#elif FLT_MANT_DIG == 113
5863typedef float zig_f128;5856typedef float zig_f128;
5864#define zig_make_f128(fp, repr) fp##f5857#define zig_make_f128(fp, repr) fp##f
5865#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 1135858#elif DBL_MANT_DIG == 113
5866typedef double zig_f128;5859typedef double zig_f128;
5867#define zig_make_f128(fp, repr) fp5860#define zig_make_f128(fp, repr) fp
5868#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 1135861#elif LDBL_MANT_DIG == 113
5869typedef long double zig_f128;5862typedef long double zig_f128;
5870#define zig_make_f128(fp, repr) fp##l5863#define zig_make_f128(fp, repr) fp##l
5871#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 1135864#elif FLT128_MANT_DIG == 113
5872typedef _Float128 zig_f128;5865typedef _Float128 zig_f128;
5873#define zig_make_f128(fp, repr) fp##f1285866#define zig_make_f128(fp, repr) fp##f128
5874#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 1135867#elif FLT64X_MANT_DIG == 113
5875typedef _Float64x zig_f128;5868typedef _Float64x zig_f128;
5876#define zig_make_f128(fp, repr) fp##f64x5869#define zig_make_f128(fp, repr) fp##f64x
5877#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)5870#elif defined(__SIZEOF_FLOAT128__)
5878typedef __float128 zig_f128;5871typedef __float128 zig_f128;
5879#define zig_make_f128(fp, repr) fp##q5872#define zig_make_f128(fp, repr) fp##q
5880#undef zig_make_special_f1285873#undef zig_make_special_f128
src/Zcu.zig+6-24
...@@ -4617,44 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4617,44 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4617 .m68k_rtd,4617 .m68k_rtd,
4618 .m68k_interrupt,4618 .m68k_interrupt,
4619 .msp430_interrupt,4619 .msp430_interrupt,
4620 => |opts| opts.incoming_stack_alignment == null,
4621
4622 .arm_aapcs_vfp,4620 .arm_aapcs_vfp,
4623 => |opts| opts.incoming_stack_alignment == null,
4624
4625 .arc_interrupt,4621 .arc_interrupt,
4626 => |opts| opts.incoming_stack_alignment == null,
4627
4628 .arm_interrupt,4622 .arm_interrupt,
4629 => |opts| opts.incoming_stack_alignment == null,
4630
4631 .microblaze_interrupt,4623 .microblaze_interrupt,
4632 => |opts| opts.incoming_stack_alignment == null,
4633
4634 .mips_interrupt,4624 .mips_interrupt,
4635 .mips64_interrupt,4625 .mips64_interrupt,
4636 => |opts| opts.incoming_stack_alignment == null,
4637
4638 .riscv32_interrupt,4626 .riscv32_interrupt,
4639 .riscv64_interrupt,4627 .riscv64_interrupt,
4640 => |opts| opts.incoming_stack_alignment == null,
4641
4642 .sh_interrupt,4628 .sh_interrupt,
4643 => |opts| opts.incoming_stack_alignment == null,4629 .avr_interrupt,
4630 .avr_signal,
4631 .ez80_tiflags,
4632 .naked,
4633 => true, // incoming stack alignment supported
46444634
4645 .x86_sysv,4635 .x86_sysv,
4646 .x86_win,4636 .x86_win,
4647 .x86_mingw,4637 .x86_mingw,
4648 .x86_stdcall,4638 .x86_stdcall,
4649 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,4639 => |opts| opts.register_params == 0, // incoming stack alignment supported
4650
4651 .avr_interrupt,
4652 .avr_signal,
4653 => true,
4654
4655 .ez80_tiflags => true,
4656
4657 .naked => true,
46584640
4659 else => false,4641 else => false,
4660 };4642 };
src/codegen/c.zig+41-101
...@@ -1750,8 +1750,6 @@ pub const DeclGen = struct {...@@ -1750,8 +1750,6 @@ pub const DeclGen = struct {
1750 try w.writeAll("zig_no_builtin ");1750 try w.writeAll("zig_no_builtin ");
1751 }1751 }
17521752
1753 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1754
1755 // While incomplete types are usually an acceptable substitute for "void", this is not true1753 // While incomplete types are usually an acceptable substitute for "void", this is not true
1756 // in function return types, where "void" is the only incomplete type permitted.1754 // in function return types, where "void" is the only incomplete type permitted.
1757 const actual_return_type: Type = .fromInterned(fn_info.return_type);1755 const actual_return_type: Type = .fromInterned(fn_info.return_type);
...@@ -1763,8 +1761,9 @@ pub const DeclGen = struct {...@@ -1763,8 +1761,9 @@ pub const DeclGen = struct {
17631761
1764 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);1762 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);
1765 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});1763 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
1766 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {1764 switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) {
1767 try w.print("zig_callconv({s}) ", .{call_conv});1765 .c => {},
1766 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
1768 }1767 }
1769 switch (name) {1768 switch (name) {
1770 .nav => |nav| try renderNavName(w, nav, ip),1769 .nav => |nav| try renderNavName(w, nav, ip),
...@@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn(...@@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn(
22212220
2222 const fn_val = zcu.navValue(fn_nav);2221 const fn_val = zcu.navValue(fn_nav);
22232222
2223 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
2224 try w.print("static zig_{t} ", .{kind});2224 try w.print("static zig_{t} ", .{kind});
2225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {2225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {
2226 .never_tail => .{ .nav_never_tail = fn_nav },2226 .never_tail => .{ .nav_never_tail = fn_nav },
...@@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
2326 const gpa = f.dg.gpa;2326 const gpa = f.dg.gpa;
2327 const nav_index = f.dg.owner_nav.unwrap().?;2327 const nav_index = f.dg.owner_nav.unwrap().?;
2328 const nav_val = zcu.navValue(nav_index);2328 const nav_val = zcu.navValue(nav_index);
2329 const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?;
2329 const nav = ip.getNav(nav_index);2330 const nav = ip.getNav(nav_index);
23302331
2332 if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn ");
2331 try fwd_decl_writer.writeAll("static ");2333 try fwd_decl_writer.writeAll("static ");
2332 try f.dg.renderFunctionSignature(2334 try f.dg.renderFunctionSignature(
2333 fwd_decl_writer,2335 fwd_decl_writer,
...@@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
23542356
2355 const main_body = f.air.getMainBody();2357 const main_body = f.air.getMainBody();
2356 f.indent();2358 f.indent();
2359 if (switch (fn_info.cc) {
2360 inline else => |pl| switch (@TypeOf(pl)) {
2361 void,
2362 std.lang.CallingConvention.SpirvKernelOptions,
2363 std.lang.CallingConvention.SpirvFragmentOptions,
2364 std.lang.CallingConvention.SpirvMeshOptions,
2365 => null,
2366 std.lang.CallingConvention.ArcInterruptOptions,
2367 std.lang.CallingConvention.ArmInterruptOptions,
2368 std.lang.CallingConvention.RiscvInterruptOptions,
2369 std.lang.CallingConvention.ShInterruptOptions,
2370 std.lang.CallingConvention.MicroblazeInterruptOptions,
2371 std.lang.CallingConvention.MipsInterruptOptions,
2372 std.lang.CallingConvention.CommonOptions,
2373 std.lang.CallingConvention.X86RegparmOptions,
2374 => pl.incoming_stack_alignment,
2375 else => @compileError(@tagName(pl)),
2376 },
2377 }) |incoming_stack_alignment| realign_stack: {
2378 const normal_stack_align = zcu.getTarget().stackAlignment();
2379 if (incoming_stack_alignment >= normal_stack_align) break :realign_stack;
2380 try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{
2381 normal_stack_align << 1,
2382 });
2383 try f.code.writer.writeAll(
2384 \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack));
2385 );
2386 try f.newline();
2387 }
2357 try genBodyResolveState(f, undefined, &.{}, main_body, true);2388 try genBodyResolveState(f, undefined, &.{}, main_body, true);
2358 try f.outdent();2389 try f.outdent();
2359 try f.code.writer.writeByte('}');2390 try f.code.writer.writeByte('}');
...@@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {...@@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
24562487
2457 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {2488 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
2458 .@"fn" => {2489 .@"fn" => {
2490 const fn_val: Value = .fromInterned(nav.resolved.?.value);
2491 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
2459 try w.writeAll("zig_extern ");2492 try w.writeAll("zig_extern ");
2460 try dg.renderFunctionSignature(2493 try dg.renderFunctionSignature(
2461 w,2494 w,
2462 .fromInterned(nav.resolved.?.value),2495 fn_val,
2463 nav.resolved.?.@"align",2496 nav.resolved.?.@"align",
2464 .forward_decl,2497 .forward_decl,
2465 .{ .@"export" = .{2498 .{ .@"export" = .{
...@@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic...@@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
2560 const exported_val = exported.getValue(zcu);2593 const exported_val = exported.getValue(zcu);
2561 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {2594 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
2562 const @"export" = export_index.ptr(zcu);2595 const @"export" = export_index.ptr(zcu);
2596 const fn_val = exported.getValue(zcu);
2597 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
2563 try w.writeAll("zig_extern ");2598 try w.writeAll("zig_extern ");
2564 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");2599 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");
2565 try dg.renderFunctionSignature(2600 try dg.renderFunctionSignature(
2566 w,2601 w,
2567 exported.getValue(zcu),2602 fn_val,
2568 exported.getAlign(zcu),2603 exported.getAlign(zcu),
2569 .forward_decl,2604 .forward_decl,
2570 .{ .@"export" = .{2605 .{ .@"export" = .{
...@@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {...@@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {
7277 return w.writeAll(toMemoryOrder(order));7312 return w.writeAll(toMemoryOrder(order));
7278}7313}
72797314
7280fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 {
7281 if (zcu.getTarget().cCallingConvention()) |ccc| {
7282 if (cc.eql(ccc)) {
7283 return null;
7284 }
7285 }
7286 return switch (cc) {
7287 .auto, .naked => null,
7288
7289 .x86_16_cdecl => "cdecl",
7290 .x86_16_regparmcall => "regparmcall",
7291 .x86_64_sysv, .x86_sysv => "sysv_abi",
7292 .x86_64_win, .x86_win, .x86_mingw => "ms_abi",
7293 .x86_16_stdcall, .x86_stdcall => "stdcall",
7294 .x86_fastcall => "fastcall",
7295 .x86_thiscall => "thiscall",
7296
7297 .x86_vectorcall,
7298 .x86_64_vectorcall,
7299 => "vectorcall",
7300
7301 .x86_64_regcall_v3_sysv,
7302 .x86_64_regcall_v4_win,
7303 .x86_regcall_v3,
7304 .x86_regcall_v4_win,
7305 => "regcall",
7306
7307 .aarch64_vfabi => "aarch64_vector_pcs",
7308 .aarch64_vfabi_sve => "aarch64_sve_pcs",
7309
7310 .arm_aapcs => "pcs(\"aapcs\")",
7311 .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")",
7312
7313 .arc_interrupt => |opts| switch (opts.type) {
7314 inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")",
7315 },
7316
7317 .arm_interrupt => |opts| switch (opts.type) {
7318 .generic => "interrupt",
7319 .irq => "interrupt(\"IRQ\")",
7320 .fiq => "interrupt(\"FIQ\")",
7321 .swi => "interrupt(\"SWI\")",
7322 .abort => "interrupt(\"ABORT\")",
7323 .undef => "interrupt(\"UNDEF\")",
7324 },
7325
7326 .avr_signal => "signal",
7327
7328 .microblaze_interrupt => |opts| switch (opts.type) {
7329 .user => "save_volatiles",
7330 .regular => "interrupt_handler",
7331 .fast => "fast_interrupt",
7332 .breakpoint => "break_handler",
7333 },
7334
7335 .mips_interrupt,
7336 .mips64_interrupt,
7337 => |opts| switch (opts.mode) {
7338 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7339 },
7340
7341 .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc",
7342
7343 .riscv32_interrupt,
7344 .riscv64_interrupt,
7345 => |opts| switch (opts.mode) {
7346 inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")",
7347 },
7348
7349 .sh_renesas => "renesas",
7350 .sh_interrupt => |opts| switch (opts.save) {
7351 .fpscr => "trapa_handler", // Implies `interrupt_handler`.
7352 .high => "interrupt_handler, nosave_low_regs",
7353 .full => "interrupt_handler",
7354 .bank => "interrupt_handler, resbank",
7355 },
7356
7357 .m68k_rtd => "m68k_rtd",
7358
7359 .avr_interrupt,
7360 .csky_interrupt,
7361 .m68k_interrupt,
7362 .msp430_interrupt,
7363 .x86_16_interrupt,
7364 .x86_interrupt,
7365 .x86_64_interrupt,
7366 => "interrupt",
7367
7368 .ez80_tiflags,
7369 => "__tiflags__",
7370
7371 else => unreachable, // `Zcu.callconvSupported`
7372 };
7373}
7374
7375fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {7315fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {
7376 return switch (order) {7316 return switch (order) {
7377 .Xchg => "xchg",7317 .Xchg => "xchg",
src/codegen/c/type.zig+176-1
...@@ -44,8 +44,175 @@ pub const CType = union(enum) {...@@ -44,8 +44,175 @@ pub const CType = union(enum) {
44 param_tys: []const CType,44 param_tys: []const CType,
45 ret_ty: *const CType,45 ret_ty: *const CType,
46 varargs: bool,46 varargs: bool,
47 cc: CallingConvention,
47 },48 },
4849
50 pub const CallingConvention = enum {
51 c,
52
53 cdecl,
54 regparmcall,
55 sysv_abi,
56 ms_abi,
57 stdcall,
58 fastcall,
59 thiscall,
60
61 vectorcall,
62
63 regcall,
64
65 aarch64_vector_pcs,
66 aarch64_sve_pcs,
67
68 @"pcs(\"aapcs\")",
69 @"pcs(\"aapcs-vfp\")",
70
71 @"interrupt(\"ilink1\")",
72 @"interrupt(\"ilink2\")",
73 @"interrupt(\"ilink\")",
74 @"interrupt(\"firq\")",
75
76 interrupt,
77 @"interrupt(\"IRQ\")",
78 @"interrupt(\"FIQ\")",
79 @"interrupt(\"SWI\")",
80 @"interrupt(\"ABORT\")",
81 @"interrupt(\"UNDEF\")",
82
83 signal,
84
85 save_volatiles,
86 interrupt_handler,
87 fast_interrupt,
88 break_handler,
89
90 @"interrupt(\"eic\")",
91 @"interrupt(\"sw0\")",
92 @"interrupt(\"sw1\")",
93 @"interrupt(\"hw0\")",
94 @"interrupt(\"hw1\")",
95 @"interrupt(\"hw2\")",
96 @"interrupt(\"hw3\")",
97 @"interrupt(\"hw4\")",
98 @"interrupt(\"hw5\")",
99
100 riscv_vector_cc,
101 @"interrupt(\"supervisor\")",
102 @"interrupt(\"machine\")",
103
104 renesas,
105 /// Implies `interrupt_handler`.
106 trapa_handler,
107 @"interrupt_handler, nosave_low_regs",
108 @"interrupt_handler, resbank",
109
110 m68k_rtd,
111
112 tiflags,
113
114 pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention {
115 if (target.cCallingConvention()) |ccc| {
116 if (cc.eql(ccc)) {
117 return .c;
118 }
119 }
120 return switch (cc) {
121 .auto, .naked => .c,
122
123 .x86_16_cdecl => .cdecl,
124 .x86_16_regparmcall => .regparmcall,
125 .x86_64_sysv, .x86_sysv => .sysv_abi,
126 .x86_64_win, .x86_win, .x86_mingw => .ms_abi,
127 .x86_16_stdcall, .x86_stdcall => .stdcall,
128 .x86_fastcall => .fastcall,
129 .x86_thiscall => .thiscall,
130
131 .x86_vectorcall,
132 .x86_64_vectorcall,
133 => .vectorcall,
134
135 .x86_64_regcall_v3_sysv,
136 .x86_64_regcall_v4_win,
137 .x86_regcall_v3,
138 .x86_regcall_v4_win,
139 => .regcall,
140
141 .aarch64_vfabi => .aarch64_vector_pcs,
142 .aarch64_vfabi_sve => .aarch64_sve_pcs,
143
144 .arm_aapcs => .@"pcs(\"aapcs\")",
145 .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")",
146
147 .arc_interrupt => |opts| switch (opts.type) {
148 .ilink1 => .@"interrupt(\"ilink1\")",
149 .ilink2 => .@"interrupt(\"ilink2\")",
150 .ilink => .@"interrupt(\"ilink\")",
151 .firq => .@"interrupt(\"firq\")",
152 },
153
154 .arm_interrupt => |opts| switch (opts.type) {
155 .generic => .interrupt,
156 .irq => .@"interrupt(\"IRQ\")",
157 .fiq => .@"interrupt(\"FIQ\")",
158 .swi => .@"interrupt(\"SWI\")",
159 .abort => .@"interrupt(\"ABORT\")",
160 .undef => .@"interrupt(\"UNDEF\")",
161 },
162
163 .avr_signal => .signal,
164
165 .microblaze_interrupt => |opts| switch (opts.type) {
166 .user => .save_volatiles,
167 .regular => .interrupt_handler,
168 .fast => .fast_interrupt,
169 .breakpoint => .break_handler,
170 },
171
172 .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) {
173 .eic => .@"interrupt(\"eic\")",
174 .sw0 => .@"interrupt(\"sw0\")",
175 .sw1 => .@"interrupt(\"sw1\")",
176 .hw0 => .@"interrupt(\"hw0\")",
177 .hw1 => .@"interrupt(\"hw1\")",
178 .hw2 => .@"interrupt(\"hw2\")",
179 .hw3 => .@"interrupt(\"hw3\")",
180 .hw4 => .@"interrupt(\"hw4\")",
181 .hw5 => .@"interrupt(\"hw5\")",
182 },
183
184 .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc,
185 .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) {
186 .supervisor => .@"interrupt(\"supervisor\")",
187 .machine => .@"interrupt(\"machine\")",
188 },
189
190 .sh_renesas => .renesas,
191 .sh_interrupt => |opts| switch (opts.save) {
192 .fpscr => .trapa_handler,
193 .high => .@"interrupt_handler, nosave_low_regs",
194 .full => .interrupt_handler,
195 .bank => .@"interrupt_handler, resbank",
196 },
197
198 .m68k_rtd => .m68k_rtd,
199
200 .avr_interrupt,
201 .csky_interrupt,
202 .m68k_interrupt,
203 .msp430_interrupt,
204 .x86_16_interrupt,
205 .x86_interrupt,
206 .x86_64_interrupt,
207 => .interrupt,
208
209 .ez80_tiflags => .tiflags,
210
211 else => unreachable, // `Zcu.callconvSupported`
212 };
213 }
214 };
215
49 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears216 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears
50 /// after the identifier in a declarator with this type. In this case, if this node is wrapped217 /// after the identifier in a declarator with this type. In this case, if this node is wrapped
51 /// in a pointer type, we will need to add parentheses due to operator precedence.218 /// in a pointer type, we will need to add parentheses due to operator precedence.
...@@ -376,6 +543,7 @@ pub const CType = union(enum) {...@@ -376,6 +543,7 @@ pub const CType = union(enum) {
376 .ret_ty = ret_cty_buf,543 .ret_ty = ret_cty_buf,
377 .param_tys = param_cty_buf,544 .param_tys = param_cty_buf,
378 .varargs = func_type.is_var_args,545 .varargs = func_type.is_var_args,
546 .cc = .fromLang(func_type.cc, zcu.getTarget()),
379 } };547 } };
380 }548 }
381 try deps.addType(gpa, cur_ty, allow_incomplete);549 try deps.addType(gpa, cur_ty, allow_incomplete);
...@@ -763,6 +931,13 @@ pub const CType = union(enum) {...@@ -763,6 +931,13 @@ pub const CType = union(enum) {
763 try w.writeByte('(');931 try w.writeByte('(');
764 },932 },
765 }933 }
934 switch (ptr.elem_ty.*) {
935 else => {},
936 .function => |function| switch (function.cc) {
937 .c => {},
938 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
939 },
940 }
766 try w.writeByte('*');941 try w.writeByte('*');
767 },942 },
768943
...@@ -812,7 +987,7 @@ pub const CType = union(enum) {...@@ -812,7 +987,7 @@ pub const CType = union(enum) {
812 => {},987 => {},
813988
814 .pointer => |ptr| {989 .pointer => |ptr| {
815 // Match opening paren "(" write `writeTypePrefix`.990 // Match opening paren "(" in `writeTypePrefix`.
816 switch (ptr.elem_ty.kind()) {991 switch (ptr.elem_ty.kind()) {
817 .specifier, .pointer => {},992 .specifier, .pointer => {},
818 .postfix_op => try w.writeByte(')'),993 .postfix_op => try w.writeByte(')'),
src/codegen/c/type/render_defs.zig+8-8
...@@ -203,10 +203,12 @@ pub fn defineComplete(...@@ -203,10 +203,12 @@ pub fn defineComplete(
203 const name_cty: CType = .{ .@"fn" = ty };203 const name_cty: CType = .{ .@"fn" = ty };
204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);
205205
206 try w.print("typedef {f}{f}(", .{206 try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
207 ret_cty.fmtDeclaratorPrefix(zcu),207 switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) {
208 name_cty.fmtTypeName(zcu),208 .c => {},
209 });209 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
210 }
211 try w.print("{f}(", .{name_cty.fmtTypeName(zcu)});
210 var any_params = false;212 var any_params = false;
211 for (func_type.param_types.get(ip)) |param_ty_ip| {213 for (func_type.param_types.get(ip)) |param_ty_ip| {
212 const param_ty: Type = .fromInterned(param_ty_ip);214 const param_ty: Type = .fromInterned(param_ty_ip);
...@@ -222,9 +224,7 @@ pub fn defineComplete(...@@ -222,9 +224,7 @@ pub fn defineComplete(
222 } else if (!any_params) {224 } else if (!any_params) {
223 try w.writeAll("void");225 try w.writeAll("void");
224 }226 }
225 try w.print("){f};", .{227 try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)});
226 ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu),
227 });
228 break :check_cty null;228 break :check_cty null;
229 },229 },
230 .@"enum" => {230 .@"enum" => {
...@@ -254,7 +254,7 @@ pub fn defineComplete(...@@ -254,7 +254,7 @@ pub fn defineComplete(
254 try w.print(254 try w.print(
255 \\{f} {{255 \\{f} {{
256 \\ {f}ptr{f};256 \\ {f}ptr{f};
257 \\ size_t len;257 \\ uintptr_t len;
258 \\}};258 \\}};
259 , .{259 , .{
260 name_cty.fmtTypeName(zcu),260 name_cty.fmtTypeName(zcu),
src/codegen/llvm.zig+2-2
...@@ -2550,7 +2550,7 @@ pub const Object = struct {...@@ -2550,7 +2550,7 @@ pub const Object = struct {
2550 llvm_function.setCallConv(cc_info.llvm_cc, &o.builder);2550 llvm_function.setCallConv(cc_info.llvm_cc, &o.builder);
25512551
2552 if (cc_info.align_stack) {2552 if (cc_info.align_stack) {
2553 try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder);2553 try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder);
2554 }2554 }
25552555
2556 if (cc_info.naked) {2556 if (cc_info.naked) {
...@@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)...@@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
4522 std.lang.CallingConvention.SpirvFragmentOptions,4522 std.lang.CallingConvention.SpirvFragmentOptions,
4523 std.lang.CallingConvention.SpirvMeshOptions,4523 std.lang.CallingConvention.SpirvMeshOptions,
4524 => .{ null, 0, 0 },4524 => .{ null, 0, 0 },
4525 else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),4525 else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"),
4526 },4526 },
4527 };4527 };
4528 return .{4528 return .{