authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-10-23 16:48:33+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-23 16:48:33+01:00
log6bf52b0505ad7317b5f0d6fa77b7c41318b9c73b
tree22b5acedc288f3f2085fa4a170ee3d7629e8a9fe
parent2d888a8e639856e8cb6e4c6f9e6a27647b464952
parentf7d679ceae2403d4137d75d4afe32a3e8eb0cf16
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21697 from mlugg/callconv

Replace `std.builtin.CallingConvention` with a tagged union, eliminating `@setAlignStack`

79 files changed, 2020 insertions(+), 942 deletions(-)

doc/langref/enum_export_error.zig+2-1
......@@ -3,4 +3,5 @@ export fn entry(foo: Foo) void {
33 _ = foo;
44}
55
6// obj=parameter of type 'enum_export_error.Foo' not allowed in function with calling convention 'C'
6// obj=parameter of type 'enum_export_error.Foo' not allowed in function with calling convention 'x86_64_sysv'
7// target=x86_64-linux
lib/compiler/aro_translate_c/ast.zig+60-8
......@@ -550,12 +550,26 @@ pub const Payload = struct {
550550 is_var_args: bool,
551551 name: ?[]const u8,
552552 linksection_string: ?[]const u8,
553 explicit_callconv: ?std.builtin.CallingConvention,
553 explicit_callconv: ?CallingConvention,
554554 params: []Param,
555555 return_type: Node,
556556 body: ?Node,
557557 alignment: ?c_uint,
558558 },
559
560 pub const CallingConvention = enum {
561 c,
562 x86_64_sysv,
563 x86_64_win,
564 x86_stdcall,
565 x86_fastcall,
566 x86_thiscall,
567 x86_vectorcall,
568 aarch64_vfabi,
569 arm_aapcs,
570 arm_aapcs_vfp,
571 m68k_rtd,
572 };
559573 };
560574
561575 pub const Param = struct {
......@@ -2812,14 +2826,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
28122826 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
28132827 _ = try c.addToken(.keyword_callconv, "callconv");
28142828 _ = try c.addToken(.l_paren, "(");
2815 _ = try c.addToken(.period, ".");
2816 const res = try c.addNode(.{
2817 .tag = .enum_literal,
2818 .main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}),
2819 .data = undefined,
2820 });
2829 const cc_node = switch (some) {
2830 .c => cc_node: {
2831 _ = try c.addToken(.period, ".");
2832 break :cc_node try c.addNode(.{
2833 .tag = .enum_literal,
2834 .main_token = try c.addToken(.identifier, "c"),
2835 .data = undefined,
2836 });
2837 },
2838 .x86_64_sysv,
2839 .x86_64_win,
2840 .x86_stdcall,
2841 .x86_fastcall,
2842 .x86_thiscall,
2843 .x86_vectorcall,
2844 .aarch64_vfabi,
2845 .arm_aapcs,
2846 .arm_aapcs_vfp,
2847 .m68k_rtd,
2848 => cc_node: {
2849 // .{ .foo = .{} }
2850 _ = try c.addToken(.period, ".");
2851 const outer_lbrace = try c.addToken(.l_brace, "{");
2852 _ = try c.addToken(.period, ".");
2853 _ = try c.addToken(.identifier, @tagName(some));
2854 _ = try c.addToken(.equal, "=");
2855 _ = try c.addToken(.period, ".");
2856 const inner_lbrace = try c.addToken(.l_brace, "{");
2857 _ = try c.addToken(.r_brace, "}");
2858 _ = try c.addToken(.r_brace, "}");
2859 break :cc_node try c.addNode(.{
2860 .tag = .struct_init_dot_two,
2861 .main_token = outer_lbrace,
2862 .data = .{
2863 .lhs = try c.addNode(.{
2864 .tag = .struct_init_dot_two,
2865 .main_token = inner_lbrace,
2866 .data = .{ .lhs = 0, .rhs = 0 },
2867 }),
2868 .rhs = 0,
2869 },
2870 });
2871 },
2872 };
28212873 _ = try c.addToken(.r_paren, ")");
2822 break :blk res;
2874 break :blk cc_node;
28232875 } else 0;
28242876
28252877 const return_type_expr = try renderNode(c, payload.return_type);
lib/compiler_rt/int.zig-39
......@@ -10,7 +10,6 @@ const is_test = builtin.is_test;
1010const common = @import("common.zig");
1111const udivmod = @import("udivmod.zig").udivmod;
1212const __divti3 = @import("divti3.zig").__divti3;
13const arm = @import("arm.zig");
1413
1514pub const panic = common.panic;
1615
......@@ -102,25 +101,6 @@ test "test_divmoddi4" {
102101 }
103102}
104103
105fn test_one_aeabi_ldivmod(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
106 const LdivmodRes = extern struct {
107 q: i64, // r1:r0
108 r: i64, // r3:r2
109 };
110 const actualIdivmod = @as(*const fn (a: i64, b: i64) callconv(.AAPCS) LdivmodRes, @ptrCast(&arm.__aeabi_ldivmod));
111 const arm_res = actualIdivmod(a, b);
112 try testing.expectEqual(expected_q, arm_res.q);
113 try testing.expectEqual(expected_r, arm_res.r);
114}
115
116test "arm.__aeabi_ldivmod" {
117 if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
118
119 for (cases__divmodsi4) |case| {
120 try test_one_aeabi_ldivmod(case[0], case[1], case[2], case[3]);
121 }
122}
123
124104pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {
125105 return udivmod(u64, a, b, maybe_rem);
126106}
......@@ -261,25 +241,6 @@ test "test_divmodsi4" {
261241 }
262242}
263243
264fn test_one_aeabi_idivmod(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
265 const IdivmodRes = extern struct {
266 q: i32, // r0
267 r: i32, // r1
268 };
269 const actualIdivmod = @as(*const fn (a: i32, b: i32) callconv(.AAPCS) IdivmodRes, @ptrCast(&arm.__aeabi_idivmod));
270 const arm_res = actualIdivmod(a, b);
271 try testing.expectEqual(expected_q, arm_res.q);
272 try testing.expectEqual(expected_r, arm_res.r);
273}
274
275test "arm.__aeabi_idivmod" {
276 if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
277
278 for (cases__divmodsi4) |case| {
279 try test_one_aeabi_idivmod(case[0], case[1], case[2], case[3]);
280 }
281}
282
283244pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
284245 const d = __udivsi3(a, b);
285246 rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));
lib/compiler_rt/udivmoddi4_test.zig-21
......@@ -3,7 +3,6 @@
33const testing = @import("std").testing;
44const builtin = @import("builtin");
55const __udivmoddi4 = @import("int.zig").__udivmoddi4;
6const __aeabi_uldivmod = @import("arm.zig").__aeabi_uldivmod;
76
87fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) !void {
98 var r: u64 = undefined;
......@@ -18,26 +17,6 @@ test "udivmoddi4" {
1817 }
1918}
2019
21const ARMRes = extern struct {
22 q: u64, // r1:r0
23 r: u64, // r3:r2
24};
25
26fn test__aeabi_uldivmod(a: u64, b: u64, expected_q: u64, expected_r: u64) !void {
27 const actualUldivmod = @as(*const fn (a: u64, b: u64) callconv(.AAPCS) ARMRes, @ptrCast(&__aeabi_uldivmod));
28 const arm_res = actualUldivmod(a, b);
29 try testing.expectEqual(expected_q, arm_res.q);
30 try testing.expectEqual(expected_r, arm_res.r);
31}
32
33test "arm.__aeabi_uldivmod" {
34 if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
35
36 for (cases) |case| {
37 try test__aeabi_uldivmod(case[0], case[1], case[2], case[3]);
38 }
39}
40
4120const cases = [_][4]u64{
4221 [_]u64{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
4322 [_]u64{0x0000000000000000, 0x0000000000000002, 0x0000000000000000, 0x0000000000000000},
lib/compiler_rt/udivmodsi4_test.zig+8-17
......@@ -2,27 +2,18 @@
22// zig fmt: off
33const testing = @import("std").testing;
44const builtin = @import("builtin");
5const __aeabi_uidivmod = @import("arm.zig").__aeabi_uidivmod;
5const __udivmodsi4 = @import("int.zig").__udivmodsi4;
66
7const ARMRes = extern struct {
8 q: u32, // r0
9 r: u32, // r1
10};
11
12fn test__aeabi_uidivmod(a: u32, b: u32, expected_q: u32, expected_r: u32) !void {
13 const actualUidivmod = @as(*const fn (a: u32, b: u32) callconv(.AAPCS) ARMRes, @ptrCast(&__aeabi_uidivmod));
14 const arm_res = actualUidivmod(a, b);
15 try testing.expectEqual(expected_q, arm_res.q);
16 try testing.expectEqual(expected_r, arm_res.r);
7fn test__udivmodsi4(a: u32, b: u32, expected_q: u32, expected_r: u32) !void {
8 var r: u32 = undefined;
9 const q = __udivmodsi4(a, b, &r);
10 try testing.expectEqual(expected_q, q);
11 try testing.expectEqual(expected_r, r);
1712}
1813
19test "arm.__aeabi_uidivmod" {
20 if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
21
22 var i: i32 = 0;
14test "udivmodsi4" {
2315 for (cases) |case| {
24 try test__aeabi_uidivmod(case[0], case[1], case[2], case[3]);
25 i+=1;
16 try test__udivmodsi4(case[0], case[1], case[2], case[3]);
2617 }
2718}
2819
lib/std/Target.zig+229
......@@ -1609,6 +1609,165 @@ pub const Cpu = struct {
16091609 else => ".X",
16101610 };
16111611 }
1612
1613 /// Returns the array of `Arch` to which a specific `std.builtin.CallingConvention` applies.
1614 /// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
1615 pub fn fromCallingConvention(cc: std.builtin.CallingConvention.Tag) []const Arch {
1616 return switch (cc) {
1617 .auto,
1618 .@"async",
1619 .naked,
1620 .@"inline",
1621 => unreachable,
1622
1623 .x86_64_sysv,
1624 .x86_64_win,
1625 .x86_64_regcall_v3_sysv,
1626 .x86_64_regcall_v4_win,
1627 .x86_64_vectorcall,
1628 .x86_64_interrupt,
1629 => &.{.x86_64},
1630
1631 .x86_sysv,
1632 .x86_win,
1633 .x86_stdcall,
1634 .x86_fastcall,
1635 .x86_thiscall,
1636 .x86_thiscall_mingw,
1637 .x86_regcall_v3,
1638 .x86_regcall_v4_win,
1639 .x86_vectorcall,
1640 .x86_interrupt,
1641 => &.{.x86},
1642
1643 .aarch64_aapcs,
1644 .aarch64_aapcs_darwin,
1645 .aarch64_aapcs_win,
1646 .aarch64_vfabi,
1647 .aarch64_vfabi_sve,
1648 => &.{ .aarch64, .aarch64_be },
1649
1650 .arm_apcs,
1651 .arm_aapcs,
1652 .arm_aapcs_vfp,
1653 .arm_aapcs16_vfp,
1654 .arm_interrupt,
1655 => &.{ .arm, .armeb, .thumb, .thumbeb },
1656
1657 .mips64_n64,
1658 .mips64_n32,
1659 .mips64_interrupt,
1660 => &.{ .mips64, .mips64el },
1661
1662 .mips_o32,
1663 .mips_interrupt,
1664 => &.{ .mips, .mipsel },
1665
1666 .riscv64_lp64,
1667 .riscv64_lp64_v,
1668 .riscv64_interrupt,
1669 => &.{.riscv64},
1670
1671 .riscv32_ilp32,
1672 .riscv32_ilp32_v,
1673 .riscv32_interrupt,
1674 => &.{.riscv32},
1675
1676 .sparc64_sysv,
1677 => &.{.sparc64},
1678
1679 .sparc_sysv,
1680 => &.{.sparc},
1681
1682 .powerpc64_elf,
1683 .powerpc64_elf_altivec,
1684 .powerpc64_elf_v2,
1685 => &.{ .powerpc64, .powerpc64le },
1686
1687 .powerpc_sysv,
1688 .powerpc_sysv_altivec,
1689 .powerpc_aix,
1690 .powerpc_aix_altivec,
1691 => &.{ .powerpc, .powerpcle },
1692
1693 .wasm_watc,
1694 => &.{ .wasm64, .wasm32 },
1695
1696 .arc_sysv,
1697 => &.{.arc},
1698
1699 .avr_gnu,
1700 .avr_builtin,
1701 .avr_signal,
1702 .avr_interrupt,
1703 => &.{.avr},
1704
1705 .bpf_std,
1706 => &.{ .bpfel, .bpfeb },
1707
1708 .csky_sysv,
1709 .csky_interrupt,
1710 => &.{.csky},
1711
1712 .hexagon_sysv,
1713 .hexagon_sysv_hvx,
1714 => &.{.hexagon},
1715
1716 .lanai_sysv,
1717 => &.{.lanai},
1718
1719 .loongarch64_lp64,
1720 => &.{.loongarch64},
1721
1722 .loongarch32_ilp32,
1723 => &.{.loongarch32},
1724
1725 .m68k_sysv,
1726 .m68k_gnu,
1727 .m68k_rtd,
1728 .m68k_interrupt,
1729 => &.{.m68k},
1730
1731 .msp430_eabi,
1732 => &.{.msp430},
1733
1734 .propeller1_sysv,
1735 => &.{.propeller1},
1736
1737 .propeller2_sysv,
1738 => &.{.propeller2},
1739
1740 .s390x_sysv,
1741 .s390x_sysv_vx,
1742 => &.{.s390x},
1743
1744 .ve_sysv,
1745 => &.{.ve},
1746
1747 .xcore_xs1,
1748 .xcore_xs2,
1749 => &.{.xcore},
1750
1751 .xtensa_call0,
1752 .xtensa_windowed,
1753 => &.{.xtensa},
1754
1755 .amdgcn_device,
1756 .amdgcn_kernel,
1757 .amdgcn_cs,
1758 => &.{.amdgcn},
1759
1760 .nvptx_device,
1761 .nvptx_kernel,
1762 => &.{ .nvptx, .nvptx64 },
1763
1764 .spirv_device,
1765 .spirv_kernel,
1766 .spirv_fragment,
1767 .spirv_vertex,
1768 => &.{ .spirv, .spirv32, .spirv64 },
1769 };
1770 }
16121771 };
16131772
16141773 pub const Model = struct {
......@@ -2873,6 +3032,76 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
28733032 );
28743033}
28753034
3035pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention {
3036 return switch (target.cpu.arch) {
3037 .x86_64 => switch (target.os.tag) {
3038 .windows, .uefi => .{ .x86_64_win = .{} },
3039 else => .{ .x86_64_sysv = .{} },
3040 },
3041 .x86 => switch (target.os.tag) {
3042 .windows, .uefi => .{ .x86_win = .{} },
3043 else => .{ .x86_sysv = .{} },
3044 },
3045 .aarch64, .aarch64_be => if (target.os.tag.isDarwin()) cc: {
3046 break :cc .{ .aarch64_aapcs_darwin = .{} };
3047 } else switch (target.os.tag) {
3048 .windows => .{ .aarch64_aapcs_win = .{} },
3049 else => .{ .aarch64_aapcs = .{} },
3050 },
3051 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
3052 .netbsd => .{ .arm_apcs = .{} },
3053 else => switch (target.abi.floatAbi()) {
3054 .soft => .{ .arm_aapcs = .{} },
3055 .hard => .{ .arm_aapcs_vfp = .{} },
3056 },
3057 },
3058 .mips64, .mips64el => switch (target.abi) {
3059 .gnuabin32 => .{ .mips64_n32 = .{} },
3060 else => .{ .mips64_n64 = .{} },
3061 },
3062 .mips, .mipsel => .{ .mips_o32 = .{} },
3063 .riscv64 => .{ .riscv64_lp64 = .{} },
3064 .riscv32 => .{ .riscv32_ilp32 = .{} },
3065 .sparc64 => .{ .sparc64_sysv = .{} },
3066 .sparc => .{ .sparc_sysv = .{} },
3067 .powerpc64 => if (target.isMusl())
3068 .{ .powerpc64_elf_v2 = .{} }
3069 else
3070 .{ .powerpc64_elf = .{} },
3071 .powerpc64le => .{ .powerpc64_elf_v2 = .{} },
3072 .powerpc, .powerpcle => switch (target.os.tag) {
3073 .aix => .{ .powerpc_aix = .{} },
3074 else => .{ .powerpc_sysv = .{} },
3075 },
3076 .wasm32 => .{ .wasm_watc = .{} },
3077 .wasm64 => .{ .wasm_watc = .{} },
3078 .arc => .{ .arc_sysv = .{} },
3079 .avr => .avr_gnu,
3080 .bpfel, .bpfeb => .{ .bpf_std = .{} },
3081 .csky => .{ .csky_sysv = .{} },
3082 .hexagon => .{ .hexagon_sysv = .{} },
3083 .kalimba => null,
3084 .lanai => .{ .lanai_sysv = .{} },
3085 .loongarch64 => .{ .loongarch64_lp64 = .{} },
3086 .loongarch32 => .{ .loongarch32_ilp32 = .{} },
3087 .m68k => if (target.abi.isGnu() or target.abi.isMusl())
3088 .{ .m68k_gnu = .{} }
3089 else
3090 .{ .m68k_sysv = .{} },
3091 .msp430 => .{ .msp430_eabi = .{} },
3092 .propeller1 => .{ .propeller1_sysv = .{} },
3093 .propeller2 => .{ .propeller2_sysv = .{} },
3094 .s390x => .{ .s390x_sysv = .{} },
3095 .spu_2 => null,
3096 .ve => .{ .ve_sysv = .{} },
3097 .xcore => .{ .xcore_xs1 = .{} },
3098 .xtensa => .{ .xtensa_call0 = .{} },
3099 .amdgcn => .{ .amdgcn_device = .{} },
3100 .nvptx, .nvptx64 => .nvptx_device,
3101 .spirv, .spirv32, .spirv64 => .spirv_device,
3102 };
3103}
3104
28763105pub fn osArchName(target: std.Target) [:0]const u8 {
28773106 return target.os.tag.archName(target.cpu.arch);
28783107}
lib/std/builtin.zig+330-44
......@@ -160,54 +160,340 @@ pub const OptimizeMode = enum {
160160/// Deprecated; use OptimizeMode.
161161pub const Mode = OptimizeMode;
162162
163/// The calling convention of a function defines how arguments and return values are passed, as well
164/// as any other requirements which callers and callees must respect, such as register preservation
165/// and stack alignment.
166///
163167/// This data structure is used by the Zig language code generation and
164168/// therefore must be kept in sync with the compiler implementation.
165pub const CallingConvention = enum(u8) {
166 /// This is the default Zig calling convention used when not using `export` on `fn`
167 /// and no other calling convention is specified.
168 Unspecified,
169 /// Matches the C ABI for the target.
170 /// This is the default calling convention when using `export` on `fn`
171 /// and no other calling convention is specified.
172 C,
173 /// This makes a function not have any function prologue or epilogue,
174 /// making the function itself uncallable in regular Zig code.
175 /// This can be useful when integrating with assembly.
176 Naked,
177 /// Functions with this calling convention are called asynchronously,
178 /// as if called as `async function()`.
179 Async,
180 /// Functions with this calling convention are inlined at all call sites.
181 Inline,
182 /// x86-only.
183 Interrupt,
184 Signal,
185 /// x86-only.
186 Stdcall,
187 /// x86-only.
188 Fastcall,
189 /// x86-only.
190 Vectorcall,
191 /// x86-only.
192 Thiscall,
169pub const CallingConvention = union(enum(u8)) {
170 pub const Tag = @typeInfo(CallingConvention).@"union".tag_type.?;
171
172 /// This is an alias for the default C calling convention for this target.
173 /// Functions marked as `extern` or `export` are given this calling convention by default.
174 pub const c = builtin.target.cCallingConvention().?;
175
176 pub const winapi: CallingConvention = switch (builtin.target.cpu.arch) {
177 .x86_64 => .{ .x86_64_win = .{} },
178 .x86 => .{ .x86_stdcall = .{} },
179 .aarch64 => .{ .aarch64_aapcs_win = .{} },
180 .thumb => .{ .arm_aapcs_vfp = .{} },
181 else => unreachable,
182 };
183
184 pub const kernel: CallingConvention = switch (builtin.target.cpu.arch) {
185 .amdgcn => .amdgcn_kernel,
186 .nvptx, .nvptx64 => .nvptx_kernel,
187 .spirv, .spirv32, .spirv64 => .spirv_kernel,
188 else => unreachable,
189 };
190
191 /// Deprecated; use `.auto`.
192 pub const Unspecified: CallingConvention = .auto;
193 /// Deprecated; use `.c`.
194 pub const C: CallingConvention = .c;
195 /// Deprecated; use `.naked`.
196 pub const Naked: CallingConvention = .naked;
197 /// Deprecated; use `.@"async"`.
198 pub const Async: CallingConvention = .@"async";
199 /// Deprecated; use `.@"inline"`.
200 pub const Inline: CallingConvention = .@"inline";
201 /// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.
202 pub const Interrupt: CallingConvention = switch (builtin.target.cpu.arch) {
203 .x86_64 => .{ .x86_64_interrupt = .{} },
204 .x86 => .{ .x86_interrupt = .{} },
205 .avr => .avr_interrupt,
206 else => unreachable,
207 };
208 /// Deprecated; use `.avr_signal`.
209 pub const Signal: CallingConvention = .avr_signal;
210 /// Deprecated; use `.x86_stdcall`.
211 pub const Stdcall: CallingConvention = .{ .x86_stdcall = .{} };
212 /// Deprecated; use `.x86_fastcall`.
213 pub const Fastcall: CallingConvention = .{ .x86_fastcall = .{} };
214 /// Deprecated; use `.x86_64_vectorcall`, `.x86_vectorcall`, or `aarch64_vfabi`.
215 pub const Vectorcall: CallingConvention = switch (builtin.target.cpu.arch) {
216 .x86_64 => .{ .x86_64_vectorcall = .{} },
217 .x86 => .{ .x86_vectorcall = .{} },
218 .aarch64, .aarch64_be => .{ .aarch64_vfabi = .{} },
219 else => unreachable,
220 };
221 /// Deprecated; use `.x86_thiscall`.
222 pub const Thiscall: CallingConvention = .{ .x86_thiscall = .{} };
223 /// Deprecated; use `.arm_apcs`.
224 pub const APCS: CallingConvention = .{ .arm_apcs = .{} };
225 /// Deprecated; use `.arm_aapcs`.
226 pub const AAPCS: CallingConvention = .{ .arm_aapcs = .{} };
227 /// Deprecated; use `.arm_aapcs_vfp`.
228 pub const AAPCSVFP: CallingConvention = .{ .arm_aapcs_vfp = .{} };
229 /// Deprecated; use `.x86_64_sysv`.
230 pub const SysV: CallingConvention = .{ .x86_64_sysv = .{} };
231 /// Deprecated; use `.x86_64_win`.
232 pub const Win64: CallingConvention = .{ .x86_64_win = .{} };
233 /// Deprecated; use `.kernel`.
234 pub const Kernel: CallingConvention = .kernel;
235 /// Deprecated; use `.spirv_fragment`.
236 pub const Fragment: CallingConvention = .spirv_fragment;
237 /// Deprecated; use `.spirv_vertex`.
238 pub const Vertex: CallingConvention = .spirv_vertex;
239
240 /// The default Zig calling convention when neither `export` nor `inline` is specified.
241 /// This calling convention makes no guarantees about stack alignment, registers, etc.
242 /// It can only be used within this Zig compilation unit.
243 auto,
244
245 /// The calling convention of a function that can be called with `async` syntax. An `async` call
246 /// of a runtime-known function must target a function with this calling convention.
247 /// Comptime-known functions with other calling conventions may be coerced to this one.
248 @"async",
249
250 /// Functions with this calling convention have no prologue or epilogue, making the function
251 /// uncallable in regular Zig code. This can be useful when integrating with assembly.
252 naked,
253
254 /// This calling convention is exactly equivalent to using the `inline` keyword on a function
255 /// definition. This function will be semantically inlined by the Zig compiler at call sites.
256 /// Pointers to inline functions are comptime-only.
257 @"inline",
258
259 // Calling conventions for the `x86_64` architecture.
260 x86_64_sysv: CommonOptions,
261 x86_64_win: CommonOptions,
262 x86_64_regcall_v3_sysv: CommonOptions,
263 x86_64_regcall_v4_win: CommonOptions,
264 x86_64_vectorcall: CommonOptions,
265 x86_64_interrupt: CommonOptions,
266
267 // Calling conventions for the `x86` architecture.
268 x86_sysv: X86RegparmOptions,
269 x86_win: X86RegparmOptions,
270 x86_stdcall: X86RegparmOptions,
271 x86_fastcall: CommonOptions,
272 x86_thiscall: CommonOptions,
273 x86_thiscall_mingw: CommonOptions,
274 x86_regcall_v3: CommonOptions,
275 x86_regcall_v4_win: CommonOptions,
276 x86_vectorcall: CommonOptions,
277 x86_interrupt: CommonOptions,
278
279 // Calling conventions for the `aarch64` and `aarch64_be` architectures.
280 aarch64_aapcs: CommonOptions,
281 aarch64_aapcs_darwin: CommonOptions,
282 aarch64_aapcs_win: CommonOptions,
283 aarch64_vfabi: CommonOptions,
284 aarch64_vfabi_sve: CommonOptions,
285
286 // Calling convetions for the `arm`, `armeb`, `thumb`, and `thumbeb` architectures.
193287 /// ARM Procedure Call Standard (obsolete)
194 /// ARM-only.
195 APCS,
196 /// ARM Architecture Procedure Call Standard (current standard)
197 /// ARM-only.
198 AAPCS,
288 arm_apcs: CommonOptions,
289 /// ARM Architecture Procedure Call Standard
290 arm_aapcs: CommonOptions,
199291 /// ARM Architecture Procedure Call Standard Vector Floating-Point
200 /// ARM-only.
201 AAPCSVFP,
202 /// x86-64-only.
203 SysV,
204 /// x86-64-only.
205 Win64,
206 /// AMD GPU, NVPTX, or SPIR-V kernel
207 Kernel,
208 // Vulkan-only
209 Fragment,
210 Vertex,
292 arm_aapcs_vfp: CommonOptions,
293 arm_aapcs16_vfp: CommonOptions,
294 arm_interrupt: ArmInterruptOptions,
295
296 // Calling conventions for the `mips64` architecture.
297 mips64_n64: CommonOptions,
298 mips64_n32: CommonOptions,
299 mips64_interrupt: MipsInterruptOptions,
300
301 // Calling conventions for the `mips` architecture.
302 mips_o32: CommonOptions,
303 mips_interrupt: MipsInterruptOptions,
304
305 // Calling conventions for the `riscv64` architecture.
306 riscv64_lp64: CommonOptions,
307 riscv64_lp64_v: CommonOptions,
308 riscv64_interrupt: RiscvInterruptOptions,
309
310 // Calling conventions for the `riscv32` architecture.
311 riscv32_ilp32: CommonOptions,
312 riscv32_ilp32_v: CommonOptions,
313 riscv32_interrupt: RiscvInterruptOptions,
314
315 // Calling conventions for the `sparc64` architecture.
316 sparc64_sysv: CommonOptions,
317
318 // Calling conventions for the `sparc` architecture.
319 sparc_sysv: CommonOptions,
320
321 // Calling conventions for the `powerpc64` and `powerpc64le` architectures.
322 powerpc64_elf: CommonOptions,
323 powerpc64_elf_altivec: CommonOptions,
324 powerpc64_elf_v2: CommonOptions,
325
326 // Calling conventions for the `powerpc` and `powerpcle` architectures.
327 powerpc_sysv: CommonOptions,
328 powerpc_sysv_altivec: CommonOptions,
329 powerpc_aix: CommonOptions,
330 powerpc_aix_altivec: CommonOptions,
331
332 /// The standard `wasm32`/`wasm64` calling convention, as specified in the WebAssembly Tool Conventions.
333 wasm_watc: CommonOptions,
334
335 /// The standard `arc` calling convention.
336 arc_sysv: CommonOptions,
337
338 // Calling conventions for the `avr` architecture.
339 avr_gnu,
340 avr_builtin,
341 avr_signal,
342 avr_interrupt,
343
344 /// The standard `bpfel`/`bpfeb` calling convention.
345 bpf_std: CommonOptions,
346
347 // Calling conventions for the `csky` architecture.
348 csky_sysv: CommonOptions,
349 csky_interrupt: CommonOptions,
350
351 // Calling conventions for the `hexagon` architecture.
352 hexagon_sysv: CommonOptions,
353 hexagon_sysv_hvx: CommonOptions,
354
355 /// The standard `lanai` calling convention.
356 lanai_sysv: CommonOptions,
357
358 /// The standard `loongarch64` calling convention.
359 loongarch64_lp64: CommonOptions,
360
361 /// The standard `loongarch32` calling convention.
362 loongarch32_ilp32: CommonOptions,
363
364 // Calling conventions for the `m68k` architecture.
365 m68k_sysv: CommonOptions,
366 m68k_gnu: CommonOptions,
367 m68k_rtd: CommonOptions,
368 m68k_interrupt: CommonOptions,
369
370 /// The standard `msp430` calling convention.
371 msp430_eabi: CommonOptions,
372
373 /// The standard `propeller1` calling convention.
374 propeller1_sysv: CommonOptions,
375
376 /// The standard `propeller2` calling convention.
377 propeller2_sysv: CommonOptions,
378
379 // Calling conventions for the `s390x` architecture.
380 s390x_sysv: CommonOptions,
381 s390x_sysv_vx: CommonOptions,
382
383 /// The standard `ve` calling convention.
384 ve_sysv: CommonOptions,
385
386 // Calling conventions for the `xcore` architecture.
387 xcore_xs1: CommonOptions,
388 xcore_xs2: CommonOptions,
389
390 // Calling conventions for the `xtensa` architecture.
391 xtensa_call0: CommonOptions,
392 xtensa_windowed: CommonOptions,
393
394 // Calling conventions for the `amdgcn` architecture.
395 amdgcn_device: CommonOptions,
396 amdgcn_kernel,
397 amdgcn_cs: CommonOptions,
398
399 // Calling conventions for the `nvptx` architecture.
400 nvptx_device,
401 nvptx_kernel,
402
403 // Calling conventions for kernels and shaders on the `spirv`, `spirv32`, and `spirv64` architectures.
404 spirv_device,
405 spirv_kernel,
406 spirv_fragment,
407 spirv_vertex,
408
409 /// Options shared across most calling conventions.
410 pub const CommonOptions = struct {
411 /// The boundary the stack is aligned to when the function is called.
412 /// `null` means the default for this calling convention.
413 incoming_stack_alignment: ?u64 = null,
414 };
415
416 /// Options for x86 calling conventions which support the regparm attribute to pass some
417 /// arguments in registers.
418 pub const X86RegparmOptions = struct {
419 /// The boundary the stack is aligned to when the function is called.
420 /// `null` means the default for this calling convention.
421 incoming_stack_alignment: ?u64 = null,
422 /// The number of arguments to pass in registers before passing the remaining arguments
423 /// according to the calling convention.
424 /// Equivalent to `__attribute__((regparm(x)))` in Clang and GCC.
425 register_params: u2 = 0,
426 };
427
428 /// Options for the `arm_interrupt` calling convention.
429 pub const ArmInterruptOptions = struct {
430 /// The boundary the stack is aligned to when the function is called.
431 /// `null` means the default for this calling convention.
432 incoming_stack_alignment: ?u64 = null,
433 /// The kind of interrupt being received.
434 type: InterruptType = .generic,
435
436 pub const InterruptType = enum(u3) {
437 generic,
438 irq,
439 fiq,
440 swi,
441 abort,
442 undef,
443 };
444 };
445
446 /// Options for the `mips_interrupt` and `mips64_interrupt` calling conventions.
447 pub const MipsInterruptOptions = struct {
448 /// The boundary the stack is aligned to when the function is called.
449 /// `null` means the default for this calling convention.
450 incoming_stack_alignment: ?u64 = null,
451 /// The interrupt mode.
452 mode: InterruptMode = .eic,
453
454 pub const InterruptMode = enum(u4) {
455 eic,
456 sw0,
457 sw1,
458 hw0,
459 hw1,
460 hw2,
461 hw3,
462 hw4,
463 hw5,
464 };
465 };
466
467 /// Options for the `riscv32_interrupt` and `riscv64_interrupt` calling conventions.
468 pub const RiscvInterruptOptions = struct {
469 /// The boundary the stack is aligned to when the function is called.
470 /// `null` means the default for this calling convention.
471 incoming_stack_alignment: ?u64 = null,
472 /// The privilege mode.
473 mode: PrivilegeMode = .machine,
474
475 pub const PrivilegeMode = enum(u2) {
476 supervisor,
477 machine,
478 };
479 };
480
481 /// Returns the array of `std.Target.Cpu.Arch` to which this `CallingConvention` applies.
482 /// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
483 pub fn archs(cc: CallingConvention) []const std.Target.Cpu.Arch {
484 return std.Target.Cpu.Arch.fromCallingConvention(cc);
485 }
486
487 pub fn eql(a: CallingConvention, b: CallingConvention) bool {
488 return std.meta.eql(a, b);
489 }
490
491 pub fn withStackAlign(cc: CallingConvention, incoming_stack_alignment: u64) CallingConvention {
492 const tag: CallingConvention.Tag = cc;
493 var result = cc;
494 @field(result, @tagName(tag)).incoming_stack_alignment = incoming_stack_alignment;
495 return result;
496 }
211497};
212498
213499/// This data structure is used by the Zig language code generation and
lib/std/crypto/25519/field.zig+3-3
......@@ -6,9 +6,9 @@ const NonCanonicalError = crypto.errors.NonCanonicalError;
66const NotSquareError = crypto.errors.NotSquareError;
77
88// Inline conditionally, when it can result in large code generation.
9const bloaty_inline = switch (builtin.mode) {
10 .ReleaseSafe, .ReleaseFast => .Inline,
11 .Debug, .ReleaseSmall => .Unspecified,
9const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {
10 .ReleaseSafe, .ReleaseFast => .@"inline",
11 .Debug, .ReleaseSmall => .auto,
1212};
1313
1414pub const Fe = struct {
lib/std/os/windows.zig+1-4
......@@ -2824,10 +2824,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;
28242824/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
28252825pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;
28262826
2827pub const WINAPI: std.builtin.CallingConvention = if (native_arch == .x86)
2828 .Stdcall
2829else
2830 .C;
2827pub const WINAPI: std.builtin.CallingConvention = .winapi;
28312828
28322829pub const BOOL = c_int;
28332830pub const BOOLEAN = BYTE;
lib/std/start.zig+4-7
......@@ -55,7 +55,7 @@ comptime {
5555 if (builtin.link_libc and @hasDecl(root, "main")) {
5656 if (native_arch.isWasm()) {
5757 @export(&mainWithoutEnv, .{ .name = "main" });
58 } else if (@typeInfo(@TypeOf(root.main)).@"fn".calling_convention != .C) {
58 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
5959 @export(&main, .{ .name = "main" });
6060 }
6161 } else if (native_os == .windows) {
......@@ -102,12 +102,11 @@ fn main2() callconv(.C) c_int {
102102 return 0;
103103}
104104
105fn _start2() callconv(.C) noreturn {
105fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {
106106 callMain2();
107107}
108108
109109fn callMain2() noreturn {
110 @setAlignStack(16);
111110 root.main();
112111 exit2(0);
113112}
......@@ -428,8 +427,7 @@ fn _start() callconv(.Naked) noreturn {
428427 );
429428}
430429
431fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
432 @setAlignStack(16);
430fn WinStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
433431 if (!builtin.single_threaded and !builtin.link_libc) {
434432 _ = @import("os/windows/tls.zig");
435433 }
......@@ -439,8 +437,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
439437 std.os.windows.ntdll.RtlExitUserProcess(callMain());
440438}
441439
442fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
443 @setAlignStack(16);
440fn wWinMainCRTStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
444441 if (!builtin.single_threaded and !builtin.link_libc) {
445442 _ = @import("os/windows/tls.zig");
446443 }
lib/std/zig/AstGen.zig-9
......@@ -2902,7 +2902,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29022902 .breakpoint,
29032903 .disable_instrumentation,
29042904 .set_float_mode,
2905 .set_align_stack,
29062905 .branch_hint,
29072906 => break :b true,
29082907 else => break :b false,
......@@ -9324,14 +9323,6 @@ fn builtinCall(
93249323 });
93259324 return rvalue(gz, ri, .void_value, node);
93269325 },
9327 .set_align_stack => {
9328 const order = try expr(gz, scope, coerced_align_ri, params[0]);
9329 _ = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{
9330 .node = gz.nodeIndexToRelative(node),
9331 .operand = order,
9332 });
9333 return rvalue(gz, ri, .void_value, node);
9334 },
93359326
93369327 .src => {
93379328 // Incorporate the source location into the source hash, so that
lib/std/zig/AstRlAnnotate.zig-1
......@@ -909,7 +909,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
909909 .wasm_memory_size,
910910 .splat,
911911 .set_float_mode,
912 .set_align_stack,
913912 .type_info,
914913 .work_item_id,
915914 .work_group_size,
lib/std/zig/BuiltinFn.zig-9
......@@ -82,7 +82,6 @@ pub const Tag = enum {
8282 rem,
8383 return_address,
8484 select,
85 set_align_stack,
8685 set_eval_branch_quota,
8786 set_float_mode,
8887 set_runtime_safety,
......@@ -744,14 +743,6 @@ pub const list = list: {
744743 .param_count = 4,
745744 },
746745 },
747 .{
748 "@setAlignStack",
749 .{
750 .tag = .set_align_stack,
751 .param_count = 1,
752 .illegal_outside_function = true,
753 },
754 },
755746 .{
756747 "@setEvalBranchQuota",
757748 .{
lib/std/zig/Zir.zig-4
......@@ -1982,9 +1982,6 @@ pub const Inst = struct {
19821982 /// Implement builtin `@setFloatMode`.
19831983 /// `operand` is payload index to `UnNode`.
19841984 set_float_mode,
1985 /// Implement builtin `@setAlignStack`.
1986 /// `operand` is payload index to `UnNode`.
1987 set_align_stack,
19881985 /// Implements the `@errorCast` builtin.
19891986 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
19901987 error_cast,
......@@ -4012,7 +4009,6 @@ fn findDeclsInner(
40124009 .wasm_memory_grow,
40134010 .prefetch,
40144011 .set_float_mode,
4015 .set_align_stack,
40164012 .error_cast,
40174013 .await_nosuspend,
40184014 .breakpoint,
lib/std/zig/c_builtins.zig+1-1
......@@ -265,4 +265,4 @@ pub fn __builtin_mul_overflow(a: anytype, b: anytype, result: *@TypeOf(a, b)) c_
265265// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented
266266// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the
267267// run-translated-c test and the test-translate-c test to use a different non-implemented builtin.
268// pub fn __builtin_alloca_with_align(size: usize, alignment: usize) callconv(.Inline) *anyopaque {}
268// pub inline fn __builtin_alloca_with_align(size: usize, alignment: usize) *anyopaque {}
lib/std/zig/parser_test.zig+5-5
......@@ -107,15 +107,15 @@ test "zig fmt: respect line breaks before functions" {
107107 );
108108}
109109
110test "zig fmt: rewrite callconv(.Inline) to the inline keyword" {
110test "zig fmt: rewrite callconv(.@\"inline\") to the inline keyword" {
111111 try testTransform(
112 \\fn foo() callconv(.Inline) void {}
113 \\const bar = .Inline;
112 \\fn foo() callconv(.@"inline") void {}
113 \\const bar: @import("std").builtin.CallingConvention = .@"inline";
114114 \\fn foo() callconv(bar) void {}
115115 \\
116116 ,
117117 \\inline fn foo() void {}
118 \\const bar = .Inline;
118 \\const bar: @import("std").builtin.CallingConvention = .@"inline";
119119 \\fn foo() callconv(bar) void {}
120120 \\
121121 );
......@@ -3062,7 +3062,7 @@ test "zig fmt: functions" {
30623062 \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
30633063 \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
30643064 \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
3065 \\pub fn callInlineFn(func: fn () callconv(.Inline) void) void {
3065 \\pub fn callInlineFn(func: fn () callconv(.@"inline") void) void {
30663066 \\ func();
30673067 \\}
30683068 \\
lib/std/zig/render.zig+4-2
......@@ -184,8 +184,9 @@ fn renderMember(
184184 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr
185185 else
186186 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;
187 // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE
187188 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {
188 if (mem.eql(u8, "Inline", tree.tokenSlice(main_tokens[callconv_expr]))) {
189 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) {
189190 try ais.writer().writeAll("inline ");
190191 }
191192 }
......@@ -1839,7 +1840,8 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
18391840 try renderToken(r, section_rparen, .space); // )
18401841 }
18411842
1842 const is_callconv_inline = mem.eql(u8, "Inline", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));
1843 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1844 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));
18431845 const is_declaration = fn_proto.name_token != null;
18441846 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {
18451847 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;
src/InternPool.zig+88-30
......@@ -2011,10 +2011,10 @@ pub const Key = union(enum) {
20112011 a.return_type == b.return_type and
20122012 a.comptime_bits == b.comptime_bits and
20132013 a.noalias_bits == b.noalias_bits and
2014 a.cc == b.cc and
20152014 a.is_var_args == b.is_var_args and
20162015 a.is_generic == b.is_generic and
2017 a.is_noinline == b.is_noinline;
2016 a.is_noinline == b.is_noinline and
2017 std.meta.eql(a.cc, b.cc);
20182018 }
20192019
20202020 pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void {
......@@ -5444,7 +5444,7 @@ pub const Tag = enum(u8) {
54445444 flags: Flags,
54455445
54465446 pub const Flags = packed struct(u32) {
5447 cc: std.builtin.CallingConvention,
5447 cc: PackedCallingConvention,
54485448 is_var_args: bool,
54495449 is_generic: bool,
54505450 has_comptime_bits: bool,
......@@ -5453,7 +5453,7 @@ pub const Tag = enum(u8) {
54535453 cc_is_generic: bool,
54545454 section_is_generic: bool,
54555455 addrspace_is_generic: bool,
5456 _: u16 = 0,
5456 _: u6 = 0,
54575457 };
54585458 };
54595459
......@@ -5618,12 +5618,11 @@ pub const FuncAnalysis = packed struct(u32) {
56185618 branch_hint: std.builtin.BranchHint,
56195619 is_noinline: bool,
56205620 calls_or_awaits_errorable_fn: bool,
5621 stack_alignment: Alignment,
56225621 /// True if this function has an inferred error set.
56235622 inferred_error_set: bool,
56245623 disable_instrumentation: bool,
56255624
5626 _: u17 = 0,
5625 _: u23 = 0,
56275626
56285627 pub const State = enum(u2) {
56295628 /// The runtime function has never been referenced.
......@@ -6912,7 +6911,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
69126911 .return_type = type_function.data.return_type,
69136912 .comptime_bits = comptime_bits,
69146913 .noalias_bits = noalias_bits,
6915 .cc = type_function.data.flags.cc,
6914 .cc = type_function.data.flags.cc.unpack(),
69166915 .is_var_args = type_function.data.flags.is_var_args,
69176916 .is_noinline = type_function.data.flags.is_noinline,
69186917 .cc_is_generic = type_function.data.flags.cc_is_generic,
......@@ -8526,7 +8525,7 @@ pub const GetFuncTypeKey = struct {
85268525 comptime_bits: u32 = 0,
85278526 noalias_bits: u32 = 0,
85288527 /// `null` means generic.
8529 cc: ?std.builtin.CallingConvention = .Unspecified,
8528 cc: ?std.builtin.CallingConvention = .auto,
85308529 is_var_args: bool = false,
85318530 is_generic: bool = false,
85328531 is_noinline: bool = false,
......@@ -8564,7 +8563,7 @@ pub fn getFuncType(
85648563 .params_len = params_len,
85658564 .return_type = key.return_type,
85668565 .flags = .{
8567 .cc = key.cc orelse .Unspecified,
8566 .cc = .pack(key.cc orelse .auto),
85688567 .is_var_args = key.is_var_args,
85698568 .has_comptime_bits = key.comptime_bits != 0,
85708569 .has_noalias_bits = key.noalias_bits != 0,
......@@ -8696,7 +8695,6 @@ pub fn getFuncDecl(
86968695 .branch_hint = .none,
86978696 .is_noinline = key.is_noinline,
86988697 .calls_or_awaits_errorable_fn = false,
8699 .stack_alignment = .none,
87008698 .inferred_error_set = false,
87018699 .disable_instrumentation = false,
87028700 },
......@@ -8800,7 +8798,6 @@ pub fn getFuncDeclIes(
88008798 .branch_hint = .none,
88018799 .is_noinline = key.is_noinline,
88028800 .calls_or_awaits_errorable_fn = false,
8803 .stack_alignment = .none,
88048801 .inferred_error_set = true,
88058802 .disable_instrumentation = false,
88068803 },
......@@ -8818,7 +8815,7 @@ pub fn getFuncDeclIes(
88188815 .params_len = params_len,
88198816 .return_type = error_union_type,
88208817 .flags = .{
8821 .cc = key.cc orelse .Unspecified,
8818 .cc = .pack(key.cc orelse .auto),
88228819 .is_var_args = key.is_var_args,
88238820 .has_comptime_bits = key.comptime_bits != 0,
88248821 .has_noalias_bits = key.noalias_bits != 0,
......@@ -8992,7 +8989,6 @@ pub fn getFuncInstance(
89928989 .branch_hint = .none,
89938990 .is_noinline = arg.is_noinline,
89948991 .calls_or_awaits_errorable_fn = false,
8995 .stack_alignment = .none,
89968992 .inferred_error_set = false,
89978993 .disable_instrumentation = false,
89988994 },
......@@ -9092,7 +9088,6 @@ pub fn getFuncInstanceIes(
90929088 .branch_hint = .none,
90939089 .is_noinline = arg.is_noinline,
90949090 .calls_or_awaits_errorable_fn = false,
9095 .stack_alignment = .none,
90969091 .inferred_error_set = true,
90979092 .disable_instrumentation = false,
90989093 },
......@@ -9110,7 +9105,7 @@ pub fn getFuncInstanceIes(
91109105 .params_len = params_len,
91119106 .return_type = error_union_type,
91129107 .flags = .{
9113 .cc = arg.cc,
9108 .cc = .pack(arg.cc),
91149109 .is_var_args = false,
91159110 .has_comptime_bits = false,
91169111 .has_noalias_bits = arg.noalias_bits != 0,
......@@ -11871,21 +11866,6 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
1187111866 return @atomicLoad(FuncAnalysis, @constCast(ip).funcAnalysisPtr(func), .unordered);
1187211867}
1187311868
11874pub fn funcMaxStackAlignment(ip: *InternPool, func: Index, new_stack_alignment: Alignment) void {
11875 const unwrapped_func = func.unwrap(ip);
11876 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
11877 extra_mutex.lock();
11878 defer extra_mutex.unlock();
11879
11880 const analysis_ptr = ip.funcAnalysisPtr(func);
11881 var analysis = analysis_ptr.*;
11882 analysis.stack_alignment = switch (analysis.stack_alignment) {
11883 .none => new_stack_alignment,
11884 else => |old_stack_alignment| old_stack_alignment.maxStrict(new_stack_alignment),
11885 };
11886 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
11887}
11888
1188911869pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
1189011870 const unwrapped_func = func.unwrap(ip);
1189111871 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
......@@ -12224,3 +12204,81 @@ pub fn getErrorValue(
1222412204pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {
1222512205 return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null);
1222612206}
12207
12208const PackedCallingConvention = packed struct(u18) {
12209 tag: std.builtin.CallingConvention.Tag,
12210 /// May be ignored depending on `tag`.
12211 incoming_stack_alignment: Alignment,
12212 /// Interpretation depends on `tag`.
12213 extra: u4,
12214
12215 fn pack(cc: std.builtin.CallingConvention) PackedCallingConvention {
12216 return switch (cc) {
12217 inline else => |pl, tag| switch (@TypeOf(pl)) {
12218 void => .{
12219 .tag = tag,
12220 .incoming_stack_alignment = .none, // unused
12221 .extra = 0, // unused
12222 },
12223 std.builtin.CallingConvention.CommonOptions => .{
12224 .tag = tag,
12225 .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
12226 .extra = 0, // unused
12227 },
12228 std.builtin.CallingConvention.X86RegparmOptions => .{
12229 .tag = tag,
12230 .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
12231 .extra = pl.register_params,
12232 },
12233 std.builtin.CallingConvention.ArmInterruptOptions => .{
12234 .tag = tag,
12235 .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
12236 .extra = @intFromEnum(pl.type),
12237 },
12238 std.builtin.CallingConvention.MipsInterruptOptions => .{
12239 .tag = tag,
12240 .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
12241 .extra = @intFromEnum(pl.mode),
12242 },
12243 std.builtin.CallingConvention.RiscvInterruptOptions => .{
12244 .tag = tag,
12245 .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
12246 .extra = @intFromEnum(pl.mode),
12247 },
12248 else => comptime unreachable,
12249 },
12250 };
12251 }
12252
12253 fn unpack(cc: PackedCallingConvention) std.builtin.CallingConvention {
12254 return switch (cc.tag) {
12255 inline else => |tag| @unionInit(
12256 std.builtin.CallingConvention,
12257 @tagName(tag),
12258 switch (@FieldType(std.builtin.CallingConvention, @tagName(tag))) {
12259 void => {},
12260 std.builtin.CallingConvention.CommonOptions => .{
12261 .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
12262 },
12263 std.builtin.CallingConvention.X86RegparmOptions => .{
12264 .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
12265 .register_params = @intCast(cc.extra),
12266 },
12267 std.builtin.CallingConvention.ArmInterruptOptions => .{
12268 .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
12269 .type = @enumFromInt(cc.extra),
12270 },
12271 std.builtin.CallingConvention.MipsInterruptOptions => .{
12272 .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
12273 .mode = @enumFromInt(cc.extra),
12274 },
12275 std.builtin.CallingConvention.RiscvInterruptOptions => .{
12276 .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
12277 .mode = @enumFromInt(cc.extra),
12278 },
12279 else => comptime unreachable,
12280 },
12281 ),
12282 };
12283 }
12284};
src/Sema.zig+260-141
......@@ -26,7 +26,7 @@ owner: AnalUnit,
2626/// in the case of an inline or comptime function call.
2727/// This could be `none`, a `func_decl`, or a `func_instance`.
2828func_index: InternPool.Index,
29/// Whether the type of func_index has a calling convention of `.Naked`.
29/// Whether the type of func_index has a calling convention of `.naked`.
3030func_is_naked: bool,
3131/// Used to restore the error return trace when returning a non-error from a function.
3232error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
......@@ -1326,11 +1326,6 @@ fn analyzeBodyInner(
13261326 i += 1;
13271327 continue;
13281328 },
1329 .set_align_stack => {
1330 try sema.zirSetAlignStack(block, extended);
1331 i += 1;
1332 continue;
1333 },
13341329 .breakpoint => {
13351330 if (!block.is_comptime) {
13361331 _ = try block.addNoOp(.breakpoint);
......@@ -1355,7 +1350,7 @@ fn analyzeBodyInner(
13551350 },
13561351 .value_placeholder => unreachable, // never appears in a body
13571352 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
1358 .builtin_value => try sema.zirBuiltinValue(extended),
1353 .builtin_value => try sema.zirBuiltinValue(block, extended),
13591354 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),
13601355 };
13611356 },
......@@ -2698,6 +2693,20 @@ fn analyzeAsInt(
26982693 return try val.toUnsignedIntSema(sema.pt);
26992694}
27002695
2696fn analyzeValueAsCallconv(
2697 sema: *Sema,
2698 block: *Block,
2699 src: LazySrcLoc,
2700 unresolved_val: Value,
2701) !std.builtin.CallingConvention {
2702 const resolved_val = try sema.resolveLazyValue(unresolved_val);
2703 return resolved_val.interpret(std.builtin.CallingConvention, sema.pt) catch |err| switch (err) {
2704 error.OutOfMemory => |e| return e,
2705 error.UndefinedValue => return sema.failWithUseOfUndef(block, src),
2706 error.TypeMismatch => @panic("std.builtin is corrupt"),
2707 };
2708}
2709
27012710/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
27022711/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
27032712fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
......@@ -6496,35 +6505,6 @@ pub fn analyzeExport(
64966505 });
64976506}
64986507
6499fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6500 const pt = sema.pt;
6501 const zcu = pt.zcu;
6502 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
6503 const operand_src = block.builtinCallArgSrc(extra.node, 0);
6504 const src = block.nodeOffset(extra.node);
6505 const alignment = try sema.resolveAlign(block, operand_src, extra.operand);
6506
6507 const func = switch (sema.owner.unwrap()) {
6508 .func => |func| func,
6509 .cau => return sema.fail(block, src, "@setAlignStack outside of function scope", .{}),
6510 };
6511
6512 if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) {
6513 return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{
6514 alignment.toByteUnits().?,
6515 });
6516 }
6517
6518 switch (Value.fromInterned(func).typeOf(zcu).fnCallingConvention(zcu)) {
6519 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
6520 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
6521 else => {},
6522 }
6523
6524 zcu.intern_pool.funcMaxStackAlignment(sema.func_index, alignment);
6525 sema.allow_memoize = false;
6526}
6527
65286508fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
65296509 const pt = sema.pt;
65306510 const zcu = pt.zcu;
......@@ -7554,7 +7534,7 @@ fn analyzeCall(
75547534 if (try sema.resolveValue(func)) |func_val|
75557535 if (func_val.isUndef(zcu))
75567536 return sema.failWithUseOfUndef(block, call_src);
7557 if (cc == .Naked) {
7537 if (cc == .naked) {
75587538 const maybe_func_inst = try sema.funcDeclSrcInst(func);
75597539 const msg = msg: {
75607540 const msg = try sema.errMsg(
......@@ -7587,7 +7567,7 @@ fn analyzeCall(
75877567 .async_kw => return sema.failWithUseOfAsync(block, call_src),
75887568 };
75897569
7590 if (modifier == .never_inline and func_ty_info.cc == .Inline) {
7570 if (modifier == .never_inline and func_ty_info.cc == .@"inline") {
75917571 return sema.fail(block, call_src, "'never_inline' call of inline function", .{});
75927572 }
75937573 if (modifier == .always_inline and func_ty_info.is_noinline) {
......@@ -7598,7 +7578,7 @@ fn analyzeCall(
75987578
75997579 const is_generic_call = func_ty_info.is_generic;
76007580 var is_comptime_call = block.is_comptime or modifier == .compile_time;
7601 var is_inline_call = is_comptime_call or modifier == .always_inline or func_ty_info.cc == .Inline;
7581 var is_inline_call = is_comptime_call or modifier == .always_inline or func_ty_info.cc == .@"inline";
76027582 var comptime_reason: ?*const Block.ComptimeReason = null;
76037583 if (!is_inline_call and !is_comptime_call) {
76047584 if (try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) {
......@@ -8455,7 +8435,7 @@ fn instantiateGenericCall(
84558435 }
84568436 // Similarly, if the call evaluated to a generic type we need to instead
84578437 // call it inline.
8458 if (func_ty_info.is_generic or func_ty_info.cc == .Inline) {
8438 if (func_ty_info.is_generic or func_ty_info.cc == .@"inline") {
84598439 return error.GenericPoison;
84608440 }
84618441
......@@ -9505,7 +9485,7 @@ fn zirFunc(
95059485
95069486 // If this instruction has a body, then it's a function declaration, and we decide
95079487 // the callconv based on whether it is exported. Otherwise, the callconv defaults
9508 // to `.Unspecified`.
9488 // to `.auto`.
95099489 const cc: std.builtin.CallingConvention = if (has_body) cc: {
95109490 const func_decl_cau = if (sema.generic_owner != .none) cau: {
95119491 const generic_owner_fn = zcu.funcInfo(sema.generic_owner);
......@@ -9518,8 +9498,26 @@ fn zirFunc(
95189498 const zir_decl = sema.code.getDeclaration(decl_inst)[0];
95199499 break :exported zir_decl.flags.is_export;
95209500 };
9521 break :cc if (fn_is_exported) .C else .Unspecified;
9522 } else .Unspecified;
9501 if (fn_is_exported) {
9502 break :cc target.cCallingConvention() orelse {
9503 // This target has no default C calling convention. We sometimes trigger a similar
9504 // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
9505 // let's eval that now and just get the transitive error. (It's guaranteed to error
9506 // because it does the exact `cCallingConvention` call we just did.)
9507 const cc_type = try sema.getBuiltinType("CallingConvention");
9508 _ = try sema.namespaceLookupVal(
9509 block,
9510 LazySrcLoc.unneeded,
9511 cc_type.getNamespaceIndex(zcu),
9512 try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls),
9513 );
9514 // The above should have errored.
9515 @panic("std.builtin is corrupt");
9516 };
9517 } else {
9518 break :cc .auto;
9519 }
9520 } else .auto;
95239521
95249522 return sema.funcCommon(
95259523 block,
......@@ -9654,35 +9652,91 @@ fn handleExternLibName(
96549652/// These are calling conventions that are confirmed to work with variadic functions.
96559653/// Any calling conventions not included here are either not yet verified to work with variadic
96569654/// functions or there are no more other calling conventions that support variadic functions.
9657const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention{
9658 .C,
9655const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention.Tag{
9656 .x86_64_sysv,
9657 .x86_64_win,
9658 .x86_sysv,
9659 .x86_win,
9660 .aarch64_aapcs,
9661 .aarch64_aapcs_darwin,
9662 .aarch64_aapcs_win,
9663 .aarch64_vfabi,
9664 .aarch64_vfabi_sve,
9665 .arm_apcs,
9666 .arm_aapcs,
9667 .arm_aapcs_vfp,
9668 .arm_aapcs16_vfp,
9669 .mips64_n64,
9670 .mips64_n32,
9671 .mips_o32,
9672 .riscv64_lp64,
9673 .riscv64_lp64_v,
9674 .riscv32_ilp32,
9675 .riscv32_ilp32_v,
9676 .sparc64_sysv,
9677 .sparc_sysv,
9678 .powerpc64_elf,
9679 .powerpc64_elf_altivec,
9680 .powerpc64_elf_v2,
9681 .powerpc_sysv,
9682 .powerpc_sysv_altivec,
9683 .powerpc_aix,
9684 .powerpc_aix_altivec,
9685 .wasm_watc,
9686 .arc_sysv,
9687 .avr_gnu,
9688 .bpf_std,
9689 .csky_sysv,
9690 .hexagon_sysv,
9691 .hexagon_sysv_hvx,
9692 .lanai_sysv,
9693 .loongarch64_lp64,
9694 .loongarch32_ilp32,
9695 .m68k_sysv,
9696 .m68k_gnu,
9697 .m68k_rtd,
9698 .msp430_eabi,
9699 .s390x_sysv,
9700 .s390x_sysv_vx,
9701 .ve_sysv,
9702 .xcore_xs1,
9703 .xcore_xs2,
9704 .xtensa_call0,
9705 .xtensa_windowed,
96599706};
9660fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention) bool {
9707fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
96619708 return for (calling_conventions_supporting_var_args) |supported_cc| {
96629709 if (cc == supported_cc) return true;
96639710 } else false;
96649711}
9665fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention) CompileError!void {
9712fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention.Tag) CompileError!void {
96669713 const CallingConventionsSupportingVarArgsList = struct {
9667 pub fn format(_: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
9714 arch: std.Target.Cpu.Arch,
9715 pub fn format(ctx: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
96689716 _ = fmt;
96699717 _ = options;
9670 for (calling_conventions_supporting_var_args, 0..) |cc_inner, i| {
9671 if (i != 0)
9718 var first = true;
9719 for (calling_conventions_supporting_var_args) |cc_inner| {
9720 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| {
9721 if (supported_arch == ctx.arch) break;
9722 } else continue; // callconv not supported by this arch
9723 if (!first) {
96729724 try writer.writeAll(", ");
9673 try writer.print("'.{s}'", .{@tagName(cc_inner)});
9725 }
9726 first = false;
9727 try writer.print("'{s}'", .{@tagName(cc_inner)});
96749728 }
96759729 }
96769730 };
96779731
96789732 if (!callConvSupportsVarArgs(cc)) {
9679 const msg = msg: {
9680 const msg = try sema.errMsg(src, "variadic function does not support '.{s}' calling convention", .{@tagName(cc)});
9733 return sema.failWithOwnedErrorMsg(block, msg: {
9734 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
96819735 errdefer msg.destroy(sema.gpa);
9682 try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{}});
9736 const target = sema.pt.zcu.getTarget();
9737 try sema.errNote(src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }});
96839738 break :msg msg;
9684 };
9685 return sema.failWithOwnedErrorMsg(block, msg);
9739 });
96869740 }
96879741}
96889742
......@@ -9743,7 +9797,7 @@ fn funcCommon(
97439797 // default values which are only meaningful for the generic function, *not*
97449798 // the instantiation, which can depend on comptime parameters.
97459799 // Related proposal: https://github.com/ziglang/zig/issues/11834
9746 const cc_resolved = cc orelse .Unspecified;
9800 const cc_resolved = cc orelse .auto;
97479801 var comptime_bits: u32 = 0;
97489802 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
97499803 const param_ty = Type.fromInterned(param_ty_ip);
......@@ -9761,10 +9815,10 @@ fn funcCommon(
97619815 }
97629816 const this_generic = param_ty.isGenericPoison();
97639817 is_generic = is_generic or this_generic;
9764 if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
9818 if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(cc_resolved)) {
97659819 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
97669820 }
9767 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
9821 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(cc_resolved)) {
97689822 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
97699823 }
97709824 if (!param_ty.isValidParamType(zcu)) {
......@@ -9773,7 +9827,7 @@ fn funcCommon(
97739827 opaque_str, param_ty.fmt(pt),
97749828 });
97759829 }
9776 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
9830 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
97779831 const msg = msg: {
97789832 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
97799833 param_ty.fmt(pt), @tagName(cc_resolved),
......@@ -9807,15 +9861,24 @@ fn funcCommon(
98079861 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
98089862 }
98099863 switch (cc_resolved) {
9810 .Interrupt => if (target.cpu.arch.isX86()) {
9864 .x86_64_interrupt, .x86_interrupt => {
98119865 const err_code_size = target.ptrBitWidth();
98129866 switch (i) {
9813 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with 'Interrupt' calling convention must be a pointer type", .{}),
9814 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with 'Interrupt' calling convention must be a {d}-bit integer", .{err_code_size}),
9815 else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}),
9816 }
9817 } else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}),
9818 .Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}),
9867 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc_resolved)}),
9868 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc_resolved), err_code_size }),
9869 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc_resolved), i + 1 }),
9870 }
9871 },
9872 .arm_interrupt,
9873 .mips64_interrupt,
9874 .mips_interrupt,
9875 .riscv64_interrupt,
9876 .riscv32_interrupt,
9877 .avr_interrupt,
9878 .csky_interrupt,
9879 .m68k_interrupt,
9880 .avr_signal,
9881 => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc_resolved)}),
98199882 else => {},
98209883 }
98219884 }
......@@ -10064,7 +10127,6 @@ fn finishFunc(
1006410127 const zcu = pt.zcu;
1006510128 const ip = &zcu.intern_pool;
1006610129 const gpa = sema.gpa;
10067 const target = zcu.getTarget();
1006810130
1006910131 const return_type: Type = if (opt_func_index == .none or ret_poison)
1007010132 bare_return_type
......@@ -10077,7 +10139,7 @@ fn finishFunc(
1007710139 opaque_str, return_type.fmt(pt),
1007810140 });
1007910141 }
10080 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
10142 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and
1008110143 !try sema.validateExternType(return_type, .ret_ty))
1008210144 {
1008310145 const msg = msg: {
......@@ -10133,57 +10195,63 @@ fn finishFunc(
1013310195 return sema.failWithOwnedErrorMsg(block, msg);
1013410196 }
1013510197
10198 validate_incoming_stack_align: {
10199 const a: u64 = switch (cc_resolved) {
10200 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment"))
10201 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align
10202 else
10203 break :validate_incoming_stack_align,
10204 };
10205 if (!std.math.isPowerOfTwo(a)) {
10206 return sema.fail(block, cc_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a});
10207 }
10208 }
10209
1013610210 switch (cc_resolved) {
10137 .Interrupt, .Signal => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) {
10211 .x86_64_interrupt,
10212 .x86_interrupt,
10213 .arm_interrupt,
10214 .mips64_interrupt,
10215 .mips_interrupt,
10216 .riscv64_interrupt,
10217 .riscv32_interrupt,
10218 .avr_interrupt,
10219 .csky_interrupt,
10220 .m68k_interrupt,
10221 .avr_signal,
10222 => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) {
1013810223 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
1013910224 },
10140 .Inline => if (is_noinline) {
10141 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10225 .@"inline" => if (is_noinline) {
10226 return sema.fail(block, cc_src, "'noinline' function cannot have calling convention 'inline'", .{});
1014210227 },
1014310228 else => {},
1014410229 }
1014510230
10146 const arch = target.cpu.arch;
10147 if (@as(?[]const u8, switch (cc_resolved) {
10148 .Unspecified, .C, .Naked, .Async, .Inline => null,
10149 .Interrupt => switch (arch) {
10150 .x86, .x86_64, .avr, .msp430 => null,
10151 else => "x86, x86_64, AVR, and MSP430",
10152 },
10153 .Signal => switch (arch) {
10154 .avr => null,
10155 else => "AVR",
10156 },
10157 .Stdcall, .Fastcall, .Thiscall => switch (arch) {
10158 .x86 => null,
10159 else => "x86",
10160 },
10161 .Vectorcall => switch (arch) {
10162 .x86, .aarch64, .aarch64_be => null,
10163 else => "x86 and AArch64",
10164 },
10165 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {
10166 .arm, .armeb, .aarch64, .aarch64_be, .thumb, .thumbeb => null,
10167 else => "ARM",
10168 },
10169 .SysV, .Win64 => switch (arch) {
10170 .x86_64 => null,
10171 else => "x86_64",
10172 },
10173 .Kernel => switch (arch) {
10174 .nvptx, .nvptx64, .amdgcn, .spirv, .spirv32, .spirv64 => null,
10175 else => "nvptx, amdgcn and SPIR-V",
10176 },
10177 .Fragment, .Vertex => switch (arch) {
10178 .spirv, .spirv32, .spirv64 => null,
10179 else => "SPIR-V",
10180 },
10181 })) |allowed_platform| {
10182 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{
10231 switch (zcu.callconvSupported(cc_resolved)) {
10232 .ok => {},
10233 .bad_arch => |allowed_archs| {
10234 const ArchListFormatter = struct {
10235 archs: []const std.Target.Cpu.Arch,
10236 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
10237 _ = fmt;
10238 _ = options;
10239 for (formatter.archs, 0..) |arch, i| {
10240 if (i != 0)
10241 try writer.writeAll(", ");
10242 try writer.print("'{s}'", .{@tagName(arch)});
10243 }
10244 }
10245 };
10246 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {}", .{
10247 @tagName(cc_resolved),
10248 ArchListFormatter{ .archs = allowed_archs },
10249 });
10250 },
10251 .bad_backend => |bad_backend| return sema.fail(block, cc_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{
1018310252 @tagName(cc_resolved),
10184 allowed_platform,
10185 @tagName(arch),
10186 });
10253 @tagName(bad_backend),
10254 }),
1018710255 }
1018810256
1018910257 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
......@@ -18342,10 +18410,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1834218410 } });
1834318411
1834418412 const callconv_ty = try sema.getBuiltinType("CallingConvention");
18413 const callconv_val = Value.uninterpret(func_ty_info.cc, callconv_ty, pt) catch |err| switch (err) {
18414 error.TypeMismatch => @panic("std.builtin is corrupt"),
18415 error.OutOfMemory => |e| return e,
18416 };
1834518417
18346 const field_values = .{
18418 const field_values: [5]InternPool.Index = .{
1834718419 // calling_convention: CallingConvention,
18348 (try pt.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),
18420 callconv_val.toIntern(),
1834918421 // is_generic: bool,
1835018422 Value.makeBool(func_ty_info.is_generic).toIntern(),
1835118423 // is_var_args: bool,
......@@ -22171,7 +22243,7 @@ fn zirReify(
2217122243 }
2217222244
2217322245 const is_var_args = is_var_args_val.toBool();
22174 const cc = zcu.toEnum(std.builtin.CallingConvention, calling_convention_val);
22246 const cc = try sema.analyzeValueAsCallconv(block, src, calling_convention_val);
2217522247 if (is_var_args) {
2217622248 try sema.checkCallConvSupportsVarArgs(block, src, cc);
2217722249 }
......@@ -26670,7 +26742,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2667026742 if (val.isGenericPoison()) {
2667126743 break :blk null;
2667226744 }
26673 break :blk zcu.toEnum(std.builtin.CallingConvention, val);
26745 break :blk try sema.analyzeValueAsCallconv(block, cc_src, val);
2667426746 } else if (extra.data.bits.has_cc_ref) blk: {
2667526747 const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
2667626748 extra_index += 1;
......@@ -26689,7 +26761,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2668926761 error.GenericPoison => break :blk null,
2669026762 else => |e| return e,
2669126763 };
26692 break :blk zcu.toEnum(std.builtin.CallingConvention, cc_val);
26764 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);
2669326765 } else cc: {
2669426766 if (has_body) {
2669526767 const decl_inst = if (sema.generic_owner != .none) decl_inst: {
......@@ -26705,7 +26777,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2670526777 break :cc .C;
2670626778 }
2670726779 }
26708 break :cc .Unspecified;
26780 break :cc .auto;
2670926781 };
2671026782
2671126783 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
......@@ -27132,9 +27204,15 @@ fn zirInComptime(
2713227204 return if (block.is_comptime) .bool_true else .bool_false;
2713327205}
2713427206
27135fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
27207fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
2713627208 const pt = sema.pt;
27209 const zcu = pt.zcu;
27210 const gpa = zcu.gpa;
27211 const ip = &zcu.intern_pool;
27212
27213 const src = block.nodeOffset(@bitCast(extended.operand));
2713727214 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
27215
2713827216 const type_name = switch (value) {
2713927217 .atomic_order => "AtomicOrder",
2714027218 .atomic_rmw_op => "AtomicRmwOp",
......@@ -27152,21 +27230,25 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr
2715227230 // Values are handled here.
2715327231 .calling_convention_c => {
2715427232 const callconv_ty = try sema.getBuiltinType("CallingConvention");
27155 comptime assert(@intFromEnum(std.builtin.CallingConvention.C) == 1);
27156 const val = try pt.intern(.{ .enum_tag = .{
27157 .ty = callconv_ty.toIntern(),
27158 .int = .one_u8,
27159 } });
27160 return Air.internedToRef(val);
27233 return try sema.namespaceLookupVal(
27234 block,
27235 src,
27236 callconv_ty.getNamespaceIndex(zcu),
27237 try ip.getOrPutString(gpa, pt.tid, "c", .no_embedded_nulls),
27238 ) orelse @panic("std.builtin is corrupt");
2716127239 },
2716227240 .calling_convention_inline => {
27241 comptime assert(@typeInfo(std.builtin.CallingConvention.Tag).@"enum".tag_type == u8);
2716327242 const callconv_ty = try sema.getBuiltinType("CallingConvention");
27164 comptime assert(@intFromEnum(std.builtin.CallingConvention.Inline) == 4);
27165 const val = try pt.intern(.{ .enum_tag = .{
27166 .ty = callconv_ty.toIntern(),
27167 .int = .four_u8,
27168 } });
27169 return Air.internedToRef(val);
27243 const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt");
27244 const inline_tag_val = try pt.enumValue(
27245 callconv_tag_ty,
27246 (try pt.intValue(
27247 Type.u8,
27248 @intFromEnum(std.builtin.CallingConvention.@"inline"),
27249 )).toIntern(),
27250 );
27251 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
2717027252 },
2717127253 };
2717227254 const ty = try sema.getBuiltinType(type_name);
......@@ -27353,7 +27435,7 @@ fn explainWhyTypeIsComptimeInner(
2735327435 try sema.errNote(src_loc, msg, "function is generic", .{});
2735427436 }
2735527437 switch (fn_info.cc) {
27356 .Inline => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}),
27438 .@"inline" => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}),
2735727439 else => {},
2735827440 }
2735927441 if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) {
......@@ -27461,13 +27543,12 @@ fn validateExternType(
2746127543 },
2746227544 .@"fn" => {
2746327545 if (position != .other) return false;
27464 const target = zcu.getTarget();
2746527546 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
2746627547 // The goal is to experiment with more integrated CPU/GPU code.
27467 if (ty.fnCallingConvention(zcu) == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) {
27548 if (ty.fnCallingConvention(zcu) == .nvptx_kernel) {
2746827549 return true;
2746927550 }
27470 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(zcu));
27551 return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu));
2747127552 },
2747227553 .@"enum" => {
2747327554 return sema.validateExternType(ty.intTagType(zcu), position);
......@@ -27547,9 +27628,9 @@ fn explainWhyTypeIsNotExtern(
2754727628 return;
2754827629 }
2754927630 switch (ty.fnCallingConvention(zcu)) {
27550 .Unspecified => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}),
27551 .Async => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}),
27552 .Inline => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}),
27631 .auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}),
27632 .@"async" => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}),
27633 .@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}),
2755327634 else => return,
2755427635 }
2755527636 },
......@@ -31176,8 +31257,8 @@ fn coerceInMemoryAllowedFns(
3117631257 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
3117731258 }
3117831259
31179 if (dest_info.cc != src_info.cc) {
31180 return InMemoryCoercionResult{ .fn_cc = .{
31260 if (!callconvCoerceAllowed(target, src_info.cc, dest_info.cc)) {
31261 return .{ .fn_cc = .{
3118131262 .actual = src_info.cc,
3118231263 .wanted = dest_info.cc,
3118331264 } };
......@@ -31250,6 +31331,44 @@ fn coerceInMemoryAllowedFns(
3125031331 return .ok;
3125131332}
3125231333
31334fn callconvCoerceAllowed(
31335 target: std.Target,
31336 src_cc: std.builtin.CallingConvention,
31337 dest_cc: std.builtin.CallingConvention,
31338) bool {
31339 const Tag = std.builtin.CallingConvention.Tag;
31340 if (@as(Tag, src_cc) != @as(Tag, dest_cc)) return false;
31341
31342 switch (src_cc) {
31343 inline else => |src_data, tag| {
31344 const dest_data = @field(dest_cc, @tagName(tag));
31345 if (@TypeOf(src_data) != void) {
31346 const default_stack_align = target.stackAlignment();
31347 const src_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
31348 const dest_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
31349 if (dest_stack_align < src_stack_align) return false;
31350 }
31351 switch (@TypeOf(src_data)) {
31352 void, std.builtin.CallingConvention.CommonOptions => {},
31353 std.builtin.CallingConvention.X86RegparmOptions => {
31354 if (src_data.register_params != dest_data.register_params) return false;
31355 },
31356 std.builtin.CallingConvention.ArmInterruptOptions => {
31357 if (src_data.type != dest_data.type) return false;
31358 },
31359 std.builtin.CallingConvention.MipsInterruptOptions => {
31360 if (src_data.mode != dest_data.mode) return false;
31361 },
31362 std.builtin.CallingConvention.RiscvInterruptOptions => {
31363 if (src_data.mode != dest_data.mode) return false;
31364 },
31365 else => comptime unreachable,
31366 }
31367 },
31368 }
31369 return true;
31370}
31371
3125331372fn coerceInMemoryAllowedPtrs(
3125431373 sema: *Sema,
3125531374 block: *Block,
......@@ -36306,7 +36425,7 @@ fn resolveInferredErrorSet(
3630636425 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
3630736426 // so here we can simply skip this case.
3630836427 if (ies_func_info.return_type == .generic_poison_type) {
36309 assert(ies_func_info.cc == .Inline);
36428 assert(ies_func_info.cc == .@"inline");
3631036429 } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) {
3631136430 if (ies_func_info.is_generic) {
3631236431 return sema.failWithOwnedErrorMsg(block, msg: {
src/Type.zig+12-5
......@@ -390,10 +390,17 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
390390 try writer.writeAll("...");
391391 }
392392 try writer.writeAll(") ");
393 if (fn_info.cc != .Unspecified) {
394 try writer.writeAll("callconv(.");
395 try writer.writeAll(@tagName(fn_info.cc));
396 try writer.writeAll(") ");
393 if (fn_info.cc != .auto) print_cc: {
394 if (zcu.getTarget().cCallingConvention()) |ccc| {
395 if (fn_info.cc.eql(ccc)) {
396 try writer.writeAll("callconv(.c) ");
397 break :print_cc;
398 }
399 }
400 switch (fn_info.cc) {
401 .auto, .@"async", .naked, .@"inline" => try writer.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),
402 else => try writer.print("callconv({any}) ", .{fn_info.cc}),
403 }
397404 }
398405 if (fn_info.return_type == .generic_poison_type) {
399406 try writer.writeAll("anytype");
......@@ -791,7 +798,7 @@ pub fn fnHasRuntimeBitsInner(
791798 const fn_info = zcu.typeToFunc(ty).?;
792799 if (fn_info.is_generic) return false;
793800 if (fn_info.is_var_args) return true;
794 if (fn_info.cc == .Inline) return false;
801 if (fn_info.cc == .@"inline") return false;
795802 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid);
796803}
797804
src/Value.zig+156
......@@ -4490,3 +4490,159 @@ pub fn resolveLazy(
44904490 else => return val,
44914491 }
44924492}
4493
4494/// Given a `Value` representing a comptime-known value of type `T`, unwrap it into an actual `T` known to the compiler.
4495/// This is useful for accessing `std.builtin` structures received from comptime logic.
4496/// `val` must be fully resolved.
4497pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T {
4498 const zcu = pt.zcu;
4499 const ip = &zcu.intern_pool;
4500 const ty = val.typeOf(zcu);
4501 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;
4502 if (val.isUndef(zcu)) return error.UndefinedValue;
4503
4504 return switch (@typeInfo(T)) {
4505 .type,
4506 .noreturn,
4507 .comptime_float,
4508 .comptime_int,
4509 .undefined,
4510 .null,
4511 .@"fn",
4512 .@"opaque",
4513 .enum_literal,
4514 => comptime unreachable, // comptime-only or otherwise impossible
4515
4516 .pointer,
4517 .array,
4518 .error_union,
4519 .error_set,
4520 .frame,
4521 .@"anyframe",
4522 .vector,
4523 => comptime unreachable, // unsupported
4524
4525 .void => {},
4526
4527 .bool => switch (val.toIntern()) {
4528 .bool_false => false,
4529 .bool_true => true,
4530 else => unreachable,
4531 },
4532
4533 .int => switch (ip.indexToKey(val.toIntern()).int.storage) {
4534 .lazy_align, .lazy_size => unreachable, // `val` is fully resolved
4535 inline .u64, .i64 => |x| std.math.cast(T, x) orelse return error.TypeMismatch,
4536 .big_int => |big| big.to(T) catch return error.TypeMismatch,
4537 },
4538
4539 .float => val.toFloat(T, zcu),
4540
4541 .optional => |opt| if (val.optionalValue(zcu)) |unwrapped|
4542 try unwrapped.interpret(opt.child, pt)
4543 else
4544 null,
4545
4546 .@"enum" => zcu.toEnum(T, val),
4547
4548 .@"union" => |@"union"| {
4549 const union_obj = zcu.typeToUnion(ty) orelse return error.TypeMismatch;
4550 if (union_obj.field_types.len != @"union".fields.len) return error.TypeMismatch;
4551 const tag_val = val.unionTag(zcu) orelse return error.TypeMismatch;
4552 const tag = try tag_val.interpret(@"union".tag_type.?, pt);
4553 return switch (tag) {
4554 inline else => |tag_comptime| @unionInit(
4555 T,
4556 @tagName(tag_comptime),
4557 try val.unionValue(zcu).interpret(@FieldType(T, @tagName(tag_comptime)), pt),
4558 ),
4559 };
4560 },
4561
4562 .@"struct" => |@"struct"| {
4563 if (ty.structFieldCount(zcu) != @"struct".fields.len) return error.TypeMismatch;
4564 var result: T = undefined;
4565 inline for (@"struct".fields, 0..) |field, field_idx| {
4566 const field_val = try val.fieldValue(pt, field_idx);
4567 @field(result, field.name) = try field_val.interpret(field.type, pt);
4568 }
4569 return result;
4570 },
4571 };
4572}
4573
4574/// Given any `val` and a `Type` corresponding `@TypeOf(val)`, construct a `Value` representing it which can be used
4575/// within the compilation. This is useful for passing `std.builtin` structures in the compiler back to the compilation.
4576/// This is the inverse of `interpret`.
4577pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory, TypeMismatch }!Value {
4578 const T = @TypeOf(val);
4579
4580 const zcu = pt.zcu;
4581 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;
4582
4583 return switch (@typeInfo(T)) {
4584 .type,
4585 .noreturn,
4586 .comptime_float,
4587 .comptime_int,
4588 .undefined,
4589 .null,
4590 .@"fn",
4591 .@"opaque",
4592 .enum_literal,
4593 => comptime unreachable, // comptime-only or otherwise impossible
4594
4595 .pointer,
4596 .array,
4597 .error_union,
4598 .error_set,
4599 .frame,
4600 .@"anyframe",
4601 .vector,
4602 => comptime unreachable, // unsupported
4603
4604 .void => .void,
4605
4606 .bool => if (val) .true else .false,
4607
4608 .int => try pt.intValue(ty, val),
4609
4610 .float => try pt.floatValue(ty, val),
4611
4612 .optional => if (val) |some|
4613 .fromInterned(try pt.intern(.{ .opt = .{
4614 .ty = ty.toIntern(),
4615 .val = (try uninterpret(some, ty.optionalChild(zcu), pt)).toIntern(),
4616 } }))
4617 else
4618 try pt.nullValue(ty),
4619
4620 .@"enum" => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()),
4621
4622 .@"union" => |@"union"| {
4623 const tag: @"union".tag_type.? = val;
4624 const tag_val = try uninterpret(tag, ty.unionTagType(zcu).?, pt);
4625 const field_ty = ty.unionFieldType(tag_val, zcu) orelse return error.TypeMismatch;
4626 return switch (val) {
4627 inline else => |payload| try pt.unionValue(
4628 ty,
4629 tag_val,
4630 try uninterpret(payload, field_ty, pt),
4631 ),
4632 };
4633 },
4634
4635 .@"struct" => |@"struct"| {
4636 if (ty.structFieldCount(zcu) != @"struct".fields.len) return error.TypeMismatch;
4637 var field_vals: [@"struct".fields.len]InternPool.Index = undefined;
4638 inline for (&field_vals, @"struct".fields, 0..) |*field_val, field, field_idx| {
4639 const field_ty = ty.fieldType(field_idx, zcu);
4640 field_val.* = (try uninterpret(@field(val, field.name), field_ty, pt)).toIntern();
4641 }
4642 return .fromInterned(try pt.intern(.{ .aggregate = .{
4643 .ty = ty.toIntern(),
4644 .storage = .{ .elems = &field_vals },
4645 } }));
4646 },
4647 };
4648}
src/Zcu.zig+108
......@@ -3539,3 +3539,111 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void {
35393539 zcu.intern_pool.funcSetIesResolved(func_index, .none);
35403540 }
35413541}
3542
3543pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enum) {
3544 ok,
3545 bad_arch: []const std.Target.Cpu.Arch, // value is allowed archs for cc
3546 bad_backend: std.builtin.CompilerBackend, // value is current backend
3547} {
3548 const target = zcu.getTarget();
3549 const backend = target_util.zigBackend(target, zcu.comp.config.use_llvm);
3550 switch (cc) {
3551 .auto, .@"inline" => return .ok,
3552 .@"async" => return .{ .bad_backend = backend }, // nothing supports async currently
3553 .naked => {}, // depends only on backend
3554 else => for (cc.archs()) |allowed_arch| {
3555 if (allowed_arch == target.cpu.arch) break;
3556 } else return .{ .bad_arch = cc.archs() },
3557 }
3558 const backend_ok = switch (backend) {
3559 .stage1 => unreachable,
3560 .other => unreachable,
3561 _ => unreachable,
3562
3563 .stage2_llvm => @import("codegen/llvm.zig").toLlvmCallConv(cc, target) != null,
3564 .stage2_c => ok: {
3565 if (target.cCallingConvention()) |default_c| {
3566 if (cc.eql(default_c)) {
3567 break :ok true;
3568 }
3569 }
3570 break :ok switch (cc) {
3571 .x86_64_sysv,
3572 .x86_64_win,
3573 .x86_64_vectorcall,
3574 .x86_64_regcall_v3_sysv,
3575 .x86_64_regcall_v4_win,
3576 .x86_fastcall,
3577 .x86_thiscall,
3578 .x86_vectorcall,
3579 .x86_regcall_v3,
3580 .x86_regcall_v4_win,
3581 .aarch64_vfabi,
3582 .aarch64_vfabi_sve,
3583 .arm_aapcs,
3584 .arm_aapcs_vfp,
3585 .riscv64_lp64_v,
3586 .riscv32_ilp32_v,
3587 .m68k_rtd,
3588 => |opts| opts.incoming_stack_alignment == null,
3589
3590 .x86_sysv,
3591 .x86_win,
3592 .x86_stdcall,
3593 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
3594
3595 .naked => true,
3596
3597 else => false,
3598 };
3599 },
3600 .stage2_wasm => switch (cc) {
3601 .wasm_watc => |opts| opts.incoming_stack_alignment == null,
3602 else => false,
3603 },
3604 .stage2_arm => switch (cc) {
3605 .arm_aapcs => |opts| opts.incoming_stack_alignment == null,
3606 .naked => true,
3607 else => false,
3608 },
3609 .stage2_x86_64 => switch (cc) {
3610 .x86_64_sysv, .x86_64_win, .naked => true, // incoming stack alignment supported
3611 else => false,
3612 },
3613 .stage2_aarch64 => switch (cc) {
3614 .aarch64_aapcs,
3615 .aarch64_aapcs_darwin,
3616 .aarch64_aapcs_win,
3617 => |opts| opts.incoming_stack_alignment == null,
3618 .naked => true,
3619 else => false,
3620 },
3621 .stage2_x86 => switch (cc) {
3622 .x86_sysv,
3623 .x86_win,
3624 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
3625 .naked => true,
3626 else => false,
3627 },
3628 .stage2_riscv64 => switch (cc) {
3629 .riscv64_lp64 => |opts| opts.incoming_stack_alignment == null,
3630 .naked => true,
3631 else => false,
3632 },
3633 .stage2_sparc64 => switch (cc) {
3634 .sparc64_sysv => |opts| opts.incoming_stack_alignment == null,
3635 .naked => true,
3636 else => false,
3637 },
3638 .stage2_spirv64 => switch (cc) {
3639 .spirv_device,
3640 .spirv_kernel,
3641 .spirv_fragment,
3642 .spirv_vertex,
3643 => true,
3644 else => false,
3645 },
3646 };
3647 if (!backend_ok) return .{ .bad_backend = backend };
3648 return .ok;
3649}
src/Zcu/PerThread.zig+1-1
......@@ -2090,7 +2090,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
20902090 .code = zir,
20912091 .owner = anal_unit,
20922092 .func_index = func_index,
2093 .func_is_naked = fn_ty_info.cc == .Naked,
2093 .func_is_naked = fn_ty_info.cc == .naked,
20942094 .fn_ret_ty = Type.fromInterned(fn_ty_info.return_type),
20952095 .fn_ret_ty_ies = null,
20962096 .branch_quota = @max(func.branchQuotaUnordered(ip), Sema.default_branch_quota),
src/arch/aarch64/CodeGen.zig+5-5
......@@ -468,7 +468,7 @@ fn gen(self: *Self) !void {
468468 const pt = self.pt;
469469 const zcu = pt.zcu;
470470 const cc = self.fn_type.fnCallingConvention(zcu);
471 if (cc != .Naked) {
471 if (cc != .naked) {
472472 // stp fp, lr, [sp, #-16]!
473473 _ = try self.addInst(.{
474474 .tag = .stp,
......@@ -6229,14 +6229,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62296229 const ret_ty = fn_ty.fnReturnType(zcu);
62306230
62316231 switch (cc) {
6232 .Naked => {
6232 .naked => {
62336233 assert(result.args.len == 0);
62346234 result.return_value = .{ .unreach = {} };
62356235 result.stack_byte_count = 0;
62366236 result.stack_align = 1;
62376237 return result;
62386238 },
6239 .C => {
6239 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
62406240 // ARM64 Procedure Call Standard
62416241 var ncrn: usize = 0; // Next Core Register Number
62426242 var nsaa: u32 = 0; // Next stacked argument address
......@@ -6266,7 +6266,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62666266
62676267 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
62686268 // values to spread across odd-numbered registers.
6269 if (Type.fromInterned(ty).abiAlignment(zcu) == .@"16" and !self.target.isDarwin()) {
6269 if (Type.fromInterned(ty).abiAlignment(zcu) == .@"16" and cc != .aarch64_aapcs_darwin) {
62706270 // Round up NCRN to the next even number
62716271 ncrn += ncrn % 2;
62726272 }
......@@ -6298,7 +6298,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62986298 result.stack_byte_count = nsaa;
62996299 result.stack_align = 16;
63006300 },
6301 .Unspecified => {
6301 .auto => {
63026302 if (ret_ty.zigTypeTag(zcu) == .noreturn) {
63036303 result.return_value = .{ .unreach = {} };
63046304 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) {
src/arch/arm/CodeGen.zig+4-4
......@@ -475,7 +475,7 @@ fn gen(self: *Self) !void {
475475 const pt = self.pt;
476476 const zcu = pt.zcu;
477477 const cc = self.fn_type.fnCallingConvention(zcu);
478 if (cc != .Naked) {
478 if (cc != .naked) {
479479 // push {fp, lr}
480480 const push_reloc = try self.addNop();
481481
......@@ -6196,14 +6196,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61966196 const ret_ty = fn_ty.fnReturnType(zcu);
61976197
61986198 switch (cc) {
6199 .Naked => {
6199 .naked => {
62006200 assert(result.args.len == 0);
62016201 result.return_value = .{ .unreach = {} };
62026202 result.stack_byte_count = 0;
62036203 result.stack_align = 1;
62046204 return result;
62056205 },
6206 .C => {
6206 .arm_aapcs => {
62076207 // ARM Procedure Call Standard, Chapter 6.5
62086208 var ncrn: usize = 0; // Next Core Register Number
62096209 var nsaa: u32 = 0; // Next stacked argument address
......@@ -6254,7 +6254,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62546254 result.stack_byte_count = nsaa;
62556255 result.stack_align = 8;
62566256 },
6257 .Unspecified => {
6257 .auto => {
62586258 if (ret_ty.zigTypeTag(zcu) == .noreturn) {
62596259 result.return_value = .{ .unreach = {} };
62606260 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) {
src/arch/riscv64/CodeGen.zig+9-11
......@@ -18,6 +18,7 @@ const Zcu = @import("../../Zcu.zig");
1818const Package = @import("../../Package.zig");
1919const InternPool = @import("../../InternPool.zig");
2020const Compilation = @import("../../Compilation.zig");
21const target_util = @import("../../target.zig");
2122const trace = @import("../../tracy.zig").trace;
2223const codegen = @import("../../codegen.zig");
2324
......@@ -819,10 +820,7 @@ pub fn generate(
819820 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
820821 function.frame_allocs.set(
821822 @intFromEnum(FrameIndex.stack_frame),
822 FrameAlloc.init(.{
823 .size = 0,
824 .alignment = func.analysisUnordered(ip).stack_alignment.max(.@"1"),
825 }),
823 FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }),
826824 );
827825 function.frame_allocs.set(
828826 @intFromEnum(FrameIndex.call_frame),
......@@ -977,7 +975,7 @@ pub fn generateLazy(
977975 .pt = pt,
978976 .allocator = gpa,
979977 .mir = mir,
980 .cc = .Unspecified,
978 .cc = .auto,
981979 .src_loc = src_loc,
982980 .output_mode = comp.config.output_mode,
983981 .link_mode = comp.config.link_mode,
......@@ -1036,7 +1034,7 @@ fn formatWipMir(
10361034 .instructions = data.func.mir_instructions.slice(),
10371035 .frame_locs = data.func.frame_locs.slice(),
10381036 },
1039 .cc = .Unspecified,
1037 .cc = .auto,
10401038 .src_loc = data.func.src_loc,
10411039 .output_mode = comp.config.output_mode,
10421040 .link_mode = comp.config.link_mode,
......@@ -1238,7 +1236,7 @@ fn gen(func: *Func) !void {
12381236 }
12391237 }
12401238
1241 if (fn_info.cc != .Naked) {
1239 if (fn_info.cc != .naked) {
12421240 _ = try func.addPseudo(.pseudo_dbg_prologue_end);
12431241
12441242 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);
......@@ -4894,7 +4892,7 @@ fn genCall(
48944892 .lib => |lib| try pt.funcType(.{
48954893 .param_types = lib.param_types,
48964894 .return_type = lib.return_type,
4897 .cc = .C,
4895 .cc = func.target.cCallingConvention().?,
48984896 }),
48994897 };
49004898
......@@ -8289,12 +8287,12 @@ fn resolveCallingConventionValues(
82898287 const ret_ty = Type.fromInterned(fn_info.return_type);
82908288
82918289 switch (cc) {
8292 .Naked => {
8290 .naked => {
82938291 assert(result.args.len == 0);
82948292 result.return_value = InstTracking.init(.unreach);
82958293 result.stack_align = .@"8";
82968294 },
8297 .C, .Unspecified => {
8295 .riscv64_lp64, .auto => {
82988296 if (result.args.len > 8) {
82998297 return func.fail("RISC-V calling convention does not support more than 8 arguments", .{});
83008298 }
......@@ -8359,7 +8357,7 @@ fn resolveCallingConventionValues(
83598357
83608358 for (param_types, result.args) |ty, *arg| {
83618359 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
8362 assert(cc == .Unspecified);
8360 assert(cc == .auto);
83638361 arg.* = .none;
83648362 continue;
83658363 }
src/arch/sparc64/CodeGen.zig+3-3
......@@ -366,7 +366,7 @@ fn gen(self: *Self) !void {
366366 const pt = self.pt;
367367 const zcu = pt.zcu;
368368 const cc = self.fn_type.fnCallingConvention(zcu);
369 if (cc != .Naked) {
369 if (cc != .naked) {
370370 // TODO Finish function prologue and epilogue for sparc64.
371371
372372 // save %sp, stack_reserved_area, %sp
......@@ -4441,14 +4441,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44414441 const ret_ty = fn_ty.fnReturnType(zcu);
44424442
44434443 switch (cc) {
4444 .Naked => {
4444 .naked => {
44454445 assert(result.args.len == 0);
44464446 result.return_value = .{ .unreach = {} };
44474447 result.stack_byte_count = 0;
44484448 result.stack_align = .@"1";
44494449 return result;
44504450 },
4451 .Unspecified, .C => {
4451 .auto, .sparc64_sysv => {
44524452 // SPARC Compliance Definition 2.4.1, Chapter 3
44534453 // Low-Level System Information (64-bit psABI) - Function Calling Sequence
44544454
src/arch/wasm/CodeGen.zig+16-15
......@@ -710,7 +710,7 @@ stack_size: u32 = 0,
710710/// The stack alignment, which is 16 bytes by default. This is specified by the
711711/// tool-conventions: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
712712/// and also what the llvm backend will emit.
713/// However, local variables or the usage of `@setAlignStack` can overwrite this default.
713/// However, local variables or the usage of `incoming_stack_alignment` in a `CallingConvention` can overwrite this default.
714714stack_alignment: Alignment = .@"16",
715715
716716// For each individual Wasm valtype we store a seperate free list which
......@@ -1160,7 +1160,7 @@ fn genFunctype(
11601160 if (firstParamSRet(cc, return_type, pt, target)) {
11611161 try temp_params.append(.i32); // memory address is always a 32-bit handle
11621162 } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) {
1163 if (cc == .C) {
1163 if (cc == .wasm_watc) {
11641164 const res_classes = abi.classifyType(return_type, zcu);
11651165 assert(res_classes[0] == .direct and res_classes[1] == .none);
11661166 const scalar_type = abi.scalarType(return_type, zcu);
......@@ -1178,7 +1178,7 @@ fn genFunctype(
11781178 if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11791179
11801180 switch (cc) {
1181 .C => {
1181 .wasm_watc => {
11821182 const param_classes = abi.classifyType(param_type, zcu);
11831183 if (param_classes[1] == .none) {
11841184 if (param_classes[0] == .direct) {
......@@ -1367,7 +1367,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13671367 .args = &.{},
13681368 .return_value = .none,
13691369 };
1370 if (cc == .Naked) return result;
1370 if (cc == .naked) return result;
13711371
13721372 var args = std.ArrayList(WValue).init(func.gpa);
13731373 defer args.deinit();
......@@ -1382,7 +1382,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13821382 }
13831383
13841384 switch (cc) {
1385 .Unspecified => {
1385 .auto => {
13861386 for (fn_info.param_types.get(ip)) |ty| {
13871387 if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) {
13881388 continue;
......@@ -1392,7 +1392,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13921392 func.local_index += 1;
13931393 }
13941394 },
1395 .C => {
1395 .wasm_watc => {
13961396 for (fn_info.param_types.get(ip)) |ty| {
13971397 const ty_classes = abi.classifyType(Type.fromInterned(ty), zcu);
13981398 for (ty_classes) |class| {
......@@ -1410,8 +1410,9 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
14101410
14111411fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread, target: std.Target) bool {
14121412 switch (cc) {
1413 .Unspecified, .Inline => return isByRef(return_type, pt, target),
1414 .C => {
1413 .@"inline" => unreachable,
1414 .auto => return isByRef(return_type, pt, target),
1415 .wasm_watc => {
14151416 const ty_classes = abi.classifyType(return_type, pt.zcu);
14161417 if (ty_classes[0] == .indirect) return true;
14171418 if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true;
......@@ -1424,7 +1425,7 @@ fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.
14241425/// Lowers a Zig type and its value based on a given calling convention to ensure
14251426/// it matches the ABI.
14261427fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void {
1427 if (cc != .C) {
1428 if (cc != .wasm_watc) {
14281429 return func.lowerToStack(value);
14291430 }
14301431
......@@ -2108,7 +2109,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21082109 // to the stack instead
21092110 if (func.return_value != .none) {
21102111 try func.store(func.return_value, operand, ret_ty, 0);
2111 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2112 } else if (fn_info.cc == .wasm_watc and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
21122113 switch (ret_ty.zigTypeTag(zcu)) {
21132114 // Aggregate types can be lowered as a singular value
21142115 .@"struct", .@"union" => {
......@@ -2286,7 +2287,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22862287 } else if (first_param_sret) {
22872288 break :result_value sret;
22882289 // TODO: Make this less fragile and optimize
2289 } else if (zcu.typeToFunc(fn_ty).?.cc == .C and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") {
2290 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_watc and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") {
22902291 const result_local = try func.allocLocal(ret_ty);
22912292 try func.addLabel(.local_set, result_local.local.value);
22922293 const scalar_type = abi.scalarType(ret_ty, zcu);
......@@ -2565,7 +2566,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25652566 const arg = func.args[arg_index];
25662567 const cc = zcu.typeToFunc(zcu.navValue(func.owner_nav).typeOf(zcu)).?.cc;
25672568 const arg_ty = func.typeOfIndex(inst);
2568 if (cc == .C) {
2569 if (cc == .wasm_watc) {
25692570 const arg_classes = abi.classifyType(arg_ty, zcu);
25702571 for (arg_classes) |class| {
25712572 if (class != .none) {
......@@ -7175,12 +7176,12 @@ fn callIntrinsic(
71757176 // Always pass over C-ABI
71767177 const pt = func.pt;
71777178 const zcu = pt.zcu;
7178 var func_type = try genFunctype(func.gpa, .C, param_types, return_type, pt, func.target.*);
7179 var func_type = try genFunctype(func.gpa, .{ .wasm_watc = .{} }, param_types, return_type, pt, func.target.*);
71797180 defer func_type.deinit(func.gpa);
71807181 const func_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, func_type);
71817182 try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index);
71827183
7183 const want_sret_param = firstParamSRet(.C, return_type, pt, func.target.*);
7184 const want_sret_param = firstParamSRet(.{ .wasm_watc = .{} }, return_type, pt, func.target.*);
71847185 // if we want return as first param, we allocate a pointer to stack,
71857186 // and emit it as our first argument
71867187 const sret = if (want_sret_param) blk: {
......@@ -7193,7 +7194,7 @@ fn callIntrinsic(
71937194 for (args, 0..) |arg, arg_i| {
71947195 assert(!(want_sret_param and arg == .stack));
71957196 assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu));
7196 try func.lowerArg(.C, Type.fromInterned(param_types[arg_i]), arg);
7197 try func.lowerArg(.{ .wasm_watc = .{} }, Type.fromInterned(param_types[arg_i]), arg);
71977198 }
71987199
71997200 // Actually call our intrinsic
src/arch/x86_64/CodeGen.zig+47-43
......@@ -11,6 +11,7 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking);
1111const wip_mir_log = std.log.scoped(.wip_mir);
1212const math = std.math;
1313const mem = std.mem;
14const target_util = @import("../../target.zig");
1415const trace = @import("../../tracy.zig").trace;
1516
1617const Air = @import("../../Air.zig");
......@@ -870,10 +871,7 @@ pub fn generate(
870871 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
871872 function.frame_allocs.set(
872873 @intFromEnum(FrameIndex.stack_frame),
873 FrameAlloc.init(.{
874 .size = 0,
875 .alignment = func.analysisUnordered(ip).stack_alignment.max(.@"1"),
876 }),
874 FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }),
877875 );
878876 function.frame_allocs.set(
879877 @intFromEnum(FrameIndex.call_frame),
......@@ -918,13 +916,13 @@ pub fn generate(
918916 );
919917 function.va_info = switch (cc) {
920918 else => undefined,
921 .SysV => .{ .sysv = .{
919 .x86_64_sysv => .{ .sysv = .{
922920 .gp_count = call_info.gp_count,
923921 .fp_count = call_info.fp_count,
924922 .overflow_arg_area = .{ .index = .args_frame, .off = call_info.stack_byte_count },
925923 .reg_save_area = undefined,
926924 } },
927 .Win64 => .{ .win64 = .{} },
925 .x86_64_win => .{ .win64 = .{} },
928926 };
929927
930928 function.gen() catch |err| switch (err) {
......@@ -1053,7 +1051,7 @@ pub fn generateLazy(
10531051 .bin_file = bin_file,
10541052 .allocator = gpa,
10551053 .mir = mir,
1056 .cc = abi.resolveCallingConvention(.Unspecified, function.target.*),
1054 .cc = abi.resolveCallingConvention(.auto, function.target.*),
10571055 .src_loc = src_loc,
10581056 .output_mode = comp.config.output_mode,
10591057 .link_mode = comp.config.link_mode,
......@@ -1159,7 +1157,7 @@ fn formatWipMir(
11591157 .extra = data.self.mir_extra.items,
11601158 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),
11611159 },
1162 .cc = .Unspecified,
1160 .cc = .auto,
11631161 .src_loc = data.self.src_loc,
11641162 .output_mode = comp.config.output_mode,
11651163 .link_mode = comp.config.link_mode,
......@@ -2023,7 +2021,7 @@ fn gen(self: *Self) InnerError!void {
20232021 const zcu = pt.zcu;
20242022 const fn_info = zcu.typeToFunc(self.fn_type).?;
20252023 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
2026 if (cc != .Naked) {
2024 if (cc != .naked) {
20272025 try self.asmRegister(.{ ._, .push }, .rbp);
20282026 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));
20292027 try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));
......@@ -2056,7 +2054,7 @@ fn gen(self: *Self) InnerError!void {
20562054 }
20572055
20582056 if (fn_info.is_var_args) switch (cc) {
2059 .SysV => {
2057 .x86_64_sysv => {
20602058 const info = &self.va_info.sysv;
20612059 const reg_save_area_fi = try self.allocFrameIndex(FrameAlloc.init(.{
20622060 .size = abi.SysV.c_abi_int_param_regs.len * 8 +
......@@ -2089,7 +2087,7 @@ fn gen(self: *Self) InnerError!void {
20892087
20902088 self.performReloc(skip_sse_reloc);
20912089 },
2092 .Win64 => return self.fail("TODO implement gen var arg function for Win64", .{}),
2090 .x86_64_win => return self.fail("TODO implement gen var arg function for Win64", .{}),
20932091 else => unreachable,
20942092 };
20952093
......@@ -2541,7 +2539,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
25412539 const enum_ty = Type.fromInterned(lazy_sym.ty);
25422540 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});
25432541
2544 const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*);
2542 const resolved_cc = abi.resolveCallingConvention(.auto, self.target.*);
25452543 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
25462544 const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
25472545 defer for (param_locks) |lock| self.register_manager.unlockReg(lock);
......@@ -3008,9 +3006,8 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
30083006
30093007pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void {
30103008 switch (cc) {
3011 inline .SysV, .Win64 => |known_cc| try self.spillRegisters(
3012 comptime abi.getCallerPreservedRegs(known_cc),
3013 ),
3009 .x86_64_sysv => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_sysv = .{} })),
3010 .x86_64_win => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_win = .{} })),
30143011 else => unreachable,
30153012 }
30163013}
......@@ -12384,7 +12381,7 @@ fn genCall(self: *Self, info: union(enum) {
1238412381 .lib => |lib| try pt.funcType(.{
1238512382 .param_types = lib.param_types,
1238612383 .return_type = lib.return_type,
12387 .cc = .C,
12384 .cc = self.target.cCallingConvention().?,
1238812385 }),
1238912386 };
1239012387 const fn_info = zcu.typeToFunc(fn_ty).?;
......@@ -12543,7 +12540,7 @@ fn genCall(self: *Self, info: union(enum) {
1254312540 src_arg,
1254412541 .{},
1254512542 ),
12546 .C, .SysV, .Win64 => {
12543 .x86_64_sysv, .x86_64_win => {
1254712544 const promoted_ty = self.promoteInt(arg_ty);
1254812545 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu));
1254912546 const dst_alias = registerAlias(dst_reg, promoted_abi_size);
......@@ -16822,7 +16819,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
1682216819 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1682316820 const inst_ty = self.typeOfIndex(inst);
1682416821 const enum_ty = self.typeOf(un_op);
16825 const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*);
16822 const resolved_cc = abi.resolveCallingConvention(.auto, self.target.*);
1682616823
1682716824 // We need a properly aligned and sized call frame to be able to call this function.
1682816825 {
......@@ -18915,7 +18912,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
1891518912 self.fn_type.fnCallingConvention(zcu),
1891618913 self.target.*,
1891718914 )) {
18918 .SysV => result: {
18915 .x86_64_sysv => result: {
1891918916 const info = self.va_info.sysv;
1892018917 const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, zcu));
1892118918 var field_off: u31 = 0;
......@@ -18957,7 +18954,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
1895718954 field_off += @intCast(ptr_anyopaque_ty.abiSize(zcu));
1895818955 break :result .{ .load_frame = .{ .index = dst_fi } };
1895918956 },
18960 .Win64 => return self.fail("TODO implement c_va_start for Win64", .{}),
18957 .x86_64_win => return self.fail("TODO implement c_va_start for Win64", .{}),
1896118958 else => unreachable,
1896218959 };
1896318960 return self.finishAir(inst, result, .{ .none, .none, .none });
......@@ -18976,7 +18973,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1897618973 self.fn_type.fnCallingConvention(zcu),
1897718974 self.target.*,
1897818975 )) {
18979 .SysV => result: {
18976 .x86_64_sysv => result: {
1898018977 try self.spillEflagsIfOccupied();
1898118978
1898218979 const tmp_regs =
......@@ -19155,7 +19152,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1915519152 );
1915619153 break :result promote_mcv;
1915719154 },
19158 .Win64 => return self.fail("TODO implement c_va_arg for Win64", .{}),
19155 .x86_64_win => return self.fail("TODO implement c_va_arg for Win64", .{}),
1915919156 else => unreachable,
1916019157 };
1916119158 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -19324,21 +19321,21 @@ fn resolveCallingConventionValues(
1932419321
1932519322 const resolved_cc = abi.resolveCallingConvention(cc, self.target.*);
1932619323 switch (cc) {
19327 .Naked => {
19324 .naked => {
1932819325 assert(result.args.len == 0);
1932919326 result.return_value = InstTracking.init(.unreach);
1933019327 result.stack_align = .@"8";
1933119328 },
19332 .C, .SysV, .Win64 => {
19329 .x86_64_sysv, .x86_64_win => |cc_opts| {
1933319330 var ret_int_reg_i: u32 = 0;
1933419331 var ret_sse_reg_i: u32 = 0;
1933519332 var param_int_reg_i: u32 = 0;
1933619333 var param_sse_reg_i: u32 = 0;
19337 result.stack_align = .@"16";
19334 result.stack_align = .fromByteUnits(cc_opts.incoming_stack_alignment orelse 16);
1933819335
1933919336 switch (resolved_cc) {
19340 .SysV => {},
19341 .Win64 => {
19337 .x86_64_sysv => {},
19338 .x86_64_win => {
1934219339 // Align the stack to 16bytes before allocating shadow stack space (if any).
1934319340 result.stack_byte_count += @intCast(4 * Type.usize.abiSize(zcu));
1934419341 },
......@@ -19356,8 +19353,8 @@ fn resolveCallingConventionValues(
1935619353 var ret_tracking_i: usize = 0;
1935719354
1935819355 const classes = switch (resolved_cc) {
19359 .SysV => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
19360 .Win64 => &.{abi.classifyWindows(ret_ty, zcu)},
19356 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
19357 .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)},
1936119358 else => unreachable,
1936219359 };
1936319360 for (classes) |class| switch (class) {
......@@ -19419,8 +19416,8 @@ fn resolveCallingConventionValues(
1941919416 for (param_types, result.args) |ty, *arg| {
1942019417 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
1942119418 switch (resolved_cc) {
19422 .SysV => {},
19423 .Win64 => {
19419 .x86_64_sysv => {},
19420 .x86_64_win => {
1942419421 param_int_reg_i = @max(param_int_reg_i, param_sse_reg_i);
1942519422 param_sse_reg_i = param_int_reg_i;
1942619423 },
......@@ -19431,8 +19428,8 @@ fn resolveCallingConventionValues(
1943119428 var arg_mcv_i: usize = 0;
1943219429
1943319430 const classes = switch (resolved_cc) {
19434 .SysV => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
19435 .Win64 => &.{abi.classifyWindows(ty, zcu)},
19431 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
19432 .x86_64_win => &.{abi.classifyWindows(ty, zcu)},
1943619433 else => unreachable,
1943719434 };
1943819435 for (classes) |class| switch (class) {
......@@ -19464,11 +19461,11 @@ fn resolveCallingConventionValues(
1946419461 },
1946519462 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),
1946619463 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {
19467 .SysV => switch (class) {
19464 .x86_64_sysv => switch (class) {
1946819465 .x87, .x87up, .complex_x87, .memory => break,
1946919466 else => unreachable,
1947019467 },
19471 .Win64 => if (ty.abiSize(zcu) > 8) {
19468 .x86_64_win => if (ty.abiSize(zcu) > 8) {
1947219469 const param_int_reg =
1947319470 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
1947419471 param_int_reg_i += 1;
......@@ -19515,10 +19512,13 @@ fn resolveCallingConventionValues(
1951519512 }
1951619513
1951719514 const param_size: u31 = @intCast(ty.abiSize(zcu));
19518 const param_align: u31 =
19519 @intCast(@max(ty.abiAlignment(zcu).toByteUnits().?, 8));
19520 result.stack_byte_count =
19521 mem.alignForward(u31, result.stack_byte_count, param_align);
19515 const param_align = ty.abiAlignment(zcu).max(.@"8");
19516 result.stack_byte_count = mem.alignForward(
19517 u31,
19518 result.stack_byte_count,
19519 @intCast(param_align.toByteUnits().?),
19520 );
19521 result.stack_align = result.stack_align.max(param_align);
1952219522 arg.* = .{ .load_frame = .{
1952319523 .index = stack_frame_base,
1952419524 .off = result.stack_byte_count,
......@@ -19530,7 +19530,7 @@ fn resolveCallingConventionValues(
1953019530 assert(param_sse_reg_i <= 16);
1953119531 result.fp_count = param_sse_reg_i;
1953219532 },
19533 .Unspecified => {
19533 .auto => {
1953419534 result.stack_align = .@"16";
1953519535
1953619536 // Return values
......@@ -19560,9 +19560,13 @@ fn resolveCallingConventionValues(
1956019560 continue;
1956119561 }
1956219562 const param_size: u31 = @intCast(ty.abiSize(zcu));
19563 const param_align: u31 = @intCast(ty.abiAlignment(zcu).toByteUnits().?);
19564 result.stack_byte_count =
19565 mem.alignForward(u31, result.stack_byte_count, param_align);
19563 const param_align = ty.abiAlignment(zcu);
19564 result.stack_byte_count = mem.alignForward(
19565 u31,
19566 result.stack_byte_count,
19567 @intCast(param_align.toByteUnits().?),
19568 );
19569 result.stack_align = result.stack_align.max(param_align);
1956619570 arg.* = .{ .load_frame = .{
1956719571 .index = stack_frame_base,
1956819572 .off = result.stack_byte_count,
src/arch/x86_64/abi.zig+15-15
......@@ -440,9 +440,9 @@ pub fn resolveCallingConvention(
440440 target: std.Target,
441441) std.builtin.CallingConvention {
442442 return switch (cc) {
443 .Unspecified, .C => switch (target.os.tag) {
444 else => .SysV,
445 .windows => .Win64,
443 .auto => switch (target.os.tag) {
444 else => .{ .x86_64_sysv = .{} },
445 .windows => .{ .x86_64_win = .{} },
446446 },
447447 else => cc,
448448 };
......@@ -450,48 +450,48 @@ pub fn resolveCallingConvention(
450450
451451pub fn getCalleePreservedRegs(cc: std.builtin.CallingConvention) []const Register {
452452 return switch (cc) {
453 .SysV => &SysV.callee_preserved_regs,
454 .Win64 => &Win64.callee_preserved_regs,
453 .x86_64_sysv => &SysV.callee_preserved_regs,
454 .x86_64_win => &Win64.callee_preserved_regs,
455455 else => unreachable,
456456 };
457457}
458458
459459pub fn getCallerPreservedRegs(cc: std.builtin.CallingConvention) []const Register {
460460 return switch (cc) {
461 .SysV => &SysV.caller_preserved_regs,
462 .Win64 => &Win64.caller_preserved_regs,
461 .x86_64_sysv => &SysV.caller_preserved_regs,
462 .x86_64_win => &Win64.caller_preserved_regs,
463463 else => unreachable,
464464 };
465465}
466466
467467pub fn getCAbiIntParamRegs(cc: std.builtin.CallingConvention) []const Register {
468468 return switch (cc) {
469 .SysV => &SysV.c_abi_int_param_regs,
470 .Win64 => &Win64.c_abi_int_param_regs,
469 .x86_64_sysv => &SysV.c_abi_int_param_regs,
470 .x86_64_win => &Win64.c_abi_int_param_regs,
471471 else => unreachable,
472472 };
473473}
474474
475475pub fn getCAbiSseParamRegs(cc: std.builtin.CallingConvention) []const Register {
476476 return switch (cc) {
477 .SysV => &SysV.c_abi_sse_param_regs,
478 .Win64 => &Win64.c_abi_sse_param_regs,
477 .x86_64_sysv => &SysV.c_abi_sse_param_regs,
478 .x86_64_win => &Win64.c_abi_sse_param_regs,
479479 else => unreachable,
480480 };
481481}
482482
483483pub fn getCAbiIntReturnRegs(cc: std.builtin.CallingConvention) []const Register {
484484 return switch (cc) {
485 .SysV => &SysV.c_abi_int_return_regs,
486 .Win64 => &Win64.c_abi_int_return_regs,
485 .x86_64_sysv => &SysV.c_abi_int_return_regs,
486 .x86_64_win => &Win64.c_abi_int_return_regs,
487487 else => unreachable,
488488 };
489489}
490490
491491pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention) []const Register {
492492 return switch (cc) {
493 .SysV => &SysV.c_abi_sse_return_regs,
494 .Win64 => &Win64.c_abi_sse_return_regs,
493 .x86_64_sysv => &SysV.c_abi_sse_return_regs,
494 .x86_64_win => &Win64.c_abi_sse_return_regs,
495495 else => unreachable,
496496 };
497497}
src/codegen/c.zig+35-8
......@@ -1783,7 +1783,7 @@ pub const DeclGen = struct {
17831783 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);
17841784
17851785 const fn_info = zcu.typeToFunc(fn_ty).?;
1786 if (fn_info.cc == .Naked) {
1786 if (fn_info.cc == .naked) {
17871787 switch (kind) {
17881788 .forward => try w.writeAll("zig_naked_decl "),
17891789 .complete => try w.writeAll("zig_naked "),
......@@ -1796,7 +1796,7 @@ pub const DeclGen = struct {
17961796
17971797 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});
17981798
1799 if (toCallingConvention(fn_info.cc)) |call_conv| {
1799 if (toCallingConvention(fn_info.cc, zcu)) |call_conv| {
18001800 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
18011801 trailing = .maybe_space;
18021802 }
......@@ -7604,12 +7604,39 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void {
76047604 return w.writeAll(toMemoryOrder(order));
76057605}
76067606
7607fn toCallingConvention(call_conv: std.builtin.CallingConvention) ?[]const u8 {
7608 return switch (call_conv) {
7609 .Stdcall => "stdcall",
7610 .Fastcall => "fastcall",
7611 .Vectorcall => "vectorcall",
7612 else => null,
7607fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 {
7608 if (zcu.getTarget().cCallingConvention()) |ccc| {
7609 if (cc.eql(ccc)) {
7610 return null;
7611 }
7612 }
7613 return switch (cc) {
7614 .auto, .naked => null,
7615
7616 .x86_64_sysv, .x86_sysv => "sysv_abi",
7617 .x86_64_win, .x86_win => "ms_abi",
7618 .x86_stdcall => "stdcall",
7619 .x86_fastcall => "fastcall",
7620 .x86_thiscall => "thiscall",
7621
7622 .x86_vectorcall,
7623 .x86_64_vectorcall,
7624 => "vectorcall",
7625
7626 .x86_64_regcall_v3_sysv,
7627 .x86_64_regcall_v4_win,
7628 .x86_regcall_v3,
7629 .x86_regcall_v4_win,
7630 => "regcall",
7631
7632 .aarch64_vfabi => "aarch64_vector_pcs",
7633 .aarch64_vfabi_sve => "aarch64_sve_pcs",
7634 .arm_aapcs => "pcs(\"aapcs\")",
7635 .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")",
7636 .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc",
7637 .m68k_rtd => "m68k_rtd",
7638
7639 else => unreachable, // `Zcu.callconvSupported`
76137640 };
76147641}
76157642
src/codegen/llvm.zig+348-242
......@@ -1159,7 +1159,7 @@ pub const Object = struct {
11591159 }
11601160
11611161 {
1162 var module_flags = try std.ArrayList(Builder.Metadata).initCapacity(o.gpa, 6);
1162 var module_flags = try std.ArrayList(Builder.Metadata).initCapacity(o.gpa, 7);
11631163 defer module_flags.deinit();
11641164
11651165 const behavior_error = try o.builder.metadataConstant(try o.builder.intConst(.i32, 1));
......@@ -1233,6 +1233,18 @@ pub const Object = struct {
12331233 }
12341234 }
12351235
1236 const target = comp.root_mod.resolved_target.result;
1237 if (target.os.tag == .windows and (target.cpu.arch == .x86_64 or target.cpu.arch == .x86)) {
1238 // Add the "RegCallv4" flag so that any functions using `x86_regcallcc` use regcall
1239 // v4, which is essentially a requirement on Windows. See corresponding logic in
1240 // `toLlvmCallConvTag`.
1241 module_flags.appendAssumeCapacity(try o.builder.metadataModuleFlag(
1242 behavior_max,
1243 try o.builder.metadataString("RegCallv4"),
1244 try o.builder.metadataConstant(.@"1"),
1245 ));
1246 }
1247
12361248 try o.builder.metadataNamed(try o.builder.metadataString("llvm.module.flags"), module_flags.items);
12371249 }
12381250
......@@ -1467,14 +1479,6 @@ pub const Object = struct {
14671479 _ = try attributes.removeFnAttr(.@"noinline");
14681480 }
14691481
1470 const stack_alignment = func.analysisUnordered(ip).stack_alignment;
1471 if (stack_alignment != .none) {
1472 try attributes.addFnAttr(.{ .alignstack = stack_alignment.toLlvm() }, &o.builder);
1473 try attributes.addFnAttr(.@"noinline", &o.builder);
1474 } else {
1475 _ = try attributes.removeFnAttr(.alignstack);
1476 }
1477
14781482 if (func_analysis.branch_hint == .cold) {
14791483 try attributes.addFnAttr(.cold, &o.builder);
14801484 } else {
......@@ -1486,7 +1490,7 @@ pub const Object = struct {
14861490 } else {
14871491 _ = try attributes.removeFnAttr(.sanitize_thread);
14881492 }
1489 const is_naked = fn_info.cc == .Naked;
1493 const is_naked = fn_info.cc == .naked;
14901494 if (owner_mod.fuzz and !func_analysis.disable_instrumentation and !is_naked) {
14911495 try attributes.addFnAttr(.optforfuzzing, &o.builder);
14921496 _ = try attributes.removeFnAttr(.skipprofile);
......@@ -1784,7 +1788,7 @@ pub const Object = struct {
17841788 .liveness = liveness,
17851789 .ng = &ng,
17861790 .wip = wip,
1787 .is_naked = fn_info.cc == .Naked,
1791 .is_naked = fn_info.cc == .naked,
17881792 .fuzz = fuzz,
17891793 .ret_ptr = ret_ptr,
17901794 .args = args.items,
......@@ -3038,14 +3042,33 @@ pub const Object = struct {
30383042 llvm_arg_i += 1;
30393043 }
30403044
3041 switch (fn_info.cc) {
3042 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),
3043 .Naked => try attributes.addFnAttr(.naked, &o.builder),
3044 .Async => {
3045 function_index.setCallConv(.fastcc, &o.builder);
3046 @panic("TODO: LLVM backend lower async function");
3047 },
3048 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
3045 if (fn_info.cc == .@"async") {
3046 @panic("TODO: LLVM backend lower async function");
3047 }
3048
3049 {
3050 const cc_info = toLlvmCallConv(fn_info.cc, target).?;
3051
3052 function_index.setCallConv(cc_info.llvm_cc, &o.builder);
3053
3054 if (cc_info.align_stack) {
3055 try attributes.addFnAttr(.{ .alignstack = .fromByteUnits(target.stackAlignment()) }, &o.builder);
3056 } else {
3057 _ = try attributes.removeFnAttr(.alignstack);
3058 }
3059
3060 if (cc_info.naked) {
3061 try attributes.addFnAttr(.naked, &o.builder);
3062 } else {
3063 _ = try attributes.removeFnAttr(.naked);
3064 }
3065
3066 for (0..cc_info.inreg_param_count) |param_idx| {
3067 try attributes.addParamAttr(param_idx, .inreg, &o.builder);
3068 }
3069 for (cc_info.inreg_param_count..std.math.maxInt(u2)) |param_idx| {
3070 _ = try attributes.removeParamAttr(param_idx, .inreg);
3071 }
30493072 }
30503073
30513074 if (resolved.alignment != .none)
......@@ -3061,7 +3084,7 @@ pub const Object = struct {
30613084 // suppress generation of the prologue and epilogue, and the prologue is where the
30623085 // frame pointer normally gets set up. At time of writing, this is the case for at
30633086 // least x86 and RISC-V.
3064 owner_mod.omit_frame_pointer or fn_info.cc == .Naked,
3087 owner_mod.omit_frame_pointer or fn_info.cc == .naked,
30653088 );
30663089
30673090 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
......@@ -4618,9 +4641,14 @@ pub const Object = struct {
46184641 if (!param_ty.isPtrLikeOptional(zcu) and !ptr_info.flags.is_allowzero) {
46194642 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
46204643 }
4621 if (fn_info.cc == .Interrupt) {
4622 const child_type = try lowerType(o, Type.fromInterned(ptr_info.child));
4623 try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder);
4644 switch (fn_info.cc) {
4645 else => {},
4646 .x86_64_interrupt,
4647 .x86_interrupt,
4648 => {
4649 const child_type = try lowerType(o, Type.fromInterned(ptr_info.child));
4650 try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder);
4651 },
46244652 }
46254653 if (ptr_info.flags.is_const) {
46264654 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
......@@ -5677,7 +5705,7 @@ pub const FuncGen = struct {
56775705 .always_tail => .musttail,
56785706 .async_kw, .no_async, .always_inline, .compile_time => unreachable,
56795707 },
5680 toLlvmCallConv(fn_info.cc, target),
5708 toLlvmCallConvTag(fn_info.cc, target).?,
56815709 try attributes.finish(&o.builder),
56825710 try o.lowerType(zig_fn_ty),
56835711 llvm_fn,
......@@ -5756,7 +5784,7 @@ pub const FuncGen = struct {
57565784 _ = try fg.wip.callIntrinsicAssumeCold();
57575785 _ = try fg.wip.call(
57585786 .normal,
5759 toLlvmCallConv(fn_info.cc, target),
5787 toLlvmCallConvTag(fn_info.cc, target).?,
57605788 .none,
57615789 panic_global.typeOf(&o.builder),
57625790 panic_global.toValue(&o.builder),
......@@ -11554,36 +11582,146 @@ fn toLlvmAtomicRmwBinOp(
1155411582 };
1155511583}
1155611584
11557fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) Builder.CallConv {
11558 return switch (cc) {
11559 .Unspecified, .Inline, .Async => .fastcc,
11560 .C, .Naked => .ccc,
11561 .Stdcall => .x86_stdcallcc,
11562 .Fastcall => .x86_fastcallcc,
11563 .Vectorcall => return switch (target.cpu.arch) {
11564 .x86, .x86_64 => .x86_vectorcallcc,
11565 .aarch64, .aarch64_be => .aarch64_vector_pcs,
11566 else => unreachable,
11567 },
11568 .Thiscall => .x86_thiscallcc,
11569 .APCS => .arm_apcscc,
11570 .AAPCS => .arm_aapcscc,
11571 .AAPCSVFP => .arm_aapcs_vfpcc,
11572 .Interrupt => return switch (target.cpu.arch) {
11573 .x86, .x86_64 => .x86_intrcc,
11574 .avr => .avr_intrcc,
11575 .msp430 => .msp430_intrcc,
11576 else => unreachable,
11577 },
11578 .Signal => .avr_signalcc,
11579 .SysV => .x86_64_sysvcc,
11580 .Win64 => .win64cc,
11581 .Kernel => return switch (target.cpu.arch) {
11582 .nvptx, .nvptx64 => .ptx_kernel,
11583 .amdgcn => .amdgpu_kernel,
11585const CallingConventionInfo = struct {
11586 /// The LLVM calling convention to use.
11587 llvm_cc: Builder.CallConv,
11588 /// Whether to use an `alignstack` attribute to forcibly re-align the stack pointer in the function's prologue.
11589 align_stack: bool,
11590 /// Whether the function needs a `naked` attribute.
11591 naked: bool,
11592 /// How many leading parameters to apply the `inreg` attribute to.
11593 inreg_param_count: u2 = 0,
11594};
11595
11596pub fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) ?CallingConventionInfo {
11597 const llvm_cc = toLlvmCallConvTag(cc, target) orelse return null;
11598 const incoming_stack_alignment: ?u64, const register_params: u2 = switch (cc) {
11599 inline else => |pl| switch (@TypeOf(pl)) {
11600 void => .{ null, 0 },
11601 std.builtin.CallingConvention.CommonOptions => .{ pl.incoming_stack_alignment, 0 },
11602 std.builtin.CallingConvention.X86RegparmOptions => .{ pl.incoming_stack_alignment, pl.register_params },
1158411603 else => unreachable,
1158511604 },
11586 .Vertex, .Fragment => unreachable,
11605 };
11606 return .{
11607 .llvm_cc = llvm_cc,
11608 .align_stack = if (incoming_stack_alignment) |a| need_align: {
11609 const normal_stack_align = target.stackAlignment();
11610 break :need_align a < normal_stack_align;
11611 } else false,
11612 .naked = cc == .naked,
11613 .inreg_param_count = register_params,
11614 };
11615}
11616fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: std.Target) ?Builder.CallConv {
11617 if (target.cCallingConvention()) |default_c| {
11618 if (cc_tag == default_c) {
11619 return .ccc;
11620 }
11621 }
11622 return switch (cc_tag) {
11623 .@"inline" => unreachable,
11624 .auto, .@"async" => .fastcc,
11625 .naked => .ccc,
11626 .x86_64_sysv => .x86_64_sysvcc,
11627 .x86_64_win => .win64cc,
11628 .x86_64_regcall_v3_sysv => if (target.cpu.arch == .x86_64 and target.os.tag != .windows)
11629 .x86_regcallcc
11630 else
11631 null,
11632 .x86_64_regcall_v4_win => if (target.cpu.arch == .x86_64 and target.os.tag == .windows)
11633 .x86_regcallcc // we use the "RegCallv4" module flag to make this correct
11634 else
11635 null,
11636 .x86_64_vectorcall => .x86_vectorcallcc,
11637 .x86_64_interrupt => .x86_intrcc,
11638 .x86_stdcall => .x86_stdcallcc,
11639 .x86_fastcall => .x86_fastcallcc,
11640 .x86_thiscall => .x86_thiscallcc,
11641 .x86_regcall_v3 => if (target.cpu.arch == .x86 and target.os.tag != .windows)
11642 .x86_regcallcc
11643 else
11644 null,
11645 .x86_regcall_v4_win => if (target.cpu.arch == .x86 and target.os.tag == .windows)
11646 .x86_regcallcc // we use the "RegCallv4" module flag to make this correct
11647 else
11648 null,
11649 .x86_vectorcall => .x86_vectorcallcc,
11650 .x86_interrupt => .x86_intrcc,
11651 .aarch64_vfabi => .aarch64_vector_pcs,
11652 .aarch64_vfabi_sve => .aarch64_sve_vector_pcs,
11653 .arm_apcs => .arm_apcscc,
11654 .arm_aapcs => .arm_aapcscc,
11655 .arm_aapcs_vfp => .arm_aapcs_vfpcc,
11656 .riscv64_lp64_v => .riscv_vectorcallcc,
11657 .riscv32_ilp32_v => .riscv_vectorcallcc,
11658 .avr_builtin => .avr_builtincc,
11659 .avr_signal => .avr_signalcc,
11660 .avr_interrupt => .avr_intrcc,
11661 .m68k_rtd => .m68k_rtdcc,
11662 .m68k_interrupt => .m68k_intrcc,
11663 .amdgcn_kernel => .amdgpu_kernel,
11664 .amdgcn_cs => .amdgpu_cs,
11665 .nvptx_device => .ptx_device,
11666 .nvptx_kernel => .ptx_kernel,
11667
11668 // All the calling conventions which LLVM does not have a general representation for.
11669 // Note that these are often still supported through the `cCallingConvention` path above via `ccc`.
11670 .x86_sysv,
11671 .x86_win,
11672 .x86_thiscall_mingw,
11673 .aarch64_aapcs,
11674 .aarch64_aapcs_darwin,
11675 .aarch64_aapcs_win,
11676 .arm_aapcs16_vfp,
11677 .arm_interrupt,
11678 .mips64_n64,
11679 .mips64_n32,
11680 .mips64_interrupt,
11681 .mips_o32,
11682 .mips_interrupt,
11683 .riscv64_lp64,
11684 .riscv64_interrupt,
11685 .riscv32_ilp32,
11686 .riscv32_interrupt,
11687 .sparc64_sysv,
11688 .sparc_sysv,
11689 .powerpc64_elf,
11690 .powerpc64_elf_altivec,
11691 .powerpc64_elf_v2,
11692 .powerpc_sysv,
11693 .powerpc_sysv_altivec,
11694 .powerpc_aix,
11695 .powerpc_aix_altivec,
11696 .wasm_watc,
11697 .arc_sysv,
11698 .avr_gnu,
11699 .bpf_std,
11700 .csky_sysv,
11701 .csky_interrupt,
11702 .hexagon_sysv,
11703 .hexagon_sysv_hvx,
11704 .lanai_sysv,
11705 .loongarch64_lp64,
11706 .loongarch32_ilp32,
11707 .m68k_sysv,
11708 .m68k_gnu,
11709 .msp430_eabi,
11710 .propeller1_sysv,
11711 .propeller2_sysv,
11712 .s390x_sysv,
11713 .s390x_sysv_vx,
11714 .ve_sysv,
11715 .xcore_xs1,
11716 .xcore_xs2,
11717 .xtensa_call0,
11718 .xtensa_windowed,
11719 .amdgcn_device,
11720 .spirv_device,
11721 .spirv_kernel,
11722 .spirv_fragment,
11723 .spirv_vertex,
11724 => null,
1158711725 };
1158811726}
1158911727
......@@ -11711,31 +11849,27 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe
1171111849 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false;
1171211850
1171311851 return switch (fn_info.cc) {
11714 .Unspecified, .Inline => returnTypeByRef(zcu, target, return_type),
11715 .C => switch (target.cpu.arch) {
11716 .mips, .mipsel => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11717 .memory, .i32_array => true,
11718 .byval => false,
11719 },
11720 .x86 => isByRef(return_type, zcu),
11721 .x86_64 => switch (target.os.tag) {
11722 .windows => x86_64_abi.classifyWindows(return_type, zcu) == .memory,
11723 else => firstParamSRetSystemV(return_type, zcu, target),
11724 },
11725 .wasm32 => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect,
11726 .aarch64, .aarch64_be => aarch64_c_abi.classifyType(return_type, zcu) == .memory,
11727 .arm, .armeb => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11728 .memory, .i64_array => true,
11729 .i32_array => |size| size != 1,
11730 .byval => false,
11731 },
11732 .riscv32, .riscv64 => riscv_c_abi.classifyType(return_type, zcu) == .memory,
11733 else => false, // TODO investigate C ABI for other architectures
11852 .auto => returnTypeByRef(zcu, target, return_type),
11853 .x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
11854 .x86_64_win => x86_64_abi.classifyWindows(return_type, zcu) == .memory,
11855 .x86_sysv, .x86_win => isByRef(return_type, zcu),
11856 .x86_stdcall => !isScalar(zcu, return_type),
11857 .wasm_watc => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect,
11858 .aarch64_aapcs,
11859 .aarch64_aapcs_darwin,
11860 .aarch64_aapcs_win,
11861 => aarch64_c_abi.classifyType(return_type, zcu) == .memory,
11862 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11863 .memory, .i64_array => true,
11864 .i32_array => |size| size != 1,
11865 .byval => false,
1173411866 },
11735 .SysV => firstParamSRetSystemV(return_type, zcu, target),
11736 .Win64 => x86_64_abi.classifyWindows(return_type, zcu) == .memory,
11737 .Stdcall => !isScalar(zcu, return_type),
11738 else => false,
11867 .riscv64_lp64, .riscv32_ilp32 => riscv_c_abi.classifyType(return_type, zcu) == .memory,
11868 .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11869 .memory, .i32_array => true,
11870 .byval => false,
11871 },
11872 else => false, // TODO: investigate other targets/callconvs
1173911873 };
1174011874}
1174111875
......@@ -11761,82 +11895,64 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
1176111895 }
1176211896 const target = zcu.getTarget();
1176311897 switch (fn_info.cc) {
11764 .Unspecified,
11765 .Inline,
11766 => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type),
11767
11768 .C => {
11769 switch (target.cpu.arch) {
11770 .mips, .mipsel => {
11771 switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11772 .memory, .i32_array => return .void,
11773 .byval => return o.lowerType(return_type),
11774 }
11775 },
11776 .x86 => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type),
11777 .x86_64 => switch (target.os.tag) {
11778 .windows => return lowerWin64FnRetTy(o, fn_info),
11779 else => return lowerSystemVFnRetTy(o, fn_info),
11780 },
11781 .wasm32 => {
11782 if (isScalar(zcu, return_type)) {
11783 return o.lowerType(return_type);
11784 }
11785 const classes = wasm_c_abi.classifyType(return_type, zcu);
11786 if (classes[0] == .indirect or classes[0] == .none) {
11787 return .void;
11788 }
11789
11790 assert(classes[0] == .direct and classes[1] == .none);
11791 const scalar_type = wasm_c_abi.scalarType(return_type, zcu);
11792 return o.builder.intType(@intCast(scalar_type.abiSize(zcu) * 8));
11793 },
11794 .aarch64, .aarch64_be => {
11795 switch (aarch64_c_abi.classifyType(return_type, zcu)) {
11796 .memory => return .void,
11797 .float_array => return o.lowerType(return_type),
11798 .byval => return o.lowerType(return_type),
11799 .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))),
11800 .double_integer => return o.builder.arrayType(2, .i64),
11801 }
11802 },
11803 .arm, .armeb => {
11804 switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11805 .memory, .i64_array => return .void,
11806 .i32_array => |len| return if (len == 1) .i32 else .void,
11807 .byval => return o.lowerType(return_type),
11808 }
11809 },
11810 .riscv32, .riscv64 => {
11811 switch (riscv_c_abi.classifyType(return_type, zcu)) {
11812 .memory => return .void,
11813 .integer => {
11814 return o.builder.intType(@intCast(return_type.bitSize(zcu)));
11815 },
11816 .double_integer => {
11817 return o.builder.structType(.normal, &.{ .i64, .i64 });
11818 },
11819 .byval => return o.lowerType(return_type),
11820 .fields => {
11821 var types_len: usize = 0;
11822 var types: [8]Builder.Type = undefined;
11823 for (0..return_type.structFieldCount(zcu)) |field_index| {
11824 const field_ty = return_type.fieldType(field_index, zcu);
11825 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11826 types[types_len] = try o.lowerType(field_ty);
11827 types_len += 1;
11828 }
11829 return o.builder.structType(.normal, types[0..types_len]);
11830 },
11831 }
11832 },
11833 // TODO investigate C ABI for other architectures
11834 else => return o.lowerType(return_type),
11898 .@"inline" => unreachable,
11899 .auto => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type),
11900
11901 .x86_64_sysv => return lowerSystemVFnRetTy(o, fn_info),
11902 .x86_64_win => return lowerWin64FnRetTy(o, fn_info),
11903 .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void,
11904 .x86_sysv, .x86_win => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type),
11905 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(return_type, zcu)) {
11906 .memory => return .void,
11907 .float_array => return o.lowerType(return_type),
11908 .byval => return o.lowerType(return_type),
11909 .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))),
11910 .double_integer => return o.builder.arrayType(2, .i64),
11911 },
11912 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11913 .memory, .i64_array => return .void,
11914 .i32_array => |len| return if (len == 1) .i32 else .void,
11915 .byval => return o.lowerType(return_type),
11916 },
11917 .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11918 .memory, .i32_array => return .void,
11919 .byval => return o.lowerType(return_type),
11920 },
11921 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(return_type, zcu)) {
11922 .memory => return .void,
11923 .integer => {
11924 return o.builder.intType(@intCast(return_type.bitSize(zcu)));
11925 },
11926 .double_integer => {
11927 return o.builder.structType(.normal, &.{ .i64, .i64 });
11928 },
11929 .byval => return o.lowerType(return_type),
11930 .fields => {
11931 var types_len: usize = 0;
11932 var types: [8]Builder.Type = undefined;
11933 for (0..return_type.structFieldCount(zcu)) |field_index| {
11934 const field_ty = return_type.fieldType(field_index, zcu);
11935 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11936 types[types_len] = try o.lowerType(field_ty);
11937 types_len += 1;
11938 }
11939 return o.builder.structType(.normal, types[0..types_len]);
11940 },
11941 },
11942 .wasm_watc => {
11943 if (isScalar(zcu, return_type)) {
11944 return o.lowerType(return_type);
11945 }
11946 const classes = wasm_c_abi.classifyType(return_type, zcu);
11947 if (classes[0] == .indirect or classes[0] == .none) {
11948 return .void;
1183511949 }
11950
11951 assert(classes[0] == .direct and classes[1] == .none);
11952 const scalar_type = wasm_c_abi.scalarType(return_type, zcu);
11953 return o.builder.intType(@intCast(scalar_type.abiSize(zcu) * 8));
1183611954 },
11837 .Win64 => return lowerWin64FnRetTy(o, fn_info),
11838 .SysV => return lowerSystemVFnRetTy(o, fn_info),
11839 .Stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void,
11955 // TODO investigate other callconvs
1184011956 else => return o.lowerType(return_type),
1184111957 }
1184211958}
......@@ -11989,7 +12105,8 @@ const ParamTypeIterator = struct {
1198912105 return .no_bits;
1199012106 }
1199112107 switch (it.fn_info.cc) {
11992 .Unspecified, .Inline => {
12108 .@"inline" => unreachable,
12109 .auto => {
1199312110 it.zig_index += 1;
1199412111 it.llvm_index += 1;
1199512112 if (ty.isSlice(zcu) or
......@@ -12010,97 +12127,12 @@ const ParamTypeIterator = struct {
1201012127 return .byval;
1201112128 }
1201212129 },
12013 .Async => {
12130 .@"async" => {
1201412131 @panic("TODO implement async function lowering in the LLVM backend");
1201512132 },
12016 .C => switch (target.cpu.arch) {
12017 .mips, .mipsel => {
12018 it.zig_index += 1;
12019 it.llvm_index += 1;
12020 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
12021 .memory => {
12022 it.byval_attr = true;
12023 return .byref;
12024 },
12025 .byval => return .byval,
12026 .i32_array => |size| return Lowering{ .i32_array = size },
12027 }
12028 },
12029 .x86_64 => switch (target.os.tag) {
12030 .windows => return it.nextWin64(ty),
12031 else => return it.nextSystemV(ty),
12032 },
12033 .wasm32 => {
12034 it.zig_index += 1;
12035 it.llvm_index += 1;
12036 if (isScalar(zcu, ty)) {
12037 return .byval;
12038 }
12039 const classes = wasm_c_abi.classifyType(ty, zcu);
12040 if (classes[0] == .indirect) {
12041 return .byref;
12042 }
12043 return .abi_sized_int;
12044 },
12045 .aarch64, .aarch64_be => {
12046 it.zig_index += 1;
12047 it.llvm_index += 1;
12048 switch (aarch64_c_abi.classifyType(ty, zcu)) {
12049 .memory => return .byref_mut,
12050 .float_array => |len| return Lowering{ .float_array = len },
12051 .byval => return .byval,
12052 .integer => {
12053 it.types_len = 1;
12054 it.types_buffer[0] = .i64;
12055 return .multiple_llvm_types;
12056 },
12057 .double_integer => return Lowering{ .i64_array = 2 },
12058 }
12059 },
12060 .arm, .armeb => {
12061 it.zig_index += 1;
12062 it.llvm_index += 1;
12063 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
12064 .memory => {
12065 it.byval_attr = true;
12066 return .byref;
12067 },
12068 .byval => return .byval,
12069 .i32_array => |size| return Lowering{ .i32_array = size },
12070 .i64_array => |size| return Lowering{ .i64_array = size },
12071 }
12072 },
12073 .riscv32, .riscv64 => {
12074 it.zig_index += 1;
12075 it.llvm_index += 1;
12076 switch (riscv_c_abi.classifyType(ty, zcu)) {
12077 .memory => return .byref_mut,
12078 .byval => return .byval,
12079 .integer => return .abi_sized_int,
12080 .double_integer => return Lowering{ .i64_array = 2 },
12081 .fields => {
12082 it.types_len = 0;
12083 for (0..ty.structFieldCount(zcu)) |field_index| {
12084 const field_ty = ty.fieldType(field_index, zcu);
12085 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
12086 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty);
12087 it.types_len += 1;
12088 }
12089 it.llvm_index += it.types_len - 1;
12090 return .multiple_llvm_types;
12091 },
12092 }
12093 },
12094 // TODO investigate C ABI for other architectures
12095 else => {
12096 it.zig_index += 1;
12097 it.llvm_index += 1;
12098 return .byval;
12099 },
12100 },
12101 .Win64 => return it.nextWin64(ty),
12102 .SysV => return it.nextSystemV(ty),
12103 .Stdcall => {
12133 .x86_64_sysv => return it.nextSystemV(ty),
12134 .x86_64_win => return it.nextWin64(ty),
12135 .x86_stdcall => {
1210412136 it.zig_index += 1;
1210512137 it.llvm_index += 1;
1210612138
......@@ -12111,6 +12143,80 @@ const ParamTypeIterator = struct {
1211112143 return .byref;
1211212144 }
1211312145 },
12146 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
12147 it.zig_index += 1;
12148 it.llvm_index += 1;
12149 switch (aarch64_c_abi.classifyType(ty, zcu)) {
12150 .memory => return .byref_mut,
12151 .float_array => |len| return Lowering{ .float_array = len },
12152 .byval => return .byval,
12153 .integer => {
12154 it.types_len = 1;
12155 it.types_buffer[0] = .i64;
12156 return .multiple_llvm_types;
12157 },
12158 .double_integer => return Lowering{ .i64_array = 2 },
12159 }
12160 },
12161 .arm_aapcs, .arm_aapcs_vfp => {
12162 it.zig_index += 1;
12163 it.llvm_index += 1;
12164 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
12165 .memory => {
12166 it.byval_attr = true;
12167 return .byref;
12168 },
12169 .byval => return .byval,
12170 .i32_array => |size| return Lowering{ .i32_array = size },
12171 .i64_array => |size| return Lowering{ .i64_array = size },
12172 }
12173 },
12174 .mips_o32 => {
12175 it.zig_index += 1;
12176 it.llvm_index += 1;
12177 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
12178 .memory => {
12179 it.byval_attr = true;
12180 return .byref;
12181 },
12182 .byval => return .byval,
12183 .i32_array => |size| return Lowering{ .i32_array = size },
12184 }
12185 },
12186 .riscv64_lp64, .riscv32_ilp32 => {
12187 it.zig_index += 1;
12188 it.llvm_index += 1;
12189 switch (riscv_c_abi.classifyType(ty, zcu)) {
12190 .memory => return .byref_mut,
12191 .byval => return .byval,
12192 .integer => return .abi_sized_int,
12193 .double_integer => return Lowering{ .i64_array = 2 },
12194 .fields => {
12195 it.types_len = 0;
12196 for (0..ty.structFieldCount(zcu)) |field_index| {
12197 const field_ty = ty.fieldType(field_index, zcu);
12198 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
12199 it.types_buffer[it.types_len] = try it.object.lowerType(field_ty);
12200 it.types_len += 1;
12201 }
12202 it.llvm_index += it.types_len - 1;
12203 return .multiple_llvm_types;
12204 },
12205 }
12206 },
12207 .wasm_watc => {
12208 it.zig_index += 1;
12209 it.llvm_index += 1;
12210 if (isScalar(zcu, ty)) {
12211 return .byval;
12212 }
12213 const classes = wasm_c_abi.classifyType(ty, zcu);
12214 if (classes[0] == .indirect) {
12215 return .byref;
12216 }
12217 return .abi_sized_int;
12218 },
12219 // TODO investigate other callconvs
1211412220 else => {
1211512221 it.zig_index += 1;
1211612222 it.llvm_index += 1;
......@@ -12269,7 +12375,7 @@ fn ccAbiPromoteInt(
1226912375) ?std.builtin.Signedness {
1227012376 const target = zcu.getTarget();
1227112377 switch (cc) {
12272 .Unspecified, .Inline, .Async => return null,
12378 .auto, .@"inline", .@"async" => return null,
1227312379 else => {},
1227412380 }
1227512381 const int_info = switch (ty.zigTypeTag(zcu)) {
src/codegen/llvm/Builder.zig+13
......@@ -2052,6 +2052,7 @@ pub const CallConv = enum(u10) {
20522052 x86_intrcc,
20532053 avr_intrcc,
20542054 avr_signalcc,
2055 avr_builtincc,
20552056
20562057 amdgpu_vs = 87,
20572058 amdgpu_gs,
......@@ -2060,6 +2061,7 @@ pub const CallConv = enum(u10) {
20602061 amdgpu_kernel,
20612062 x86_regcallcc,
20622063 amdgpu_hs,
2064 msp430_builtincc,
20632065
20642066 amdgpu_ls = 95,
20652067 amdgpu_es,
......@@ -2068,9 +2070,15 @@ pub const CallConv = enum(u10) {
20682070
20692071 amdgpu_gfx = 100,
20702072
2073 m68k_intrcc,
2074
20712075 aarch64_sme_preservemost_from_x0 = 102,
20722076 aarch64_sme_preservemost_from_x2,
20732077
2078 m68k_rtdcc = 106,
2079
2080 riscv_vectorcallcc = 110,
2081
20742082 _,
20752083
20762084 pub const default = CallConv.ccc;
......@@ -2115,6 +2123,7 @@ pub const CallConv = enum(u10) {
21152123 .x86_intrcc,
21162124 .avr_intrcc,
21172125 .avr_signalcc,
2126 .avr_builtincc,
21182127 .amdgpu_vs,
21192128 .amdgpu_gs,
21202129 .amdgpu_ps,
......@@ -2122,13 +2131,17 @@ pub const CallConv = enum(u10) {
21222131 .amdgpu_kernel,
21232132 .x86_regcallcc,
21242133 .amdgpu_hs,
2134 .msp430_builtincc,
21252135 .amdgpu_ls,
21262136 .amdgpu_es,
21272137 .aarch64_vector_pcs,
21282138 .aarch64_sve_vector_pcs,
21292139 .amdgpu_gfx,
2140 .m68k_intrcc,
21302141 .aarch64_sme_preservemost_from_x0,
21312142 .aarch64_sme_preservemost_from_x2,
2143 .m68k_rtdcc,
2144 .riscv_vectorcallcc,
21322145 => try writer.print(" {s}", .{@tagName(self)}),
21332146 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
21342147 }
src/codegen/spirv.zig+3-3
......@@ -1640,8 +1640,8 @@ const NavGen = struct {
16401640
16411641 comptime assert(zig_call_abi_ver == 3);
16421642 switch (fn_info.cc) {
1643 .Unspecified, .Kernel, .Fragment, .Vertex, .C => {},
1644 else => unreachable, // TODO
1643 .auto, .spirv_kernel, .spirv_fragment, .spirv_vertex => {},
1644 else => @panic("TODO"),
16451645 }
16461646
16471647 // TODO: Put this somewhere in Sema.zig
......@@ -2970,7 +2970,7 @@ const NavGen = struct {
29702970 .id_result_type = return_ty_id,
29712971 .id_result = result_id,
29722972 .function_control = switch (fn_info.cc) {
2973 .Inline => .{ .Inline = true },
2973 .@"inline" => .{ .Inline = true },
29742974 else => .{},
29752975 },
29762976 .function_type = prototype_ty_id,
src/link/C.zig+1-1
......@@ -217,7 +217,7 @@ pub fn updateFunc(
217217 .mod = zcu.navFileScope(func.owner_nav).mod,
218218 .error_msg = null,
219219 .pass = .{ .nav = func.owner_nav },
220 .is_naked_fn = zcu.navValue(func.owner_nav).typeOf(zcu).fnCallingConvention(zcu) == .Naked,
220 .is_naked_fn = zcu.navValue(func.owner_nav).typeOf(zcu).fnCallingConvention(zcu) == .naked,
221221 .fwd_decl = fwd_decl.toManaged(gpa),
222222 .ctype_pool = ctype_pool.*,
223223 .scratch = .{},
src/link/Coff.zig+6-4
......@@ -1488,14 +1488,16 @@ pub fn updateExports(
14881488 const exported_nav = ip.getNav(exported_nav_index);
14891489 const exported_ty = exported_nav.typeOf(ip);
14901490 if (!ip.isFunctionType(exported_ty)) continue;
1491 const c_cc = target.cCallingConvention().?;
14911492 const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
1492 .x86 => .Stdcall,
1493 else => .C,
1493 .x86 => .{ .x86_stdcall = .{} },
1494 else => c_cc,
14941495 };
14951496 const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);
1496 if (exported_cc == .C and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
1497 const CcTag = std.builtin.CallingConvention.Tag;
1498 if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
14971499 zcu.stage1_flags.have_c_main = true;
1498 } else if (exported_cc == winapi_cc and target.os.tag == .windows) {
1500 } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) {
14991501 if (exp.opts.name.eqlSlice("WinMain", ip)) {
15001502 zcu.stage1_flags.have_winmain = true;
15011503 } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
src/link/Dwarf.zig+65-15
......@@ -3398,21 +3398,71 @@ fn updateType(
33983398 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
33993399 try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);
34003400 try wip_nav.strp(name);
3401 try diw.writeByte(@intFromEnum(@as(DW.CC, switch (func_type.cc) {
3402 .Unspecified, .C => .normal,
3403 .Naked, .Async, .Inline => .nocall,
3404 .Interrupt, .Signal => .nocall,
3405 .Stdcall => .BORLAND_stdcall,
3406 .Fastcall => .BORLAND_fastcall,
3407 .Vectorcall => .LLVM_vectorcall,
3408 .Thiscall => .BORLAND_thiscall,
3409 .APCS => .nocall,
3410 .AAPCS => .LLVM_AAPCS,
3411 .AAPCSVFP => .LLVM_AAPCS_VFP,
3412 .SysV => .LLVM_X86_64SysV,
3413 .Win64 => .LLVM_Win64,
3414 .Kernel, .Fragment, .Vertex => .nocall,
3415 })));
3401 const cc: DW.CC = cc: {
3402 if (zcu.getTarget().cCallingConvention()) |cc| {
3403 if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) {
3404 break :cc .normal;
3405 }
3406 }
3407 // For better or worse, we try to match what Clang emits.
3408 break :cc switch (func_type.cc) {
3409 .@"inline" => unreachable,
3410 .@"async", .auto, .naked => .normal,
3411 .x86_64_sysv => .LLVM_X86_64SysV,
3412 .x86_64_win => .LLVM_Win64,
3413 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
3414 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
3415 .x86_64_vectorcall => .LLVM_vectorcall,
3416 .x86_sysv => .nocall,
3417 .x86_win => .nocall,
3418 .x86_stdcall => .BORLAND_stdcall,
3419 .x86_fastcall => .BORLAND_msfastcall,
3420 .x86_thiscall => .BORLAND_thiscall,
3421 .x86_thiscall_mingw => .BORLAND_thiscall,
3422 .x86_regcall_v3 => .LLVM_X86RegCall,
3423 .x86_regcall_v4_win => .LLVM_X86RegCall,
3424 .x86_vectorcall => .LLVM_vectorcall,
3425
3426 .aarch64_aapcs => .LLVM_AAPCS,
3427 .aarch64_aapcs_darwin => .LLVM_AAPCS,
3428 .aarch64_aapcs_win => .LLVM_AAPCS,
3429 .aarch64_vfabi => .LLVM_AAPCS,
3430 .aarch64_vfabi_sve => .LLVM_AAPCS,
3431
3432 .arm_apcs => .nocall,
3433 .arm_aapcs => .LLVM_AAPCS,
3434 .arm_aapcs_vfp => .LLVM_AAPCS_VFP,
3435 .arm_aapcs16_vfp => .nocall,
3436
3437 .riscv64_lp64_v,
3438 .riscv32_ilp32_v,
3439 => .LLVM_RISCVVectorCall,
3440
3441 .m68k_rtd => .LLVM_M68kRTD,
3442
3443 .amdgcn_kernel,
3444 .nvptx_kernel,
3445 .spirv_kernel,
3446 => .LLVM_OpenCLKernel,
3447
3448 .x86_64_interrupt,
3449 .x86_interrupt,
3450 .arm_interrupt,
3451 .mips64_interrupt,
3452 .mips_interrupt,
3453 .riscv64_interrupt,
3454 .riscv32_interrupt,
3455 .avr_builtin,
3456 .avr_signal,
3457 .avr_interrupt,
3458 .csky_interrupt,
3459 .m68k_interrupt,
3460 => .normal,
3461
3462 else => .nocall,
3463 };
3464 };
3465 try diw.writeByte(@intFromEnum(cc));
34163466 try wip_nav.refType(Type.fromInterned(func_type.return_type));
34173467 for (0..func_type.param_types.len) |param_index| {
34183468 try wip_nav.abbrevCode(.func_type_param);
src/link/SpirV.zig+3-4
......@@ -165,10 +165,9 @@ pub fn updateExports(
165165 const target = zcu.getTarget();
166166 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
167167 const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) {
168 .Vertex => spec.ExecutionModel.Vertex,
169 .Fragment => spec.ExecutionModel.Fragment,
170 .Kernel => spec.ExecutionModel.Kernel,
171 .C => return, // TODO: What to do here?
168 .spirv_vertex => spec.ExecutionModel.Vertex,
169 .spirv_fragment => spec.ExecutionModel.Fragment,
170 .spirv_kernel => spec.ExecutionModel.Kernel,
172171 else => unreachable,
173172 };
174173 const is_vulkan = target.os.tag == .vulkan;
src/print_zir.zig-1
......@@ -567,7 +567,6 @@ const Writer = struct {
567567 .c_undef,
568568 .c_include,
569569 .set_float_mode,
570 .set_align_stack,
571570 .wasm_memory_size,
572571 .int_from_error,
573572 .error_from_int,
src/target.zig+3-3
......@@ -544,13 +544,13 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
544544 };
545545}
546546
547pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConvention) bool {
547pub fn fnCallConvAllowsZigTypes(cc: std.builtin.CallingConvention) bool {
548548 return switch (cc) {
549 .Unspecified, .Async, .Inline => true,
549 .auto, .@"async", .@"inline" => true,
550550 // For now we want to authorize PTX kernel to use zig objects, even if
551551 // we end up exposing the ABI. The goal is to experiment with more
552552 // integrated CPU/GPU code.
553 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,
553 .nvptx_kernel => true,
554554 else => false,
555555 };
556556}
src/translate_c.zig+16-14
......@@ -4,7 +4,6 @@ const assert = std.debug.assert;
44const mem = std.mem;
55const math = std.math;
66const meta = std.meta;
7const CallingConvention = std.builtin.CallingConvention;
87const clang = @import("clang.zig");
98const aro = @import("aro");
109const CToken = aro.Tokenizer.Token;
......@@ -5001,17 +5000,20 @@ fn transCC(
50015000 c: *Context,
50025001 fn_ty: *const clang.FunctionType,
50035002 source_loc: clang.SourceLocation,
5004) !CallingConvention {
5003) !ast.Payload.Func.CallingConvention {
50055004 const clang_cc = fn_ty.getCallConv();
5006 switch (clang_cc) {
5007 .C => return CallingConvention.C,
5008 .X86StdCall => return CallingConvention.Stdcall,
5009 .X86FastCall => return CallingConvention.Fastcall,
5010 .X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall,
5011 .X86ThisCall => return CallingConvention.Thiscall,
5012 .AAPCS => return CallingConvention.AAPCS,
5013 .AAPCS_VFP => return CallingConvention.AAPCSVFP,
5014 .X86_64SysV => return CallingConvention.SysV,
5005 return switch (clang_cc) {
5006 .C => .c,
5007 .X86_64SysV => .x86_64_sysv,
5008 .Win64 => .x86_64_win,
5009 .X86StdCall => .x86_stdcall,
5010 .X86FastCall => .x86_fastcall,
5011 .X86ThisCall => .x86_thiscall,
5012 .X86VectorCall => .x86_vectorcall,
5013 .AArch64VectorCall => .aarch64_vfabi,
5014 .AAPCS => .arm_aapcs,
5015 .AAPCS_VFP => .arm_aapcs_vfp,
5016 .M68kRTD => .m68k_rtd,
50155017 else => return fail(
50165018 c,
50175019 error.UnsupportedType,
......@@ -5019,7 +5021,7 @@ fn transCC(
50195021 "unsupported calling convention: {s}",
50205022 .{@tagName(clang_cc)},
50215023 ),
5022 }
5024 };
50235025}
50245026
50255027fn transFnProto(
......@@ -5056,7 +5058,7 @@ fn finishTransFnProto(
50565058 source_loc: clang.SourceLocation,
50575059 fn_decl_context: ?FnDeclContext,
50585060 is_var_args: bool,
5059 cc: CallingConvention,
5061 cc: ast.Payload.Func.CallingConvention,
50605062 is_pub: bool,
50615063) !*ast.Payload.Func {
50625064 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
......@@ -5104,7 +5106,7 @@ fn finishTransFnProto(
51045106
51055107 const alignment = if (fn_decl) |decl| ClangAlignment.forFunc(c, decl).zigAlignment() else null;
51065108
5107 const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .C) null else cc;
5109 const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .c) null else cc;
51085110
51095111 const return_type_node = blk: {
51105112 if (fn_ty.getNoReturnAttr()) {
stage1/zig.h+35-25
......@@ -248,37 +248,55 @@ typedef char bool;
248248
249249#if zig_has_builtin(trap)
250250#define zig_trap() __builtin_trap()
251#elif _MSC_VER && (_M_IX86 || _M_X64)
251#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
252252#define zig_trap() __ud2()
253#elif _MSC_VER
254#define zig_trap() __fastfail(0)
255#elif defined(__i386__) || defined(__x86_64__)
256#define zig_trap() __asm__ volatile("ud2");
253#elif defined(_MSC_VER)
254#define zig_trap() __fastfail(7)
255#elif defined(__thumb__)
256#define zig_trap() __asm__ volatile("udf #0xfe")
257257#elif defined(__arm__) || defined(__aarch64__)
258#define zig_trap() __asm__ volatile("udf #0");
258#define zig_trap() __asm__ volatile("udf #0xfdee")
259#elif defined(__loongarch__) || defined(__powerpc__)
260#define zig_trap() __asm__ volatile(".word 0x0")
261#elif defined(__mips__)
262#define zig_trap() __asm__ volatile(".word 0x3d")
263#elif defined(__riscv)
264#define zig_trap() __asm__ volatile("unimp")
265#elif defined(__s390__)
266#define zig_trap() __asm__ volatile("j 0x2")
267#elif defined(__sparc__)
268#define zig_trap() __asm__ volatile("illtrap")
269#elif defined(__i386__) || defined(__x86_64__)
270#define zig_trap() __asm__ volatile("ud2")
259271#else
260#include <stdlib.h>
261#define zig_trap() abort()
272#define zig_trap() zig_trap_unavailable
262273#endif
263274
264275#if zig_has_builtin(debugtrap)
265276#define zig_breakpoint() __builtin_debugtrap()
266277#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
267278#define zig_breakpoint() __debugbreak()
268#elif defined(__i386__) || defined(__x86_64__)
269#define zig_breakpoint() __asm__ volatile("int $0x03");
270279#elif defined(__arm__)
271#define zig_breakpoint() __asm__ volatile("bkpt #0");
280#define zig_breakpoint() __asm__ volatile("bkpt #0x0")
272281#elif defined(__aarch64__)
273#define zig_breakpoint() __asm__ volatile("brk #0");
274#else
275#include <signal.h>
276#if defined(SIGTRAP)
277#define zig_breakpoint() raise(SIGTRAP)
282#define zig_breakpoint() __asm__ volatile("brk #0xf000")
283#elif defined(__loongarch__)
284#define zig_breakpoint() __asm__ volatile("break 0x0")
285#elif defined(__mips__)
286#define zig_breakpoint() __asm__ volatile("break")
287#elif defined(__powerpc__)
288#define zig_breakpoint() __asm__ volatile("trap")
289#elif defined(__riscv)
290#define zig_breakpoint() __asm__ volatile("ebreak")
291#elif defined(__s390__)
292#define zig_breakpoint() __asm__ volatile("j 0x6")
293#elif defined(__sparc__)
294#define zig_breakpoint() __asm__ volatile("ta 0x1")
295#elif defined(__i386__) || defined(__x86_64__)
296#define zig_breakpoint() __asm__ volatile("int $0x3")
278297#else
279298#define zig_breakpoint() zig_breakpoint_unavailable
280299#endif
281#endif
282300
283301#if zig_has_builtin(return_address) || defined(zig_gnuc)
284302#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
......@@ -3592,7 +3610,6 @@ typedef enum memory_order zig_memory_order;
35923610#define zig_atomicrmw_add_float zig_atomicrmw_add
35933611#undef zig_atomicrmw_sub_float
35943612#define zig_atomicrmw_sub_float zig_atomicrmw_sub
3595#define zig_fence(order) atomic_thread_fence(order)
35963613#elif defined(__GNUC__)
35973614typedef int zig_memory_order;
35983615#define zig_memory_order_relaxed __ATOMIC_RELAXED
......@@ -3616,7 +3633,6 @@ typedef int zig_memory_order;
36163633#define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order)
36173634#undef zig_atomicrmw_xchg_float
36183635#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
3619#define zig_fence(order) __atomic_thread_fence(order)
36203636#elif _MSC_VER && (_M_IX86 || _M_X64)
36213637#define zig_memory_order_relaxed 0
36223638#define zig_memory_order_acquire 2
......@@ -3637,11 +3653,6 @@ typedef int zig_memory_order;
36373653#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg)
36383654#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg)
36393655#define zig_atomic_load(res, obj, order, Type, ReprType) res = zig_msvc_atomic_load_ ##order##_##Type(obj)
3640#if _M_X64
3641#define zig_fence(order) __faststorefence()
3642#else
3643#define zig_fence(order) zig_msvc_atomic_barrier()
3644#endif
36453656/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */
36463657#else
36473658#define zig_memory_order_relaxed 0
......@@ -3663,7 +3674,6 @@ typedef int zig_memory_order;
36633674#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
36643675#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable
36653676#define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable
3666#define zig_fence(order) zig_fence_unavailable
36673677#endif
36683678
36693679#if _MSC_VER && (_M_IX86 || _M_X64)
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/behavior/align.zig-9
......@@ -210,15 +210,6 @@ test "alignment and size of structs with 128-bit fields" {
210210 }
211211}
212212
213test "alignstack" {
214 try expect(fnWithAlignedStack() == 1234);
215}
216
217fn fnWithAlignedStack() i32 {
218 @setAlignStack(256);
219 return 1234;
220}
221
222213test "implicitly decreasing slice alignment" {
223214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
224215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1
......@@ -20,7 +20,6 @@ test {
2020 try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined));
2121 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
2222 try testing.expectEqual({}, @prefetch(&val, .{}));
23 try testing.expectEqual({}, @setAlignStack(16));
2423 try testing.expectEqual({}, @setEvalBranchQuota(0));
2524 try testing.expectEqual({}, @setFloatMode(.optimized));
2625 try testing.expectEqual({}, @setRuntimeSafety(true));
test/behavior/type_info.zig+5-4
......@@ -350,6 +350,7 @@ fn testOpaque() !void {
350350
351351test "type info: function type info" {
352352 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
353 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
353354
354355 try testFunction();
355356 try comptime testFunction();
......@@ -358,7 +359,7 @@ test "type info: function type info" {
358359fn testFunction() !void {
359360 const foo_fn_type = @TypeOf(typeInfoFoo);
360361 const foo_fn_info = @typeInfo(foo_fn_type);
361 try expect(foo_fn_info.@"fn".calling_convention == .C);
362 try expect(foo_fn_info.@"fn".calling_convention.eql(.c));
362363 try expect(!foo_fn_info.@"fn".is_generic);
363364 try expect(foo_fn_info.@"fn".params.len == 2);
364365 try expect(foo_fn_info.@"fn".is_var_args);
......@@ -374,7 +375,7 @@ fn testFunction() !void {
374375
375376 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
376377 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
377 try expect(aligned_foo_fn_info.@"fn".calling_convention == .C);
378 try expect(aligned_foo_fn_info.@"fn".calling_convention.eql(.c));
378379 try expect(!aligned_foo_fn_info.@"fn".is_generic);
379380 try expect(aligned_foo_fn_info.@"fn".params.len == 2);
380381 try expect(aligned_foo_fn_info.@"fn".is_var_args);
......@@ -390,8 +391,8 @@ fn testFunction() !void {
390391 try expect(aligned_foo_ptr_fn_info.pointer.sentinel == null);
391392}
392393
393extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;
394extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
394extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.c) usize;
395extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.c) usize;
395396
396397test "type info: generic function types" {
397398 const G1 = @typeInfo(@TypeOf(generic1));
test/behavior/typename.zig+3-3
......@@ -79,9 +79,9 @@ test "basic" {
7979 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
8080 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
8181
82 try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () callconv(.C) void));
83 try expectEqualStrings("fn (...) callconv(.C) void", @typeName(fn (...) callconv(.C) void));
84 try expectEqualStrings("fn (u32, ...) callconv(.C) void", @typeName(fn (u32, ...) callconv(.C) void));
82 try expectEqualStrings("fn () callconv(.c) void", @typeName(fn () callconv(.c) void));
83 try expectEqualStrings("fn (...) callconv(.c) void", @typeName(fn (...) callconv(.c) void));
84 try expectEqualStrings("fn (u32, ...) callconv(.c) void", @typeName(fn (u32, ...) callconv(.c) void));
8585}
8686
8787test "top level decl" {
test/cases/compile_errors/array_in_c_exported_function.zig+3-4
......@@ -7,10 +7,9 @@ export fn zig_return_array() [10]u8 {
77}
88
99// error
10// backend=stage2
11// target=native
10// target=x86_64-linux
1211//
13// :1:21: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
12// :1:21: error: parameter of type '[10]u8' not allowed in function with calling convention 'x86_64_sysv'
1413// :1:21: note: arrays are not allowed as a parameter type
15// :5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
14// :5:30: error: return type '[10]u8' not allowed in function with calling convention 'x86_64_sysv'
1615// :5:30: note: arrays are not allowed as a return type
test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig+1-1
......@@ -8,5 +8,5 @@ inline fn b() void {}
88// backend=stage2
99// target=native
1010//
11// :2:9: error: variable of type '*const fn () callconv(.Inline) void' must be const or comptime
11// :2:9: error: variable of type '*const fn () callconv(.@"inline") void' must be const or comptime
1212// :2:9: note: function has inline calling convention
test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig+1-1
......@@ -1,7 +1,7 @@
11const Foo = packed struct(u32) {
22 x: u1,
33};
4fn bar(_: Foo) callconv(.C) void {}
4fn bar(_: Foo) callconv(.c) void {}
55pub export fn entry() void {
66 bar(.{ .x = 0 });
77}
test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig+3-4
......@@ -3,9 +3,8 @@ export fn entry2() callconv(.AAPCS) void {}
33export fn entry3() callconv(.AAPCSVFP) void {}
44
55// error
6// backend=stage2
76// target=x86_64-linux-none
87//
9// :1:30: error: callconv 'APCS' is only available on ARM, not x86_64
10// :2:30: error: callconv 'AAPCS' is only available on ARM, not x86_64
11// :3:30: error: callconv 'AAPCSVFP' is only available on ARM, not x86_64
8// :1:30: error: calling convention 'arm_apcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb'
9// :2:30: error: calling convention 'arm_aapcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb'
10// :3:30: error: calling convention 'arm_aapcs_vfp' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb'
test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig+1-1
......@@ -4,4 +4,4 @@ export fn entry() callconv(.Interrupt) void {}
44// backend=stage2
55// target=aarch64-linux-none
66//
7// :1:29: error: callconv 'Interrupt' is only available on x86, x86_64, AVR, and MSP430, not aarch64
7// :1:29: error: calling convention 'Interrupt' is only available on x86, x86_64, AVR, and MSP430, not aarch64
test/cases/compile_errors/callconv_signal_on_unsupported_platform.zig+2-2
......@@ -1,7 +1,7 @@
1export fn entry() callconv(.Signal) void {}
1export fn entry() callconv(.avr_signal) void {}
22
33// error
44// backend=stage2
55// target=x86_64-linux-none
66//
7// :1:29: error: callconv 'Signal' is only available on AVR, not x86_64
7// :1:29: error: calling convention 'avr_signal' only available on architectures 'avr'
test/cases/compile_errors/callconv_stdcall_fastcall_thiscall_on_unsupported_platform.zig+6-6
......@@ -1,6 +1,6 @@
1const F1 = fn () callconv(.Stdcall) void;
2const F2 = fn () callconv(.Fastcall) void;
3const F3 = fn () callconv(.Thiscall) void;
1const F1 = fn () callconv(.{ .x86_stdcall = .{} }) void;
2const F2 = fn () callconv(.{ .x86_fastcall = .{} }) void;
3const F3 = fn () callconv(.{ .x86_thiscall = .{} }) void;
44export fn entry1() void {
55 const a: F1 = undefined;
66 _ = a;
......@@ -18,6 +18,6 @@ export fn entry3() void {
1818// backend=stage2
1919// target=x86_64-linux-none
2020//
21// :1:28: error: callconv 'Stdcall' is only available on x86, not x86_64
22// :2:28: error: callconv 'Fastcall' is only available on x86, not x86_64
23// :3:28: error: callconv 'Thiscall' is only available on x86, not x86_64
21// :1:28: error: calling convention 'x86_stdcall' only available on architectures 'x86'
22// :2:28: error: calling convention 'x86_fastcall' only available on architectures 'x86'
23// :3:28: error: calling convention 'x86_thiscall' only available on architectures 'x86'
test/cases/compile_errors/callconv_vectorcall_on_unsupported_platform.zig deleted-7
......@@ -1,7 +0,0 @@
1export fn entry() callconv(.Vectorcall) void {}
2
3// error
4// backend=stage2
5// target=x86_64-linux-none
6//
7// :1:29: error: callconv 'Vectorcall' is only available on x86 and AArch64, not x86_64
test/cases/compile_errors/closure_get_depends_on_failed_decl.zig+1-1
......@@ -4,7 +4,7 @@ pub inline fn requestAdapter(
44 comptime callbackArg: fn () callconv(.Inline) void,
55) void {
66 _ = &(struct {
7 pub fn callback() callconv(.C) void {
7 pub fn callback() callconv(.c) void {
88 callbackArg();
99 }
1010 }).callback;
test/cases/compile_errors/export_function_with_comptime_parameter.zig+2-3
......@@ -3,7 +3,6 @@ export fn foo(comptime x: anytype, y: i32) i32 {
33}
44
55// error
6// backend=stage2
7// target=native
6// target=x86_64-linux
87//
9// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
8// :1:15: error: comptime parameters not allowed in function with calling convention 'x86_64_sysv'
test/cases/compile_errors/export_generic_function.zig+2-3
......@@ -4,7 +4,6 @@ export fn foo(num: anytype) i32 {
44}
55
66// error
7// backend=stage2
8// target=native
7// target=x86_64-linux
98//
10// :1:15: error: generic parameters not allowed in function with calling convention 'C'
9// :1:15: error: generic parameters not allowed in function with calling convention 'x86_64_sysv'
test/cases/compile_errors/extern_function_pointer_mismatch.zig+3-4
......@@ -14,8 +14,7 @@ export fn entry() usize {
1414}
1515
1616// error
17// backend=stage2
18// target=native
17// target=x86_64-linux
1918//
20// :1:38: error: expected type 'fn (i32) i32', found 'fn (i32) callconv(.C) i32'
21// :1:38: note: calling convention 'C' cannot cast into calling convention 'Unspecified'
19// :1:38: error: expected type 'fn (i32) i32', found 'fn (i32) callconv(.c) i32'
20// :1:38: note: calling convention 'x86_64_sysv' cannot cast into calling convention 'auto'
test/cases/compile_errors/extern_function_with_comptime_parameter.zig+4-5
......@@ -15,9 +15,8 @@ comptime {
1515}
1616
1717// error
18// backend=stage2
19// target=native
18// target=x86_64-linux
2019//
21// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
22// :5:30: error: comptime parameters not allowed in function with calling convention 'C'
23// :6:30: error: generic parameters not allowed in function with calling convention 'C'
20// :1:15: error: comptime parameters not allowed in function with calling convention 'x86_64_sysv'
21// :5:30: error: comptime parameters not allowed in function with calling convention 'x86_64_sysv'
22// :6:30: error: generic parameters not allowed in function with calling convention 'x86_64_sysv'
test/cases/compile_errors/function-only_builtins_outside_function.zig+12-17
......@@ -1,7 +1,3 @@
1comptime {
2 @setAlignStack(1);
3}
4
51comptime {
62 @branchHint(.cold);
73}
......@@ -54,16 +50,15 @@ comptime {
5450// backend=stage2
5551// target=native
5652//
57// :2:5: error: '@setAlignStack' outside function scope
58// :6:5: error: '@branchHint' outside function scope
59// :10:5: error: '@src' outside function scope
60// :14:5: error: '@returnAddress' outside function scope
61// :18:5: error: '@frameAddress' outside function scope
62// :22:5: error: '@breakpoint' outside function scope
63// :26:5: error: '@cVaArg' outside function scope
64// :30:5: error: '@cVaCopy' outside function scope
65// :34:5: error: '@cVaEnd' outside function scope
66// :38:5: error: '@cVaStart' outside function scope
67// :42:5: error: '@workItemId' outside function scope
68// :46:5: error: '@workGroupSize' outside function scope
69// :50:5: error: '@workGroupId' outside function scope
53// :2:5: error: '@branchHint' outside function scope
54// :6:5: error: '@src' outside function scope
55// :10:5: error: '@returnAddress' outside function scope
56// :14:5: error: '@frameAddress' outside function scope
57// :18:5: error: '@breakpoint' outside function scope
58// :22:5: error: '@cVaArg' outside function scope
59// :26:5: error: '@cVaCopy' outside function scope
60// :30:5: error: '@cVaEnd' outside function scope
61// :34:5: error: '@cVaStart' outside function scope
62// :38:5: error: '@workItemId' outside function scope
63// :42:5: error: '@workGroupSize' outside function scope
64// :46:5: error: '@workGroupId' outside function scope
test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig+2-3
......@@ -4,10 +4,9 @@ export fn entry(foo: Foo) void {
44}
55
66// error
7// backend=stage2
8// target=native
7// target=x86_64-linux
98//
10// :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
9// :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv'
1110// :2:17: note: enum tag type 'u2' is not extern compatible
1211// :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible
1312// :1:13: note: enum declared here
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+2-3
......@@ -8,9 +8,8 @@ export fn entry(foo: Foo) void {
88}
99
1010// error
11// backend=stage2
12// target=native
11// target=x86_64-linux
1312//
14// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv'
1514// :6:17: note: only extern structs and ABI sized packed structs are extern compatible
1615// :1:13: note: struct declared here
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+2-3
......@@ -8,9 +8,8 @@ export fn entry(foo: Foo) void {
88}
99
1010// error
11// backend=stage2
12// target=native
11// target=x86_64-linux
1312//
14// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv'
1514// :6:17: note: only extern unions and ABI sized packed unions are extern compatible
1615// :1:13: note: union declared here
test/cases/compile_errors/invalid_extern_function_call.zig+1-1
......@@ -1,4 +1,4 @@
1const x = @extern(*const fn () callconv(.C) void, .{ .name = "foo" });
1const x = @extern(*const fn () callconv(.c) void, .{ .name = "foo" });
22
33export fn entry0() void {
44 comptime x();
test/cases/compile_errors/invalid_func_for_callconv.zig+7-8
......@@ -9,12 +9,11 @@ export fn signal_param(_: u32) callconv(.Signal) void {}
99export fn signal_ret() callconv(.Signal) noreturn {}
1010
1111// error
12// backend=stage2
1312// target=x86_64-linux
14//
15// :1:28: error: first parameter of function with 'Interrupt' calling convention must be a pointer type
16// :2:43: error: second parameter of function with 'Interrupt' calling convention must be a 64-bit integer
17// :3:51: error: 'Interrupt' calling convention supports up to 2 parameters, found 3
18// :4:69: error: function with calling convention 'Interrupt' must return 'void' or 'noreturn'
19// :8:24: error: parameters are not allowed with 'Signal' calling convention
20// :9:34: error: callconv 'Signal' is only available on AVR, not x86_64
13//
14// :1:28: error: first parameter of function with 'x86_64_interrupt' calling convention must be a pointer type
15// :2:43: error: second parameter of function with 'x86_64_interrupt' calling convention must be a 64-bit integer
16// :3:51: error: 'x86_64_interrupt' calling convention supports up to 2 parameters, found 3
17// :4:69: error: function with calling convention 'x86_64_interrupt' must return 'void' or 'noreturn'
18// :8:24: error: parameters are not allowed with 'avr_signal' calling convention
19// :9:34: error: calling convention 'avr_signal' only available on architectures 'avr'
test/cases/compile_errors/invalid_tail_call.zig+1-1
......@@ -9,4 +9,4 @@ pub export fn entry() void {
99// backend=llvm
1010// target=native
1111//
12// :5:5: error: unable to perform tail call: type of function being called 'fn (usize) void' does not match type of calling function 'fn () callconv(.C) void'
12// :5:5: error: unable to perform tail call: type of function being called 'fn (usize) void' does not match type of calling function 'fn () callconv(.c) void'
test/cases/compile_errors/invalid_variadic_function.zig+5-6
......@@ -13,11 +13,10 @@ comptime {
1313}
1414
1515// error
16// backend=stage2
17// target=native
16// target=x86_64-linux
1817//
19// :1:1: error: variadic function does not support '.Unspecified' calling convention
20// :1:1: note: supported calling conventions: '.C'
21// :1:1: error: variadic function does not support '.Inline' calling convention
22// :1:1: note: supported calling conventions: '.C'
18// :1:1: error: variadic function does not support 'auto' calling convention
19// :1:1: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win'
20// :1:1: error: variadic function does not support 'inline' calling convention
21// :1:1: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win'
2322// :2:1: error: generic function cannot be variadic
test/cases/compile_errors/noinline_fn_cc_inline.zig+2-3
......@@ -1,5 +1,4 @@
1const cc = .Inline;
2noinline fn foo() callconv(cc) void {}
1noinline fn foo() callconv(.@"inline") void {}
32
43comptime {
54 _ = foo;
......@@ -9,4 +8,4 @@ comptime {
98// backend=stage2
109// target=native
1110//
12// :2:28: error: 'noinline' function cannot have callconv 'Inline'
11// :1:29: error: 'noinline' function cannot have calling convention 'inline'
test/cases/compile_errors/old_fn_ptr_in_extern_context.zig+4-4
......@@ -1,20 +1,20 @@
11const S = extern struct {
2 a: fn () callconv(.C) void,
2 a: fn () callconv(.c) void,
33};
44comptime {
55 _ = @sizeOf(S) == 1;
66}
77comptime {
8 _ = [*c][4]fn () callconv(.C) void;
8 _ = [*c][4]fn () callconv(.c) void;
99}
1010
1111// error
1212// backend=stage2
1313// target=native
1414//
15// :2:8: error: extern structs cannot contain fields of type 'fn () callconv(.C) void'
15// :2:8: error: extern structs cannot contain fields of type 'fn () callconv(.c) void'
1616// :2:8: note: type has no guaranteed in-memory representation
1717// :2:8: note: use '*const ' to make a function pointer type
18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn () callconv(.C) void'
18// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn () callconv(.c) void'
1919// :8:13: note: type has no guaranteed in-memory representation
2020// :8:13: note: use '*const ' to make a function pointer type
test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig+3-4
......@@ -12,8 +12,7 @@ comptime {
1212}
1313
1414// error
15// backend=stage2
16// target=native
15// target=x86_64-linux
1716//
18// :1:13: error: variadic function does not support '.Unspecified' calling convention
19// :1:13: note: supported calling conventions: '.C'
17// :1:13: error: variadic function does not support 'auto' calling convention
18// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win'
test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig+2-2
......@@ -1,5 +1,5 @@
11const GuSettings = struct {
2 fin: ?fn (c_int) callconv(.C) void,
2 fin: ?fn (c_int) callconv(.c) void,
33};
44pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
55 const settings: ?*GuSettings = @as(?*GuSettings, @ptrFromInt(@intFromPtr(arg)));
......@@ -13,4 +13,4 @@ pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
1313//
1414// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known
1515// :2:10: note: struct requires comptime because of this field
16// :2:10: note: use '*const fn (c_int) callconv(.C) void' for a function pointer type
16// :2:10: note: use '*const fn (c_int) callconv(.c) void' for a function pointer type
test/cases/compile_errors/setAlignStack_in_naked_function.zig deleted-9
......@@ -1,9 +0,0 @@
1export fn entry() callconv(.Naked) void {
2 @setAlignStack(16);
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:5: error: @setAlignStack in naked function
test/cases/compile_errors/setAlignStack_too_big.zig deleted-9
......@@ -1,9 +0,0 @@
1export fn entry() void {
2 @setAlignStack(511 + 1);
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:5: error: attempt to @setAlignStack(512); maximum is 256
test/cases/compile_errors/slice_used_as_extern_fn_param.zig+3-4
......@@ -1,11 +1,10 @@
1extern fn Text(str: []const u8, num: i32) callconv(.C) void;
1extern fn Text(str: []const u8, num: i32) callconv(.c) void;
22export fn entry() void {
33 _ = Text;
44}
55
66// error
7// backend=stage2
8// target=native
7// target=x86_64-linux
98//
10// :1:16: error: parameter of type '[]const u8' not allowed in function with calling convention 'C'
9// :1:16: error: parameter of type '[]const u8' not allowed in function with calling convention 'x86_64_sysv'
1110// :1:16: note: slices have no guaranteed in-memory representation
test/cases/compile_errors/type_mismatch_in_C_prototype_with_varargs.zig+2-2
......@@ -1,4 +1,4 @@
1const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void;
1const fn_ty = ?fn ([*c]u8, ...) callconv(.c) void;
22extern fn fn_decl(fmt: [*:0]u8, ...) void;
33
44export fn main() void {
......@@ -10,6 +10,6 @@ export fn main() void {
1010// backend=stage2
1111// target=native
1212//
13// :5:22: error: expected type '?fn ([*c]u8, ...) callconv(.C) void', found 'fn ([*:0]u8, ...) callconv(.C) void'
13// :5:22: error: expected type '?fn ([*c]u8, ...) callconv(.c) void', found 'fn ([*:0]u8, ...) callconv(.c) void'
1414// :5:22: note: parameter 0 '[*:0]u8' cannot cast into '[*c]u8'
1515// :5:22: note: '[*c]u8' could have null values which are illegal in type '[*:0]u8'
test/cases/compile_errors/wrong_types_given_to_export.zig+1-1
......@@ -1,4 +1,4 @@
1fn entry() callconv(.C) void {}
1fn entry() callconv(.c) void {}
22comptime {
33 @export(&entry, .{ .name = "entry", .linkage = @as(u32, 1234) });
44}
test/cases/translate_c/static empty struct.c +1-1
......@@ -9,7 +9,7 @@ static inline void foo() {
99// c_frontend=clang
1010//
1111// pub const struct_empty_struct = extern struct {};
12// pub fn foo() callconv(.C) void {
12// pub fn foo() callconv(.c) void {
1313// const bar = struct {
1414// var static: struct_empty_struct = @import("std").mem.zeroes(struct_empty_struct);
1515// };
test/translate_c.zig+34-34
......@@ -484,11 +484,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
484484 \\ fnptr_attr_ty qux;
485485 \\};
486486 , &[_][]const u8{
487 \\pub const fnptr_ty = ?*const fn () callconv(.C) void;
488 \\pub const fnptr_attr_ty = ?*const fn () callconv(.C) void;
487 \\pub const fnptr_ty = ?*const fn () callconv(.c) void;
488 \\pub const fnptr_attr_ty = ?*const fn () callconv(.c) void;
489489 \\pub const struct_foo = extern struct {
490 \\ foo: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
491 \\ bar: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
490 \\ foo: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void),
491 \\ bar: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void),
492492 \\ baz: fnptr_ty = @import("std").mem.zeroes(fnptr_ty),
493493 \\ qux: fnptr_attr_ty = @import("std").mem.zeroes(fnptr_attr_ty),
494494 \\};
......@@ -735,7 +735,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
735735 \\static void bar(void) {}
736736 , &[_][]const u8{
737737 \\pub export fn foo() void {}
738 \\pub fn bar() callconv(.C) void {}
738 \\pub fn bar() callconv(.c) void {}
739739 });
740740
741741 cases.add("typedef void",
......@@ -769,7 +769,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
769769 \\pub export fn bar() void {
770770 \\ var func_ptr: ?*anyopaque = @as(?*anyopaque, @ptrCast(&foo));
771771 \\ _ = &func_ptr;
772 \\ var typed_func_ptr: ?*const fn () callconv(.C) void = @as(?*const fn () callconv(.C) void, @ptrFromInt(@as(c_ulong, @intCast(@intFromPtr(func_ptr)))));
772 \\ var typed_func_ptr: ?*const fn () callconv(.c) void = @as(?*const fn () callconv(.c) void, @ptrFromInt(@as(c_ulong, @intCast(@intFromPtr(func_ptr)))));
773773 \\ _ = &typed_func_ptr;
774774 \\}
775775 });
......@@ -839,9 +839,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
839839 \\ lws_callback_function *callback_http;
840840 \\};
841841 , &[_][]const u8{
842 \\pub const lws_callback_function = fn () callconv(.C) void;
842 \\pub const lws_callback_function = fn () callconv(.c) void;
843843 \\pub const struct_Foo = extern struct {
844 \\ func: ?*const fn () callconv(.C) void = @import("std").mem.zeroes(?*const fn () callconv(.C) void),
844 \\ func: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void),
845845 \\ callback_http: ?*const lws_callback_function = @import("std").mem.zeroes(?*const lws_callback_function),
846846 \\};
847847 });
......@@ -867,7 +867,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
867867 \\};
868868 , &[_][]const u8{
869869 \\pub const struct_Foo = extern struct {
870 \\ derp: ?*const fn ([*c]struct_Foo) callconv(.C) void = @import("std").mem.zeroes(?*const fn ([*c]struct_Foo) callconv(.C) void),
870 \\ derp: ?*const fn ([*c]struct_Foo) callconv(.c) void = @import("std").mem.zeroes(?*const fn ([*c]struct_Foo) callconv(.c) void),
871871 \\};
872872 ,
873873 \\pub const Foo = struct_Foo;
......@@ -1111,7 +1111,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11111111 cases.add("__cdecl doesn't mess up function pointers",
11121112 \\void foo(void (__cdecl *fn_ptr)(void));
11131113 , &[_][]const u8{
1114 \\pub extern fn foo(fn_ptr: ?*const fn () callconv(.C) void) void;
1114 \\pub extern fn foo(fn_ptr: ?*const fn () callconv(.c) void) void;
11151115 });
11161116
11171117 cases.add("void cast",
......@@ -1477,8 +1477,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14771477 \\typedef void (*fn0)();
14781478 \\typedef void (*fn1)(char);
14791479 , &[_][]const u8{
1480 \\pub const fn0 = ?*const fn (...) callconv(.C) void;
1481 \\pub const fn1 = ?*const fn (u8) callconv(.C) void;
1480 \\pub const fn0 = ?*const fn (...) callconv(.c) void;
1481 \\pub const fn1 = ?*const fn (u8) callconv(.c) void;
14821482 });
14831483
14841484 cases.addWithTarget("Calling convention", .{
......@@ -1492,11 +1492,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14921492 \\void __attribute__((cdecl)) foo4(float *a);
14931493 \\void __attribute__((thiscall)) foo5(float *a);
14941494 , &[_][]const u8{
1495 \\pub extern fn foo1(a: [*c]f32) callconv(.Fastcall) void;
1496 \\pub extern fn foo2(a: [*c]f32) callconv(.Stdcall) void;
1497 \\pub extern fn foo3(a: [*c]f32) callconv(.Vectorcall) void;
1495 \\pub extern fn foo1(a: [*c]f32) callconv(.{ .x86_fastcall = .{} }) void;
1496 \\pub extern fn foo2(a: [*c]f32) callconv(.{ .x86_stdcall = .{} }) void;
1497 \\pub extern fn foo3(a: [*c]f32) callconv(.{ .x86_vectorcall = .{} }) void;
14981498 \\pub extern fn foo4(a: [*c]f32) void;
1499 \\pub extern fn foo5(a: [*c]f32) callconv(.Thiscall) void;
1499 \\pub extern fn foo5(a: [*c]f32) callconv(.{ .x86_thiscall = .{} }) void;
15001500 });
15011501
15021502 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
......@@ -1506,8 +1506,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15061506 \\void __attribute__((pcs("aapcs"))) foo1(float *a);
15071507 \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
15081508 , &[_][]const u8{
1509 \\pub extern fn foo1(a: [*c]f32) callconv(.AAPCS) void;
1510 \\pub extern fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
1509 \\pub extern fn foo1(a: [*c]f32) callconv(.{ .arm_aapcs = .{} }) void;
1510 \\pub extern fn foo2(a: [*c]f32) callconv(.{ .arm_aapcs_vfp = .{} }) void;
15111511 });
15121512
15131513 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
......@@ -1516,7 +1516,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15161516 }) catch unreachable,
15171517 \\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
15181518 , &[_][]const u8{
1519 \\pub extern fn foo1(a: [*c]f32) callconv(.Vectorcall) void;
1519 \\pub extern fn foo1(a: [*c]f32) callconv(.{ .aarch64_vfabi = .{} }) void;
15201520 });
15211521
15221522 cases.add("Parameterless function prototypes",
......@@ -1533,8 +1533,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15331533 \\pub export fn b() void {}
15341534 \\pub extern fn c(...) void;
15351535 \\pub extern fn d() void;
1536 \\pub fn e() callconv(.C) void {}
1537 \\pub fn f() callconv(.C) void {}
1536 \\pub fn e() callconv(.c) void {}
1537 \\pub fn f() callconv(.c) void {}
15381538 \\pub extern fn g() void;
15391539 \\pub extern fn h() void;
15401540 });
......@@ -1555,7 +1555,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15551555 \\ char *arr1[10] ={0};
15561556 \\}
15571557 , &[_][]const u8{
1558 \\pub fn foo() callconv(.C) void {
1558 \\pub fn foo() callconv(.c) void {
15591559 \\ var arr: [10]u8 = [1]u8{
15601560 \\ 1,
15611561 \\ } ++ [1]u8{0} ** 9;
......@@ -1686,13 +1686,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16861686 \\extern char (*fn_ptr2)(int, float);
16871687 \\#define bar fn_ptr2
16881688 , &[_][]const u8{
1689 \\pub extern var fn_ptr: ?*const fn () callconv(.C) void;
1689 \\pub extern var fn_ptr: ?*const fn () callconv(.c) void;
16901690 ,
16911691 \\pub inline fn foo() void {
16921692 \\ return fn_ptr.?();
16931693 \\}
16941694 ,
1695 \\pub extern var fn_ptr2: ?*const fn (c_int, f32) callconv(.C) u8;
1695 \\pub extern var fn_ptr2: ?*const fn (c_int, f32) callconv(.c) u8;
16961696 ,
16971697 \\pub inline fn bar(arg_1: c_int, arg_2: f32) u8 {
16981698 \\ return fn_ptr2.?(arg_1, arg_2);
......@@ -1714,8 +1714,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17141714 \\#define glClearPFN PFNGLCLEARPROC
17151715 , &[_][]const u8{
17161716 \\pub const GLbitfield = c_uint;
1717 \\pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.C) void;
1718 \\pub const OpenGLProc = ?*const fn () callconv(.C) void;
1717 \\pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.c) void;
1718 \\pub const OpenGLProc = ?*const fn () callconv(.c) void;
17191719 \\const struct_unnamed_1 = extern struct {
17201720 \\ Clear: PFNGLCLEARPROC = @import("std").mem.zeroes(PFNGLCLEARPROC),
17211721 \\};
......@@ -2691,9 +2691,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26912691 \\ return 0;
26922692 \\}
26932693 \\pub export fn bar() void {
2694 \\ var f: ?*const fn () callconv(.C) void = &foo;
2694 \\ var f: ?*const fn () callconv(.c) void = &foo;
26952695 \\ _ = &f;
2696 \\ var b: ?*const fn () callconv(.C) c_int = &baz;
2696 \\ var b: ?*const fn () callconv(.c) c_int = &baz;
26972697 \\ _ = &b;
26982698 \\ f.?();
26992699 \\ f.?();
......@@ -3048,8 +3048,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
30483048 \\ baz();
30493049 \\}
30503050 , &[_][]const u8{
3051 \\pub fn bar() callconv(.C) void {}
3052 \\pub export fn foo(arg_baz: ?*const fn () callconv(.C) [*c]c_int) void {
3051 \\pub fn bar() callconv(.c) void {}
3052 \\pub export fn foo(arg_baz: ?*const fn () callconv(.c) [*c]c_int) void {
30533053 \\ var baz = arg_baz;
30543054 \\ _ = &baz;
30553055 \\ bar();
......@@ -3112,7 +3112,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
31123112 \\ do {} while (0);
31133113 \\}
31143114 , &[_][]const u8{
3115 \\pub fn foo() callconv(.C) void {
3115 \\pub fn foo() callconv(.c) void {
31163116 \\ if (true) while (true) {
31173117 \\ if (!false) break;
31183118 \\ };
......@@ -3212,10 +3212,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
32123212 \\void c(void) {}
32133213 \\static void foo() {}
32143214 , &[_][]const u8{
3215 \\pub fn a() callconv(.C) void {}
3216 \\pub fn b() callconv(.C) void {}
3215 \\pub fn a() callconv(.c) void {}
3216 \\pub fn b() callconv(.c) void {}
32173217 \\pub export fn c() void {}
3218 \\pub fn foo() callconv(.C) void {}
3218 \\pub fn foo() callconv(.c) void {}
32193219 });
32203220
32213221 cases.add("casting away const and volatile",