From bb296ab9b9752893eb362ed951c4ce344214eb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20IRMAK?= Date: Sun, 26 Jul 2026 11:16:51 +0300 Subject: [PATCH] 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 --- lib/std/Target.zig | 2 ++ lib/std/lang.zig | 2 ++ lib/std/zig/llvm/Builder.zig | 2 ++ src/Zcu.zig | 2 ++ src/codegen/c/type.zig | 6 +++++ src/codegen/llvm.zig | 2 ++ src/link/Dwarf.zig | 2 ++ test/c_abi/cfuncs.c | 10 +++++++++ test/c_abi/main.zig | 22 +++++++++++++++++++ ..._preserve_none_on_unsupported_platform.zig | 16 ++++++++++++++ 10 files changed, 66 insertions(+) create mode 100644 test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 2f395dc0f03d6aa5673df31b4aa3bb92d66bf50a..8ad977e5a528583032f075fb84b5c72fcc504d54 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1793,6 +1793,7 @@ pub const Cpu = struct { .x86_64_regcall_v4_win, .x86_64_vectorcall, .x86_64_interrupt, + .x86_64_preserve_none, => &.{.x86_64}, .x86_sysv, @@ -1819,6 +1820,7 @@ pub const Cpu = struct { .aarch64_aapcs_win, .aarch64_vfabi, .aarch64_vfabi_sve, + .aarch64_preserve_none, => &.{ .aarch64, .aarch64_be }, .alpha_osf, diff --git a/lib/std/lang.zig b/lib/std/lang.zig index f15f26d9f9330431846e52ff9d98b131fbc666e2..c5ff616dc563537fc7016535e07872e9d657362b 100644 --- a/lib/std/lang.zig +++ b/lib/std/lang.zig @@ -210,6 +210,7 @@ pub const CallingConvention = union(enum(u8)) { x86_64_regcall_v4_win: CommonOptions, x86_64_vectorcall: CommonOptions, x86_64_interrupt: CommonOptions, + x86_64_preserve_none: CommonOptions, // Calling conventions for the `x86` architecture. x86_sysv: X86RegparmOptions, @@ -237,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) { aarch64_aapcs_win: CommonOptions, aarch64_vfabi: CommonOptions, aarch64_vfabi_sve: CommonOptions, + aarch64_preserve_none: CommonOptions, /// The standard `alpha` calling convention. alpha_osf: CommonOptions, diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 8b9e87f8139f951b7abc475c5afb3035176cb209..9016796a73b0f98f2ded17ef132ea9b4466140ca 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -2749,6 +2749,7 @@ pub const CallConv = enum(u10) { tailcc, cfguard_checkcc, swifttailcc, + preserve_nonecc, x86_stdcallcc = 64, x86_fastcallcc, @@ -2817,6 +2818,7 @@ pub const CallConv = enum(u10) { .tailcc, .cfguard_checkcc, .swifttailcc, + .preserve_nonecc, .x86_stdcallcc, .x86_fastcallcc, .arm_apcscc, diff --git a/src/Zcu.zig b/src/Zcu.zig index 875ffd44b29c92738f12e3cf32f300301edf2d7d..9ed2ed7dc708d3939a1baf479fdd11798415e6fb 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4602,6 +4602,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_64_regcall_v3_sysv, .x86_64_regcall_v4_win, .x86_64_interrupt, + .x86_64_preserve_none, .x86_fastcall, .x86_thiscall, .x86_vectorcall, @@ -4610,6 +4611,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) .x86_interrupt, .aarch64_vfabi, .aarch64_vfabi_sve, + .aarch64_preserve_none, .arm_aapcs, .csky_interrupt, .riscv64_lp64_v, diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 347dc7e16e27dce1c3dd41b006f860f5772fce6c..01b474dc9c7cfa2c995cae0f3e75b238b8447619 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -62,6 +62,8 @@ pub const CType = union(enum) { regcall, + preserve_none, + aarch64_vector_pcs, aarch64_sve_pcs, @@ -138,6 +140,10 @@ pub const CType = union(enum) { .x86_regcall_v4_win, => .regcall, + .x86_64_preserve_none, + .aarch64_preserve_none, + => .preserve_none, + .aarch64_vfabi => .aarch64_vector_pcs, .aarch64_vfabi_sve => .aarch64_sve_pcs, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 31e67026821a109d79a6e677014fa0bcf8712615..9e9b32eeab4c25e5d01ecc9bd3fdd80c5703c704 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4558,6 +4558,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const null, .x86_64_vectorcall => .x86_vectorcallcc, .x86_64_interrupt => .x86_intrcc, + .x86_64_preserve_none => .preserve_nonecc, .x86_stdcall => .x86_stdcallcc, .x86_fastcall => .x86_fastcallcc, .x86_thiscall => .x86_thiscallcc, @@ -4573,6 +4574,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const .x86_interrupt => .x86_intrcc, .aarch64_vfabi => .aarch64_vector_pcs, .aarch64_vfabi_sve => .aarch64_sve_vector_pcs, + .aarch64_preserve_none => .preserve_nonecc, .arm_aapcs => .arm_aapcscc, .arm_aapcs_vfp => .arm_aapcs_vfpcc, .riscv64_lp64_v => .riscv_vectorcallcc, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 52d0fc57a1d5238ac2fd837d10878083a94510c7..c8eef4c8651367edbc1abffcd3cf24d76b847603 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4152,6 +4152,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .x86_64_regcall_v4_win => .LLVM_X86RegCall, .x86_64_vectorcall => .LLVM_vectorcall, .x86_sysv, .x86_win, .x86_mingw => .normal, + .x86_64_preserve_none => .LLVM_PreserveNone, .x86_stdcall => .BORLAND_stdcall, .x86_fastcall => .BORLAND_msfastcall, .x86_thiscall => .BORLAND_thiscall, @@ -4165,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .aarch64_aapcs_win => .normal, .aarch64_vfabi => .LLVM_AAPCS, .aarch64_vfabi_sve => .LLVM_AAPCS, + .aarch64_preserve_none => .LLVM_PreserveNone, .arm_aapcs => .LLVM_AAPCS, .arm_aapcs_vfp => .LLVM_AAPCS_VFP, diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c index a1471283bfbc5ce35b9bdd4edd6e6cb6df81d831..b74ea9ffef180944eb00c919dd5a6513fa6d32ad 100644 --- a/test/c_abi/cfuncs.c +++ b/test/c_abi/cfuncs.c @@ -16488,6 +16488,16 @@ struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) { } #endif +#if defined __x86_64__ || defined __aarch64__ +int __attribute__((preserve_none)) c_preserve_none(int x) { + return x + 1; +} +int __attribute__((preserve_none)) zig_preserve_none(int); +void c_preserve_none_check(void) { + assert_or_panic(zig_preserve_none(41) == 42); +} +#endif + struct byval_tail_callsite_attr_Point { double x; double y; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 16b99134cf70bc44a77179f48c68704d7a9041ec..a80bacd7ae3d5659902e670ebd38386ecd8c0928 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -17798,3 +17798,25 @@ test "win64 varargs" { @as(Opv, .{}), ); } + +const preserve_none_cc: ?std.lang.CallingConvention = if (builtin.zig_backend != .stage2_llvm) + null +else switch (builtin.cpu.arch) { + .x86_64 => .{ .x86_64_preserve_none = .{} }, + .aarch64, .aarch64_be => .{ .aarch64_preserve_none = .{} }, + else => null, +}; + +export fn zig_preserve_none(x: i32) callconv(preserve_none_cc orelse .c) i32 { + return x + 1; +} + +test "preserve_none calling convention" { + if (preserve_none_cc == null) return error.SkipZigTest; + const static = struct { + extern fn c_preserve_none(x: i32) callconv(preserve_none_cc.?) i32; + extern fn c_preserve_none_check() void; + }; + try expect(static.c_preserve_none(41) == 42); + static.c_preserve_none_check(); +} diff --git a/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig new file mode 100644 index 0000000000000000000000000000000000000000..3997609595403f793e1aae1ac0f5c935e320a5c7 --- /dev/null +++ b/test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig @@ -0,0 +1,16 @@ +const F1 = fn () callconv(.{ .x86_64_preserve_none = .{} }) void; +const F2 = fn () callconv(.{ .aarch64_preserve_none = .{} }) void; +export fn entry1() void { + const a: F1 = undefined; + _ = a; +} +export fn entry2() void { + const a: F2 = undefined; + _ = a; +} + +// error +// target=riscv64-linux-none +// +// :1:28: error: calling convention 'x86_64_preserve_none' only available on architectures 'x86_64' +// :2:28: error: calling convention 'aarch64_preserve_none' only available on architectures 'aarch64', 'aarch64_be' -- 2.54.0