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 @@
199199#endif
200200
201201#if defined(zig_msvc)
202#define zig_const_arr
203202#define zig_callconv(c) __##c
204203#else
205#define zig_const_arr static const
206204#define zig_callconv(c) __attribute__((c))
207205#endif
208206
......@@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80;
58415839#define zig_init_special_f80(sign, name, arg, repr) repr
58425840#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
58495842#define zig_has_f128 1
58505843#define zig_libc_name_f128(name) name##f128
58515844#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;
58595852#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo }
58605853#define zig_lo_repr_f128(arg) (arg).lo
58615854#define zig_hi_repr_f128(arg) (arg).hi
5862#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
5855#elif FLT_MANT_DIG == 113
58635856typedef float zig_f128;
58645857#define zig_make_f128(fp, repr) fp##f
5865#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
5858#elif DBL_MANT_DIG == 113
58665859typedef double zig_f128;
58675860#define zig_make_f128(fp, repr) fp
5868#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
5861#elif LDBL_MANT_DIG == 113
58695862typedef long double zig_f128;
58705863#define zig_make_f128(fp, repr) fp##l
5871#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
5864#elif FLT128_MANT_DIG == 113
58725865typedef _Float128 zig_f128;
58735866#define zig_make_f128(fp, repr) fp##f128
5874#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
5867#elif FLT64X_MANT_DIG == 113
58755868typedef _Float64x zig_f128;
58765869#define zig_make_f128(fp, repr) fp##f64x
5877#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
5870#elif defined(__SIZEOF_FLOAT128__)
58785871typedef __float128 zig_f128;
58795872#define zig_make_f128(fp, repr) fp##q
58805873#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)
46174617 .m68k_rtd,
46184618 .m68k_interrupt,
46194619 .msp430_interrupt,
4620 => |opts| opts.incoming_stack_alignment == null,
4621
46224620 .arm_aapcs_vfp,
4623 => |opts| opts.incoming_stack_alignment == null,
4624
46254621 .arc_interrupt,
4626 => |opts| opts.incoming_stack_alignment == null,
4627
46284622 .arm_interrupt,
4629 => |opts| opts.incoming_stack_alignment == null,
4630
46314623 .microblaze_interrupt,
4632 => |opts| opts.incoming_stack_alignment == null,
4633
46344624 .mips_interrupt,
46354625 .mips64_interrupt,
4636 => |opts| opts.incoming_stack_alignment == null,
4637
46384626 .riscv32_interrupt,
46394627 .riscv64_interrupt,
4640 => |opts| opts.incoming_stack_alignment == null,
4641
46424628 .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
46454635 .x86_sysv,
46464636 .x86_win,
46474637 .x86_mingw,
46484638 .x86_stdcall,
4649 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
4650
4651 .avr_interrupt,
4652 .avr_signal,
4653 => true,
4654
4655 .ez80_tiflags => true,
4656
4657 .naked => true,
4639 => |opts| opts.register_params == 0, // incoming stack alignment supported
46584640
46594641 else => false,
46604642 };
src/codegen/c.zig+41-101
......@@ -1750,8 +1750,6 @@ pub const DeclGen = struct {
17501750 try w.writeAll("zig_no_builtin ");
17511751 }
17521752
1753 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
1754
17551753 // While incomplete types are usually an acceptable substitute for "void", this is not true
17561754 // in function return types, where "void" is the only incomplete type permitted.
17571755 const actual_return_type: Type = .fromInterned(fn_info.return_type);
......@@ -1763,8 +1761,9 @@ pub const DeclGen = struct {
17631761
17641762 const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu);
17651763 try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
1766 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
1767 try w.print("zig_callconv({s}) ", .{call_conv});
1764 switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) {
1765 .c => {},
1766 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
17681767 }
17691768 switch (name) {
17701769 .nav => |nav| try renderNavName(w, nav, ip),
......@@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn(
22212220
22222221 const fn_val = zcu.navValue(fn_nav);
22232222
2223 if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn ");
22242224 try w.print("static zig_{t} ", .{kind});
22252225 try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) {
22262226 .never_tail => .{ .nav_never_tail = fn_nav },
......@@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
23262326 const gpa = f.dg.gpa;
23272327 const nav_index = f.dg.owner_nav.unwrap().?;
23282328 const nav_val = zcu.navValue(nav_index);
2329 const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?;
23292330 const nav = ip.getNav(nav_index);
23302331
2332 if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn ");
23312333 try fwd_decl_writer.writeAll("static ");
23322334 try f.dg.renderFunctionSignature(
23332335 fwd_decl_writer,
......@@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
23542356
23552357 const main_body = f.air.getMainBody();
23562358 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 }
23572388 try genBodyResolveState(f, undefined, &.{}, main_body, true);
23582389 try f.outdent();
23592390 try f.code.writer.writeByte('}');
......@@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
24562487
24572488 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
24582489 .@"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 ");
24592492 try w.writeAll("zig_extern ");
24602493 try dg.renderFunctionSignature(
24612494 w,
2462 .fromInterned(nav.resolved.?.value),
2495 fn_val,
24632496 nav.resolved.?.@"align",
24642497 .forward_decl,
24652498 .{ .@"export" = .{
......@@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
25602593 const exported_val = exported.getValue(zcu);
25612594 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
25622595 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 ");
25632598 try w.writeAll("zig_extern ");
25642599 if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn ");
25652600 try dg.renderFunctionSignature(
25662601 w,
2567 exported.getValue(zcu),
2602 fn_val,
25682603 exported.getAlign(zcu),
25692604 .forward_decl,
25702605 .{ .@"export" = .{
......@@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void {
72777312 return w.writeAll(toMemoryOrder(order));
72787313}
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
73757315fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 {
73767316 return switch (order) {
73777317 .Xchg => "xchg",
src/codegen/c/type.zig+176-1
......@@ -44,8 +44,175 @@ pub const CType = union(enum) {
4444 param_tys: []const CType,
4545 ret_ty: *const CType,
4646 varargs: bool,
47 cc: CallingConvention,
4748 },
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
49216 /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears
50217 /// after the identifier in a declarator with this type. In this case, if this node is wrapped
51218 /// in a pointer type, we will need to add parentheses due to operator precedence.
......@@ -376,6 +543,7 @@ pub const CType = union(enum) {
376543 .ret_ty = ret_cty_buf,
377544 .param_tys = param_cty_buf,
378545 .varargs = func_type.is_var_args,
546 .cc = .fromLang(func_type.cc, zcu.getTarget()),
379547 } };
380548 }
381549 try deps.addType(gpa, cur_ty, allow_incomplete);
......@@ -763,6 +931,13 @@ pub const CType = union(enum) {
763931 try w.writeByte('(');
764932 },
765933 }
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 }
766941 try w.writeByte('*');
767942 },
768943
......@@ -812,7 +987,7 @@ pub const CType = union(enum) {
812987 => {},
813988
814989 .pointer => |ptr| {
815 // Match opening paren "(" write `writeTypePrefix`.
990 // Match opening paren "(" in `writeTypePrefix`.
816991 switch (ptr.elem_ty.kind()) {
817992 .specifier, .pointer => {},
818993 .postfix_op => try w.writeByte(')'),
src/codegen/c/type/render_defs.zig+8-8
......@@ -203,10 +203,12 @@ pub fn defineComplete(
203203 const name_cty: CType = .{ .@"fn" = ty };
204204 const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu);
205205
206 try w.print("typedef {f}{f}(", .{
207 ret_cty.fmtDeclaratorPrefix(zcu),
208 name_cty.fmtTypeName(zcu),
209 });
206 try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)});
207 switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) {
208 .c => {},
209 else => |cc| try w.print("zig_callconv({t}) ", .{cc}),
210 }
211 try w.print("{f}(", .{name_cty.fmtTypeName(zcu)});
210212 var any_params = false;
211213 for (func_type.param_types.get(ip)) |param_ty_ip| {
212214 const param_ty: Type = .fromInterned(param_ty_ip);
......@@ -222,9 +224,7 @@ pub fn defineComplete(
222224 } else if (!any_params) {
223225 try w.writeAll("void");
224226 }
225 try w.print("){f};", .{
226 ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu),
227 });
227 try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)});
228228 break :check_cty null;
229229 },
230230 .@"enum" => {
......@@ -254,7 +254,7 @@ pub fn defineComplete(
254254 try w.print(
255255 \\{f} {{
256256 \\ {f}ptr{f};
257 \\ size_t len;
257 \\ uintptr_t len;
258258 \\}};
259259 , .{
260260 name_cty.fmtTypeName(zcu),
src/codegen/llvm.zig+2-2
......@@ -2550,7 +2550,7 @@ pub const Object = struct {
25502550 llvm_function.setCallConv(cc_info.llvm_cc, &o.builder);
25512551
25522552 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);
25542554 }
25552555
25562556 if (cc_info.naked) {
......@@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target)
45224522 std.lang.CallingConvention.SpirvFragmentOptions,
45234523 std.lang.CallingConvention.SpirvMeshOptions,
45244524 => .{ null, 0, 0 },
4525 else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)),
4525 else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"),
45264526 },
45274527 };
45284528 return .{