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 {...@@ -3,4 +3,5 @@ export fn entry(foo: Foo) void {
3 _ = foo;3 _ = foo;
4}4}
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 {...@@ -550,12 +550,26 @@ pub const Payload = struct {
550 is_var_args: bool,550 is_var_args: bool,
551 name: ?[]const u8,551 name: ?[]const u8,
552 linksection_string: ?[]const u8,552 linksection_string: ?[]const u8,
553 explicit_callconv: ?std.builtin.CallingConvention,553 explicit_callconv: ?CallingConvention,
554 params: []Param,554 params: []Param,
555 return_type: Node,555 return_type: Node,
556 body: ?Node,556 body: ?Node,
557 alignment: ?c_uint,557 alignment: ?c_uint,
558 },558 },
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 };
559 };573 };
560574
561 pub const Param = struct {575 pub const Param = struct {
...@@ -2812,14 +2826,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2812,14 +2826,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2812 const callconv_expr = if (payload.explicit_callconv) |some| blk: {2826 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
2813 _ = try c.addToken(.keyword_callconv, "callconv");2827 _ = try c.addToken(.keyword_callconv, "callconv");
2814 _ = try c.addToken(.l_paren, "(");2828 _ = try c.addToken(.l_paren, "(");
2815 _ = try c.addToken(.period, ".");2829 const cc_node = switch (some) {
2816 const res = try c.addNode(.{2830 .c => cc_node: {
2817 .tag = .enum_literal,2831 _ = try c.addToken(.period, ".");
2818 .main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}),2832 break :cc_node try c.addNode(.{
2819 .data = undefined,2833 .tag = .enum_literal,
2820 });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 };
2821 _ = try c.addToken(.r_paren, ")");2873 _ = try c.addToken(.r_paren, ")");
2822 break :blk res;2874 break :blk cc_node;
2823 } else 0;2875 } else 0;
28242876
2825 const return_type_expr = try renderNode(c, payload.return_type);2877 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;...@@ -10,7 +10,6 @@ const is_test = builtin.is_test;
10const common = @import("common.zig");10const common = @import("common.zig");
11const udivmod = @import("udivmod.zig").udivmod;11const udivmod = @import("udivmod.zig").udivmod;
12const __divti3 = @import("divti3.zig").__divti3;12const __divti3 = @import("divti3.zig").__divti3;
13const arm = @import("arm.zig");
1413
15pub const panic = common.panic;14pub const panic = common.panic;
1615
...@@ -102,25 +101,6 @@ test "test_divmoddi4" {...@@ -102,25 +101,6 @@ test "test_divmoddi4" {
102 }101 }
103}102}
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
124pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {104pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {
125 return udivmod(u64, a, b, maybe_rem);105 return udivmod(u64, a, b, maybe_rem);
126}106}
...@@ -261,25 +241,6 @@ test "test_divmodsi4" {...@@ -261,25 +241,6 @@ test "test_divmodsi4" {
261 }241 }
262}242}
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
283pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {244pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
284 const d = __udivsi3(a, b);245 const d = __udivsi3(a, b);
285 rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));246 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 @@...@@ -3,7 +3,6 @@
3const testing = @import("std").testing;3const testing = @import("std").testing;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const __udivmoddi4 = @import("int.zig").__udivmoddi4;5const __udivmoddi4 = @import("int.zig").__udivmoddi4;
6const __aeabi_uldivmod = @import("arm.zig").__aeabi_uldivmod;
76
8fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) !void {7fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) !void {
9 var r: u64 = undefined;8 var r: u64 = undefined;
...@@ -18,26 +17,6 @@ test "udivmoddi4" {...@@ -18,26 +17,6 @@ test "udivmoddi4" {
18 }17 }
19}18}
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
41const cases = [_][4]u64{20const cases = [_][4]u64{
42 [_]u64{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},21 [_]u64{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
43 [_]u64{0x0000000000000000, 0x0000000000000002, 0x0000000000000000, 0x0000000000000000},22 [_]u64{0x0000000000000000, 0x0000000000000002, 0x0000000000000000, 0x0000000000000000},
lib/compiler_rt/udivmodsi4_test.zig+8-17
...@@ -2,27 +2,18 @@...@@ -2,27 +2,18 @@
2// zig fmt: off2// zig fmt: off
3const testing = @import("std").testing;3const testing = @import("std").testing;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const __aeabi_uidivmod = @import("arm.zig").__aeabi_uidivmod;5const __udivmodsi4 = @import("int.zig").__udivmodsi4;
66
7const ARMRes = extern struct {7fn test__udivmodsi4(a: u32, b: u32, expected_q: u32, expected_r: u32) !void {
8 q: u32, // r08 var r: u32 = undefined;
9 r: u32, // r19 const q = __udivmodsi4(a, b, &r);
10};10 try testing.expectEqual(expected_q, q);
1111 try testing.expectEqual(expected_r, r);
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);
17}12}
1813
19test "arm.__aeabi_uidivmod" {14test "udivmodsi4" {
20 if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
21
22 var i: i32 = 0;
23 for (cases) |case| {15 for (cases) |case| {
24 try test__aeabi_uidivmod(case[0], case[1], case[2], case[3]);16 try test__udivmodsi4(case[0], case[1], case[2], case[3]);
25 i+=1;
26 }17 }
27}18}
2819
lib/std/Target.zig+229
...@@ -1609,6 +1609,165 @@ pub const Cpu = struct {...@@ -1609,6 +1609,165 @@ pub const Cpu = struct {
1609 else => ".X",1609 else => ".X",
1610 };1610 };
1611 }1611 }
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 }
1612 };1771 };
16131772
1614 pub const Model = struct {1773 pub const Model = struct {
...@@ -2873,6 +3032,76 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {...@@ -2873,6 +3032,76 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
2873 );3032 );
2874}3033}
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
2876pub fn osArchName(target: std.Target) [:0]const u8 {3105pub fn osArchName(target: std.Target) [:0]const u8 {
2877 return target.os.tag.archName(target.cpu.arch);3106 return target.os.tag.archName(target.cpu.arch);
2878}3107}
lib/std/builtin.zig+330-44
...@@ -160,54 +160,340 @@ pub const OptimizeMode = enum {...@@ -160,54 +160,340 @@ pub const OptimizeMode = enum {
160/// Deprecated; use OptimizeMode.160/// Deprecated; use OptimizeMode.
161pub const Mode = OptimizeMode;161pub 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///
163/// This data structure is used by the Zig language code generation and167/// This data structure is used by the Zig language code generation and
164/// therefore must be kept in sync with the compiler implementation.168/// therefore must be kept in sync with the compiler implementation.
165pub const CallingConvention = enum(u8) {169pub const CallingConvention = union(enum(u8)) {
166 /// This is the default Zig calling convention used when not using `export` on `fn`170 pub const Tag = @typeInfo(CallingConvention).@"union".tag_type.?;
167 /// and no other calling convention is specified.171
168 Unspecified,172 /// This is an alias for the default C calling convention for this target.
169 /// Matches the C ABI for the target.173 /// Functions marked as `extern` or `export` are given this calling convention by default.
170 /// This is the default calling convention when using `export` on `fn`174 pub const c = builtin.target.cCallingConvention().?;
171 /// and no other calling convention is specified.175
172 C,176 pub const winapi: CallingConvention = switch (builtin.target.cpu.arch) {
173 /// This makes a function not have any function prologue or epilogue,177 .x86_64 => .{ .x86_64_win = .{} },
174 /// making the function itself uncallable in regular Zig code.178 .x86 => .{ .x86_stdcall = .{} },
175 /// This can be useful when integrating with assembly.179 .aarch64 => .{ .aarch64_aapcs_win = .{} },
176 Naked,180 .thumb => .{ .arm_aapcs_vfp = .{} },
177 /// Functions with this calling convention are called asynchronously,181 else => unreachable,
178 /// as if called as `async function()`.182 };
179 Async,183
180 /// Functions with this calling convention are inlined at all call sites.184 pub const kernel: CallingConvention = switch (builtin.target.cpu.arch) {
181 Inline,185 .amdgcn => .amdgcn_kernel,
182 /// x86-only.186 .nvptx, .nvptx64 => .nvptx_kernel,
183 Interrupt,187 .spirv, .spirv32, .spirv64 => .spirv_kernel,
184 Signal,188 else => unreachable,
185 /// x86-only.189 };
186 Stdcall,190
187 /// x86-only.191 /// Deprecated; use `.auto`.
188 Fastcall,192 pub const Unspecified: CallingConvention = .auto;
189 /// x86-only.193 /// Deprecated; use `.c`.
190 Vectorcall,194 pub const C: CallingConvention = .c;
191 /// x86-only.195 /// Deprecated; use `.naked`.
192 Thiscall,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.
193 /// ARM Procedure Call Standard (obsolete)287 /// ARM Procedure Call Standard (obsolete)
194 /// ARM-only.288 arm_apcs: CommonOptions,
195 APCS,289 /// ARM Architecture Procedure Call Standard
196 /// ARM Architecture Procedure Call Standard (current standard)290 arm_aapcs: CommonOptions,
197 /// ARM-only.
198 AAPCS,
199 /// ARM Architecture Procedure Call Standard Vector Floating-Point291 /// ARM Architecture Procedure Call Standard Vector Floating-Point
200 /// ARM-only.292 arm_aapcs_vfp: CommonOptions,
201 AAPCSVFP,293 arm_aapcs16_vfp: CommonOptions,
202 /// x86-64-only.294 arm_interrupt: ArmInterruptOptions,
203 SysV,295
204 /// x86-64-only.296 // Calling conventions for the `mips64` architecture.
205 Win64,297 mips64_n64: CommonOptions,
206 /// AMD GPU, NVPTX, or SPIR-V kernel298 mips64_n32: CommonOptions,
207 Kernel,299 mips64_interrupt: MipsInterruptOptions,
208 // Vulkan-only300
209 Fragment,301 // Calling conventions for the `mips` architecture.
210 Vertex,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 }
211};497};
212498
213/// This data structure is used by the Zig language code generation and499/// 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;...@@ -6,9 +6,9 @@ const NonCanonicalError = crypto.errors.NonCanonicalError;
6const NotSquareError = crypto.errors.NotSquareError;6const NotSquareError = crypto.errors.NotSquareError;
77
8// Inline conditionally, when it can result in large code generation.8// Inline conditionally, when it can result in large code generation.
9const bloaty_inline = switch (builtin.mode) {9const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {
10 .ReleaseSafe, .ReleaseFast => .Inline,10 .ReleaseSafe, .ReleaseFast => .@"inline",
11 .Debug, .ReleaseSmall => .Unspecified,11 .Debug, .ReleaseSmall => .auto,
12};12};
1313
14pub const Fe = struct {14pub const Fe = struct {
lib/std/os/windows.zig+1-4
...@@ -2824,10 +2824,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;...@@ -2824,10 +2824,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;
2824/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.2824/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
2825pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;2825pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;
28262826
2827pub const WINAPI: std.builtin.CallingConvention = if (native_arch == .x86)2827pub const WINAPI: std.builtin.CallingConvention = .winapi;
2828 .Stdcall
2829else
2830 .C;
28312828
2832pub const BOOL = c_int;2829pub const BOOL = c_int;
2833pub const BOOLEAN = BYTE;2830pub const BOOLEAN = BYTE;
lib/std/start.zig+4-7
...@@ -55,7 +55,7 @@ comptime {...@@ -55,7 +55,7 @@ comptime {
55 if (builtin.link_libc and @hasDecl(root, "main")) {55 if (builtin.link_libc and @hasDecl(root, "main")) {
56 if (native_arch.isWasm()) {56 if (native_arch.isWasm()) {
57 @export(&mainWithoutEnv, .{ .name = "main" });57 @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)) {
59 @export(&main, .{ .name = "main" });59 @export(&main, .{ .name = "main" });
60 }60 }
61 } else if (native_os == .windows) {61 } else if (native_os == .windows) {
...@@ -102,12 +102,11 @@ fn main2() callconv(.C) c_int {...@@ -102,12 +102,11 @@ fn main2() callconv(.C) c_int {
102 return 0;102 return 0;
103}103}
104104
105fn _start2() callconv(.C) noreturn {105fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {
106 callMain2();106 callMain2();
107}107}
108108
109fn callMain2() noreturn {109fn callMain2() noreturn {
110 @setAlignStack(16);
111 root.main();110 root.main();
112 exit2(0);111 exit2(0);
113}112}
...@@ -428,8 +427,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -428,8 +427,7 @@ fn _start() callconv(.Naked) noreturn {
428 );427 );
429}428}
430429
431fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {430fn WinStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
432 @setAlignStack(16);
433 if (!builtin.single_threaded and !builtin.link_libc) {431 if (!builtin.single_threaded and !builtin.link_libc) {
434 _ = @import("os/windows/tls.zig");432 _ = @import("os/windows/tls.zig");
435 }433 }
...@@ -439,8 +437,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {...@@ -439,8 +437,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
439 std.os.windows.ntdll.RtlExitUserProcess(callMain());437 std.os.windows.ntdll.RtlExitUserProcess(callMain());
440}438}
441439
442fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {440fn wWinMainCRTStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
443 @setAlignStack(16);
444 if (!builtin.single_threaded and !builtin.link_libc) {441 if (!builtin.single_threaded and !builtin.link_libc) {
445 _ = @import("os/windows/tls.zig");442 _ = @import("os/windows/tls.zig");
446 }443 }
lib/std/zig/AstGen.zig-9
...@@ -2902,7 +2902,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2902,7 +2902,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2902 .breakpoint,2902 .breakpoint,
2903 .disable_instrumentation,2903 .disable_instrumentation,
2904 .set_float_mode,2904 .set_float_mode,
2905 .set_align_stack,
2906 .branch_hint,2905 .branch_hint,
2907 => break :b true,2906 => break :b true,
2908 else => break :b false,2907 else => break :b false,
...@@ -9324,14 +9323,6 @@ fn builtinCall(...@@ -9324,14 +9323,6 @@ fn builtinCall(
9324 });9323 });
9325 return rvalue(gz, ri, .void_value, node);9324 return rvalue(gz, ri, .void_value, node);
9326 },9325 },
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
9336 .src => {9327 .src => {
9337 // Incorporate the source location into the source hash, so that9328 // 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....@@ -909,7 +909,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
909 .wasm_memory_size,909 .wasm_memory_size,
910 .splat,910 .splat,
911 .set_float_mode,911 .set_float_mode,
912 .set_align_stack,
913 .type_info,912 .type_info,
914 .work_item_id,913 .work_item_id,
915 .work_group_size,914 .work_group_size,
lib/std/zig/BuiltinFn.zig-9
...@@ -82,7 +82,6 @@ pub const Tag = enum {...@@ -82,7 +82,6 @@ pub const Tag = enum {
82 rem,82 rem,
83 return_address,83 return_address,
84 select,84 select,
85 set_align_stack,
86 set_eval_branch_quota,85 set_eval_branch_quota,
87 set_float_mode,86 set_float_mode,
88 set_runtime_safety,87 set_runtime_safety,
...@@ -744,14 +743,6 @@ pub const list = list: {...@@ -744,14 +743,6 @@ pub const list = list: {
744 .param_count = 4,743 .param_count = 4,
745 },744 },
746 },745 },
747 .{
748 "@setAlignStack",
749 .{
750 .tag = .set_align_stack,
751 .param_count = 1,
752 .illegal_outside_function = true,
753 },
754 },
755 .{746 .{
756 "@setEvalBranchQuota",747 "@setEvalBranchQuota",
757 .{748 .{
lib/std/zig/Zir.zig-4
...@@ -1982,9 +1982,6 @@ pub const Inst = struct {...@@ -1982,9 +1982,6 @@ pub const Inst = struct {
1982 /// Implement builtin `@setFloatMode`.1982 /// Implement builtin `@setFloatMode`.
1983 /// `operand` is payload index to `UnNode`.1983 /// `operand` is payload index to `UnNode`.
1984 set_float_mode,1984 set_float_mode,
1985 /// Implement builtin `@setAlignStack`.
1986 /// `operand` is payload index to `UnNode`.
1987 set_align_stack,
1988 /// Implements the `@errorCast` builtin.1985 /// Implements the `@errorCast` builtin.
1989 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.1986 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
1990 error_cast,1987 error_cast,
...@@ -4012,7 +4009,6 @@ fn findDeclsInner(...@@ -4012,7 +4009,6 @@ fn findDeclsInner(
4012 .wasm_memory_grow,4009 .wasm_memory_grow,
4013 .prefetch,4010 .prefetch,
4014 .set_float_mode,4011 .set_float_mode,
4015 .set_align_stack,
4016 .error_cast,4012 .error_cast,
4017 .await_nosuspend,4013 .await_nosuspend,
4018 .breakpoint,4014 .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_...@@ -265,4 +265,4 @@ pub fn __builtin_mul_overflow(a: anytype, b: anytype, result: *@TypeOf(a, b)) c_
265// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented265// It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented
266// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the266// builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the
267// run-translated-c test and the test-translate-c test to use a different non-implemented builtin.267// 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" {...@@ -107,15 +107,15 @@ test "zig fmt: respect line breaks before functions" {
107 );107 );
108}108}
109109
110test "zig fmt: rewrite callconv(.Inline) to the inline keyword" {110test "zig fmt: rewrite callconv(.@\"inline\") to the inline keyword" {
111 try testTransform(111 try testTransform(
112 \\fn foo() callconv(.Inline) void {}112 \\fn foo() callconv(.@"inline") void {}
113 \\const bar = .Inline;113 \\const bar: @import("std").builtin.CallingConvention = .@"inline";
114 \\fn foo() callconv(bar) void {}114 \\fn foo() callconv(bar) void {}
115 \\115 \\
116 ,116 ,
117 \\inline fn foo() void {}117 \\inline fn foo() void {}
118 \\const bar = .Inline;118 \\const bar: @import("std").builtin.CallingConvention = .@"inline";
119 \\fn foo() callconv(bar) void {}119 \\fn foo() callconv(bar) void {}
120 \\120 \\
121 );121 );
...@@ -3062,7 +3062,7 @@ test "zig fmt: functions" {...@@ -3062,7 +3062,7 @@ test "zig fmt: functions" {
3062 \\pub export fn puts(s: *const u8) align(2 + 2) c_int;3062 \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
3063 \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;3063 \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
3064 \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;3064 \\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 {
3066 \\ func();3066 \\ func();
3067 \\}3067 \\}
3068 \\3068 \\
lib/std/zig/render.zig+4-2
...@@ -184,8 +184,9 @@ fn renderMember(...@@ -184,8 +184,9 @@ fn renderMember(
184 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr184 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr
185 else185 else
186 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;186 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
187 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {188 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]))) {
189 try ais.writer().writeAll("inline ");190 try ais.writer().writeAll("inline ");
190 }191 }
191 }192 }
...@@ -1839,7 +1840,8 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1839,7 +1840,8 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1839 try renderToken(r, section_rparen, .space); // )1840 try renderToken(r, section_rparen, .space); // )
1840 }1841 }
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]));
1843 const is_declaration = fn_proto.name_token != null;1845 const is_declaration = fn_proto.name_token != null;
1844 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {1846 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {
1845 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;1847 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) {...@@ -2011,10 +2011,10 @@ pub const Key = union(enum) {
2011 a.return_type == b.return_type and2011 a.return_type == b.return_type and
2012 a.comptime_bits == b.comptime_bits and2012 a.comptime_bits == b.comptime_bits and
2013 a.noalias_bits == b.noalias_bits and2013 a.noalias_bits == b.noalias_bits and
2014 a.cc == b.cc and
2015 a.is_var_args == b.is_var_args and2014 a.is_var_args == b.is_var_args and
2016 a.is_generic == b.is_generic and2015 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);
2018 }2018 }
20192019
2020 pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void {2020 pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void {
...@@ -5444,7 +5444,7 @@ pub const Tag = enum(u8) {...@@ -5444,7 +5444,7 @@ pub const Tag = enum(u8) {
5444 flags: Flags,5444 flags: Flags,
54455445
5446 pub const Flags = packed struct(u32) {5446 pub const Flags = packed struct(u32) {
5447 cc: std.builtin.CallingConvention,5447 cc: PackedCallingConvention,
5448 is_var_args: bool,5448 is_var_args: bool,
5449 is_generic: bool,5449 is_generic: bool,
5450 has_comptime_bits: bool,5450 has_comptime_bits: bool,
...@@ -5453,7 +5453,7 @@ pub const Tag = enum(u8) {...@@ -5453,7 +5453,7 @@ pub const Tag = enum(u8) {
5453 cc_is_generic: bool,5453 cc_is_generic: bool,
5454 section_is_generic: bool,5454 section_is_generic: bool,
5455 addrspace_is_generic: bool,5455 addrspace_is_generic: bool,
5456 _: u16 = 0,5456 _: u6 = 0,
5457 };5457 };
5458 };5458 };
54595459
...@@ -5618,12 +5618,11 @@ pub const FuncAnalysis = packed struct(u32) {...@@ -5618,12 +5618,11 @@ pub const FuncAnalysis = packed struct(u32) {
5618 branch_hint: std.builtin.BranchHint,5618 branch_hint: std.builtin.BranchHint,
5619 is_noinline: bool,5619 is_noinline: bool,
5620 calls_or_awaits_errorable_fn: bool,5620 calls_or_awaits_errorable_fn: bool,
5621 stack_alignment: Alignment,
5622 /// True if this function has an inferred error set.5621 /// True if this function has an inferred error set.
5623 inferred_error_set: bool,5622 inferred_error_set: bool,
5624 disable_instrumentation: bool,5623 disable_instrumentation: bool,
56255624
5626 _: u17 = 0,5625 _: u23 = 0,
56275626
5628 pub const State = enum(u2) {5627 pub const State = enum(u2) {
5629 /// The runtime function has never been referenced.5628 /// The runtime function has never been referenced.
...@@ -6912,7 +6911,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke...@@ -6912,7 +6911,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
6912 .return_type = type_function.data.return_type,6911 .return_type = type_function.data.return_type,
6913 .comptime_bits = comptime_bits,6912 .comptime_bits = comptime_bits,
6914 .noalias_bits = noalias_bits,6913 .noalias_bits = noalias_bits,
6915 .cc = type_function.data.flags.cc,6914 .cc = type_function.data.flags.cc.unpack(),
6916 .is_var_args = type_function.data.flags.is_var_args,6915 .is_var_args = type_function.data.flags.is_var_args,
6917 .is_noinline = type_function.data.flags.is_noinline,6916 .is_noinline = type_function.data.flags.is_noinline,
6918 .cc_is_generic = type_function.data.flags.cc_is_generic,6917 .cc_is_generic = type_function.data.flags.cc_is_generic,
...@@ -8526,7 +8525,7 @@ pub const GetFuncTypeKey = struct {...@@ -8526,7 +8525,7 @@ pub const GetFuncTypeKey = struct {
8526 comptime_bits: u32 = 0,8525 comptime_bits: u32 = 0,
8527 noalias_bits: u32 = 0,8526 noalias_bits: u32 = 0,
8528 /// `null` means generic.8527 /// `null` means generic.
8529 cc: ?std.builtin.CallingConvention = .Unspecified,8528 cc: ?std.builtin.CallingConvention = .auto,
8530 is_var_args: bool = false,8529 is_var_args: bool = false,
8531 is_generic: bool = false,8530 is_generic: bool = false,
8532 is_noinline: bool = false,8531 is_noinline: bool = false,
...@@ -8564,7 +8563,7 @@ pub fn getFuncType(...@@ -8564,7 +8563,7 @@ pub fn getFuncType(
8564 .params_len = params_len,8563 .params_len = params_len,
8565 .return_type = key.return_type,8564 .return_type = key.return_type,
8566 .flags = .{8565 .flags = .{
8567 .cc = key.cc orelse .Unspecified,8566 .cc = .pack(key.cc orelse .auto),
8568 .is_var_args = key.is_var_args,8567 .is_var_args = key.is_var_args,
8569 .has_comptime_bits = key.comptime_bits != 0,8568 .has_comptime_bits = key.comptime_bits != 0,
8570 .has_noalias_bits = key.noalias_bits != 0,8569 .has_noalias_bits = key.noalias_bits != 0,
...@@ -8696,7 +8695,6 @@ pub fn getFuncDecl(...@@ -8696,7 +8695,6 @@ pub fn getFuncDecl(
8696 .branch_hint = .none,8695 .branch_hint = .none,
8697 .is_noinline = key.is_noinline,8696 .is_noinline = key.is_noinline,
8698 .calls_or_awaits_errorable_fn = false,8697 .calls_or_awaits_errorable_fn = false,
8699 .stack_alignment = .none,
8700 .inferred_error_set = false,8698 .inferred_error_set = false,
8701 .disable_instrumentation = false,8699 .disable_instrumentation = false,
8702 },8700 },
...@@ -8800,7 +8798,6 @@ pub fn getFuncDeclIes(...@@ -8800,7 +8798,6 @@ pub fn getFuncDeclIes(
8800 .branch_hint = .none,8798 .branch_hint = .none,
8801 .is_noinline = key.is_noinline,8799 .is_noinline = key.is_noinline,
8802 .calls_or_awaits_errorable_fn = false,8800 .calls_or_awaits_errorable_fn = false,
8803 .stack_alignment = .none,
8804 .inferred_error_set = true,8801 .inferred_error_set = true,
8805 .disable_instrumentation = false,8802 .disable_instrumentation = false,
8806 },8803 },
...@@ -8818,7 +8815,7 @@ pub fn getFuncDeclIes(...@@ -8818,7 +8815,7 @@ pub fn getFuncDeclIes(
8818 .params_len = params_len,8815 .params_len = params_len,
8819 .return_type = error_union_type,8816 .return_type = error_union_type,
8820 .flags = .{8817 .flags = .{
8821 .cc = key.cc orelse .Unspecified,8818 .cc = .pack(key.cc orelse .auto),
8822 .is_var_args = key.is_var_args,8819 .is_var_args = key.is_var_args,
8823 .has_comptime_bits = key.comptime_bits != 0,8820 .has_comptime_bits = key.comptime_bits != 0,
8824 .has_noalias_bits = key.noalias_bits != 0,8821 .has_noalias_bits = key.noalias_bits != 0,
...@@ -8992,7 +8989,6 @@ pub fn getFuncInstance(...@@ -8992,7 +8989,6 @@ pub fn getFuncInstance(
8992 .branch_hint = .none,8989 .branch_hint = .none,
8993 .is_noinline = arg.is_noinline,8990 .is_noinline = arg.is_noinline,
8994 .calls_or_awaits_errorable_fn = false,8991 .calls_or_awaits_errorable_fn = false,
8995 .stack_alignment = .none,
8996 .inferred_error_set = false,8992 .inferred_error_set = false,
8997 .disable_instrumentation = false,8993 .disable_instrumentation = false,
8998 },8994 },
...@@ -9092,7 +9088,6 @@ pub fn getFuncInstanceIes(...@@ -9092,7 +9088,6 @@ pub fn getFuncInstanceIes(
9092 .branch_hint = .none,9088 .branch_hint = .none,
9093 .is_noinline = arg.is_noinline,9089 .is_noinline = arg.is_noinline,
9094 .calls_or_awaits_errorable_fn = false,9090 .calls_or_awaits_errorable_fn = false,
9095 .stack_alignment = .none,
9096 .inferred_error_set = true,9091 .inferred_error_set = true,
9097 .disable_instrumentation = false,9092 .disable_instrumentation = false,
9098 },9093 },
...@@ -9110,7 +9105,7 @@ pub fn getFuncInstanceIes(...@@ -9110,7 +9105,7 @@ pub fn getFuncInstanceIes(
9110 .params_len = params_len,9105 .params_len = params_len,
9111 .return_type = error_union_type,9106 .return_type = error_union_type,
9112 .flags = .{9107 .flags = .{
9113 .cc = arg.cc,9108 .cc = .pack(arg.cc),
9114 .is_var_args = false,9109 .is_var_args = false,
9115 .has_comptime_bits = false,9110 .has_comptime_bits = false,
9116 .has_noalias_bits = arg.noalias_bits != 0,9111 .has_noalias_bits = arg.noalias_bits != 0,
...@@ -11871,21 +11866,6 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {...@@ -11871,21 +11866,6 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
11871 return @atomicLoad(FuncAnalysis, @constCast(ip).funcAnalysisPtr(func), .unordered);11866 return @atomicLoad(FuncAnalysis, @constCast(ip).funcAnalysisPtr(func), .unordered);
11872}11867}
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
11889pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {11869pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
11890 const unwrapped_func = func.unwrap(ip);11870 const unwrapped_func = func.unwrap(ip);
11891 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;11871 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
...@@ -12224,3 +12204,81 @@ pub fn getErrorValue(...@@ -12224,3 +12204,81 @@ pub fn getErrorValue(
12224pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {12204pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {
12225 return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null);12205 return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null);
12226}12206}
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,...@@ -26,7 +26,7 @@ owner: AnalUnit,
26/// in the case of an inline or comptime function call.26/// in the case of an inline or comptime function call.
27/// This could be `none`, a `func_decl`, or a `func_instance`.27/// This could be `none`, a `func_decl`, or a `func_instance`.
28func_index: InternPool.Index,28func_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`.
30func_is_naked: bool,30func_is_naked: bool,
31/// Used to restore the error return trace when returning a non-error from a function.31/// Used to restore the error return trace when returning a non-error from a function.
32error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,32error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
...@@ -1326,11 +1326,6 @@ fn analyzeBodyInner(...@@ -1326,11 +1326,6 @@ fn analyzeBodyInner(
1326 i += 1;1326 i += 1;
1327 continue;1327 continue;
1328 },1328 },
1329 .set_align_stack => {
1330 try sema.zirSetAlignStack(block, extended);
1331 i += 1;
1332 continue;
1333 },
1334 .breakpoint => {1329 .breakpoint => {
1335 if (!block.is_comptime) {1330 if (!block.is_comptime) {
1336 _ = try block.addNoOp(.breakpoint);1331 _ = try block.addNoOp(.breakpoint);
...@@ -1355,7 +1350,7 @@ fn analyzeBodyInner(...@@ -1355,7 +1350,7 @@ fn analyzeBodyInner(
1355 },1350 },
1356 .value_placeholder => unreachable, // never appears in a body1351 .value_placeholder => unreachable, // never appears in a body
1357 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),1352 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
1358 .builtin_value => try sema.zirBuiltinValue(extended),1353 .builtin_value => try sema.zirBuiltinValue(block, extended),
1359 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),1354 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),
1360 };1355 };
1361 },1356 },
...@@ -2698,6 +2693,20 @@ fn analyzeAsInt(...@@ -2698,6 +2693,20 @@ fn analyzeAsInt(
2698 return try val.toUnsignedIntSema(sema.pt);2693 return try val.toUnsignedIntSema(sema.pt);
2699}2694}
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
2701/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,2710/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
2702/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.2711/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
2703fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {2712fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
...@@ -6496,35 +6505,6 @@ pub fn analyzeExport(...@@ -6496,35 +6505,6 @@ pub fn analyzeExport(
6496 });6505 });
6497}6506}
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
6528fn zirDisableInstrumentation(sema: *Sema) CompileError!void {6508fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6529 const pt = sema.pt;6509 const pt = sema.pt;
6530 const zcu = pt.zcu;6510 const zcu = pt.zcu;
...@@ -7554,7 +7534,7 @@ fn analyzeCall(...@@ -7554,7 +7534,7 @@ fn analyzeCall(
7554 if (try sema.resolveValue(func)) |func_val|7534 if (try sema.resolveValue(func)) |func_val|
7555 if (func_val.isUndef(zcu))7535 if (func_val.isUndef(zcu))
7556 return sema.failWithUseOfUndef(block, call_src);7536 return sema.failWithUseOfUndef(block, call_src);
7557 if (cc == .Naked) {7537 if (cc == .naked) {
7558 const maybe_func_inst = try sema.funcDeclSrcInst(func);7538 const maybe_func_inst = try sema.funcDeclSrcInst(func);
7559 const msg = msg: {7539 const msg = msg: {
7560 const msg = try sema.errMsg(7540 const msg = try sema.errMsg(
...@@ -7587,7 +7567,7 @@ fn analyzeCall(...@@ -7587,7 +7567,7 @@ fn analyzeCall(
7587 .async_kw => return sema.failWithUseOfAsync(block, call_src),7567 .async_kw => return sema.failWithUseOfAsync(block, call_src),
7588 };7568 };
75897569
7590 if (modifier == .never_inline and func_ty_info.cc == .Inline) {7570 if (modifier == .never_inline and func_ty_info.cc == .@"inline") {
7591 return sema.fail(block, call_src, "'never_inline' call of inline function", .{});7571 return sema.fail(block, call_src, "'never_inline' call of inline function", .{});
7592 }7572 }
7593 if (modifier == .always_inline and func_ty_info.is_noinline) {7573 if (modifier == .always_inline and func_ty_info.is_noinline) {
...@@ -7598,7 +7578,7 @@ fn analyzeCall(...@@ -7598,7 +7578,7 @@ fn analyzeCall(
75987578
7599 const is_generic_call = func_ty_info.is_generic;7579 const is_generic_call = func_ty_info.is_generic;
7600 var is_comptime_call = block.is_comptime or modifier == .compile_time;7580 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";
7602 var comptime_reason: ?*const Block.ComptimeReason = null;7582 var comptime_reason: ?*const Block.ComptimeReason = null;
7603 if (!is_inline_call and !is_comptime_call) {7583 if (!is_inline_call and !is_comptime_call) {
7604 if (try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) {7584 if (try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) {
...@@ -8455,7 +8435,7 @@ fn instantiateGenericCall(...@@ -8455,7 +8435,7 @@ fn instantiateGenericCall(
8455 }8435 }
8456 // Similarly, if the call evaluated to a generic type we need to instead8436 // Similarly, if the call evaluated to a generic type we need to instead
8457 // call it inline.8437 // 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") {
8459 return error.GenericPoison;8439 return error.GenericPoison;
8460 }8440 }
84618441
...@@ -9505,7 +9485,7 @@ fn zirFunc(...@@ -9505,7 +9485,7 @@ fn zirFunc(
95059485
9506 // If this instruction has a body, then it's a function declaration, and we decide9486 // If this instruction has a body, then it's a function declaration, and we decide
9507 // the callconv based on whether it is exported. Otherwise, the callconv defaults9487 // the callconv based on whether it is exported. Otherwise, the callconv defaults
9508 // to `.Unspecified`.9488 // to `.auto`.
9509 const cc: std.builtin.CallingConvention = if (has_body) cc: {9489 const cc: std.builtin.CallingConvention = if (has_body) cc: {
9510 const func_decl_cau = if (sema.generic_owner != .none) cau: {9490 const func_decl_cau = if (sema.generic_owner != .none) cau: {
9511 const generic_owner_fn = zcu.funcInfo(sema.generic_owner);9491 const generic_owner_fn = zcu.funcInfo(sema.generic_owner);
...@@ -9518,8 +9498,26 @@ fn zirFunc(...@@ -9518,8 +9498,26 @@ fn zirFunc(
9518 const zir_decl = sema.code.getDeclaration(decl_inst)[0];9498 const zir_decl = sema.code.getDeclaration(decl_inst)[0];
9519 break :exported zir_decl.flags.is_export;9499 break :exported zir_decl.flags.is_export;
9520 };9500 };
9521 break :cc if (fn_is_exported) .C else .Unspecified;9501 if (fn_is_exported) {
9522 } else .Unspecified;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
9524 return sema.funcCommon(9522 return sema.funcCommon(
9525 block,9523 block,
...@@ -9654,35 +9652,91 @@ fn handleExternLibName(...@@ -9654,35 +9652,91 @@ fn handleExternLibName(
9654/// These are calling conventions that are confirmed to work with variadic functions.9652/// These are calling conventions that are confirmed to work with variadic functions.
9655/// Any calling conventions not included here are either not yet verified to work with variadic9653/// Any calling conventions not included here are either not yet verified to work with variadic
9656/// functions or there are no more other calling conventions that support variadic functions.9654/// functions or there are no more other calling conventions that support variadic functions.
9657const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention{9655const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention.Tag{
9658 .C,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,
9659};9706};
9660fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention) bool {9707fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention.Tag) bool {
9661 return for (calling_conventions_supporting_var_args) |supported_cc| {9708 return for (calling_conventions_supporting_var_args) |supported_cc| {
9662 if (cc == supported_cc) return true;9709 if (cc == supported_cc) return true;
9663 } else false;9710 } else false;
9664}9711}
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 {
9666 const CallingConventionsSupportingVarArgsList = struct {9713 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 {
9668 _ = fmt;9716 _ = fmt;
9669 _ = options;9717 _ = options;
9670 for (calling_conventions_supporting_var_args, 0..) |cc_inner, i| {9718 var first = true;
9671 if (i != 0)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) {
9672 try writer.writeAll(", ");9724 try writer.writeAll(", ");
9673 try writer.print("'.{s}'", .{@tagName(cc_inner)});9725 }
9726 first = false;
9727 try writer.print("'{s}'", .{@tagName(cc_inner)});
9674 }9728 }
9675 }9729 }
9676 };9730 };
96779731
9678 if (!callConvSupportsVarArgs(cc)) {9732 if (!callConvSupportsVarArgs(cc)) {
9679 const msg = msg: {9733 return sema.failWithOwnedErrorMsg(block, msg: {
9680 const msg = try sema.errMsg(src, "variadic function does not support '.{s}' calling convention", .{@tagName(cc)});9734 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)});
9681 errdefer msg.destroy(sema.gpa);9735 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 }});
9683 break :msg msg;9738 break :msg msg;
9684 };9739 });
9685 return sema.failWithOwnedErrorMsg(block, msg);
9686 }9740 }
9687}9741}
96889742
...@@ -9743,7 +9797,7 @@ fn funcCommon(...@@ -9743,7 +9797,7 @@ fn funcCommon(
9743 // default values which are only meaningful for the generic function, *not*9797 // default values which are only meaningful for the generic function, *not*
9744 // the instantiation, which can depend on comptime parameters.9798 // the instantiation, which can depend on comptime parameters.
9745 // Related proposal: https://github.com/ziglang/zig/issues/118349799 // Related proposal: https://github.com/ziglang/zig/issues/11834
9746 const cc_resolved = cc orelse .Unspecified;9800 const cc_resolved = cc orelse .auto;
9747 var comptime_bits: u32 = 0;9801 var comptime_bits: u32 = 0;
9748 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {9802 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
9749 const param_ty = Type.fromInterned(param_ty_ip);9803 const param_ty = Type.fromInterned(param_ty_ip);
...@@ -9761,10 +9815,10 @@ fn funcCommon(...@@ -9761,10 +9815,10 @@ fn funcCommon(
9761 }9815 }
9762 const this_generic = param_ty.isGenericPoison();9816 const this_generic = param_ty.isGenericPoison();
9763 is_generic = is_generic or this_generic;9817 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)) {
9765 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});9819 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
9766 }9820 }
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)) {
9768 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});9822 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
9769 }9823 }
9770 if (!param_ty.isValidParamType(zcu)) {9824 if (!param_ty.isValidParamType(zcu)) {
...@@ -9773,7 +9827,7 @@ fn funcCommon(...@@ -9773,7 +9827,7 @@ fn funcCommon(
9773 opaque_str, param_ty.fmt(pt),9827 opaque_str, param_ty.fmt(pt),
9774 });9828 });
9775 }9829 }
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)) {
9777 const msg = msg: {9831 const msg = msg: {
9778 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9832 const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9779 param_ty.fmt(pt), @tagName(cc_resolved),9833 param_ty.fmt(pt), @tagName(cc_resolved),
...@@ -9807,15 +9861,24 @@ fn funcCommon(...@@ -9807,15 +9861,24 @@ fn funcCommon(
9807 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});9861 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9808 }9862 }
9809 switch (cc_resolved) {9863 switch (cc_resolved) {
9810 .Interrupt => if (target.cpu.arch.isX86()) {9864 .x86_64_interrupt, .x86_interrupt => {
9811 const err_code_size = target.ptrBitWidth();9865 const err_code_size = target.ptrBitWidth();
9812 switch (i) {9866 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", .{}),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)}),
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}),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 }),
9815 else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}),9869 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc_resolved), i + 1 }),
9816 }9870 }
9817 } else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}),9871 },
9818 .Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}),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)}),
9819 else => {},9882 else => {},
9820 }9883 }
9821 }9884 }
...@@ -10064,7 +10127,6 @@ fn finishFunc(...@@ -10064,7 +10127,6 @@ fn finishFunc(
10064 const zcu = pt.zcu;10127 const zcu = pt.zcu;
10065 const ip = &zcu.intern_pool;10128 const ip = &zcu.intern_pool;
10066 const gpa = sema.gpa;10129 const gpa = sema.gpa;
10067 const target = zcu.getTarget();
1006810130
10069 const return_type: Type = if (opt_func_index == .none or ret_poison)10131 const return_type: Type = if (opt_func_index == .none or ret_poison)
10070 bare_return_type10132 bare_return_type
...@@ -10077,7 +10139,7 @@ fn finishFunc(...@@ -10077,7 +10139,7 @@ fn finishFunc(
10077 opaque_str, return_type.fmt(pt),10139 opaque_str, return_type.fmt(pt),
10078 });10140 });
10079 }10141 }
10080 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and10142 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and
10081 !try sema.validateExternType(return_type, .ret_ty))10143 !try sema.validateExternType(return_type, .ret_ty))
10082 {10144 {
10083 const msg = msg: {10145 const msg = msg: {
...@@ -10133,57 +10195,63 @@ fn finishFunc(...@@ -10133,57 +10195,63 @@ fn finishFunc(
10133 return sema.failWithOwnedErrorMsg(block, msg);10195 return sema.failWithOwnedErrorMsg(block, msg);
10134 }10196 }
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
10136 switch (cc_resolved) {10210 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) {
10138 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});10223 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
10139 },10224 },
10140 .Inline => if (is_noinline) {10225 .@"inline" => if (is_noinline) {
10141 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});10226 return sema.fail(block, cc_src, "'noinline' function cannot have calling convention 'inline'", .{});
10142 },10227 },
10143 else => {},10228 else => {},
10144 }10229 }
1014510230
10146 const arch = target.cpu.arch;10231 switch (zcu.callconvSupported(cc_resolved)) {
10147 if (@as(?[]const u8, switch (cc_resolved) {10232 .ok => {},
10148 .Unspecified, .C, .Naked, .Async, .Inline => null,10233 .bad_arch => |allowed_archs| {
10149 .Interrupt => switch (arch) {10234 const ArchListFormatter = struct {
10150 .x86, .x86_64, .avr, .msp430 => null,10235 archs: []const std.Target.Cpu.Arch,
10151 else => "x86, x86_64, AVR, and MSP430",10236 pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
10152 },10237 _ = fmt;
10153 .Signal => switch (arch) {10238 _ = options;
10154 .avr => null,10239 for (formatter.archs, 0..) |arch, i| {
10155 else => "AVR",10240 if (i != 0)
10156 },10241 try writer.writeAll(", ");
10157 .Stdcall, .Fastcall, .Thiscall => switch (arch) {10242 try writer.print("'{s}'", .{@tagName(arch)});
10158 .x86 => null,10243 }
10159 else => "x86",10244 }
10160 },10245 };
10161 .Vectorcall => switch (arch) {10246 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {}", .{
10162 .x86, .aarch64, .aarch64_be => null,10247 @tagName(cc_resolved),
10163 else => "x86 and AArch64",10248 ArchListFormatter{ .archs = allowed_archs },
10164 },10249 });
10165 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {10250 },
10166 .arm, .armeb, .aarch64, .aarch64_be, .thumb, .thumbeb => null,10251 .bad_backend => |bad_backend| return sema.fail(block, cc_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{
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}", .{
10183 @tagName(cc_resolved),10252 @tagName(cc_resolved),
10184 allowed_platform,10253 @tagName(bad_backend),
10185 @tagName(arch),10254 }),
10186 });
10187 }10255 }
1018810256
10189 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;10257 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...@@ -18342,10 +18410,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18342 } });18410 } });
1834318411
18344 const callconv_ty = try sema.getBuiltinType("CallingConvention");18412 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 = .{
18347 // calling_convention: CallingConvention,18419 // calling_convention: CallingConvention,
18348 (try pt.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),18420 callconv_val.toIntern(),
18349 // is_generic: bool,18421 // is_generic: bool,
18350 Value.makeBool(func_ty_info.is_generic).toIntern(),18422 Value.makeBool(func_ty_info.is_generic).toIntern(),
18351 // is_var_args: bool,18423 // is_var_args: bool,
...@@ -22171,7 +22243,7 @@ fn zirReify(...@@ -22171,7 +22243,7 @@ fn zirReify(
22171 }22243 }
2217222244
22173 const is_var_args = is_var_args_val.toBool();22245 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);
22175 if (is_var_args) {22247 if (is_var_args) {
22176 try sema.checkCallConvSupportsVarArgs(block, src, cc);22248 try sema.checkCallConvSupportsVarArgs(block, src, cc);
22177 }22249 }
...@@ -26670,7 +26742,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26670,7 +26742,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26670 if (val.isGenericPoison()) {26742 if (val.isGenericPoison()) {
26671 break :blk null;26743 break :blk null;
26672 }26744 }
26673 break :blk zcu.toEnum(std.builtin.CallingConvention, val);26745 break :blk try sema.analyzeValueAsCallconv(block, cc_src, val);
26674 } else if (extra.data.bits.has_cc_ref) blk: {26746 } else if (extra.data.bits.has_cc_ref) blk: {
26675 const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);26747 const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
26676 extra_index += 1;26748 extra_index += 1;
...@@ -26689,7 +26761,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26689,7 +26761,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26689 error.GenericPoison => break :blk null,26761 error.GenericPoison => break :blk null,
26690 else => |e| return e,26762 else => |e| return e,
26691 };26763 };
26692 break :blk zcu.toEnum(std.builtin.CallingConvention, cc_val);26764 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);
26693 } else cc: {26765 } else cc: {
26694 if (has_body) {26766 if (has_body) {
26695 const decl_inst = if (sema.generic_owner != .none) decl_inst: {26767 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...@@ -26705,7 +26777,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26705 break :cc .C;26777 break :cc .C;
26706 }26778 }
26707 }26779 }
26708 break :cc .Unspecified;26780 break :cc .auto;
26709 };26781 };
2671026782
26711 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {26783 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
...@@ -27132,9 +27204,15 @@ fn zirInComptime(...@@ -27132,9 +27204,15 @@ fn zirInComptime(
27132 return if (block.is_comptime) .bool_true else .bool_false;27204 return if (block.is_comptime) .bool_true else .bool_false;
27133}27205}
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 {
27136 const pt = sema.pt;27208 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));
27137 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);27214 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
27215
27138 const type_name = switch (value) {27216 const type_name = switch (value) {
27139 .atomic_order => "AtomicOrder",27217 .atomic_order => "AtomicOrder",
27140 .atomic_rmw_op => "AtomicRmwOp",27218 .atomic_rmw_op => "AtomicRmwOp",
...@@ -27152,21 +27230,25 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr...@@ -27152,21 +27230,25 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr
27152 // Values are handled here.27230 // Values are handled here.
27153 .calling_convention_c => {27231 .calling_convention_c => {
27154 const callconv_ty = try sema.getBuiltinType("CallingConvention");27232 const callconv_ty = try sema.getBuiltinType("CallingConvention");
27155 comptime assert(@intFromEnum(std.builtin.CallingConvention.C) == 1);27233 return try sema.namespaceLookupVal(
27156 const val = try pt.intern(.{ .enum_tag = .{27234 block,
27157 .ty = callconv_ty.toIntern(),27235 src,
27158 .int = .one_u8,27236 callconv_ty.getNamespaceIndex(zcu),
27159 } });27237 try ip.getOrPutString(gpa, pt.tid, "c", .no_embedded_nulls),
27160 return Air.internedToRef(val);27238 ) orelse @panic("std.builtin is corrupt");
27161 },27239 },
27162 .calling_convention_inline => {27240 .calling_convention_inline => {
27241 comptime assert(@typeInfo(std.builtin.CallingConvention.Tag).@"enum".tag_type == u8);
27163 const callconv_ty = try sema.getBuiltinType("CallingConvention");27242 const callconv_ty = try sema.getBuiltinType("CallingConvention");
27164 comptime assert(@intFromEnum(std.builtin.CallingConvention.Inline) == 4);27243 const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt");
27165 const val = try pt.intern(.{ .enum_tag = .{27244 const inline_tag_val = try pt.enumValue(
27166 .ty = callconv_ty.toIntern(),27245 callconv_tag_ty,
27167 .int = .four_u8,27246 (try pt.intValue(
27168 } });27247 Type.u8,
27169 return Air.internedToRef(val);27248 @intFromEnum(std.builtin.CallingConvention.@"inline"),
27249 )).toIntern(),
27250 );
27251 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
27170 },27252 },
27171 };27253 };
27172 const ty = try sema.getBuiltinType(type_name);27254 const ty = try sema.getBuiltinType(type_name);
...@@ -27353,7 +27435,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -27353,7 +27435,7 @@ fn explainWhyTypeIsComptimeInner(
27353 try sema.errNote(src_loc, msg, "function is generic", .{});27435 try sema.errNote(src_loc, msg, "function is generic", .{});
27354 }27436 }
27355 switch (fn_info.cc) {27437 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", .{}),
27357 else => {},27439 else => {},
27358 }27440 }
27359 if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) {27441 if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) {
...@@ -27461,13 +27543,12 @@ fn validateExternType(...@@ -27461,13 +27543,12 @@ fn validateExternType(
27461 },27543 },
27462 .@"fn" => {27544 .@"fn" => {
27463 if (position != .other) return false;27545 if (position != .other) return false;
27464 const target = zcu.getTarget();
27465 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.27546 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
27466 // The goal is to experiment with more integrated CPU/GPU code.27547 // 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) {
27468 return true;27549 return true;
27469 }27550 }
27470 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(zcu));27551 return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu));
27471 },27552 },
27472 .@"enum" => {27553 .@"enum" => {
27473 return sema.validateExternType(ty.intTagType(zcu), position);27554 return sema.validateExternType(ty.intTagType(zcu), position);
...@@ -27547,9 +27628,9 @@ fn explainWhyTypeIsNotExtern(...@@ -27547,9 +27628,9 @@ fn explainWhyTypeIsNotExtern(
27547 return;27628 return;
27548 }27629 }
27549 switch (ty.fnCallingConvention(zcu)) {27630 switch (ty.fnCallingConvention(zcu)) {
27550 .Unspecified => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}),27631 .auto => 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", .{}),27632 .@"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", .{}),27633 .@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}),
27553 else => return,27634 else => return,
27554 }27635 }
27555 },27636 },
...@@ -31176,8 +31257,8 @@ fn coerceInMemoryAllowedFns(...@@ -31176,8 +31257,8 @@ fn coerceInMemoryAllowedFns(
31176 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };31257 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
31177 }31258 }
3117831259
31179 if (dest_info.cc != src_info.cc) {31260 if (!callconvCoerceAllowed(target, src_info.cc, dest_info.cc)) {
31180 return InMemoryCoercionResult{ .fn_cc = .{31261 return .{ .fn_cc = .{
31181 .actual = src_info.cc,31262 .actual = src_info.cc,
31182 .wanted = dest_info.cc,31263 .wanted = dest_info.cc,
31183 } };31264 } };
...@@ -31250,6 +31331,44 @@ fn coerceInMemoryAllowedFns(...@@ -31250,6 +31331,44 @@ fn coerceInMemoryAllowedFns(
31250 return .ok;31331 return .ok;
31251}31332}
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
31253fn coerceInMemoryAllowedPtrs(31372fn coerceInMemoryAllowedPtrs(
31254 sema: *Sema,31373 sema: *Sema,
31255 block: *Block,31374 block: *Block,
...@@ -36306,7 +36425,7 @@ fn resolveInferredErrorSet(...@@ -36306,7 +36425,7 @@ fn resolveInferredErrorSet(
36306 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,36425 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
36307 // so here we can simply skip this case.36426 // so here we can simply skip this case.
36308 if (ies_func_info.return_type == .generic_poison_type) {36427 if (ies_func_info.return_type == .generic_poison_type) {
36309 assert(ies_func_info.cc == .Inline);36428 assert(ies_func_info.cc == .@"inline");
36310 } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) {36429 } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) {
36311 if (ies_func_info.is_generic) {36430 if (ies_func_info.is_generic) {
36312 return sema.failWithOwnedErrorMsg(block, msg: {36431 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...@@ -390,10 +390,17 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
390 try writer.writeAll("...");390 try writer.writeAll("...");
391 }391 }
392 try writer.writeAll(") ");392 try writer.writeAll(") ");
393 if (fn_info.cc != .Unspecified) {393 if (fn_info.cc != .auto) print_cc: {
394 try writer.writeAll("callconv(.");394 if (zcu.getTarget().cCallingConvention()) |ccc| {
395 try writer.writeAll(@tagName(fn_info.cc));395 if (fn_info.cc.eql(ccc)) {
396 try writer.writeAll(") ");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 }
397 }404 }
398 if (fn_info.return_type == .generic_poison_type) {405 if (fn_info.return_type == .generic_poison_type) {
399 try writer.writeAll("anytype");406 try writer.writeAll("anytype");
...@@ -791,7 +798,7 @@ pub fn fnHasRuntimeBitsInner(...@@ -791,7 +798,7 @@ pub fn fnHasRuntimeBitsInner(
791 const fn_info = zcu.typeToFunc(ty).?;798 const fn_info = zcu.typeToFunc(ty).?;
792 if (fn_info.is_generic) return false;799 if (fn_info.is_generic) return false;
793 if (fn_info.is_var_args) return true;800 if (fn_info.is_var_args) return true;
794 if (fn_info.cc == .Inline) return false;801 if (fn_info.cc == .@"inline") return false;
795 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid);802 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid);
796}803}
797804
src/Value.zig+156
...@@ -4490,3 +4490,159 @@ pub fn resolveLazy(...@@ -4490,3 +4490,159 @@ pub fn resolveLazy(
4490 else => return val,4490 else => return val,
4491 }4491 }
4492}4492}
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 {...@@ -3539,3 +3539,111 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void {
3539 zcu.intern_pool.funcSetIesResolved(func_index, .none);3539 zcu.intern_pool.funcSetIesResolved(func_index, .none);
3540 }3540 }
3541}3541}
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!...@@ -2090,7 +2090,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2090 .code = zir,2090 .code = zir,
2091 .owner = anal_unit,2091 .owner = anal_unit,
2092 .func_index = func_index,2092 .func_index = func_index,
2093 .func_is_naked = fn_ty_info.cc == .Naked,2093 .func_is_naked = fn_ty_info.cc == .naked,
2094 .fn_ret_ty = Type.fromInterned(fn_ty_info.return_type),2094 .fn_ret_ty = Type.fromInterned(fn_ty_info.return_type),
2095 .fn_ret_ty_ies = null,2095 .fn_ret_ty_ies = null,
2096 .branch_quota = @max(func.branchQuotaUnordered(ip), Sema.default_branch_quota),2096 .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 {...@@ -468,7 +468,7 @@ fn gen(self: *Self) !void {
468 const pt = self.pt;468 const pt = self.pt;
469 const zcu = pt.zcu;469 const zcu = pt.zcu;
470 const cc = self.fn_type.fnCallingConvention(zcu);470 const cc = self.fn_type.fnCallingConvention(zcu);
471 if (cc != .Naked) {471 if (cc != .naked) {
472 // stp fp, lr, [sp, #-16]!472 // stp fp, lr, [sp, #-16]!
473 _ = try self.addInst(.{473 _ = try self.addInst(.{
474 .tag = .stp,474 .tag = .stp,
...@@ -6229,14 +6229,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6229,14 +6229,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6229 const ret_ty = fn_ty.fnReturnType(zcu);6229 const ret_ty = fn_ty.fnReturnType(zcu);
62306230
6231 switch (cc) {6231 switch (cc) {
6232 .Naked => {6232 .naked => {
6233 assert(result.args.len == 0);6233 assert(result.args.len == 0);
6234 result.return_value = .{ .unreach = {} };6234 result.return_value = .{ .unreach = {} };
6235 result.stack_byte_count = 0;6235 result.stack_byte_count = 0;
6236 result.stack_align = 1;6236 result.stack_align = 1;
6237 return result;6237 return result;
6238 },6238 },
6239 .C => {6239 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => {
6240 // ARM64 Procedure Call Standard6240 // ARM64 Procedure Call Standard
6241 var ncrn: usize = 0; // Next Core Register Number6241 var ncrn: usize = 0; // Next Core Register Number
6242 var nsaa: u32 = 0; // Next stacked argument address6242 var nsaa: u32 = 0; // Next stacked argument address
...@@ -6266,7 +6266,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6266,7 +6266,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62666266
6267 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned6267 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
6268 // values to spread across odd-numbered registers.6268 // 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) {
6270 // Round up NCRN to the next even number6270 // Round up NCRN to the next even number
6271 ncrn += ncrn % 2;6271 ncrn += ncrn % 2;
6272 }6272 }
...@@ -6298,7 +6298,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6298,7 +6298,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6298 result.stack_byte_count = nsaa;6298 result.stack_byte_count = nsaa;
6299 result.stack_align = 16;6299 result.stack_align = 16;
6300 },6300 },
6301 .Unspecified => {6301 .auto => {
6302 if (ret_ty.zigTypeTag(zcu) == .noreturn) {6302 if (ret_ty.zigTypeTag(zcu) == .noreturn) {
6303 result.return_value = .{ .unreach = {} };6303 result.return_value = .{ .unreach = {} };
6304 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) {6304 } 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 {...@@ -475,7 +475,7 @@ fn gen(self: *Self) !void {
475 const pt = self.pt;475 const pt = self.pt;
476 const zcu = pt.zcu;476 const zcu = pt.zcu;
477 const cc = self.fn_type.fnCallingConvention(zcu);477 const cc = self.fn_type.fnCallingConvention(zcu);
478 if (cc != .Naked) {478 if (cc != .naked) {
479 // push {fp, lr}479 // push {fp, lr}
480 const push_reloc = try self.addNop();480 const push_reloc = try self.addNop();
481481
...@@ -6196,14 +6196,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6196,14 +6196,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6196 const ret_ty = fn_ty.fnReturnType(zcu);6196 const ret_ty = fn_ty.fnReturnType(zcu);
61976197
6198 switch (cc) {6198 switch (cc) {
6199 .Naked => {6199 .naked => {
6200 assert(result.args.len == 0);6200 assert(result.args.len == 0);
6201 result.return_value = .{ .unreach = {} };6201 result.return_value = .{ .unreach = {} };
6202 result.stack_byte_count = 0;6202 result.stack_byte_count = 0;
6203 result.stack_align = 1;6203 result.stack_align = 1;
6204 return result;6204 return result;
6205 },6205 },
6206 .C => {6206 .arm_aapcs => {
6207 // ARM Procedure Call Standard, Chapter 6.56207 // ARM Procedure Call Standard, Chapter 6.5
6208 var ncrn: usize = 0; // Next Core Register Number6208 var ncrn: usize = 0; // Next Core Register Number
6209 var nsaa: u32 = 0; // Next stacked argument address6209 var nsaa: u32 = 0; // Next stacked argument address
...@@ -6254,7 +6254,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6254,7 +6254,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6254 result.stack_byte_count = nsaa;6254 result.stack_byte_count = nsaa;
6255 result.stack_align = 8;6255 result.stack_align = 8;
6256 },6256 },
6257 .Unspecified => {6257 .auto => {
6258 if (ret_ty.zigTypeTag(zcu) == .noreturn) {6258 if (ret_ty.zigTypeTag(zcu) == .noreturn) {
6259 result.return_value = .{ .unreach = {} };6259 result.return_value = .{ .unreach = {} };
6260 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) {6260 } 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");...@@ -18,6 +18,7 @@ const Zcu = @import("../../Zcu.zig");
18const Package = @import("../../Package.zig");18const Package = @import("../../Package.zig");
19const InternPool = @import("../../InternPool.zig");19const InternPool = @import("../../InternPool.zig");
20const Compilation = @import("../../Compilation.zig");20const Compilation = @import("../../Compilation.zig");
21const target_util = @import("../../target.zig");
21const trace = @import("../../tracy.zig").trace;22const trace = @import("../../tracy.zig").trace;
22const codegen = @import("../../codegen.zig");23const codegen = @import("../../codegen.zig");
2324
...@@ -819,10 +820,7 @@ pub fn generate(...@@ -819,10 +820,7 @@ pub fn generate(
819 try function.frame_allocs.resize(gpa, FrameIndex.named_count);820 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
820 function.frame_allocs.set(821 function.frame_allocs.set(
821 @intFromEnum(FrameIndex.stack_frame),822 @intFromEnum(FrameIndex.stack_frame),
822 FrameAlloc.init(.{823 FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }),
823 .size = 0,
824 .alignment = func.analysisUnordered(ip).stack_alignment.max(.@"1"),
825 }),
826 );824 );
827 function.frame_allocs.set(825 function.frame_allocs.set(
828 @intFromEnum(FrameIndex.call_frame),826 @intFromEnum(FrameIndex.call_frame),
...@@ -977,7 +975,7 @@ pub fn generateLazy(...@@ -977,7 +975,7 @@ pub fn generateLazy(
977 .pt = pt,975 .pt = pt,
978 .allocator = gpa,976 .allocator = gpa,
979 .mir = mir,977 .mir = mir,
980 .cc = .Unspecified,978 .cc = .auto,
981 .src_loc = src_loc,979 .src_loc = src_loc,
982 .output_mode = comp.config.output_mode,980 .output_mode = comp.config.output_mode,
983 .link_mode = comp.config.link_mode,981 .link_mode = comp.config.link_mode,
...@@ -1036,7 +1034,7 @@ fn formatWipMir(...@@ -1036,7 +1034,7 @@ fn formatWipMir(
1036 .instructions = data.func.mir_instructions.slice(),1034 .instructions = data.func.mir_instructions.slice(),
1037 .frame_locs = data.func.frame_locs.slice(),1035 .frame_locs = data.func.frame_locs.slice(),
1038 },1036 },
1039 .cc = .Unspecified,1037 .cc = .auto,
1040 .src_loc = data.func.src_loc,1038 .src_loc = data.func.src_loc,
1041 .output_mode = comp.config.output_mode,1039 .output_mode = comp.config.output_mode,
1042 .link_mode = comp.config.link_mode,1040 .link_mode = comp.config.link_mode,
...@@ -1238,7 +1236,7 @@ fn gen(func: *Func) !void {...@@ -1238,7 +1236,7 @@ fn gen(func: *Func) !void {
1238 }1236 }
1239 }1237 }
12401238
1241 if (fn_info.cc != .Naked) {1239 if (fn_info.cc != .naked) {
1242 _ = try func.addPseudo(.pseudo_dbg_prologue_end);1240 _ = try func.addPseudo(.pseudo_dbg_prologue_end);
12431241
1244 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);1242 const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead);
...@@ -4894,7 +4892,7 @@ fn genCall(...@@ -4894,7 +4892,7 @@ fn genCall(
4894 .lib => |lib| try pt.funcType(.{4892 .lib => |lib| try pt.funcType(.{
4895 .param_types = lib.param_types,4893 .param_types = lib.param_types,
4896 .return_type = lib.return_type,4894 .return_type = lib.return_type,
4897 .cc = .C,4895 .cc = func.target.cCallingConvention().?,
4898 }),4896 }),
4899 };4897 };
49004898
...@@ -8289,12 +8287,12 @@ fn resolveCallingConventionValues(...@@ -8289,12 +8287,12 @@ fn resolveCallingConventionValues(
8289 const ret_ty = Type.fromInterned(fn_info.return_type);8287 const ret_ty = Type.fromInterned(fn_info.return_type);
82908288
8291 switch (cc) {8289 switch (cc) {
8292 .Naked => {8290 .naked => {
8293 assert(result.args.len == 0);8291 assert(result.args.len == 0);
8294 result.return_value = InstTracking.init(.unreach);8292 result.return_value = InstTracking.init(.unreach);
8295 result.stack_align = .@"8";8293 result.stack_align = .@"8";
8296 },8294 },
8297 .C, .Unspecified => {8295 .riscv64_lp64, .auto => {
8298 if (result.args.len > 8) {8296 if (result.args.len > 8) {
8299 return func.fail("RISC-V calling convention does not support more than 8 arguments", .{});8297 return func.fail("RISC-V calling convention does not support more than 8 arguments", .{});
8300 }8298 }
...@@ -8359,7 +8357,7 @@ fn resolveCallingConventionValues(...@@ -8359,7 +8357,7 @@ fn resolveCallingConventionValues(
83598357
8360 for (param_types, result.args) |ty, *arg| {8358 for (param_types, result.args) |ty, *arg| {
8361 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {8359 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
8362 assert(cc == .Unspecified);8360 assert(cc == .auto);
8363 arg.* = .none;8361 arg.* = .none;
8364 continue;8362 continue;
8365 }8363 }
src/arch/sparc64/CodeGen.zig+3-3
...@@ -366,7 +366,7 @@ fn gen(self: *Self) !void {...@@ -366,7 +366,7 @@ fn gen(self: *Self) !void {
366 const pt = self.pt;366 const pt = self.pt;
367 const zcu = pt.zcu;367 const zcu = pt.zcu;
368 const cc = self.fn_type.fnCallingConvention(zcu);368 const cc = self.fn_type.fnCallingConvention(zcu);
369 if (cc != .Naked) {369 if (cc != .naked) {
370 // TODO Finish function prologue and epilogue for sparc64.370 // TODO Finish function prologue and epilogue for sparc64.
371371
372 // save %sp, stack_reserved_area, %sp372 // save %sp, stack_reserved_area, %sp
...@@ -4441,14 +4441,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4441,14 +4441,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4441 const ret_ty = fn_ty.fnReturnType(zcu);4441 const ret_ty = fn_ty.fnReturnType(zcu);
44424442
4443 switch (cc) {4443 switch (cc) {
4444 .Naked => {4444 .naked => {
4445 assert(result.args.len == 0);4445 assert(result.args.len == 0);
4446 result.return_value = .{ .unreach = {} };4446 result.return_value = .{ .unreach = {} };
4447 result.stack_byte_count = 0;4447 result.stack_byte_count = 0;
4448 result.stack_align = .@"1";4448 result.stack_align = .@"1";
4449 return result;4449 return result;
4450 },4450 },
4451 .Unspecified, .C => {4451 .auto, .sparc64_sysv => {
4452 // SPARC Compliance Definition 2.4.1, Chapter 34452 // SPARC Compliance Definition 2.4.1, Chapter 3
4453 // Low-Level System Information (64-bit psABI) - Function Calling Sequence4453 // 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,...@@ -710,7 +710,7 @@ stack_size: u32 = 0,
710/// The stack alignment, which is 16 bytes by default. This is specified by the710/// The stack alignment, which is 16 bytes by default. This is specified by the
711/// tool-conventions: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md711/// tool-conventions: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
712/// and also what the llvm backend will emit.712/// 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.
714stack_alignment: Alignment = .@"16",714stack_alignment: Alignment = .@"16",
715715
716// For each individual Wasm valtype we store a seperate free list which716// For each individual Wasm valtype we store a seperate free list which
...@@ -1160,7 +1160,7 @@ fn genFunctype(...@@ -1160,7 +1160,7 @@ fn genFunctype(
1160 if (firstParamSRet(cc, return_type, pt, target)) {1160 if (firstParamSRet(cc, return_type, pt, target)) {
1161 try temp_params.append(.i32); // memory address is always a 32-bit handle1161 try temp_params.append(.i32); // memory address is always a 32-bit handle
1162 } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) {1162 } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) {
1163 if (cc == .C) {1163 if (cc == .wasm_watc) {
1164 const res_classes = abi.classifyType(return_type, zcu);1164 const res_classes = abi.classifyType(return_type, zcu);
1165 assert(res_classes[0] == .direct and res_classes[1] == .none);1165 assert(res_classes[0] == .direct and res_classes[1] == .none);
1166 const scalar_type = abi.scalarType(return_type, zcu);1166 const scalar_type = abi.scalarType(return_type, zcu);
...@@ -1178,7 +1178,7 @@ fn genFunctype(...@@ -1178,7 +1178,7 @@ fn genFunctype(
1178 if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue;1178 if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11791179
1180 switch (cc) {1180 switch (cc) {
1181 .C => {1181 .wasm_watc => {
1182 const param_classes = abi.classifyType(param_type, zcu);1182 const param_classes = abi.classifyType(param_type, zcu);
1183 if (param_classes[1] == .none) {1183 if (param_classes[1] == .none) {
1184 if (param_classes[0] == .direct) {1184 if (param_classes[0] == .direct) {
...@@ -1367,7 +1367,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1367,7 +1367,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1367 .args = &.{},1367 .args = &.{},
1368 .return_value = .none,1368 .return_value = .none,
1369 };1369 };
1370 if (cc == .Naked) return result;1370 if (cc == .naked) return result;
13711371
1372 var args = std.ArrayList(WValue).init(func.gpa);1372 var args = std.ArrayList(WValue).init(func.gpa);
1373 defer args.deinit();1373 defer args.deinit();
...@@ -1382,7 +1382,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1382,7 +1382,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1382 }1382 }
13831383
1384 switch (cc) {1384 switch (cc) {
1385 .Unspecified => {1385 .auto => {
1386 for (fn_info.param_types.get(ip)) |ty| {1386 for (fn_info.param_types.get(ip)) |ty| {
1387 if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) {1387 if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) {
1388 continue;1388 continue;
...@@ -1392,7 +1392,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1392,7 +1392,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1392 func.local_index += 1;1392 func.local_index += 1;
1393 }1393 }
1394 },1394 },
1395 .C => {1395 .wasm_watc => {
1396 for (fn_info.param_types.get(ip)) |ty| {1396 for (fn_info.param_types.get(ip)) |ty| {
1397 const ty_classes = abi.classifyType(Type.fromInterned(ty), zcu);1397 const ty_classes = abi.classifyType(Type.fromInterned(ty), zcu);
1398 for (ty_classes) |class| {1398 for (ty_classes) |class| {
...@@ -1410,8 +1410,9 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1410,8 +1410,9 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
14101410
1411fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread, target: std.Target) bool {1411fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread, target: std.Target) bool {
1412 switch (cc) {1412 switch (cc) {
1413 .Unspecified, .Inline => return isByRef(return_type, pt, target),1413 .@"inline" => unreachable,
1414 .C => {1414 .auto => return isByRef(return_type, pt, target),
1415 .wasm_watc => {
1415 const ty_classes = abi.classifyType(return_type, pt.zcu);1416 const ty_classes = abi.classifyType(return_type, pt.zcu);
1416 if (ty_classes[0] == .indirect) return true;1417 if (ty_classes[0] == .indirect) return true;
1417 if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true;1418 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....@@ -1424,7 +1425,7 @@ fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.
1424/// Lowers a Zig type and its value based on a given calling convention to ensure1425/// Lowers a Zig type and its value based on a given calling convention to ensure
1425/// it matches the ABI.1426/// it matches the ABI.
1426fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void {1427fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void {
1427 if (cc != .C) {1428 if (cc != .wasm_watc) {
1428 return func.lowerToStack(value);1429 return func.lowerToStack(value);
1429 }1430 }
14301431
...@@ -2108,7 +2109,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2108,7 +2109,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2108 // to the stack instead2109 // to the stack instead
2109 if (func.return_value != .none) {2110 if (func.return_value != .none) {
2110 try func.store(func.return_value, operand, ret_ty, 0);2111 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)) {
2112 switch (ret_ty.zigTypeTag(zcu)) {2113 switch (ret_ty.zigTypeTag(zcu)) {
2113 // Aggregate types can be lowered as a singular value2114 // Aggregate types can be lowered as a singular value
2114 .@"struct", .@"union" => {2115 .@"struct", .@"union" => {
...@@ -2286,7 +2287,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2286,7 +2287,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2286 } else if (first_param_sret) {2287 } else if (first_param_sret) {
2287 break :result_value sret;2288 break :result_value sret;
2288 // TODO: Make this less fragile and optimize2289 // 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") {
2290 const result_local = try func.allocLocal(ret_ty);2291 const result_local = try func.allocLocal(ret_ty);
2291 try func.addLabel(.local_set, result_local.local.value);2292 try func.addLabel(.local_set, result_local.local.value);
2292 const scalar_type = abi.scalarType(ret_ty, zcu);2293 const scalar_type = abi.scalarType(ret_ty, zcu);
...@@ -2565,7 +2566,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2565,7 +2566,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2565 const arg = func.args[arg_index];2566 const arg = func.args[arg_index];
2566 const cc = zcu.typeToFunc(zcu.navValue(func.owner_nav).typeOf(zcu)).?.cc;2567 const cc = zcu.typeToFunc(zcu.navValue(func.owner_nav).typeOf(zcu)).?.cc;
2567 const arg_ty = func.typeOfIndex(inst);2568 const arg_ty = func.typeOfIndex(inst);
2568 if (cc == .C) {2569 if (cc == .wasm_watc) {
2569 const arg_classes = abi.classifyType(arg_ty, zcu);2570 const arg_classes = abi.classifyType(arg_ty, zcu);
2570 for (arg_classes) |class| {2571 for (arg_classes) |class| {
2571 if (class != .none) {2572 if (class != .none) {
...@@ -7175,12 +7176,12 @@ fn callIntrinsic(...@@ -7175,12 +7176,12 @@ fn callIntrinsic(
7175 // Always pass over C-ABI7176 // Always pass over C-ABI
7176 const pt = func.pt;7177 const pt = func.pt;
7177 const zcu = pt.zcu;7178 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.*);
7179 defer func_type.deinit(func.gpa);7180 defer func_type.deinit(func.gpa);
7180 const func_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, func_type);7181 const func_type_index = try func.bin_file.zigObjectPtr().?.putOrGetFuncType(func.gpa, func_type);
7181 try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index);7182 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.*);
7184 // if we want return as first param, we allocate a pointer to stack,7185 // if we want return as first param, we allocate a pointer to stack,
7185 // and emit it as our first argument7186 // and emit it as our first argument
7186 const sret = if (want_sret_param) blk: {7187 const sret = if (want_sret_param) blk: {
...@@ -7193,7 +7194,7 @@ fn callIntrinsic(...@@ -7193,7 +7194,7 @@ fn callIntrinsic(
7193 for (args, 0..) |arg, arg_i| {7194 for (args, 0..) |arg, arg_i| {
7194 assert(!(want_sret_param and arg == .stack));7195 assert(!(want_sret_param and arg == .stack));
7195 assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu));7196 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);
7197 }7198 }
71987199
7199 // Actually call our intrinsic7200 // 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);...@@ -11,6 +11,7 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking);
11const wip_mir_log = std.log.scoped(.wip_mir);11const wip_mir_log = std.log.scoped(.wip_mir);
12const math = std.math;12const math = std.math;
13const mem = std.mem;13const mem = std.mem;
14const target_util = @import("../../target.zig");
14const trace = @import("../../tracy.zig").trace;15const trace = @import("../../tracy.zig").trace;
1516
16const Air = @import("../../Air.zig");17const Air = @import("../../Air.zig");
...@@ -870,10 +871,7 @@ pub fn generate(...@@ -870,10 +871,7 @@ pub fn generate(
870 try function.frame_allocs.resize(gpa, FrameIndex.named_count);871 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
871 function.frame_allocs.set(872 function.frame_allocs.set(
872 @intFromEnum(FrameIndex.stack_frame),873 @intFromEnum(FrameIndex.stack_frame),
873 FrameAlloc.init(.{874 FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }),
874 .size = 0,
875 .alignment = func.analysisUnordered(ip).stack_alignment.max(.@"1"),
876 }),
877 );875 );
878 function.frame_allocs.set(876 function.frame_allocs.set(
879 @intFromEnum(FrameIndex.call_frame),877 @intFromEnum(FrameIndex.call_frame),
...@@ -918,13 +916,13 @@ pub fn generate(...@@ -918,13 +916,13 @@ pub fn generate(
918 );916 );
919 function.va_info = switch (cc) {917 function.va_info = switch (cc) {
920 else => undefined,918 else => undefined,
921 .SysV => .{ .sysv = .{919 .x86_64_sysv => .{ .sysv = .{
922 .gp_count = call_info.gp_count,920 .gp_count = call_info.gp_count,
923 .fp_count = call_info.fp_count,921 .fp_count = call_info.fp_count,
924 .overflow_arg_area = .{ .index = .args_frame, .off = call_info.stack_byte_count },922 .overflow_arg_area = .{ .index = .args_frame, .off = call_info.stack_byte_count },
925 .reg_save_area = undefined,923 .reg_save_area = undefined,
926 } },924 } },
927 .Win64 => .{ .win64 = .{} },925 .x86_64_win => .{ .win64 = .{} },
928 };926 };
929927
930 function.gen() catch |err| switch (err) {928 function.gen() catch |err| switch (err) {
...@@ -1053,7 +1051,7 @@ pub fn generateLazy(...@@ -1053,7 +1051,7 @@ pub fn generateLazy(
1053 .bin_file = bin_file,1051 .bin_file = bin_file,
1054 .allocator = gpa,1052 .allocator = gpa,
1055 .mir = mir,1053 .mir = mir,
1056 .cc = abi.resolveCallingConvention(.Unspecified, function.target.*),1054 .cc = abi.resolveCallingConvention(.auto, function.target.*),
1057 .src_loc = src_loc,1055 .src_loc = src_loc,
1058 .output_mode = comp.config.output_mode,1056 .output_mode = comp.config.output_mode,
1059 .link_mode = comp.config.link_mode,1057 .link_mode = comp.config.link_mode,
...@@ -1159,7 +1157,7 @@ fn formatWipMir(...@@ -1159,7 +1157,7 @@ fn formatWipMir(
1159 .extra = data.self.mir_extra.items,1157 .extra = data.self.mir_extra.items,
1160 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),1158 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),
1161 },1159 },
1162 .cc = .Unspecified,1160 .cc = .auto,
1163 .src_loc = data.self.src_loc,1161 .src_loc = data.self.src_loc,
1164 .output_mode = comp.config.output_mode,1162 .output_mode = comp.config.output_mode,
1165 .link_mode = comp.config.link_mode,1163 .link_mode = comp.config.link_mode,
...@@ -2023,7 +2021,7 @@ fn gen(self: *Self) InnerError!void {...@@ -2023,7 +2021,7 @@ fn gen(self: *Self) InnerError!void {
2023 const zcu = pt.zcu;2021 const zcu = pt.zcu;
2024 const fn_info = zcu.typeToFunc(self.fn_type).?;2022 const fn_info = zcu.typeToFunc(self.fn_type).?;
2025 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);2023 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
2026 if (cc != .Naked) {2024 if (cc != .naked) {
2027 try self.asmRegister(.{ ._, .push }, .rbp);2025 try self.asmRegister(.{ ._, .push }, .rbp);
2028 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));2026 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));
2029 try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));2027 try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));
...@@ -2056,7 +2054,7 @@ fn gen(self: *Self) InnerError!void {...@@ -2056,7 +2054,7 @@ fn gen(self: *Self) InnerError!void {
2056 }2054 }
20572055
2058 if (fn_info.is_var_args) switch (cc) {2056 if (fn_info.is_var_args) switch (cc) {
2059 .SysV => {2057 .x86_64_sysv => {
2060 const info = &self.va_info.sysv;2058 const info = &self.va_info.sysv;
2061 const reg_save_area_fi = try self.allocFrameIndex(FrameAlloc.init(.{2059 const reg_save_area_fi = try self.allocFrameIndex(FrameAlloc.init(.{
2062 .size = abi.SysV.c_abi_int_param_regs.len * 8 +2060 .size = abi.SysV.c_abi_int_param_regs.len * 8 +
...@@ -2089,7 +2087,7 @@ fn gen(self: *Self) InnerError!void {...@@ -2089,7 +2087,7 @@ fn gen(self: *Self) InnerError!void {
20892087
2090 self.performReloc(skip_sse_reloc);2088 self.performReloc(skip_sse_reloc);
2091 },2089 },
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", .{}),
2093 else => unreachable,2091 else => unreachable,
2094 };2092 };
20952093
...@@ -2541,7 +2539,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -2541,7 +2539,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2541 const enum_ty = Type.fromInterned(lazy_sym.ty);2539 const enum_ty = Type.fromInterned(lazy_sym.ty);
2542 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});2540 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.*);
2545 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);2543 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
2546 const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);2544 const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
2547 defer for (param_locks) |lock| self.register_manager.unlockReg(lock);2545 defer for (param_locks) |lock| self.register_manager.unlockReg(lock);
...@@ -3008,9 +3006,8 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {...@@ -3008,9 +3006,8 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
30083006
3009pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void {3007pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void {
3010 switch (cc) {3008 switch (cc) {
3011 inline .SysV, .Win64 => |known_cc| try self.spillRegisters(3009 .x86_64_sysv => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_sysv = .{} })),
3012 comptime abi.getCallerPreservedRegs(known_cc),3010 .x86_64_win => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_win = .{} })),
3013 ),
3014 else => unreachable,3011 else => unreachable,
3015 }3012 }
3016}3013}
...@@ -12384,7 +12381,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12384,7 +12381,7 @@ fn genCall(self: *Self, info: union(enum) {
12384 .lib => |lib| try pt.funcType(.{12381 .lib => |lib| try pt.funcType(.{
12385 .param_types = lib.param_types,12382 .param_types = lib.param_types,
12386 .return_type = lib.return_type,12383 .return_type = lib.return_type,
12387 .cc = .C,12384 .cc = self.target.cCallingConvention().?,
12388 }),12385 }),
12389 };12386 };
12390 const fn_info = zcu.typeToFunc(fn_ty).?;12387 const fn_info = zcu.typeToFunc(fn_ty).?;
...@@ -12543,7 +12540,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12543,7 +12540,7 @@ fn genCall(self: *Self, info: union(enum) {
12543 src_arg,12540 src_arg,
12544 .{},12541 .{},
12545 ),12542 ),
12546 .C, .SysV, .Win64 => {12543 .x86_64_sysv, .x86_64_win => {
12547 const promoted_ty = self.promoteInt(arg_ty);12544 const promoted_ty = self.promoteInt(arg_ty);
12548 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu));12545 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu));
12549 const dst_alias = registerAlias(dst_reg, promoted_abi_size);12546 const dst_alias = registerAlias(dst_reg, promoted_abi_size);
...@@ -16822,7 +16819,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {...@@ -16822,7 +16819,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
16822 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;16819 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
16823 const inst_ty = self.typeOfIndex(inst);16820 const inst_ty = self.typeOfIndex(inst);
16824 const enum_ty = self.typeOf(un_op);16821 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
16827 // We need a properly aligned and sized call frame to be able to call this function.16824 // We need a properly aligned and sized call frame to be able to call this function.
16828 {16825 {
...@@ -18915,7 +18912,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -18915,7 +18912,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
18915 self.fn_type.fnCallingConvention(zcu),18912 self.fn_type.fnCallingConvention(zcu),
18916 self.target.*,18913 self.target.*,
18917 )) {18914 )) {
18918 .SysV => result: {18915 .x86_64_sysv => result: {
18919 const info = self.va_info.sysv;18916 const info = self.va_info.sysv;
18920 const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, zcu));18917 const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, zcu));
18921 var field_off: u31 = 0;18918 var field_off: u31 = 0;
...@@ -18957,7 +18954,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {...@@ -18957,7 +18954,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
18957 field_off += @intCast(ptr_anyopaque_ty.abiSize(zcu));18954 field_off += @intCast(ptr_anyopaque_ty.abiSize(zcu));
18958 break :result .{ .load_frame = .{ .index = dst_fi } };18955 break :result .{ .load_frame = .{ .index = dst_fi } };
18959 },18956 },
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", .{}),
18961 else => unreachable,18958 else => unreachable,
18962 };18959 };
18963 return self.finishAir(inst, result, .{ .none, .none, .none });18960 return self.finishAir(inst, result, .{ .none, .none, .none });
...@@ -18976,7 +18973,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -18976,7 +18973,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
18976 self.fn_type.fnCallingConvention(zcu),18973 self.fn_type.fnCallingConvention(zcu),
18977 self.target.*,18974 self.target.*,
18978 )) {18975 )) {
18979 .SysV => result: {18976 .x86_64_sysv => result: {
18980 try self.spillEflagsIfOccupied();18977 try self.spillEflagsIfOccupied();
1898118978
18982 const tmp_regs =18979 const tmp_regs =
...@@ -19155,7 +19152,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -19155,7 +19152,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
19155 );19152 );
19156 break :result promote_mcv;19153 break :result promote_mcv;
19157 },19154 },
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", .{}),
19159 else => unreachable,19156 else => unreachable,
19160 };19157 };
19161 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });19158 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -19324,21 +19321,21 @@ fn resolveCallingConventionValues(...@@ -19324,21 +19321,21 @@ fn resolveCallingConventionValues(
1932419321
19325 const resolved_cc = abi.resolveCallingConvention(cc, self.target.*);19322 const resolved_cc = abi.resolveCallingConvention(cc, self.target.*);
19326 switch (cc) {19323 switch (cc) {
19327 .Naked => {19324 .naked => {
19328 assert(result.args.len == 0);19325 assert(result.args.len == 0);
19329 result.return_value = InstTracking.init(.unreach);19326 result.return_value = InstTracking.init(.unreach);
19330 result.stack_align = .@"8";19327 result.stack_align = .@"8";
19331 },19328 },
19332 .C, .SysV, .Win64 => {19329 .x86_64_sysv, .x86_64_win => |cc_opts| {
19333 var ret_int_reg_i: u32 = 0;19330 var ret_int_reg_i: u32 = 0;
19334 var ret_sse_reg_i: u32 = 0;19331 var ret_sse_reg_i: u32 = 0;
19335 var param_int_reg_i: u32 = 0;19332 var param_int_reg_i: u32 = 0;
19336 var param_sse_reg_i: u32 = 0;19333 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
19339 switch (resolved_cc) {19336 switch (resolved_cc) {
19340 .SysV => {},19337 .x86_64_sysv => {},
19341 .Win64 => {19338 .x86_64_win => {
19342 // Align the stack to 16bytes before allocating shadow stack space (if any).19339 // Align the stack to 16bytes before allocating shadow stack space (if any).
19343 result.stack_byte_count += @intCast(4 * Type.usize.abiSize(zcu));19340 result.stack_byte_count += @intCast(4 * Type.usize.abiSize(zcu));
19344 },19341 },
...@@ -19356,8 +19353,8 @@ fn resolveCallingConventionValues(...@@ -19356,8 +19353,8 @@ fn resolveCallingConventionValues(
19356 var ret_tracking_i: usize = 0;19353 var ret_tracking_i: usize = 0;
1935719354
19358 const classes = switch (resolved_cc) {19355 const classes = switch (resolved_cc) {
19359 .SysV => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),19356 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
19360 .Win64 => &.{abi.classifyWindows(ret_ty, zcu)},19357 .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)},
19361 else => unreachable,19358 else => unreachable,
19362 };19359 };
19363 for (classes) |class| switch (class) {19360 for (classes) |class| switch (class) {
...@@ -19419,8 +19416,8 @@ fn resolveCallingConventionValues(...@@ -19419,8 +19416,8 @@ fn resolveCallingConventionValues(
19419 for (param_types, result.args) |ty, *arg| {19416 for (param_types, result.args) |ty, *arg| {
19420 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));19417 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
19421 switch (resolved_cc) {19418 switch (resolved_cc) {
19422 .SysV => {},19419 .x86_64_sysv => {},
19423 .Win64 => {19420 .x86_64_win => {
19424 param_int_reg_i = @max(param_int_reg_i, param_sse_reg_i);19421 param_int_reg_i = @max(param_int_reg_i, param_sse_reg_i);
19425 param_sse_reg_i = param_int_reg_i;19422 param_sse_reg_i = param_int_reg_i;
19426 },19423 },
...@@ -19431,8 +19428,8 @@ fn resolveCallingConventionValues(...@@ -19431,8 +19428,8 @@ fn resolveCallingConventionValues(
19431 var arg_mcv_i: usize = 0;19428 var arg_mcv_i: usize = 0;
1943219429
19433 const classes = switch (resolved_cc) {19430 const classes = switch (resolved_cc) {
19434 .SysV => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),19431 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
19435 .Win64 => &.{abi.classifyWindows(ty, zcu)},19432 .x86_64_win => &.{abi.classifyWindows(ty, zcu)},
19436 else => unreachable,19433 else => unreachable,
19437 };19434 };
19438 for (classes) |class| switch (class) {19435 for (classes) |class| switch (class) {
...@@ -19464,11 +19461,11 @@ fn resolveCallingConventionValues(...@@ -19464,11 +19461,11 @@ fn resolveCallingConventionValues(
19464 },19461 },
19465 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),19462 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),
19466 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {19463 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {
19467 .SysV => switch (class) {19464 .x86_64_sysv => switch (class) {
19468 .x87, .x87up, .complex_x87, .memory => break,19465 .x87, .x87up, .complex_x87, .memory => break,
19469 else => unreachable,19466 else => unreachable,
19470 },19467 },
19471 .Win64 => if (ty.abiSize(zcu) > 8) {19468 .x86_64_win => if (ty.abiSize(zcu) > 8) {
19472 const param_int_reg =19469 const param_int_reg =
19473 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();19470 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
19474 param_int_reg_i += 1;19471 param_int_reg_i += 1;
...@@ -19515,10 +19512,13 @@ fn resolveCallingConventionValues(...@@ -19515,10 +19512,13 @@ fn resolveCallingConventionValues(
19515 }19512 }
1951619513
19517 const param_size: u31 = @intCast(ty.abiSize(zcu));19514 const param_size: u31 = @intCast(ty.abiSize(zcu));
19518 const param_align: u31 =19515 const param_align = ty.abiAlignment(zcu).max(.@"8");
19519 @intCast(@max(ty.abiAlignment(zcu).toByteUnits().?, 8));19516 result.stack_byte_count = mem.alignForward(
19520 result.stack_byte_count =19517 u31,
19521 mem.alignForward(u31, result.stack_byte_count, param_align);19518 result.stack_byte_count,
19519 @intCast(param_align.toByteUnits().?),
19520 );
19521 result.stack_align = result.stack_align.max(param_align);
19522 arg.* = .{ .load_frame = .{19522 arg.* = .{ .load_frame = .{
19523 .index = stack_frame_base,19523 .index = stack_frame_base,
19524 .off = result.stack_byte_count,19524 .off = result.stack_byte_count,
...@@ -19530,7 +19530,7 @@ fn resolveCallingConventionValues(...@@ -19530,7 +19530,7 @@ fn resolveCallingConventionValues(
19530 assert(param_sse_reg_i <= 16);19530 assert(param_sse_reg_i <= 16);
19531 result.fp_count = param_sse_reg_i;19531 result.fp_count = param_sse_reg_i;
19532 },19532 },
19533 .Unspecified => {19533 .auto => {
19534 result.stack_align = .@"16";19534 result.stack_align = .@"16";
1953519535
19536 // Return values19536 // Return values
...@@ -19560,9 +19560,13 @@ fn resolveCallingConventionValues(...@@ -19560,9 +19560,13 @@ fn resolveCallingConventionValues(
19560 continue;19560 continue;
19561 }19561 }
19562 const param_size: u31 = @intCast(ty.abiSize(zcu));19562 const param_size: u31 = @intCast(ty.abiSize(zcu));
19563 const param_align: u31 = @intCast(ty.abiAlignment(zcu).toByteUnits().?);19563 const param_align = ty.abiAlignment(zcu);
19564 result.stack_byte_count =19564 result.stack_byte_count = mem.alignForward(
19565 mem.alignForward(u31, result.stack_byte_count, param_align);19565 u31,
19566 result.stack_byte_count,
19567 @intCast(param_align.toByteUnits().?),
19568 );
19569 result.stack_align = result.stack_align.max(param_align);
19566 arg.* = .{ .load_frame = .{19570 arg.* = .{ .load_frame = .{
19567 .index = stack_frame_base,19571 .index = stack_frame_base,
19568 .off = result.stack_byte_count,19572 .off = result.stack_byte_count,
src/arch/x86_64/abi.zig+15-15
...@@ -440,9 +440,9 @@ pub fn resolveCallingConvention(...@@ -440,9 +440,9 @@ pub fn resolveCallingConvention(
440 target: std.Target,440 target: std.Target,
441) std.builtin.CallingConvention {441) std.builtin.CallingConvention {
442 return switch (cc) {442 return switch (cc) {
443 .Unspecified, .C => switch (target.os.tag) {443 .auto => switch (target.os.tag) {
444 else => .SysV,444 else => .{ .x86_64_sysv = .{} },
445 .windows => .Win64,445 .windows => .{ .x86_64_win = .{} },
446 },446 },
447 else => cc,447 else => cc,
448 };448 };
...@@ -450,48 +450,48 @@ pub fn resolveCallingConvention(...@@ -450,48 +450,48 @@ pub fn resolveCallingConvention(
450450
451pub fn getCalleePreservedRegs(cc: std.builtin.CallingConvention) []const Register {451pub fn getCalleePreservedRegs(cc: std.builtin.CallingConvention) []const Register {
452 return switch (cc) {452 return switch (cc) {
453 .SysV => &SysV.callee_preserved_regs,453 .x86_64_sysv => &SysV.callee_preserved_regs,
454 .Win64 => &Win64.callee_preserved_regs,454 .x86_64_win => &Win64.callee_preserved_regs,
455 else => unreachable,455 else => unreachable,
456 };456 };
457}457}
458458
459pub fn getCallerPreservedRegs(cc: std.builtin.CallingConvention) []const Register {459pub fn getCallerPreservedRegs(cc: std.builtin.CallingConvention) []const Register {
460 return switch (cc) {460 return switch (cc) {
461 .SysV => &SysV.caller_preserved_regs,461 .x86_64_sysv => &SysV.caller_preserved_regs,
462 .Win64 => &Win64.caller_preserved_regs,462 .x86_64_win => &Win64.caller_preserved_regs,
463 else => unreachable,463 else => unreachable,
464 };464 };
465}465}
466466
467pub fn getCAbiIntParamRegs(cc: std.builtin.CallingConvention) []const Register {467pub fn getCAbiIntParamRegs(cc: std.builtin.CallingConvention) []const Register {
468 return switch (cc) {468 return switch (cc) {
469 .SysV => &SysV.c_abi_int_param_regs,469 .x86_64_sysv => &SysV.c_abi_int_param_regs,
470 .Win64 => &Win64.c_abi_int_param_regs,470 .x86_64_win => &Win64.c_abi_int_param_regs,
471 else => unreachable,471 else => unreachable,
472 };472 };
473}473}
474474
475pub fn getCAbiSseParamRegs(cc: std.builtin.CallingConvention) []const Register {475pub fn getCAbiSseParamRegs(cc: std.builtin.CallingConvention) []const Register {
476 return switch (cc) {476 return switch (cc) {
477 .SysV => &SysV.c_abi_sse_param_regs,477 .x86_64_sysv => &SysV.c_abi_sse_param_regs,
478 .Win64 => &Win64.c_abi_sse_param_regs,478 .x86_64_win => &Win64.c_abi_sse_param_regs,
479 else => unreachable,479 else => unreachable,
480 };480 };
481}481}
482482
483pub fn getCAbiIntReturnRegs(cc: std.builtin.CallingConvention) []const Register {483pub fn getCAbiIntReturnRegs(cc: std.builtin.CallingConvention) []const Register {
484 return switch (cc) {484 return switch (cc) {
485 .SysV => &SysV.c_abi_int_return_regs,485 .x86_64_sysv => &SysV.c_abi_int_return_regs,
486 .Win64 => &Win64.c_abi_int_return_regs,486 .x86_64_win => &Win64.c_abi_int_return_regs,
487 else => unreachable,487 else => unreachable,
488 };488 };
489}489}
490490
491pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention) []const Register {491pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention) []const Register {
492 return switch (cc) {492 return switch (cc) {
493 .SysV => &SysV.c_abi_sse_return_regs,493 .x86_64_sysv => &SysV.c_abi_sse_return_regs,
494 .Win64 => &Win64.c_abi_sse_return_regs,494 .x86_64_win => &Win64.c_abi_sse_return_regs,
495 else => unreachable,495 else => unreachable,
496 };496 };
497}497}
src/codegen/c.zig+35-8
...@@ -1783,7 +1783,7 @@ pub const DeclGen = struct {...@@ -1783,7 +1783,7 @@ pub const DeclGen = struct {
1783 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);1783 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);
17841784
1785 const fn_info = zcu.typeToFunc(fn_ty).?;1785 const fn_info = zcu.typeToFunc(fn_ty).?;
1786 if (fn_info.cc == .Naked) {1786 if (fn_info.cc == .naked) {
1787 switch (kind) {1787 switch (kind) {
1788 .forward => try w.writeAll("zig_naked_decl "),1788 .forward => try w.writeAll("zig_naked_decl "),
1789 .complete => try w.writeAll("zig_naked "),1789 .complete => try w.writeAll("zig_naked "),
...@@ -1796,7 +1796,7 @@ pub const DeclGen = struct {...@@ -1796,7 +1796,7 @@ pub const DeclGen = struct {
17961796
1797 var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{});1797 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| {
1800 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });1800 try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
1801 trailing = .maybe_space;1801 trailing = .maybe_space;
1802 }1802 }
...@@ -7604,12 +7604,39 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void {...@@ -7604,12 +7604,39 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void {
7604 return w.writeAll(toMemoryOrder(order));7604 return w.writeAll(toMemoryOrder(order));
7605}7605}
76067606
7607fn toCallingConvention(call_conv: std.builtin.CallingConvention) ?[]const u8 {7607fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 {
7608 return switch (call_conv) {7608 if (zcu.getTarget().cCallingConvention()) |ccc| {
7609 .Stdcall => "stdcall",7609 if (cc.eql(ccc)) {
7610 .Fastcall => "fastcall",7610 return null;
7611 .Vectorcall => "vectorcall",7611 }
7612 else => null,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`
7613 };7640 };
7614}7641}
76157642
src/codegen/llvm.zig+348-242
...@@ -1159,7 +1159,7 @@ pub const Object = struct {...@@ -1159,7 +1159,7 @@ pub const Object = struct {
1159 }1159 }
11601160
1161 {1161 {
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);
1163 defer module_flags.deinit();1163 defer module_flags.deinit();
11641164
1165 const behavior_error = try o.builder.metadataConstant(try o.builder.intConst(.i32, 1));1165 const behavior_error = try o.builder.metadataConstant(try o.builder.intConst(.i32, 1));
...@@ -1233,6 +1233,18 @@ pub const Object = struct {...@@ -1233,6 +1233,18 @@ pub const Object = struct {
1233 }1233 }
1234 }1234 }
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
1236 try o.builder.metadataNamed(try o.builder.metadataString("llvm.module.flags"), module_flags.items);1248 try o.builder.metadataNamed(try o.builder.metadataString("llvm.module.flags"), module_flags.items);
1237 }1249 }
12381250
...@@ -1467,14 +1479,6 @@ pub const Object = struct {...@@ -1467,14 +1479,6 @@ pub const Object = struct {
1467 _ = try attributes.removeFnAttr(.@"noinline");1479 _ = try attributes.removeFnAttr(.@"noinline");
1468 }1480 }
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
1478 if (func_analysis.branch_hint == .cold) {1482 if (func_analysis.branch_hint == .cold) {
1479 try attributes.addFnAttr(.cold, &o.builder);1483 try attributes.addFnAttr(.cold, &o.builder);
1480 } else {1484 } else {
...@@ -1486,7 +1490,7 @@ pub const Object = struct {...@@ -1486,7 +1490,7 @@ pub const Object = struct {
1486 } else {1490 } else {
1487 _ = try attributes.removeFnAttr(.sanitize_thread);1491 _ = try attributes.removeFnAttr(.sanitize_thread);
1488 }1492 }
1489 const is_naked = fn_info.cc == .Naked;1493 const is_naked = fn_info.cc == .naked;
1490 if (owner_mod.fuzz and !func_analysis.disable_instrumentation and !is_naked) {1494 if (owner_mod.fuzz and !func_analysis.disable_instrumentation and !is_naked) {
1491 try attributes.addFnAttr(.optforfuzzing, &o.builder);1495 try attributes.addFnAttr(.optforfuzzing, &o.builder);
1492 _ = try attributes.removeFnAttr(.skipprofile);1496 _ = try attributes.removeFnAttr(.skipprofile);
...@@ -1784,7 +1788,7 @@ pub const Object = struct {...@@ -1784,7 +1788,7 @@ pub const Object = struct {
1784 .liveness = liveness,1788 .liveness = liveness,
1785 .ng = &ng,1789 .ng = &ng,
1786 .wip = wip,1790 .wip = wip,
1787 .is_naked = fn_info.cc == .Naked,1791 .is_naked = fn_info.cc == .naked,
1788 .fuzz = fuzz,1792 .fuzz = fuzz,
1789 .ret_ptr = ret_ptr,1793 .ret_ptr = ret_ptr,
1790 .args = args.items,1794 .args = args.items,
...@@ -3038,14 +3042,33 @@ pub const Object = struct {...@@ -3038,14 +3042,33 @@ pub const Object = struct {
3038 llvm_arg_i += 1;3042 llvm_arg_i += 1;
3039 }3043 }
30403044
3041 switch (fn_info.cc) {3045 if (fn_info.cc == .@"async") {
3042 .Unspecified, .Inline => function_index.setCallConv(.fastcc, &o.builder),3046 @panic("TODO: LLVM backend lower async function");
3043 .Naked => try attributes.addFnAttr(.naked, &o.builder),3047 }
3044 .Async => {3048
3045 function_index.setCallConv(.fastcc, &o.builder);3049 {
3046 @panic("TODO: LLVM backend lower async function");3050 const cc_info = toLlvmCallConv(fn_info.cc, target).?;
3047 },3051
3048 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),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 }
3049 }3072 }
30503073
3051 if (resolved.alignment != .none)3074 if (resolved.alignment != .none)
...@@ -3061,7 +3084,7 @@ pub const Object = struct {...@@ -3061,7 +3084,7 @@ pub const Object = struct {
3061 // suppress generation of the prologue and epilogue, and the prologue is where the3084 // suppress generation of the prologue and epilogue, and the prologue is where the
3062 // frame pointer normally gets set up. At time of writing, this is the case for at3085 // frame pointer normally gets set up. At time of writing, this is the case for at
3063 // least x86 and RISC-V.3086 // 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,
3065 );3088 );
30663089
3067 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);3090 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
...@@ -4618,9 +4641,14 @@ pub const Object = struct {...@@ -4618,9 +4641,14 @@ pub const Object = struct {
4618 if (!param_ty.isPtrLikeOptional(zcu) and !ptr_info.flags.is_allowzero) {4641 if (!param_ty.isPtrLikeOptional(zcu) and !ptr_info.flags.is_allowzero) {
4619 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);4642 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4620 }4643 }
4621 if (fn_info.cc == .Interrupt) {4644 switch (fn_info.cc) {
4622 const child_type = try lowerType(o, Type.fromInterned(ptr_info.child));4645 else => {},
4623 try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder);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 },
4624 }4652 }
4625 if (ptr_info.flags.is_const) {4653 if (ptr_info.flags.is_const) {
4626 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);4654 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
...@@ -5677,7 +5705,7 @@ pub const FuncGen = struct {...@@ -5677,7 +5705,7 @@ pub const FuncGen = struct {
5677 .always_tail => .musttail,5705 .always_tail => .musttail,
5678 .async_kw, .no_async, .always_inline, .compile_time => unreachable,5706 .async_kw, .no_async, .always_inline, .compile_time => unreachable,
5679 },5707 },
5680 toLlvmCallConv(fn_info.cc, target),5708 toLlvmCallConvTag(fn_info.cc, target).?,
5681 try attributes.finish(&o.builder),5709 try attributes.finish(&o.builder),
5682 try o.lowerType(zig_fn_ty),5710 try o.lowerType(zig_fn_ty),
5683 llvm_fn,5711 llvm_fn,
...@@ -5756,7 +5784,7 @@ pub const FuncGen = struct {...@@ -5756,7 +5784,7 @@ pub const FuncGen = struct {
5756 _ = try fg.wip.callIntrinsicAssumeCold();5784 _ = try fg.wip.callIntrinsicAssumeCold();
5757 _ = try fg.wip.call(5785 _ = try fg.wip.call(
5758 .normal,5786 .normal,
5759 toLlvmCallConv(fn_info.cc, target),5787 toLlvmCallConvTag(fn_info.cc, target).?,
5760 .none,5788 .none,
5761 panic_global.typeOf(&o.builder),5789 panic_global.typeOf(&o.builder),
5762 panic_global.toValue(&o.builder),5790 panic_global.toValue(&o.builder),
...@@ -11554,36 +11582,146 @@ fn toLlvmAtomicRmwBinOp(...@@ -11554,36 +11582,146 @@ fn toLlvmAtomicRmwBinOp(
11554 };11582 };
11555}11583}
1155611584
11557fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) Builder.CallConv {11585const CallingConventionInfo = struct {
11558 return switch (cc) {11586 /// The LLVM calling convention to use.
11559 .Unspecified, .Inline, .Async => .fastcc,11587 llvm_cc: Builder.CallConv,
11560 .C, .Naked => .ccc,11588 /// Whether to use an `alignstack` attribute to forcibly re-align the stack pointer in the function's prologue.
11561 .Stdcall => .x86_stdcallcc,11589 align_stack: bool,
11562 .Fastcall => .x86_fastcallcc,11590 /// Whether the function needs a `naked` attribute.
11563 .Vectorcall => return switch (target.cpu.arch) {11591 naked: bool,
11564 .x86, .x86_64 => .x86_vectorcallcc,11592 /// How many leading parameters to apply the `inreg` attribute to.
11565 .aarch64, .aarch64_be => .aarch64_vector_pcs,11593 inreg_param_count: u2 = 0,
11566 else => unreachable,11594};
11567 },11595
11568 .Thiscall => .x86_thiscallcc,11596pub fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) ?CallingConventionInfo {
11569 .APCS => .arm_apcscc,11597 const llvm_cc = toLlvmCallConvTag(cc, target) orelse return null;
11570 .AAPCS => .arm_aapcscc,11598 const incoming_stack_alignment: ?u64, const register_params: u2 = switch (cc) {
11571 .AAPCSVFP => .arm_aapcs_vfpcc,11599 inline else => |pl| switch (@TypeOf(pl)) {
11572 .Interrupt => return switch (target.cpu.arch) {11600 void => .{ null, 0 },
11573 .x86, .x86_64 => .x86_intrcc,11601 std.builtin.CallingConvention.CommonOptions => .{ pl.incoming_stack_alignment, 0 },
11574 .avr => .avr_intrcc,11602 std.builtin.CallingConvention.X86RegparmOptions => .{ pl.incoming_stack_alignment, pl.register_params },
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,
11584 else => unreachable,11603 else => unreachable,
11585 },11604 },
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,
11587 };11725 };
11588}11726}
1158911727
...@@ -11711,31 +11849,27 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe...@@ -11711,31 +11849,27 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe
11711 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false;11849 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false;
1171211850
11713 return switch (fn_info.cc) {11851 return switch (fn_info.cc) {
11714 .Unspecified, .Inline => returnTypeByRef(zcu, target, return_type),11852 .auto => returnTypeByRef(zcu, target, return_type),
11715 .C => switch (target.cpu.arch) {11853 .x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
11716 .mips, .mipsel => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {11854 .x86_64_win => x86_64_abi.classifyWindows(return_type, zcu) == .memory,
11717 .memory, .i32_array => true,11855 .x86_sysv, .x86_win => isByRef(return_type, zcu),
11718 .byval => false,11856 .x86_stdcall => !isScalar(zcu, return_type),
11719 },11857 .wasm_watc => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect,
11720 .x86 => isByRef(return_type, zcu),11858 .aarch64_aapcs,
11721 .x86_64 => switch (target.os.tag) {11859 .aarch64_aapcs_darwin,
11722 .windows => x86_64_abi.classifyWindows(return_type, zcu) == .memory,11860 .aarch64_aapcs_win,
11723 else => firstParamSRetSystemV(return_type, zcu, target),11861 => aarch64_c_abi.classifyType(return_type, zcu) == .memory,
11724 },11862 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11725 .wasm32 => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect,11863 .memory, .i64_array => true,
11726 .aarch64, .aarch64_be => aarch64_c_abi.classifyType(return_type, zcu) == .memory,11864 .i32_array => |size| size != 1,
11727 .arm, .armeb => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {11865 .byval => false,
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
11734 },11866 },
11735 .SysV => firstParamSRetSystemV(return_type, zcu, target),11867 .riscv64_lp64, .riscv32_ilp32 => riscv_c_abi.classifyType(return_type, zcu) == .memory,
11736 .Win64 => x86_64_abi.classifyWindows(return_type, zcu) == .memory,11868 .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11737 .Stdcall => !isScalar(zcu, return_type),11869 .memory, .i32_array => true,
11738 else => false,11870 .byval => false,
11871 },
11872 else => false, // TODO: investigate other targets/callconvs
11739 };11873 };
11740}11874}
1174111875
...@@ -11761,82 +11895,64 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu...@@ -11761,82 +11895,64 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
11761 }11895 }
11762 const target = zcu.getTarget();11896 const target = zcu.getTarget();
11763 switch (fn_info.cc) {11897 switch (fn_info.cc) {
11764 .Unspecified,11898 .@"inline" => unreachable,
11765 .Inline,11899 .auto => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type),
11766 => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type),11900
1176711901 .x86_64_sysv => return lowerSystemVFnRetTy(o, fn_info),
11768 .C => {11902 .x86_64_win => return lowerWin64FnRetTy(o, fn_info),
11769 switch (target.cpu.arch) {11903 .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void,
11770 .mips, .mipsel => {11904 .x86_sysv, .x86_win => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type),
11771 switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {11905 .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(return_type, zcu)) {
11772 .memory, .i32_array => return .void,11906 .memory => return .void,
11773 .byval => return o.lowerType(return_type),11907 .float_array => return o.lowerType(return_type),
11774 }11908 .byval => return o.lowerType(return_type),
11775 },11909 .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))),
11776 .x86 => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type),11910 .double_integer => return o.builder.arrayType(2, .i64),
11777 .x86_64 => switch (target.os.tag) {11911 },
11778 .windows => return lowerWin64FnRetTy(o, fn_info),11912 .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {
11779 else => return lowerSystemVFnRetTy(o, fn_info),11913 .memory, .i64_array => return .void,
11780 },11914 .i32_array => |len| return if (len == 1) .i32 else .void,
11781 .wasm32 => {11915 .byval => return o.lowerType(return_type),
11782 if (isScalar(zcu, return_type)) {11916 },
11783 return o.lowerType(return_type);11917 .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) {
11784 }11918 .memory, .i32_array => return .void,
11785 const classes = wasm_c_abi.classifyType(return_type, zcu);11919 .byval => return o.lowerType(return_type),
11786 if (classes[0] == .indirect or classes[0] == .none) {11920 },
11787 return .void;11921 .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(return_type, zcu)) {
11788 }11922 .memory => return .void,
1178911923 .integer => {
11790 assert(classes[0] == .direct and classes[1] == .none);11924 return o.builder.intType(@intCast(return_type.bitSize(zcu)));
11791 const scalar_type = wasm_c_abi.scalarType(return_type, zcu);11925 },
11792 return o.builder.intType(@intCast(scalar_type.abiSize(zcu) * 8));11926 .double_integer => {
11793 },11927 return o.builder.structType(.normal, &.{ .i64, .i64 });
11794 .aarch64, .aarch64_be => {11928 },
11795 switch (aarch64_c_abi.classifyType(return_type, zcu)) {11929 .byval => return o.lowerType(return_type),
11796 .memory => return .void,11930 .fields => {
11797 .float_array => return o.lowerType(return_type),11931 var types_len: usize = 0;
11798 .byval => return o.lowerType(return_type),11932 var types: [8]Builder.Type = undefined;
11799 .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))),11933 for (0..return_type.structFieldCount(zcu)) |field_index| {
11800 .double_integer => return o.builder.arrayType(2, .i64),11934 const field_ty = return_type.fieldType(field_index, zcu);
11801 }11935 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11802 },11936 types[types_len] = try o.lowerType(field_ty);
11803 .arm, .armeb => {11937 types_len += 1;
11804 switch (arm_c_abi.classifyType(return_type, zcu, .ret)) {11938 }
11805 .memory, .i64_array => return .void,11939 return o.builder.structType(.normal, types[0..types_len]);
11806 .i32_array => |len| return if (len == 1) .i32 else .void,11940 },
11807 .byval => return o.lowerType(return_type),11941 },
11808 }11942 .wasm_watc => {
11809 },11943 if (isScalar(zcu, return_type)) {
11810 .riscv32, .riscv64 => {11944 return o.lowerType(return_type);
11811 switch (riscv_c_abi.classifyType(return_type, zcu)) {11945 }
11812 .memory => return .void,11946 const classes = wasm_c_abi.classifyType(return_type, zcu);
11813 .integer => {11947 if (classes[0] == .indirect or classes[0] == .none) {
11814 return o.builder.intType(@intCast(return_type.bitSize(zcu)));11948 return .void;
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),
11835 }11949 }
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));
11836 },11954 },
11837 .Win64 => return lowerWin64FnRetTy(o, fn_info),11955 // TODO investigate other callconvs
11838 .SysV => return lowerSystemVFnRetTy(o, fn_info),
11839 .Stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void,
11840 else => return o.lowerType(return_type),11956 else => return o.lowerType(return_type),
11841 }11957 }
11842}11958}
...@@ -11989,7 +12105,8 @@ const ParamTypeIterator = struct {...@@ -11989,7 +12105,8 @@ const ParamTypeIterator = struct {
11989 return .no_bits;12105 return .no_bits;
11990 }12106 }
11991 switch (it.fn_info.cc) {12107 switch (it.fn_info.cc) {
11992 .Unspecified, .Inline => {12108 .@"inline" => unreachable,
12109 .auto => {
11993 it.zig_index += 1;12110 it.zig_index += 1;
11994 it.llvm_index += 1;12111 it.llvm_index += 1;
11995 if (ty.isSlice(zcu) or12112 if (ty.isSlice(zcu) or
...@@ -12010,97 +12127,12 @@ const ParamTypeIterator = struct {...@@ -12010,97 +12127,12 @@ const ParamTypeIterator = struct {
12010 return .byval;12127 return .byval;
12011 }12128 }
12012 },12129 },
12013 .Async => {12130 .@"async" => {
12014 @panic("TODO implement async function lowering in the LLVM backend");12131 @panic("TODO implement async function lowering in the LLVM backend");
12015 },12132 },
12016 .C => switch (target.cpu.arch) {12133 .x86_64_sysv => return it.nextSystemV(ty),
12017 .mips, .mipsel => {12134 .x86_64_win => return it.nextWin64(ty),
12018 it.zig_index += 1;12135 .x86_stdcall => {
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 => {
12104 it.zig_index += 1;12136 it.zig_index += 1;
12105 it.llvm_index += 1;12137 it.llvm_index += 1;
1210612138
...@@ -12111,6 +12143,80 @@ const ParamTypeIterator = struct {...@@ -12111,6 +12143,80 @@ const ParamTypeIterator = struct {
12111 return .byref;12143 return .byref;
12112 }12144 }
12113 },12145 },
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
12114 else => {12220 else => {
12115 it.zig_index += 1;12221 it.zig_index += 1;
12116 it.llvm_index += 1;12222 it.llvm_index += 1;
...@@ -12269,7 +12375,7 @@ fn ccAbiPromoteInt(...@@ -12269,7 +12375,7 @@ fn ccAbiPromoteInt(
12269) ?std.builtin.Signedness {12375) ?std.builtin.Signedness {
12270 const target = zcu.getTarget();12376 const target = zcu.getTarget();
12271 switch (cc) {12377 switch (cc) {
12272 .Unspecified, .Inline, .Async => return null,12378 .auto, .@"inline", .@"async" => return null,
12273 else => {},12379 else => {},
12274 }12380 }
12275 const int_info = switch (ty.zigTypeTag(zcu)) {12381 const int_info = switch (ty.zigTypeTag(zcu)) {
src/codegen/llvm/Builder.zig+13
...@@ -2052,6 +2052,7 @@ pub const CallConv = enum(u10) {...@@ -2052,6 +2052,7 @@ pub const CallConv = enum(u10) {
2052 x86_intrcc,2052 x86_intrcc,
2053 avr_intrcc,2053 avr_intrcc,
2054 avr_signalcc,2054 avr_signalcc,
2055 avr_builtincc,
20552056
2056 amdgpu_vs = 87,2057 amdgpu_vs = 87,
2057 amdgpu_gs,2058 amdgpu_gs,
...@@ -2060,6 +2061,7 @@ pub const CallConv = enum(u10) {...@@ -2060,6 +2061,7 @@ pub const CallConv = enum(u10) {
2060 amdgpu_kernel,2061 amdgpu_kernel,
2061 x86_regcallcc,2062 x86_regcallcc,
2062 amdgpu_hs,2063 amdgpu_hs,
2064 msp430_builtincc,
20632065
2064 amdgpu_ls = 95,2066 amdgpu_ls = 95,
2065 amdgpu_es,2067 amdgpu_es,
...@@ -2068,9 +2070,15 @@ pub const CallConv = enum(u10) {...@@ -2068,9 +2070,15 @@ pub const CallConv = enum(u10) {
20682070
2069 amdgpu_gfx = 100,2071 amdgpu_gfx = 100,
20702072
2073 m68k_intrcc,
2074
2071 aarch64_sme_preservemost_from_x0 = 102,2075 aarch64_sme_preservemost_from_x0 = 102,
2072 aarch64_sme_preservemost_from_x2,2076 aarch64_sme_preservemost_from_x2,
20732077
2078 m68k_rtdcc = 106,
2079
2080 riscv_vectorcallcc = 110,
2081
2074 _,2082 _,
20752083
2076 pub const default = CallConv.ccc;2084 pub const default = CallConv.ccc;
...@@ -2115,6 +2123,7 @@ pub const CallConv = enum(u10) {...@@ -2115,6 +2123,7 @@ pub const CallConv = enum(u10) {
2115 .x86_intrcc,2123 .x86_intrcc,
2116 .avr_intrcc,2124 .avr_intrcc,
2117 .avr_signalcc,2125 .avr_signalcc,
2126 .avr_builtincc,
2118 .amdgpu_vs,2127 .amdgpu_vs,
2119 .amdgpu_gs,2128 .amdgpu_gs,
2120 .amdgpu_ps,2129 .amdgpu_ps,
...@@ -2122,13 +2131,17 @@ pub const CallConv = enum(u10) {...@@ -2122,13 +2131,17 @@ pub const CallConv = enum(u10) {
2122 .amdgpu_kernel,2131 .amdgpu_kernel,
2123 .x86_regcallcc,2132 .x86_regcallcc,
2124 .amdgpu_hs,2133 .amdgpu_hs,
2134 .msp430_builtincc,
2125 .amdgpu_ls,2135 .amdgpu_ls,
2126 .amdgpu_es,2136 .amdgpu_es,
2127 .aarch64_vector_pcs,2137 .aarch64_vector_pcs,
2128 .aarch64_sve_vector_pcs,2138 .aarch64_sve_vector_pcs,
2129 .amdgpu_gfx,2139 .amdgpu_gfx,
2140 .m68k_intrcc,
2130 .aarch64_sme_preservemost_from_x0,2141 .aarch64_sme_preservemost_from_x0,
2131 .aarch64_sme_preservemost_from_x2,2142 .aarch64_sme_preservemost_from_x2,
2143 .m68k_rtdcc,
2144 .riscv_vectorcallcc,
2132 => try writer.print(" {s}", .{@tagName(self)}),2145 => try writer.print(" {s}", .{@tagName(self)}),
2133 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),2146 _ => try writer.print(" cc{d}", .{@intFromEnum(self)}),
2134 }2147 }
src/codegen/spirv.zig+3-3
...@@ -1640,8 +1640,8 @@ const NavGen = struct {...@@ -1640,8 +1640,8 @@ const NavGen = struct {
16401640
1641 comptime assert(zig_call_abi_ver == 3);1641 comptime assert(zig_call_abi_ver == 3);
1642 switch (fn_info.cc) {1642 switch (fn_info.cc) {
1643 .Unspecified, .Kernel, .Fragment, .Vertex, .C => {},1643 .auto, .spirv_kernel, .spirv_fragment, .spirv_vertex => {},
1644 else => unreachable, // TODO1644 else => @panic("TODO"),
1645 }1645 }
16461646
1647 // TODO: Put this somewhere in Sema.zig1647 // TODO: Put this somewhere in Sema.zig
...@@ -2970,7 +2970,7 @@ const NavGen = struct {...@@ -2970,7 +2970,7 @@ const NavGen = struct {
2970 .id_result_type = return_ty_id,2970 .id_result_type = return_ty_id,
2971 .id_result = result_id,2971 .id_result = result_id,
2972 .function_control = switch (fn_info.cc) {2972 .function_control = switch (fn_info.cc) {
2973 .Inline => .{ .Inline = true },2973 .@"inline" => .{ .Inline = true },
2974 else => .{},2974 else => .{},
2975 },2975 },
2976 .function_type = prototype_ty_id,2976 .function_type = prototype_ty_id,
src/link/C.zig+1-1
...@@ -217,7 +217,7 @@ pub fn updateFunc(...@@ -217,7 +217,7 @@ pub fn updateFunc(
217 .mod = zcu.navFileScope(func.owner_nav).mod,217 .mod = zcu.navFileScope(func.owner_nav).mod,
218 .error_msg = null,218 .error_msg = null,
219 .pass = .{ .nav = func.owner_nav },219 .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,
221 .fwd_decl = fwd_decl.toManaged(gpa),221 .fwd_decl = fwd_decl.toManaged(gpa),
222 .ctype_pool = ctype_pool.*,222 .ctype_pool = ctype_pool.*,
223 .scratch = .{},223 .scratch = .{},
src/link/Coff.zig+6-4
...@@ -1488,14 +1488,16 @@ pub fn updateExports(...@@ -1488,14 +1488,16 @@ pub fn updateExports(
1488 const exported_nav = ip.getNav(exported_nav_index);1488 const exported_nav = ip.getNav(exported_nav_index);
1489 const exported_ty = exported_nav.typeOf(ip);1489 const exported_ty = exported_nav.typeOf(ip);
1490 if (!ip.isFunctionType(exported_ty)) continue;1490 if (!ip.isFunctionType(exported_ty)) continue;
1491 const c_cc = target.cCallingConvention().?;
1491 const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {1492 const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
1492 .x86 => .Stdcall,1493 .x86 => .{ .x86_stdcall = .{} },
1493 else => .C,1494 else => c_cc,
1494 };1495 };
1495 const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);1496 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) {
1497 zcu.stage1_flags.have_c_main = true;1499 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) {
1499 if (exp.opts.name.eqlSlice("WinMain", ip)) {1501 if (exp.opts.name.eqlSlice("WinMain", ip)) {
1500 zcu.stage1_flags.have_winmain = true;1502 zcu.stage1_flags.have_winmain = true;
1501 } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {1503 } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
src/link/Dwarf.zig+65-15
...@@ -3398,21 +3398,71 @@ fn updateType(...@@ -3398,21 +3398,71 @@ fn updateType(
3398 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;3398 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
3399 try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);3399 try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);
3400 try wip_nav.strp(name);3400 try wip_nav.strp(name);
3401 try diw.writeByte(@intFromEnum(@as(DW.CC, switch (func_type.cc) {3401 const cc: DW.CC = cc: {
3402 .Unspecified, .C => .normal,3402 if (zcu.getTarget().cCallingConvention()) |cc| {
3403 .Naked, .Async, .Inline => .nocall,3403 if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) {
3404 .Interrupt, .Signal => .nocall,3404 break :cc .normal;
3405 .Stdcall => .BORLAND_stdcall,3405 }
3406 .Fastcall => .BORLAND_fastcall,3406 }
3407 .Vectorcall => .LLVM_vectorcall,3407 // For better or worse, we try to match what Clang emits.
3408 .Thiscall => .BORLAND_thiscall,3408 break :cc switch (func_type.cc) {
3409 .APCS => .nocall,3409 .@"inline" => unreachable,
3410 .AAPCS => .LLVM_AAPCS,3410 .@"async", .auto, .naked => .normal,
3411 .AAPCSVFP => .LLVM_AAPCS_VFP,3411 .x86_64_sysv => .LLVM_X86_64SysV,
3412 .SysV => .LLVM_X86_64SysV,3412 .x86_64_win => .LLVM_Win64,
3413 .Win64 => .LLVM_Win64,3413 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
3414 .Kernel, .Fragment, .Vertex => .nocall,3414 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
3415 })));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));
3416 try wip_nav.refType(Type.fromInterned(func_type.return_type));3466 try wip_nav.refType(Type.fromInterned(func_type.return_type));
3417 for (0..func_type.param_types.len) |param_index| {3467 for (0..func_type.param_types.len) |param_index| {
3418 try wip_nav.abbrevCode(.func_type_param);3468 try wip_nav.abbrevCode(.func_type_param);
src/link/SpirV.zig+3-4
...@@ -165,10 +165,9 @@ pub fn updateExports(...@@ -165,10 +165,9 @@ pub fn updateExports(
165 const target = zcu.getTarget();165 const target = zcu.getTarget();
166 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);166 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
167 const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) {167 const execution_model = switch (Type.fromInterned(nav_ty).fnCallingConvention(zcu)) {
168 .Vertex => spec.ExecutionModel.Vertex,168 .spirv_vertex => spec.ExecutionModel.Vertex,
169 .Fragment => spec.ExecutionModel.Fragment,169 .spirv_fragment => spec.ExecutionModel.Fragment,
170 .Kernel => spec.ExecutionModel.Kernel,170 .spirv_kernel => spec.ExecutionModel.Kernel,
171 .C => return, // TODO: What to do here?
172 else => unreachable,171 else => unreachable,
173 };172 };
174 const is_vulkan = target.os.tag == .vulkan;173 const is_vulkan = target.os.tag == .vulkan;
src/print_zir.zig-1
...@@ -567,7 +567,6 @@ const Writer = struct {...@@ -567,7 +567,6 @@ const Writer = struct {
567 .c_undef,567 .c_undef,
568 .c_include,568 .c_include,
569 .set_float_mode,569 .set_float_mode,
570 .set_align_stack,
571 .wasm_memory_size,570 .wasm_memory_size,
572 .int_from_error,571 .int_from_error,
573 .error_from_int,572 .error_from_int,
src/target.zig+3-3
...@@ -544,13 +544,13 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {...@@ -544,13 +544,13 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
544 };544 };
545}545}
546546
547pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConvention) bool {547pub fn fnCallConvAllowsZigTypes(cc: std.builtin.CallingConvention) bool {
548 return switch (cc) {548 return switch (cc) {
549 .Unspecified, .Async, .Inline => true,549 .auto, .@"async", .@"inline" => true,
550 // For now we want to authorize PTX kernel to use zig objects, even if550 // For now we want to authorize PTX kernel to use zig objects, even if
551 // we end up exposing the ABI. The goal is to experiment with more551 // we end up exposing the ABI. The goal is to experiment with more
552 // integrated CPU/GPU code.552 // integrated CPU/GPU code.
553 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,553 .nvptx_kernel => true,
554 else => false,554 else => false,
555 };555 };
556}556}
src/translate_c.zig+16-14
...@@ -4,7 +4,6 @@ const assert = std.debug.assert;...@@ -4,7 +4,6 @@ const assert = std.debug.assert;
4const mem = std.mem;4const mem = std.mem;
5const math = std.math;5const math = std.math;
6const meta = std.meta;6const meta = std.meta;
7const CallingConvention = std.builtin.CallingConvention;
8const clang = @import("clang.zig");7const clang = @import("clang.zig");
9const aro = @import("aro");8const aro = @import("aro");
10const CToken = aro.Tokenizer.Token;9const CToken = aro.Tokenizer.Token;
...@@ -5001,17 +5000,20 @@ fn transCC(...@@ -5001,17 +5000,20 @@ fn transCC(
5001 c: *Context,5000 c: *Context,
5002 fn_ty: *const clang.FunctionType,5001 fn_ty: *const clang.FunctionType,
5003 source_loc: clang.SourceLocation,5002 source_loc: clang.SourceLocation,
5004) !CallingConvention {5003) !ast.Payload.Func.CallingConvention {
5005 const clang_cc = fn_ty.getCallConv();5004 const clang_cc = fn_ty.getCallConv();
5006 switch (clang_cc) {5005 return switch (clang_cc) {
5007 .C => return CallingConvention.C,5006 .C => .c,
5008 .X86StdCall => return CallingConvention.Stdcall,5007 .X86_64SysV => .x86_64_sysv,
5009 .X86FastCall => return CallingConvention.Fastcall,5008 .Win64 => .x86_64_win,
5010 .X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall,5009 .X86StdCall => .x86_stdcall,
5011 .X86ThisCall => return CallingConvention.Thiscall,5010 .X86FastCall => .x86_fastcall,
5012 .AAPCS => return CallingConvention.AAPCS,5011 .X86ThisCall => .x86_thiscall,
5013 .AAPCS_VFP => return CallingConvention.AAPCSVFP,5012 .X86VectorCall => .x86_vectorcall,
5014 .X86_64SysV => return CallingConvention.SysV,5013 .AArch64VectorCall => .aarch64_vfabi,
5014 .AAPCS => .arm_aapcs,
5015 .AAPCS_VFP => .arm_aapcs_vfp,
5016 .M68kRTD => .m68k_rtd,
5015 else => return fail(5017 else => return fail(
5016 c,5018 c,
5017 error.UnsupportedType,5019 error.UnsupportedType,
...@@ -5019,7 +5021,7 @@ fn transCC(...@@ -5019,7 +5021,7 @@ fn transCC(
5019 "unsupported calling convention: {s}",5021 "unsupported calling convention: {s}",
5020 .{@tagName(clang_cc)},5022 .{@tagName(clang_cc)},
5021 ),5023 ),
5022 }5024 };
5023}5025}
50245026
5025fn transFnProto(5027fn transFnProto(
...@@ -5056,7 +5058,7 @@ fn finishTransFnProto(...@@ -5056,7 +5058,7 @@ fn finishTransFnProto(
5056 source_loc: clang.SourceLocation,5058 source_loc: clang.SourceLocation,
5057 fn_decl_context: ?FnDeclContext,5059 fn_decl_context: ?FnDeclContext,
5058 is_var_args: bool,5060 is_var_args: bool,
5059 cc: CallingConvention,5061 cc: ast.Payload.Func.CallingConvention,
5060 is_pub: bool,5062 is_pub: bool,
5061) !*ast.Payload.Func {5063) !*ast.Payload.Func {
5062 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;5064 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
...@@ -5104,7 +5106,7 @@ fn finishTransFnProto(...@@ -5104,7 +5106,7 @@ fn finishTransFnProto(
51045106
5105 const alignment = if (fn_decl) |decl| ClangAlignment.forFunc(c, decl).zigAlignment() else null;5107 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
5109 const return_type_node = blk: {5111 const return_type_node = blk: {
5110 if (fn_ty.getNoReturnAttr()) {5112 if (fn_ty.getNoReturnAttr()) {
stage1/zig.h+35-25
...@@ -248,37 +248,55 @@ typedef char bool;...@@ -248,37 +248,55 @@ typedef char bool;
248248
249#if zig_has_builtin(trap)249#if zig_has_builtin(trap)
250#define zig_trap() __builtin_trap()250#define zig_trap() __builtin_trap()
251#elif _MSC_VER && (_M_IX86 || _M_X64)251#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
252#define zig_trap() __ud2()252#define zig_trap() __ud2()
253#elif _MSC_VER253#elif defined(_MSC_VER)
254#define zig_trap() __fastfail(0)254#define zig_trap() __fastfail(7)
255#elif defined(__i386__) || defined(__x86_64__)255#elif defined(__thumb__)
256#define zig_trap() __asm__ volatile("ud2");256#define zig_trap() __asm__ volatile("udf #0xfe")
257#elif defined(__arm__) || defined(__aarch64__)257#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")
259#else271#else
260#include <stdlib.h>272#define zig_trap() zig_trap_unavailable
261#define zig_trap() abort()
262#endif273#endif
263274
264#if zig_has_builtin(debugtrap)275#if zig_has_builtin(debugtrap)
265#define zig_breakpoint() __builtin_debugtrap()276#define zig_breakpoint() __builtin_debugtrap()
266#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)277#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
267#define zig_breakpoint() __debugbreak()278#define zig_breakpoint() __debugbreak()
268#elif defined(__i386__) || defined(__x86_64__)
269#define zig_breakpoint() __asm__ volatile("int $0x03");
270#elif defined(__arm__)279#elif defined(__arm__)
271#define zig_breakpoint() __asm__ volatile("bkpt #0");280#define zig_breakpoint() __asm__ volatile("bkpt #0x0")
272#elif defined(__aarch64__)281#elif defined(__aarch64__)
273#define zig_breakpoint() __asm__ volatile("brk #0");282#define zig_breakpoint() __asm__ volatile("brk #0xf000")
274#else283#elif defined(__loongarch__)
275#include <signal.h>284#define zig_breakpoint() __asm__ volatile("break 0x0")
276#if defined(SIGTRAP)285#elif defined(__mips__)
277#define zig_breakpoint() raise(SIGTRAP)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")
278#else297#else
279#define zig_breakpoint() zig_breakpoint_unavailable298#define zig_breakpoint() zig_breakpoint_unavailable
280#endif299#endif
281#endif
282300
283#if zig_has_builtin(return_address) || defined(zig_gnuc)301#if zig_has_builtin(return_address) || defined(zig_gnuc)
284#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))302#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
...@@ -3592,7 +3610,6 @@ typedef enum memory_order zig_memory_order;...@@ -3592,7 +3610,6 @@ typedef enum memory_order zig_memory_order;
3592#define zig_atomicrmw_add_float zig_atomicrmw_add3610#define zig_atomicrmw_add_float zig_atomicrmw_add
3593#undef zig_atomicrmw_sub_float3611#undef zig_atomicrmw_sub_float
3594#define zig_atomicrmw_sub_float zig_atomicrmw_sub3612#define zig_atomicrmw_sub_float zig_atomicrmw_sub
3595#define zig_fence(order) atomic_thread_fence(order)
3596#elif defined(__GNUC__)3613#elif defined(__GNUC__)
3597typedef int zig_memory_order;3614typedef int zig_memory_order;
3598#define zig_memory_order_relaxed __ATOMIC_RELAXED3615#define zig_memory_order_relaxed __ATOMIC_RELAXED
...@@ -3616,7 +3633,6 @@ typedef int zig_memory_order;...@@ -3616,7 +3633,6 @@ typedef int zig_memory_order;
3616#define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order)3633#define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order)
3617#undef zig_atomicrmw_xchg_float3634#undef zig_atomicrmw_xchg_float
3618#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg3635#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
3619#define zig_fence(order) __atomic_thread_fence(order)
3620#elif _MSC_VER && (_M_IX86 || _M_X64)3636#elif _MSC_VER && (_M_IX86 || _M_X64)
3621#define zig_memory_order_relaxed 03637#define zig_memory_order_relaxed 0
3622#define zig_memory_order_acquire 23638#define zig_memory_order_acquire 2
...@@ -3637,11 +3653,6 @@ typedef int zig_memory_order;...@@ -3637,11 +3653,6 @@ typedef int zig_memory_order;
3637#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg)3653#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg)
3638#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg)3654#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg)
3639#define zig_atomic_load(res, obj, order, Type, ReprType) res = zig_msvc_atomic_load_ ##order##_##Type(obj)3655#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
3645/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */3656/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */
3646#else3657#else
3647#define zig_memory_order_relaxed 03658#define zig_memory_order_relaxed 0
...@@ -3663,7 +3674,6 @@ typedef int zig_memory_order;...@@ -3663,7 +3674,6 @@ typedef int zig_memory_order;
3663#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable3674#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
3664#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable3675#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable
3665#define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable3676#define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable
3666#define zig_fence(order) zig_fence_unavailable
3667#endif3677#endif
36683678
3669#if _MSC_VER && (_M_IX86 || _M_X64)3679#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" {...@@ -210,15 +210,6 @@ test "alignment and size of structs with 128-bit fields" {
210 }210 }
211}211}
212212
213test "alignstack" {
214 try expect(fnWithAlignedStack() == 1234);
215}
216
217fn fnWithAlignedStack() i32 {
218 @setAlignStack(256);
219 return 1234;
220}
221
222test "implicitly decreasing slice alignment" {213test "implicitly decreasing slice alignment" {
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO215 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 {...@@ -20,7 +20,6 @@ test {
20 try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined));20 try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined));
21 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));21 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
22 try testing.expectEqual({}, @prefetch(&val, .{}));22 try testing.expectEqual({}, @prefetch(&val, .{}));
23 try testing.expectEqual({}, @setAlignStack(16));
24 try testing.expectEqual({}, @setEvalBranchQuota(0));23 try testing.expectEqual({}, @setEvalBranchQuota(0));
25 try testing.expectEqual({}, @setFloatMode(.optimized));24 try testing.expectEqual({}, @setFloatMode(.optimized));
26 try testing.expectEqual({}, @setRuntimeSafety(true));25 try testing.expectEqual({}, @setRuntimeSafety(true));
test/behavior/type_info.zig+5-4
...@@ -350,6 +350,7 @@ fn testOpaque() !void {...@@ -350,6 +350,7 @@ fn testOpaque() !void {
350350
351test "type info: function type info" {351test "type info: function type info" {
352 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;352 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
353 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
353354
354 try testFunction();355 try testFunction();
355 try comptime testFunction();356 try comptime testFunction();
...@@ -358,7 +359,7 @@ test "type info: function type info" {...@@ -358,7 +359,7 @@ test "type info: function type info" {
358fn testFunction() !void {359fn testFunction() !void {
359 const foo_fn_type = @TypeOf(typeInfoFoo);360 const foo_fn_type = @TypeOf(typeInfoFoo);
360 const foo_fn_info = @typeInfo(foo_fn_type);361 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));
362 try expect(!foo_fn_info.@"fn".is_generic);363 try expect(!foo_fn_info.@"fn".is_generic);
363 try expect(foo_fn_info.@"fn".params.len == 2);364 try expect(foo_fn_info.@"fn".params.len == 2);
364 try expect(foo_fn_info.@"fn".is_var_args);365 try expect(foo_fn_info.@"fn".is_var_args);
...@@ -374,7 +375,7 @@ fn testFunction() !void {...@@ -374,7 +375,7 @@ fn testFunction() !void {
374375
375 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);376 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
376 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);377 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));
378 try expect(!aligned_foo_fn_info.@"fn".is_generic);379 try expect(!aligned_foo_fn_info.@"fn".is_generic);
379 try expect(aligned_foo_fn_info.@"fn".params.len == 2);380 try expect(aligned_foo_fn_info.@"fn".params.len == 2);
380 try expect(aligned_foo_fn_info.@"fn".is_var_args);381 try expect(aligned_foo_fn_info.@"fn".is_var_args);
...@@ -390,8 +391,8 @@ fn testFunction() !void {...@@ -390,8 +391,8 @@ fn testFunction() !void {
390 try expect(aligned_foo_ptr_fn_info.pointer.sentinel == null);391 try expect(aligned_foo_ptr_fn_info.pointer.sentinel == null);
391}392}
392393
393extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;394extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.c) usize;
394extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;395extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.c) usize;
395396
396test "type info: generic function types" {397test "type info: generic function types" {
397 const G1 = @typeInfo(@TypeOf(generic1));398 const G1 = @typeInfo(@TypeOf(generic1));
test/behavior/typename.zig+3-3
...@@ -79,9 +79,9 @@ test "basic" {...@@ -79,9 +79,9 @@ test "basic" {
79 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));79 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
80 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));80 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
8181
82 try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () 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));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));84 try expectEqualStrings("fn (u32, ...) callconv(.c) void", @typeName(fn (u32, ...) callconv(.c) void));
85}85}
8686
87test "top level decl" {87test "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 {...@@ -7,10 +7,9 @@ export fn zig_return_array() [10]u8 {
7}7}
88
9// error9// error
10// backend=stage210// target=x86_64-linux
11// target=native
12//11//
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'
14// :1:21: note: arrays are not allowed as a parameter type13// :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'
16// :5:30: note: arrays are not allowed as a return type15// :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 {}...@@ -8,5 +8,5 @@ inline fn b() void {}
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :2:9: error: variable of type '*const fn () callconv(.Inline) void' must be const or comptime11// :2:9: error: variable of type '*const fn () callconv(.@"inline") void' must be const or comptime
12// :2:9: note: function has inline calling convention12// :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 @@...@@ -1,7 +1,7 @@
1const Foo = packed struct(u32) {1const Foo = packed struct(u32) {
2 x: u1,2 x: u1,
3};3};
4fn bar(_: Foo) callconv(.C) void {}4fn bar(_: Foo) callconv(.c) void {}
5pub export fn entry() void {5pub export fn entry() void {
6 bar(.{ .x = 0 });6 bar(.{ .x = 0 });
7}7}
test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig+3-4
...@@ -3,9 +3,8 @@ export fn entry2() callconv(.AAPCS) void {}...@@ -3,9 +3,8 @@ export fn entry2() callconv(.AAPCS) void {}
3export fn entry3() callconv(.AAPCSVFP) void {}3export fn entry3() callconv(.AAPCSVFP) void {}
44
5// error5// error
6// backend=stage2
7// target=x86_64-linux-none6// target=x86_64-linux-none
8//7//
9// :1:30: error: callconv 'APCS' is only available on ARM, not x86_648// :1:30: error: calling convention 'arm_apcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb'
10// :2:30: error: callconv 'AAPCS' is only available on ARM, not x86_649// :2:30: error: calling convention 'arm_aapcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb'
11// :3:30: error: callconv 'AAPCSVFP' is only available on ARM, not x86_6410// :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 {}...@@ -4,4 +4,4 @@ export fn entry() callconv(.Interrupt) void {}
4// backend=stage24// backend=stage2
5// target=aarch64-linux-none5// target=aarch64-linux-none
6//6//
7// :1:29: error: callconv 'Interrupt' is only available on x86, x86_64, AVR, and MSP430, not aarch647// :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 @@...@@ -1,7 +1,7 @@
1export fn entry() callconv(.Signal) void {}1export fn entry() callconv(.avr_signal) void {}
22
3// error3// error
4// backend=stage24// backend=stage2
5// target=x86_64-linux-none5// target=x86_64-linux-none
6//6//
7// :1:29: error: callconv 'Signal' is only available on AVR, not x86_647// :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 @@...@@ -1,6 +1,6 @@
1const F1 = fn () callconv(.Stdcall) void;1const F1 = fn () callconv(.{ .x86_stdcall = .{} }) void;
2const F2 = fn () callconv(.Fastcall) void;2const F2 = fn () callconv(.{ .x86_fastcall = .{} }) void;
3const F3 = fn () callconv(.Thiscall) void;3const F3 = fn () callconv(.{ .x86_thiscall = .{} }) void;
4export fn entry1() void {4export fn entry1() void {
5 const a: F1 = undefined;5 const a: F1 = undefined;
6 _ = a;6 _ = a;
...@@ -18,6 +18,6 @@ export fn entry3() void {...@@ -18,6 +18,6 @@ export fn entry3() void {
18// backend=stage218// backend=stage2
19// target=x86_64-linux-none19// target=x86_64-linux-none
20//20//
21// :1:28: error: callconv 'Stdcall' is only available on x86, not x86_6421// :1:28: error: calling convention 'x86_stdcall' only available on architectures 'x86'
22// :2:28: error: callconv 'Fastcall' is only available on x86, not x86_6422// :2:28: error: calling convention 'x86_fastcall' only available on architectures 'x86'
23// :3:28: error: callconv 'Thiscall' is only available on x86, not x86_6423// :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(...@@ -4,7 +4,7 @@ pub inline fn requestAdapter(
4 comptime callbackArg: fn () callconv(.Inline) void,4 comptime callbackArg: fn () callconv(.Inline) void,
5) void {5) void {
6 _ = &(struct {6 _ = &(struct {
7 pub fn callback() callconv(.C) void {7 pub fn callback() callconv(.c) void {
8 callbackArg();8 callbackArg();
9 }9 }
10 }).callback;10 }).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 {...@@ -3,7 +3,6 @@ export fn foo(comptime x: anytype, y: i32) i32 {
3}3}
44
5// error5// error
6// backend=stage26// target=x86_64-linux
7// target=native
8//7//
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 {...@@ -4,7 +4,6 @@ export fn foo(num: anytype) i32 {
4}4}
55
6// error6// error
7// backend=stage27// target=x86_64-linux
8// target=native
9//8//
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 {...@@ -14,8 +14,7 @@ export fn entry() usize {
14}14}
1515
16// error16// error
17// backend=stage217// target=x86_64-linux
18// target=native
19//18//
20// :1:38: error: expected type 'fn (i32) i32', found 'fn (i32) callconv(.C) i32'19// :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'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 {...@@ -15,9 +15,8 @@ comptime {
15}15}
1616
17// error17// error
18// backend=stage218// target=x86_64-linux
19// target=native
20//19//
21// :1:15: error: comptime 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'
22// :5:30: error: comptime parameters not allowed in function with calling convention 'C'21// :5:30: error: comptime parameters not allowed in function with calling convention 'x86_64_sysv'
23// :6:30: error: generic parameters not allowed in function with calling convention 'C'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 @@...@@ -1,7 +1,3 @@
1comptime {
2 @setAlignStack(1);
3}
4
5comptime {1comptime {
6 @branchHint(.cold);2 @branchHint(.cold);
7}3}
...@@ -54,16 +50,15 @@ comptime {...@@ -54,16 +50,15 @@ comptime {
54// backend=stage250// backend=stage2
55// target=native51// target=native
56//52//
57// :2:5: error: '@setAlignStack' outside function scope53// :2:5: error: '@branchHint' outside function scope
58// :6:5: error: '@branchHint' outside function scope54// :6:5: error: '@src' outside function scope
59// :10:5: error: '@src' outside function scope55// :10:5: error: '@returnAddress' outside function scope
60// :14:5: error: '@returnAddress' outside function scope56// :14:5: error: '@frameAddress' outside function scope
61// :18:5: error: '@frameAddress' outside function scope57// :18:5: error: '@breakpoint' outside function scope
62// :22:5: error: '@breakpoint' outside function scope58// :22:5: error: '@cVaArg' outside function scope
63// :26:5: error: '@cVaArg' outside function scope59// :26:5: error: '@cVaCopy' outside function scope
64// :30:5: error: '@cVaCopy' outside function scope60// :30:5: error: '@cVaEnd' outside function scope
65// :34:5: error: '@cVaEnd' outside function scope61// :34:5: error: '@cVaStart' outside function scope
66// :38:5: error: '@cVaStart' outside function scope62// :38:5: error: '@workItemId' outside function scope
67// :42:5: error: '@workItemId' outside function scope63// :42:5: error: '@workGroupSize' outside function scope
68// :46:5: error: '@workGroupSize' outside function scope64// :46:5: error: '@workGroupId' outside function scope
69// :50: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 {...@@ -4,10 +4,9 @@ export fn entry(foo: Foo) void {
4}4}
55
6// error6// error
7// backend=stage27// target=x86_64-linux
8// target=native
9//8//
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'
11// :2:17: note: enum tag type 'u2' is not extern compatible10// :2:17: note: enum tag type 'u2' is not extern compatible
12// :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible11// :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible
13// :1:13: note: enum declared here12// :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 {...@@ -8,9 +8,8 @@ export fn entry(foo: Foo) void {
8}8}
99
10// error10// error
11// backend=stage211// target=x86_64-linux
12// target=native
13//12//
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'
15// :6:17: note: only extern structs and ABI sized packed structs are extern compatible14// :6:17: note: only extern structs and ABI sized packed structs are extern compatible
16// :1:13: note: struct declared here15// :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 {...@@ -8,9 +8,8 @@ export fn entry(foo: Foo) void {
8}8}
99
10// error10// error
11// backend=stage211// target=x86_64-linux
12// target=native
13//12//
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'
15// :6:17: note: only extern unions and ABI sized packed unions are extern compatible14// :6:17: note: only extern unions and ABI sized packed unions are extern compatible
16// :1:13: note: union declared here15// :1:13: note: union declared here
test/cases/compile_errors/invalid_extern_function_call.zig+1-1
...@@ -1,4 +1,4 @@...@@ -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
3export fn entry0() void {3export fn entry0() void {
4 comptime x();4 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 {}...@@ -9,12 +9,11 @@ export fn signal_param(_: u32) callconv(.Signal) void {}
9export fn signal_ret() callconv(.Signal) noreturn {}9export fn signal_ret() callconv(.Signal) noreturn {}
1010
11// error11// error
12// backend=stage2
13// target=x86_64-linux12// target=x86_64-linux
14// 13//
15// :1:28: error: first parameter of function with 'Interrupt' calling convention must be a pointer type14// :1:28: error: first parameter of function with 'x86_64_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 integer15// :2:43: error: second parameter of function with 'x86_64_interrupt' calling convention must be a 64-bit integer
17// :3:51: error: 'Interrupt' calling convention supports up to 2 parameters, found 316// :3:51: error: 'x86_64_interrupt' calling convention supports up to 2 parameters, found 3
18// :4:69: error: function with calling convention 'Interrupt' must return 'void' or 'noreturn'17// :4:69: error: function with calling convention 'x86_64_interrupt' must return 'void' or 'noreturn'
19// :8:24: error: parameters are not allowed with 'Signal' calling convention18// :8:24: error: parameters are not allowed with 'avr_signal' calling convention
20// :9:34: error: callconv 'Signal' is only available on AVR, not x86_6419// :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 {...@@ -9,4 +9,4 @@ pub export fn entry() void {
9// backend=llvm9// backend=llvm
10// target=native10// target=native
11//11//
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 {...@@ -13,11 +13,10 @@ comptime {
13}13}
1414
15// error15// error
16// backend=stage216// target=x86_64-linux
17// target=native
18//17//
19// :1:1: error: variadic function does not support '.Unspecified' calling convention18// :1:1: error: variadic function does not support 'auto' calling convention
20// :1:1: note: supported calling conventions: '.C'19// :1:1: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win'
21// :1:1: error: variadic function does not support '.Inline' calling convention20// :1:1: error: variadic function does not support 'inline' calling convention
22// :1:1: note: supported calling conventions: '.C'21// :1:1: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win'
23// :2:1: error: generic function cannot be variadic22// :2:1: error: generic function cannot be variadic
test/cases/compile_errors/noinline_fn_cc_inline.zig+2-3
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const cc = .Inline;1noinline fn foo() callconv(.@"inline") void {}
2noinline fn foo() callconv(cc) void {}
32
4comptime {3comptime {
5 _ = foo;4 _ = foo;
...@@ -9,4 +8,4 @@ comptime {...@@ -9,4 +8,4 @@ comptime {
9// backend=stage28// backend=stage2
10// target=native9// target=native
11//10//
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 @@...@@ -1,20 +1,20 @@
1const S = extern struct {1const S = extern struct {
2 a: fn () callconv(.C) void,2 a: fn () callconv(.c) void,
3};3};
4comptime {4comptime {
5 _ = @sizeOf(S) == 1;5 _ = @sizeOf(S) == 1;
6}6}
7comptime {7comptime {
8 _ = [*c][4]fn () callconv(.C) void;8 _ = [*c][4]fn () callconv(.c) void;
9}9}
1010
11// error11// error
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
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'
16// :2:8: note: type has no guaranteed in-memory representation16// :2:8: note: type has no guaranteed in-memory representation
17// :2:8: note: use '*const ' to make a function pointer type17// :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'
19// :8:13: note: type has no guaranteed in-memory representation19// :8:13: note: type has no guaranteed in-memory representation
20// :8:13: note: use '*const ' to make a function pointer type20// :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 {...@@ -12,8 +12,7 @@ comptime {
12}12}
1313
14// error14// error
15// backend=stage215// target=x86_64-linux
16// target=native
17//16//
18// :1:13: error: variadic function does not support '.Unspecified' calling convention17// :1:13: error: variadic function does not support 'auto' calling convention
19// :1:13: note: supported calling conventions: '.C'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 @@...@@ -1,5 +1,5 @@
1const GuSettings = struct {1const GuSettings = struct {
2 fin: ?fn (c_int) callconv(.C) void,2 fin: ?fn (c_int) callconv(.c) void,
3};3};
4pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {4pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
5 const settings: ?*GuSettings = @as(?*GuSettings, @ptrFromInt(@intFromPtr(arg)));5 const settings: ?*GuSettings = @as(?*GuSettings, @ptrFromInt(@intFromPtr(arg)));
...@@ -13,4 +13,4 @@ pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {...@@ -13,4 +13,4 @@ pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
13//13//
14// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known14// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known
15// :2:10: note: struct requires comptime because of this field15// :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 type16// :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 @@...@@ -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;
2export fn entry() void {2export fn entry() void {
3 _ = Text;3 _ = Text;
4}4}
55
6// error6// error
7// backend=stage27// target=x86_64-linux
8// target=native
9//8//
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'
11// :1:16: note: slices have no guaranteed in-memory representation10// :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 @@...@@ -1,4 +1,4 @@
1const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void;1const fn_ty = ?fn ([*c]u8, ...) callconv(.c) void;
2extern fn fn_decl(fmt: [*:0]u8, ...) void;2extern fn fn_decl(fmt: [*:0]u8, ...) void;
33
4export fn main() void {4export fn main() void {
...@@ -10,6 +10,6 @@ export fn main() void {...@@ -10,6 +10,6 @@ export fn main() void {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
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'
14// :5:22: note: parameter 0 '[*:0]u8' cannot cast into '[*c]u8'14// :5:22: note: parameter 0 '[*:0]u8' cannot cast into '[*c]u8'
15// :5:22: note: '[*c]u8' could have null values which are illegal in type '[*:0]u8'15// :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 @@...@@ -1,4 +1,4 @@
1fn entry() callconv(.C) void {}1fn entry() callconv(.c) void {}
2comptime {2comptime {
3 @export(&entry, .{ .name = "entry", .linkage = @as(u32, 1234) });3 @export(&entry, .{ .name = "entry", .linkage = @as(u32, 1234) });
4}4}
test/cases/translate_c/static empty struct.c +1-1
...@@ -9,7 +9,7 @@ static inline void foo() {...@@ -9,7 +9,7 @@ static inline void foo() {
9// c_frontend=clang9// c_frontend=clang
10//10//
11// pub const struct_empty_struct = extern struct {};11// pub const struct_empty_struct = extern struct {};
12// pub fn foo() callconv(.C) void {12// pub fn foo() callconv(.c) void {
13// const bar = struct {13// const bar = struct {
14// var static: struct_empty_struct = @import("std").mem.zeroes(struct_empty_struct);14// var static: struct_empty_struct = @import("std").mem.zeroes(struct_empty_struct);
15// };15// };
test/translate_c.zig+34-34
...@@ -484,11 +484,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -484,11 +484,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
484 \\ fnptr_attr_ty qux;484 \\ fnptr_attr_ty qux;
485 \\};485 \\};
486 , &[_][]const u8{486 , &[_][]const u8{
487 \\pub const fnptr_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;488 \\pub const fnptr_attr_ty = ?*const fn () callconv(.c) void;
489 \\pub const struct_foo = extern struct {489 \\pub const struct_foo = extern struct {
490 \\ foo: ?*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),491 \\ bar: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void),
492 \\ baz: fnptr_ty = @import("std").mem.zeroes(fnptr_ty),492 \\ baz: fnptr_ty = @import("std").mem.zeroes(fnptr_ty),
493 \\ qux: fnptr_attr_ty = @import("std").mem.zeroes(fnptr_attr_ty),493 \\ qux: fnptr_attr_ty = @import("std").mem.zeroes(fnptr_attr_ty),
494 \\};494 \\};
...@@ -735,7 +735,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -735,7 +735,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
735 \\static void bar(void) {}735 \\static void bar(void) {}
736 , &[_][]const u8{736 , &[_][]const u8{
737 \\pub export fn foo() void {}737 \\pub export fn foo() void {}
738 \\pub fn bar() callconv(.C) void {}738 \\pub fn bar() callconv(.c) void {}
739 });739 });
740740
741 cases.add("typedef void",741 cases.add("typedef void",
...@@ -769,7 +769,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -769,7 +769,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
769 \\pub export fn bar() void {769 \\pub export fn bar() void {
770 \\ var func_ptr: ?*anyopaque = @as(?*anyopaque, @ptrCast(&foo));770 \\ var func_ptr: ?*anyopaque = @as(?*anyopaque, @ptrCast(&foo));
771 \\ _ = &func_ptr;771 \\ _ = &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)))));
773 \\ _ = &typed_func_ptr;773 \\ _ = &typed_func_ptr;
774 \\}774 \\}
775 });775 });
...@@ -839,9 +839,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -839,9 +839,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
839 \\ lws_callback_function *callback_http;839 \\ lws_callback_function *callback_http;
840 \\};840 \\};
841 , &[_][]const u8{841 , &[_][]const u8{
842 \\pub const lws_callback_function = fn () callconv(.C) void;842 \\pub const lws_callback_function = fn () callconv(.c) void;
843 \\pub const struct_Foo = extern struct {843 \\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),
845 \\ callback_http: ?*const lws_callback_function = @import("std").mem.zeroes(?*const lws_callback_function),845 \\ callback_http: ?*const lws_callback_function = @import("std").mem.zeroes(?*const lws_callback_function),
846 \\};846 \\};
847 });847 });
...@@ -867,7 +867,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -867,7 +867,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
867 \\};867 \\};
868 , &[_][]const u8{868 , &[_][]const u8{
869 \\pub const struct_Foo = extern struct {869 \\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),
871 \\};871 \\};
872 ,872 ,
873 \\pub const Foo = struct_Foo;873 \\pub const Foo = struct_Foo;
...@@ -1111,7 +1111,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1111,7 +1111,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1111 cases.add("__cdecl doesn't mess up function pointers",1111 cases.add("__cdecl doesn't mess up function pointers",
1112 \\void foo(void (__cdecl *fn_ptr)(void));1112 \\void foo(void (__cdecl *fn_ptr)(void));
1113 , &[_][]const u8{1113 , &[_][]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;
1115 });1115 });
11161116
1117 cases.add("void cast",1117 cases.add("void cast",
...@@ -1477,8 +1477,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1477,8 +1477,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1477 \\typedef void (*fn0)();1477 \\typedef void (*fn0)();
1478 \\typedef void (*fn1)(char);1478 \\typedef void (*fn1)(char);
1479 , &[_][]const u8{1479 , &[_][]const u8{
1480 \\pub const fn0 = ?*const fn (...) callconv(.C) void;1480 \\pub const fn0 = ?*const fn (...) callconv(.c) void;
1481 \\pub const fn1 = ?*const fn (u8) callconv(.C) void;1481 \\pub const fn1 = ?*const fn (u8) callconv(.c) void;
1482 });1482 });
14831483
1484 cases.addWithTarget("Calling convention", .{1484 cases.addWithTarget("Calling convention", .{
...@@ -1492,11 +1492,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1492,11 +1492,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1492 \\void __attribute__((cdecl)) foo4(float *a);1492 \\void __attribute__((cdecl)) foo4(float *a);
1493 \\void __attribute__((thiscall)) foo5(float *a);1493 \\void __attribute__((thiscall)) foo5(float *a);
1494 , &[_][]const u8{1494 , &[_][]const u8{
1495 \\pub extern fn foo1(a: [*c]f32) callconv(.Fastcall) void;1495 \\pub extern fn foo1(a: [*c]f32) callconv(.{ .x86_fastcall = .{} }) void;
1496 \\pub extern fn foo2(a: [*c]f32) callconv(.Stdcall) void;1496 \\pub extern fn foo2(a: [*c]f32) callconv(.{ .x86_stdcall = .{} }) void;
1497 \\pub extern fn foo3(a: [*c]f32) callconv(.Vectorcall) void;1497 \\pub extern fn foo3(a: [*c]f32) callconv(.{ .x86_vectorcall = .{} }) void;
1498 \\pub extern fn foo4(a: [*c]f32) void;1498 \\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;
1500 });1500 });
15011501
1502 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{1502 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
...@@ -1506,8 +1506,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1506,8 +1506,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1506 \\void __attribute__((pcs("aapcs"))) foo1(float *a);1506 \\void __attribute__((pcs("aapcs"))) foo1(float *a);
1507 \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);1507 \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
1508 , &[_][]const u8{1508 , &[_][]const u8{
1509 \\pub extern fn foo1(a: [*c]f32) callconv(.AAPCS) void;1509 \\pub extern fn foo1(a: [*c]f32) callconv(.{ .arm_aapcs = .{} }) void;
1510 \\pub extern fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;1510 \\pub extern fn foo2(a: [*c]f32) callconv(.{ .arm_aapcs_vfp = .{} }) void;
1511 });1511 });
15121512
1513 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{1513 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
...@@ -1516,7 +1516,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1516,7 +1516,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1516 }) catch unreachable,1516 }) catch unreachable,
1517 \\void __attribute__((aarch64_vector_pcs)) foo1(float *a);1517 \\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
1518 , &[_][]const u8{1518 , &[_][]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;
1520 });1520 });
15211521
1522 cases.add("Parameterless function prototypes",1522 cases.add("Parameterless function prototypes",
...@@ -1533,8 +1533,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1533,8 +1533,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1533 \\pub export fn b() void {}1533 \\pub export fn b() void {}
1534 \\pub extern fn c(...) void;1534 \\pub extern fn c(...) void;
1535 \\pub extern fn d() void;1535 \\pub extern fn d() void;
1536 \\pub fn e() callconv(.C) void {}1536 \\pub fn e() callconv(.c) void {}
1537 \\pub fn f() callconv(.C) void {}1537 \\pub fn f() callconv(.c) void {}
1538 \\pub extern fn g() void;1538 \\pub extern fn g() void;
1539 \\pub extern fn h() void;1539 \\pub extern fn h() void;
1540 });1540 });
...@@ -1555,7 +1555,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1555,7 +1555,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1555 \\ char *arr1[10] ={0};1555 \\ char *arr1[10] ={0};
1556 \\}1556 \\}
1557 , &[_][]const u8{1557 , &[_][]const u8{
1558 \\pub fn foo() callconv(.C) void {1558 \\pub fn foo() callconv(.c) void {
1559 \\ var arr: [10]u8 = [1]u8{1559 \\ var arr: [10]u8 = [1]u8{
1560 \\ 1,1560 \\ 1,
1561 \\ } ++ [1]u8{0} ** 9;1561 \\ } ++ [1]u8{0} ** 9;
...@@ -1686,13 +1686,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1686,13 +1686,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1686 \\extern char (*fn_ptr2)(int, float);1686 \\extern char (*fn_ptr2)(int, float);
1687 \\#define bar fn_ptr21687 \\#define bar fn_ptr2
1688 , &[_][]const u8{1688 , &[_][]const u8{
1689 \\pub extern var fn_ptr: ?*const fn () callconv(.C) void;1689 \\pub extern var fn_ptr: ?*const fn () callconv(.c) void;
1690 ,1690 ,
1691 \\pub inline fn foo() void {1691 \\pub inline fn foo() void {
1692 \\ return fn_ptr.?();1692 \\ return fn_ptr.?();
1693 \\}1693 \\}
1694 ,1694 ,
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;
1696 ,1696 ,
1697 \\pub inline fn bar(arg_1: c_int, arg_2: f32) u8 {1697 \\pub inline fn bar(arg_1: c_int, arg_2: f32) u8 {
1698 \\ return fn_ptr2.?(arg_1, arg_2);1698 \\ return fn_ptr2.?(arg_1, arg_2);
...@@ -1714,8 +1714,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1714,8 +1714,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1714 \\#define glClearPFN PFNGLCLEARPROC1714 \\#define glClearPFN PFNGLCLEARPROC
1715 , &[_][]const u8{1715 , &[_][]const u8{
1716 \\pub const GLbitfield = c_uint;1716 \\pub const GLbitfield = c_uint;
1717 \\pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.C) void;1717 \\pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.c) void;
1718 \\pub const OpenGLProc = ?*const fn () callconv(.C) void;1718 \\pub const OpenGLProc = ?*const fn () callconv(.c) void;
1719 \\const struct_unnamed_1 = extern struct {1719 \\const struct_unnamed_1 = extern struct {
1720 \\ Clear: PFNGLCLEARPROC = @import("std").mem.zeroes(PFNGLCLEARPROC),1720 \\ Clear: PFNGLCLEARPROC = @import("std").mem.zeroes(PFNGLCLEARPROC),
1721 \\};1721 \\};
...@@ -2691,9 +2691,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2691,9 +2691,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2691 \\ return 0;2691 \\ return 0;
2692 \\}2692 \\}
2693 \\pub export fn bar() void {2693 \\pub export fn bar() void {
2694 \\ var f: ?*const fn () callconv(.C) void = &foo;2694 \\ var f: ?*const fn () callconv(.c) void = &foo;
2695 \\ _ = &f;2695 \\ _ = &f;
2696 \\ var b: ?*const fn () callconv(.C) c_int = &baz;2696 \\ var b: ?*const fn () callconv(.c) c_int = &baz;
2697 \\ _ = &b;2697 \\ _ = &b;
2698 \\ f.?();2698 \\ f.?();
2699 \\ f.?();2699 \\ f.?();
...@@ -3048,8 +3048,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3048,8 +3048,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3048 \\ baz();3048 \\ baz();
3049 \\}3049 \\}
3050 , &[_][]const u8{3050 , &[_][]const u8{
3051 \\pub fn bar() callconv(.C) void {}3051 \\pub fn bar() callconv(.c) void {}
3052 \\pub export fn foo(arg_baz: ?*const fn () callconv(.C) [*c]c_int) void {3052 \\pub export fn foo(arg_baz: ?*const fn () callconv(.c) [*c]c_int) void {
3053 \\ var baz = arg_baz;3053 \\ var baz = arg_baz;
3054 \\ _ = &baz;3054 \\ _ = &baz;
3055 \\ bar();3055 \\ bar();
...@@ -3112,7 +3112,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3112,7 +3112,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3112 \\ do {} while (0);3112 \\ do {} while (0);
3113 \\}3113 \\}
3114 , &[_][]const u8{3114 , &[_][]const u8{
3115 \\pub fn foo() callconv(.C) void {3115 \\pub fn foo() callconv(.c) void {
3116 \\ if (true) while (true) {3116 \\ if (true) while (true) {
3117 \\ if (!false) break;3117 \\ if (!false) break;
3118 \\ };3118 \\ };
...@@ -3212,10 +3212,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3212,10 +3212,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3212 \\void c(void) {}3212 \\void c(void) {}
3213 \\static void foo() {}3213 \\static void foo() {}
3214 , &[_][]const u8{3214 , &[_][]const u8{
3215 \\pub fn a() callconv(.C) void {}3215 \\pub fn a() callconv(.c) void {}
3216 \\pub fn b() callconv(.C) void {}3216 \\pub fn b() callconv(.c) void {}
3217 \\pub export fn c() void {}3217 \\pub export fn c() void {}
3218 \\pub fn foo() callconv(.C) void {}3218 \\pub fn foo() callconv(.c) void {}
3219 });3219 });
32203220
3221 cases.add("casting away const and volatile",3221 cases.add("casting away const and volatile",