authorgravatar for omerfirmak@gmail.comÖmer Faruk IRMAK <omerfirmak@gmail.com> 2026-07-26 11:16:51+03:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-07-29 03:13:48+02:00
logbb296ab9b9752893eb362ed951c4ce344214eb96
treedbf68b07b7bd48f7822d79ceb86def073e111e9f
parentbdb1e9c9cf97520e41c8aff94553d5140a79dac7

Add and lower preserve_none call convention for x86_64 & aarch64

std declarations, llvm lowering, c_abi test, compiler warning test Co-authored-by: yarn <aethnem@gmail.com>

10 files changed, 66 insertions(+), 0 deletions(-)

lib/std/Target.zig+2
...@@ -1793,6 +1793,7 @@ pub const Cpu = struct {...@@ -1793,6 +1793,7 @@ pub const Cpu = struct {
1793 .x86_64_regcall_v4_win,1793 .x86_64_regcall_v4_win,
1794 .x86_64_vectorcall,1794 .x86_64_vectorcall,
1795 .x86_64_interrupt,1795 .x86_64_interrupt,
1796 .x86_64_preserve_none,
1796 => &.{.x86_64},1797 => &.{.x86_64},
17971798
1798 .x86_sysv,1799 .x86_sysv,
...@@ -1819,6 +1820,7 @@ pub const Cpu = struct {...@@ -1819,6 +1820,7 @@ pub const Cpu = struct {
1819 .aarch64_aapcs_win,1820 .aarch64_aapcs_win,
1820 .aarch64_vfabi,1821 .aarch64_vfabi,
1821 .aarch64_vfabi_sve,1822 .aarch64_vfabi_sve,
1823 .aarch64_preserve_none,
1822 => &.{ .aarch64, .aarch64_be },1824 => &.{ .aarch64, .aarch64_be },
18231825
1824 .alpha_osf,1826 .alpha_osf,
lib/std/lang.zig+2
...@@ -210,6 +210,7 @@ pub const CallingConvention = union(enum(u8)) {...@@ -210,6 +210,7 @@ pub const CallingConvention = union(enum(u8)) {
210 x86_64_regcall_v4_win: CommonOptions,210 x86_64_regcall_v4_win: CommonOptions,
211 x86_64_vectorcall: CommonOptions,211 x86_64_vectorcall: CommonOptions,
212 x86_64_interrupt: CommonOptions,212 x86_64_interrupt: CommonOptions,
213 x86_64_preserve_none: CommonOptions,
213214
214 // Calling conventions for the `x86` architecture.215 // Calling conventions for the `x86` architecture.
215 x86_sysv: X86RegparmOptions,216 x86_sysv: X86RegparmOptions,
...@@ -237,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) {...@@ -237,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) {
237 aarch64_aapcs_win: CommonOptions,238 aarch64_aapcs_win: CommonOptions,
238 aarch64_vfabi: CommonOptions,239 aarch64_vfabi: CommonOptions,
239 aarch64_vfabi_sve: CommonOptions,240 aarch64_vfabi_sve: CommonOptions,
241 aarch64_preserve_none: CommonOptions,
240242
241 /// The standard `alpha` calling convention.243 /// The standard `alpha` calling convention.
242 alpha_osf: CommonOptions,244 alpha_osf: CommonOptions,
lib/std/zig/llvm/Builder.zig+2
...@@ -2749,6 +2749,7 @@ pub const CallConv = enum(u10) {...@@ -2749,6 +2749,7 @@ pub const CallConv = enum(u10) {
2749 tailcc,2749 tailcc,
2750 cfguard_checkcc,2750 cfguard_checkcc,
2751 swifttailcc,2751 swifttailcc,
2752 preserve_nonecc,
27522753
2753 x86_stdcallcc = 64,2754 x86_stdcallcc = 64,
2754 x86_fastcallcc,2755 x86_fastcallcc,
...@@ -2817,6 +2818,7 @@ pub const CallConv = enum(u10) {...@@ -2817,6 +2818,7 @@ pub const CallConv = enum(u10) {
2817 .tailcc,2818 .tailcc,
2818 .cfguard_checkcc,2819 .cfguard_checkcc,
2819 .swifttailcc,2820 .swifttailcc,
2821 .preserve_nonecc,
2820 .x86_stdcallcc,2822 .x86_stdcallcc,
2821 .x86_fastcallcc,2823 .x86_fastcallcc,
2822 .arm_apcscc,2824 .arm_apcscc,
src/Zcu.zig+2
...@@ -4602,6 +4602,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4602,6 +4602,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4602 .x86_64_regcall_v3_sysv,4602 .x86_64_regcall_v3_sysv,
4603 .x86_64_regcall_v4_win,4603 .x86_64_regcall_v4_win,
4604 .x86_64_interrupt,4604 .x86_64_interrupt,
4605 .x86_64_preserve_none,
4605 .x86_fastcall,4606 .x86_fastcall,
4606 .x86_thiscall,4607 .x86_thiscall,
4607 .x86_vectorcall,4608 .x86_vectorcall,
...@@ -4610,6 +4611,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4610,6 +4611,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4610 .x86_interrupt,4611 .x86_interrupt,
4611 .aarch64_vfabi,4612 .aarch64_vfabi,
4612 .aarch64_vfabi_sve,4613 .aarch64_vfabi_sve,
4614 .aarch64_preserve_none,
4613 .arm_aapcs,4615 .arm_aapcs,
4614 .csky_interrupt,4616 .csky_interrupt,
4615 .riscv64_lp64_v,4617 .riscv64_lp64_v,
src/codegen/c/type.zig+6
...@@ -62,6 +62,8 @@ pub const CType = union(enum) {...@@ -62,6 +62,8 @@ pub const CType = union(enum) {
6262
63 regcall,63 regcall,
6464
65 preserve_none,
66
65 aarch64_vector_pcs,67 aarch64_vector_pcs,
66 aarch64_sve_pcs,68 aarch64_sve_pcs,
6769
...@@ -138,6 +140,10 @@ pub const CType = union(enum) {...@@ -138,6 +140,10 @@ pub const CType = union(enum) {
138 .x86_regcall_v4_win,140 .x86_regcall_v4_win,
139 => .regcall,141 => .regcall,
140142
143 .x86_64_preserve_none,
144 .aarch64_preserve_none,
145 => .preserve_none,
146
141 .aarch64_vfabi => .aarch64_vector_pcs,147 .aarch64_vfabi => .aarch64_vector_pcs,
142 .aarch64_vfabi_sve => .aarch64_sve_pcs,148 .aarch64_vfabi_sve => .aarch64_sve_pcs,
143149
src/codegen/llvm.zig+2
...@@ -4558,6 +4558,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4558,6 +4558,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4558 null,4558 null,
4559 .x86_64_vectorcall => .x86_vectorcallcc,4559 .x86_64_vectorcall => .x86_vectorcallcc,
4560 .x86_64_interrupt => .x86_intrcc,4560 .x86_64_interrupt => .x86_intrcc,
4561 .x86_64_preserve_none => .preserve_nonecc,
4561 .x86_stdcall => .x86_stdcallcc,4562 .x86_stdcall => .x86_stdcallcc,
4562 .x86_fastcall => .x86_fastcallcc,4563 .x86_fastcall => .x86_fastcallcc,
4563 .x86_thiscall => .x86_thiscallcc,4564 .x86_thiscall => .x86_thiscallcc,
...@@ -4573,6 +4574,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4573,6 +4574,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4573 .x86_interrupt => .x86_intrcc,4574 .x86_interrupt => .x86_intrcc,
4574 .aarch64_vfabi => .aarch64_vector_pcs,4575 .aarch64_vfabi => .aarch64_vector_pcs,
4575 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,4576 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,
4577 .aarch64_preserve_none => .preserve_nonecc,
4576 .arm_aapcs => .arm_aapcscc,4578 .arm_aapcs => .arm_aapcscc,
4577 .arm_aapcs_vfp => .arm_aapcs_vfpcc,4579 .arm_aapcs_vfp => .arm_aapcs_vfpcc,
4578 .riscv64_lp64_v => .riscv_vectorcallcc,4580 .riscv64_lp64_v => .riscv_vectorcallcc,
src/link/Dwarf.zig+2
...@@ -4152,6 +4152,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4152,6 +4152,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
4153 .x86_64_vectorcall => .LLVM_vectorcall,4153 .x86_64_vectorcall => .LLVM_vectorcall,
4154 .x86_sysv, .x86_win, .x86_mingw => .normal,4154 .x86_sysv, .x86_win, .x86_mingw => .normal,
4155 .x86_64_preserve_none => .LLVM_PreserveNone,
4155 .x86_stdcall => .BORLAND_stdcall,4156 .x86_stdcall => .BORLAND_stdcall,
4156 .x86_fastcall => .BORLAND_msfastcall,4157 .x86_fastcall => .BORLAND_msfastcall,
4157 .x86_thiscall => .BORLAND_thiscall,4158 .x86_thiscall => .BORLAND_thiscall,
...@@ -4165,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4165,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4165 .aarch64_aapcs_win => .normal,4166 .aarch64_aapcs_win => .normal,
4166 .aarch64_vfabi => .LLVM_AAPCS,4167 .aarch64_vfabi => .LLVM_AAPCS,
4167 .aarch64_vfabi_sve => .LLVM_AAPCS,4168 .aarch64_vfabi_sve => .LLVM_AAPCS,
4169 .aarch64_preserve_none => .LLVM_PreserveNone,
41684170
4169 .arm_aapcs => .LLVM_AAPCS,4171 .arm_aapcs => .LLVM_AAPCS,
4170 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,4172 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,
test/c_abi/cfuncs.c+10
...@@ -16488,6 +16488,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {...@@ -16488,6 +16488,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
16488}16488}
16489#endif16489#endif
1649016490
16491#if defined __x86_64__ || defined __aarch64__
16492int __attribute__((preserve_none)) c_preserve_none(int x) {
16493 return x + 1;
16494}
16495int __attribute__((preserve_none)) zig_preserve_none(int);
16496void c_preserve_none_check(void) {
16497 assert_or_panic(zig_preserve_none(41) == 42);
16498}
16499#endif
16500
16491struct byval_tail_callsite_attr_Point {16501struct byval_tail_callsite_attr_Point {
16492 double x;16502 double x;
16493 double y;16503 double y;
test/c_abi/main.zig+22
...@@ -17798,3 +17798,25 @@ test "win64 varargs" {...@@ -17798,3 +17798,25 @@ test "win64 varargs" {
17798 @as(Opv, .{}),17798 @as(Opv, .{}),
17799 );17799 );
17800}17800}
17801
17802const preserve_none_cc: ?std.lang.CallingConvention = if (builtin.zig_backend != .stage2_llvm)
17803 null
17804else switch (builtin.cpu.arch) {
17805 .x86_64 => .{ .x86_64_preserve_none = .{} },
17806 .aarch64, .aarch64_be => .{ .aarch64_preserve_none = .{} },
17807 else => null,
17808};
17809
17810export fn zig_preserve_none(x: i32) callconv(preserve_none_cc orelse .c) i32 {
17811 return x + 1;
17812}
17813
17814test "preserve_none calling convention" {
17815 if (preserve_none_cc == null) return error.SkipZigTest;
17816 const static = struct {
17817 extern fn c_preserve_none(x: i32) callconv(preserve_none_cc.?) i32;
17818 extern fn c_preserve_none_check() void;
17819 };
17820 try expect(static.c_preserve_none(41) == 42);
17821 static.c_preserve_none_check();
17822}
test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig created+16
...@@ -0,0 +1,16 @@
1const F1 = fn () callconv(.{ .x86_64_preserve_none = .{} }) void;
2const F2 = fn () callconv(.{ .aarch64_preserve_none = .{} }) void;
3export fn entry1() void {
4 const a: F1 = undefined;
5 _ = a;
6}
7export fn entry2() void {
8 const a: F2 = undefined;
9 _ = a;
10}
11
12// error
13// target=riscv64-linux-none
14//
15// :1:28: error: calling convention 'x86_64_preserve_none' only available on architectures 'x86_64'
16// :2:28: error: calling convention 'aarch64_preserve_none' only available on architectures 'aarch64', 'aarch64_be'