| author | |
| committer | |
| log | 51706af908e0c6acb822ef36760b7fe31faf62a6 |
| tree | d814bcfcfd83ebc5fd50da11f18a9a6427a54859 |
| parent | 8573836892ba1b7cd34d377b46258930161256c3 |
| signature |
This commit begins implementing accepted proposal #21209 by making
`std.builtin.CallingConvention` a tagged union.
The stage1 dance here is a little convoluted. This commit introduces the
new type as `NewCallingConvention`, keeping the old `CallingConvention`
around. The compiler uses `std.builtin.NewCallingConvention`
exclusively, but when fetching the type from `std` when running the
compiler (e.g. with `getBuiltinType`), the name `CallingConvention` is
used. This allows a prior build of Zig to be used to build this commit.
The next commit will update `zig1.wasm`, and then the compiler and
standard library can be updated to completely replace
`CallingConvention` with `NewCallingConvention`.
The second half of #21209 is to remove `@setAlignStack`, which will be
implemented in another commit after updating `zig1.wasm`.28 files changed, 1762 insertions(+), 520 deletions(-)
lib/compiler/aro_translate_c/ast.zig+56-8| ... | @@ -550,12 +550,24 @@ pub const Payload = struct { | ... | @@ -550,12 +550,24 @@ 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_stdcall, | ||
| 564 | x86_fastcall, | ||
| 565 | x86_thiscall, | ||
| 566 | x86_vectorcall, | ||
| 567 | aarch64_vfabi, | ||
| 568 | arm_aapcs, | ||
| 569 | arm_aapcs_vfp, | ||
| 570 | }; | ||
| 559 | }; | 571 | }; |
| 560 | 572 | ||
| 561 | pub const Param = struct { | 573 | pub const Param = struct { |
| ... | @@ -2812,14 +2824,50 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { | ... | @@ -2812,14 +2824,50 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2812 | const callconv_expr = if (payload.explicit_callconv) |some| blk: { | 2824 | const callconv_expr = if (payload.explicit_callconv) |some| blk: { |
| 2813 | _ = try c.addToken(.keyword_callconv, "callconv"); | 2825 | _ = try c.addToken(.keyword_callconv, "callconv"); |
| 2814 | _ = try c.addToken(.l_paren, "("); | 2826 | _ = try c.addToken(.l_paren, "("); |
| 2815 | _ = try c.addToken(.period, "."); | 2827 | const cc_node = switch (some) { |
| 2816 | const res = try c.addNode(.{ | 2828 | .c => cc_node: { |
| 2817 | .tag = .enum_literal, | 2829 | _ = try c.addToken(.period, "."); |
| 2818 | .main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}), | 2830 | break :cc_node try c.addNode(.{ |
| 2819 | .data = undefined, | 2831 | .tag = .enum_literal, |
| 2820 | }); | 2832 | .main_token = try c.addToken(.identifier, "c"), |
| 2833 | .data = undefined, | ||
| 2834 | }); | ||
| 2835 | }, | ||
| 2836 | .x86_64_sysv, | ||
| 2837 | .x86_stdcall, | ||
| 2838 | .x86_fastcall, | ||
| 2839 | .x86_thiscall, | ||
| 2840 | .x86_vectorcall, | ||
| 2841 | .aarch64_vfabi, | ||
| 2842 | .arm_aapcs, | ||
| 2843 | .arm_aapcs_vfp, | ||
| 2844 | => cc_node: { | ||
| 2845 | // .{ .foo = .{} } | ||
| 2846 | _ = try c.addToken(.period, "."); | ||
| 2847 | const outer_lbrace = try c.addToken(.l_brace, "{"); | ||
| 2848 | _ = try c.addToken(.period, "."); | ||
| 2849 | _ = try c.addToken(.identifier, @tagName(some)); | ||
| 2850 | _ = try c.addToken(.equal, "="); | ||
| 2851 | _ = try c.addToken(.period, "."); | ||
| 2852 | const inner_lbrace = try c.addToken(.l_brace, "{"); | ||
| 2853 | _ = try c.addToken(.r_brace, "}"); | ||
| 2854 | _ = try c.addToken(.r_brace, "}"); | ||
| 2855 | break :cc_node try c.addNode(.{ | ||
| 2856 | .tag = .struct_init_dot_two, | ||
| 2857 | .main_token = outer_lbrace, | ||
| 2858 | .data = .{ | ||
| 2859 | .lhs = try c.addNode(.{ | ||
| 2860 | .tag = .struct_init_dot_two, | ||
| 2861 | .main_token = inner_lbrace, | ||
| 2862 | .data = .{ .lhs = 0, .rhs = 0 }, | ||
| 2863 | }), | ||
| 2864 | .rhs = 0, | ||
| 2865 | }, | ||
| 2866 | }); | ||
| 2867 | }, | ||
| 2868 | }; | ||
| 2821 | _ = try c.addToken(.r_paren, ")"); | 2869 | _ = try c.addToken(.r_paren, ")"); |
| 2822 | break :blk res; | 2870 | break :blk cc_node; |
| 2823 | } else 0; | 2871 | } else 0; |
| 2824 | 2872 | ||
| 2825 | const return_type_expr = try renderNode(c, payload.return_type); | 2873 | const return_type_expr = try renderNode(c, payload.return_type); |
lib/std/Target.zig+223| ... | @@ -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 fromCallconv(cc: std.builtin.NewCallingConvention) []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 | }; |
| 1613 | 1772 | ||
| 1614 | pub const Model = struct { | 1773 | pub const Model = struct { |
| ... | @@ -2873,6 +3032,70 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { | ... | @@ -2873,6 +3032,70 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { |
| 2873 | ); | 3032 | ); |
| 2874 | } | 3033 | } |
| 2875 | 3034 | ||
| 3035 | pub fn defaultCCallingConvention(target: Target) ?std.builtin.NewCallingConvention { | ||
| 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 => .{ .arm_aapcs = .{} }, | ||
| 3052 | .mips64, .mips64el => switch (target.abi) { | ||
| 3053 | .gnuabin32 => .{ .mips64_n32 = .{} }, | ||
| 3054 | else => .{ .mips64_n64 = .{} }, | ||
| 3055 | }, | ||
| 3056 | .mips, .mipsel => .{ .mips_o32 = .{} }, | ||
| 3057 | .riscv64 => .{ .riscv64_lp64 = .{} }, | ||
| 3058 | .riscv32 => .{ .riscv32_ilp32 = .{} }, | ||
| 3059 | .sparc64 => .{ .sparc64_sysv = .{} }, | ||
| 3060 | .sparc => .{ .sparc_sysv = .{} }, | ||
| 3061 | .powerpc64 => if (target.isMusl()) | ||
| 3062 | .{ .powerpc64_elf_v2 = .{} } | ||
| 3063 | else | ||
| 3064 | .{ .powerpc64_elf = .{} }, | ||
| 3065 | .powerpc64le => .{ .powerpc64_elf_v2 = .{} }, | ||
| 3066 | .powerpc, .powerpcle => switch (target.os.tag) { | ||
| 3067 | .aix => .{ .powerpc_aix = .{} }, | ||
| 3068 | else => .{ .powerpc_sysv = .{} }, | ||
| 3069 | }, | ||
| 3070 | .wasm32 => .{ .wasm_watc = .{} }, | ||
| 3071 | .wasm64 => .{ .wasm_watc = .{} }, | ||
| 3072 | .arc => .{ .arc_sysv = .{} }, | ||
| 3073 | .avr => .avr_gnu, | ||
| 3074 | .bpfel, .bpfeb => .{ .bpf_std = .{} }, | ||
| 3075 | .csky => .{ .csky_sysv = .{} }, | ||
| 3076 | .hexagon => .{ .hexagon_sysv = .{} }, | ||
| 3077 | .kalimba => null, | ||
| 3078 | .lanai => .{ .lanai_sysv = .{} }, | ||
| 3079 | .loongarch64 => .{ .loongarch64_lp64 = .{} }, | ||
| 3080 | .loongarch32 => .{ .loongarch32_ilp32 = .{} }, | ||
| 3081 | .m68k => if (target.abi.isGnu() or target.abi.isMusl()) | ||
| 3082 | .{ .m68k_gnu = .{} } | ||
| 3083 | else | ||
| 3084 | .{ .m68k_sysv = .{} }, | ||
| 3085 | .msp430 => .{ .msp430_eabi = .{} }, | ||
| 3086 | .propeller1 => .{ .propeller1_sysv = .{} }, | ||
| 3087 | .propeller2 => .{ .propeller2_sysv = .{} }, | ||
| 3088 | .s390x => .{ .s390x_sysv = .{} }, | ||
| 3089 | .spu_2 => null, | ||
| 3090 | .ve => .{ .ve_sysv = .{} }, | ||
| 3091 | .xcore => .{ .xcore_xs1 = .{} }, | ||
| 3092 | .xtensa => .{ .xtensa_call0 = .{} }, | ||
| 3093 | .amdgcn => .{ .amdgcn_device = .{} }, | ||
| 3094 | .nvptx, .nvptx64 => .nvptx_device, | ||
| 3095 | .spirv, .spirv32, .spirv64 => .spirv_device, | ||
| 3096 | }; | ||
| 3097 | } | ||
| 3098 | |||
| 2876 | pub fn osArchName(target: std.Target) [:0]const u8 { | 3099 | pub fn osArchName(target: std.Target) [:0]const u8 { |
| 2877 | return target.os.tag.archName(target.cpu.arch); | 3100 | return target.os.tag.archName(target.cpu.arch); |
| 2878 | } | 3101 | } |
lib/std/builtin.zig+330| ... | @@ -210,6 +210,336 @@ pub const CallingConvention = enum(u8) { | ... | @@ -210,6 +210,336 @@ pub const CallingConvention = enum(u8) { |
| 210 | Vertex, | 210 | Vertex, |
| 211 | }; | 211 | }; |
| 212 | 212 | ||
| 213 | /// The calling convention of a function defines how arguments and return values are passed, as well | ||
| 214 | /// as any other requirements which callers and callees must respect, such as register preservation | ||
| 215 | /// and stack alignment. | ||
| 216 | /// | ||
| 217 | /// This data structure is used by the Zig language code generation and | ||
| 218 | /// therefore must be kept in sync with the compiler implementation. | ||
| 219 | /// | ||
| 220 | /// TODO: this will be renamed `CallingConvention` after an initial zig1.wasm update. | ||
| 221 | pub const NewCallingConvention = union(enum(u8)) { | ||
| 222 | pub const Tag = @typeInfo(NewCallingConvention).@"union".tag_type.?; | ||
| 223 | |||
| 224 | /// This is an alias for the default C calling convention for this target. | ||
| 225 | /// Functions marked as `extern` or `export` are given this calling convention by default. | ||
| 226 | pub const c = builtin.target.defaultCCallingConvention().?; | ||
| 227 | |||
| 228 | pub const winapi: NewCallingConvention = switch (builtin.target.arch) { | ||
| 229 | .x86_64 => .{ .x86_64_win = .{} }, | ||
| 230 | .x86 => .{ .x86_stdcall = .{} }, | ||
| 231 | .aarch64, .aarch64_be => .{ .aarch64_aapcs_win = .{} }, | ||
| 232 | .arm, .armeb, .thumb, .thumbeb => .{ .arm_aapcs_vfp = .{} }, | ||
| 233 | else => unreachable, | ||
| 234 | }; | ||
| 235 | |||
| 236 | pub const kernel: NewCallingConvention = switch (builtin.target.cpu.arch) { | ||
| 237 | .amdgcn => .amdgcn_kernel, | ||
| 238 | .nvptx, .nvptx64 => .nvptx_kernel, | ||
| 239 | .spirv, .spirv32, .spirv64 => .spirv_kernel, | ||
| 240 | else => unreachable, | ||
| 241 | }; | ||
| 242 | |||
| 243 | /// Deprecated; use `.auto`. | ||
| 244 | pub const Unspecified: NewCallingConvention = .auto; | ||
| 245 | /// Deprecated; use `.c`. | ||
| 246 | pub const C: NewCallingConvention = .c; | ||
| 247 | /// Deprecated; use `.naked`. | ||
| 248 | pub const Naked: NewCallingConvention = .naked; | ||
| 249 | /// Deprecated; use `.@"async"`. | ||
| 250 | pub const Async: NewCallingConvention = .@"async"; | ||
| 251 | /// Deprecated; use `.@"inline"`. | ||
| 252 | pub const Inline: NewCallingConvention = .@"inline"; | ||
| 253 | /// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`. | ||
| 254 | pub const Interrupt: NewCallingConvention = switch (builtin.target.cpu.arch) { | ||
| 255 | .x86_64 => .{ .x86_64_interrupt = .{} }, | ||
| 256 | .x86 => .{ .x86_interrupt = .{} }, | ||
| 257 | .avr => .avr_interrupt, | ||
| 258 | else => unreachable, | ||
| 259 | }; | ||
| 260 | /// Deprecated; use `.avr_signal`. | ||
| 261 | pub const Signal: NewCallingConvention = .avr_signal; | ||
| 262 | /// Deprecated; use `.x86_stdcall`. | ||
| 263 | pub const Stdcall: NewCallingConvention = .{ .x86_stdcall = .{} }; | ||
| 264 | /// Deprecated; use `.x86_fastcall`. | ||
| 265 | pub const Fastcall: NewCallingConvention = .{ .x86_fastcall = .{} }; | ||
| 266 | /// Deprecated; use `.x86_64_vectorcall`, `.x86_vectorcall`, or `aarch64_vfabi`. | ||
| 267 | pub const Vectorcall: NewCallingConvention = switch (builtin.target.cpu.arch) { | ||
| 268 | .x86_64 => .{ .x86_64_vectorcall = .{} }, | ||
| 269 | .x86 => .{ .x86_vectorcall = .{} }, | ||
| 270 | .aarch64, .aarch64_be => .{ .aarch64_vfabi = .{} }, | ||
| 271 | else => unreachable, | ||
| 272 | }; | ||
| 273 | /// Deprecated; use `.x86_thiscall`. | ||
| 274 | pub const Thiscall: NewCallingConvention = .{ .x86_thiscall = .{} }; | ||
| 275 | /// Deprecated; use `.arm_apcs`. | ||
| 276 | pub const APCS: NewCallingConvention = .{ .arm_apcs = .{} }; | ||
| 277 | /// Deprecated; use `.arm_aapcs`. | ||
| 278 | pub const AAPCS: NewCallingConvention = .{ .arm_aapcs = .{} }; | ||
| 279 | /// Deprecated; use `.arm_aapcs_vfp`. | ||
| 280 | pub const AAPCSVFP: NewCallingConvention = .{ .arm_aapcs_vfp = .{} }; | ||
| 281 | /// Deprecated; use `.x86_64_sysv`. | ||
| 282 | pub const SysV: NewCallingConvention = .{ .x86_64_sysv = .{} }; | ||
| 283 | /// Deprecated; use `.x86_64_win`. | ||
| 284 | pub const Win64: NewCallingConvention = .{ .x86_64_win = .{} }; | ||
| 285 | /// Deprecated; use `.kernel`. | ||
| 286 | pub const Kernel: NewCallingConvention = .kernel; | ||
| 287 | /// Deprecated; use `.spirv_fragment`. | ||
| 288 | pub const Fragment: NewCallingConvention = .spirv_fragment; | ||
| 289 | /// Deprecated; use `.spirv_vertex`. | ||
| 290 | pub const Vertex: NewCallingConvention = .spirv_vertex; | ||
| 291 | |||
| 292 | /// The default Zig calling convention when neither `export` nor `inline` is specified. | ||
| 293 | /// This calling convention makes no guarantees about stack alignment, registers, etc. | ||
| 294 | /// It can only be used within this Zig compilation unit. | ||
| 295 | auto, | ||
| 296 | |||
| 297 | /// The calling convention of a function that can be called with `async` syntax. An `async` call | ||
| 298 | /// of a runtime-known function must target a function with this calling convention. | ||
| 299 | /// Comptime-known functions with other calling conventions may be coerced to this one. | ||
| 300 | @"async", | ||
| 301 | |||
| 302 | /// Functions with this calling convention have no prologue or epilogue, making the function | ||
| 303 | /// uncallable in regular Zig code. This can be useful when integrating with assembly. | ||
| 304 | naked, | ||
| 305 | |||
| 306 | /// This calling convention is exactly equivalent to using the `inline` keyword on a function | ||
| 307 | /// definition. This function will be semantically inlined by the Zig compiler at call sites. | ||
| 308 | /// Pointers to inline functions are comptime-only. | ||
| 309 | @"inline", | ||
| 310 | |||
| 311 | // Calling conventions for the x86_64 architecture. | ||
| 312 | x86_64_sysv: CommonOptions, | ||
| 313 | x86_64_win: CommonOptions, | ||
| 314 | x86_64_regcall_v3_sysv: CommonOptions, | ||
| 315 | x86_64_regcall_v4_win: CommonOptions, | ||
| 316 | x86_64_vectorcall: CommonOptions, | ||
| 317 | x86_64_interrupt: CommonOptions, | ||
| 318 | |||
| 319 | // Calling conventions for the x86 architecture. | ||
| 320 | x86_sysv: X86RegparmOptions, | ||
| 321 | x86_win: X86RegparmOptions, | ||
| 322 | x86_stdcall: X86RegparmOptions, | ||
| 323 | x86_fastcall: CommonOptions, | ||
| 324 | x86_thiscall: CommonOptions, | ||
| 325 | x86_thiscall_mingw: CommonOptions, | ||
| 326 | x86_regcall_v3: CommonOptions, | ||
| 327 | x86_regcall_v4_win: CommonOptions, | ||
| 328 | x86_vectorcall: CommonOptions, | ||
| 329 | x86_interrupt: CommonOptions, | ||
| 330 | |||
| 331 | // Calling conventions for the aarch64 architecture. | ||
| 332 | aarch64_aapcs: CommonOptions, | ||
| 333 | aarch64_aapcs_darwin: CommonOptions, | ||
| 334 | aarch64_aapcs_win: CommonOptions, | ||
| 335 | aarch64_vfabi: CommonOptions, | ||
| 336 | aarch64_vfabi_sve: CommonOptions, | ||
| 337 | |||
| 338 | // Calling convetions for the arm architecture. | ||
| 339 | /// ARM Procedure Call Standard (obsolete) | ||
| 340 | arm_apcs: CommonOptions, | ||
| 341 | /// ARM Architecture Procedure Call Standard | ||
| 342 | arm_aapcs: CommonOptions, | ||
| 343 | /// ARM Architecture Procedure Call Standard Vector Floating-Point | ||
| 344 | arm_aapcs_vfp: CommonOptions, | ||
| 345 | arm_aapcs16_vfp: CommonOptions, | ||
| 346 | arm_interrupt: ArmInterruptOptions, | ||
| 347 | |||
| 348 | // Calling conventions for the mips64 architecture. | ||
| 349 | mips64_n64: CommonOptions, | ||
| 350 | mips64_n32: CommonOptions, | ||
| 351 | mips64_interrupt: MipsInterruptOptions, | ||
| 352 | |||
| 353 | // Calling conventions for the mips architecture. | ||
| 354 | mips_o32: CommonOptions, | ||
| 355 | mips_interrupt: MipsInterruptOptions, | ||
| 356 | |||
| 357 | // Calling conventions for the riscv64 architecture. | ||
| 358 | riscv64_lp64: CommonOptions, | ||
| 359 | riscv64_lp64_v: CommonOptions, | ||
| 360 | riscv64_interrupt: RiscvInterruptOptions, | ||
| 361 | |||
| 362 | // Calling conventions for the riscv32 architecture. | ||
| 363 | riscv32_ilp32: CommonOptions, | ||
| 364 | riscv32_ilp32_v: CommonOptions, | ||
| 365 | riscv32_interrupt: RiscvInterruptOptions, | ||
| 366 | |||
| 367 | // Calling conventions for the sparc64 architecture. | ||
| 368 | sparc64_sysv: CommonOptions, | ||
| 369 | |||
| 370 | // Calling conventions for the sparc architecture. | ||
| 371 | sparc_sysv: CommonOptions, | ||
| 372 | |||
| 373 | // Calling conventions for the powerpc64 architecture. | ||
| 374 | powerpc64_elf: CommonOptions, | ||
| 375 | powerpc64_elf_altivec: CommonOptions, | ||
| 376 | powerpc64_elf_v2: CommonOptions, | ||
| 377 | |||
| 378 | // Calling conventions for the powerpc architecture. | ||
| 379 | powerpc_sysv: CommonOptions, | ||
| 380 | powerpc_sysv_altivec: CommonOptions, | ||
| 381 | powerpc_aix: CommonOptions, | ||
| 382 | powerpc_aix_altivec: CommonOptions, | ||
| 383 | |||
| 384 | /// The standard wasm32/wasm64 calling convention, as specified in the WebAssembly Tool Conventions. | ||
| 385 | wasm_watc: CommonOptions, | ||
| 386 | |||
| 387 | /// The standard ARC calling convention. | ||
| 388 | arc_sysv: CommonOptions, | ||
| 389 | |||
| 390 | // Calling conventions for the AVR architecture. | ||
| 391 | avr_gnu, | ||
| 392 | avr_builtin, | ||
| 393 | avr_signal, | ||
| 394 | avr_interrupt, | ||
| 395 | |||
| 396 | /// The standard bpf calling convention. | ||
| 397 | bpf_std: CommonOptions, | ||
| 398 | |||
| 399 | // Calling conventions for the csky architecture. | ||
| 400 | csky_sysv: CommonOptions, | ||
| 401 | csky_interrupt: CommonOptions, | ||
| 402 | |||
| 403 | // Calling conventions for the hexagon architecture. | ||
| 404 | hexagon_sysv: CommonOptions, | ||
| 405 | hexagon_sysv_hvx: CommonOptions, | ||
| 406 | |||
| 407 | /// The standard Lanai calling convention. | ||
| 408 | lanai_sysv: CommonOptions, | ||
| 409 | |||
| 410 | /// The standard loongarch64 calling convention. | ||
| 411 | loongarch64_lp64: CommonOptions, | ||
| 412 | |||
| 413 | /// The standard loongarch32 calling convention. | ||
| 414 | loongarch32_ilp32: CommonOptions, | ||
| 415 | |||
| 416 | // Calling conventions for the m68k architecture. | ||
| 417 | m68k_sysv: CommonOptions, | ||
| 418 | m68k_gnu: CommonOptions, | ||
| 419 | m68k_rtd: CommonOptions, | ||
| 420 | m68k_interrupt: CommonOptions, | ||
| 421 | |||
| 422 | /// The standard MSP430 calling convention. | ||
| 423 | msp430_eabi: CommonOptions, | ||
| 424 | |||
| 425 | /// The standard propeller1 calling convention. | ||
| 426 | propeller1_sysv: CommonOptions, | ||
| 427 | |||
| 428 | /// The standard propeller1 calling convention. | ||
| 429 | propeller2_sysv: CommonOptions, | ||
| 430 | |||
| 431 | // Calling conventions for the S390X architecture. | ||
| 432 | s390x_sysv: CommonOptions, | ||
| 433 | s390x_sysv_vx: CommonOptions, | ||
| 434 | |||
| 435 | /// The standard VE calling convention. | ||
| 436 | ve_sysv: CommonOptions, | ||
| 437 | |||
| 438 | // Calling conventions for the xCORE architecture. | ||
| 439 | xcore_xs1: CommonOptions, | ||
| 440 | xcore_xs2: CommonOptions, | ||
| 441 | |||
| 442 | // Calling conventions for the Xtensa architecture. | ||
| 443 | xtensa_call0: CommonOptions, | ||
| 444 | xtensa_windowed: CommonOptions, | ||
| 445 | |||
| 446 | // Calling conventions for the AMDGCN architecture. | ||
| 447 | amdgcn_device: CommonOptions, | ||
| 448 | amdgcn_kernel, | ||
| 449 | amdgcn_cs: CommonOptions, | ||
| 450 | |||
| 451 | // Calling conventions for the NVPTX architecture. | ||
| 452 | nvptx_device, | ||
| 453 | nvptx_kernel, | ||
| 454 | |||
| 455 | // Calling conventions for SPIR-V kernels and shaders. | ||
| 456 | spirv_device, | ||
| 457 | spirv_kernel, | ||
| 458 | spirv_fragment, | ||
| 459 | spirv_vertex, | ||
| 460 | |||
| 461 | /// Options shared across most calling conventions. | ||
| 462 | pub const CommonOptions = struct { | ||
| 463 | /// The boundary the stack is aligned to when the function is called. | ||
| 464 | /// `null` means the default for this calling convention. | ||
| 465 | incoming_stack_alignment: ?u64 = null, | ||
| 466 | }; | ||
| 467 | |||
| 468 | /// Options for x86 calling conventions which support the regparm attribute to pass some | ||
| 469 | /// arguments in registers. | ||
| 470 | pub const X86RegparmOptions = struct { | ||
| 471 | /// The boundary the stack is aligned to when the function is called. | ||
| 472 | /// `null` means the default for this calling convention. | ||
| 473 | incoming_stack_alignment: ?u64 = null, | ||
| 474 | /// The number of arguments to pass in registers before passing the remaining arguments | ||
| 475 | /// according to the calling convention. | ||
| 476 | /// Equivalent to `__attribute__((regparm(x)))` in Clang and GCC. | ||
| 477 | register_params: u2 = 0, | ||
| 478 | }; | ||
| 479 | |||
| 480 | /// Options for the `arm_interrupt` calling convention. | ||
| 481 | pub const ArmInterruptOptions = struct { | ||
| 482 | /// The boundary the stack is aligned to when the function is called. | ||
| 483 | /// `null` means the default for this calling convention. | ||
| 484 | incoming_stack_alignment: ?u64 = null, | ||
| 485 | /// The kind of interrupt being received. | ||
| 486 | type: InterruptType = .generic, | ||
| 487 | |||
| 488 | pub const InterruptType = enum(u3) { | ||
| 489 | generic, | ||
| 490 | irq, | ||
| 491 | fiq, | ||
| 492 | swi, | ||
| 493 | abort, | ||
| 494 | undef, | ||
| 495 | }; | ||
| 496 | }; | ||
| 497 | |||
| 498 | /// Options for the `mips_interrupt` and `mips64_interrupt` calling conventions. | ||
| 499 | pub const MipsInterruptOptions = struct { | ||
| 500 | /// The boundary the stack is aligned to when the function is called. | ||
| 501 | /// `null` means the default for this calling convention. | ||
| 502 | incoming_stack_alignment: ?u64 = null, | ||
| 503 | /// The interrupt mode. | ||
| 504 | mode: InterruptMode = .eic, | ||
| 505 | |||
| 506 | pub const InterruptMode = enum(u4) { | ||
| 507 | eic, | ||
| 508 | sw0, | ||
| 509 | sw1, | ||
| 510 | hw0, | ||
| 511 | hw1, | ||
| 512 | hw2, | ||
| 513 | hw3, | ||
| 514 | hw4, | ||
| 515 | hw5, | ||
| 516 | }; | ||
| 517 | }; | ||
| 518 | |||
| 519 | /// Options for the `riscv32_interrupt` and `riscv64_interrupt` calling conventions. | ||
| 520 | pub const RiscvInterruptOptions = struct { | ||
| 521 | /// The boundary the stack is aligned to when the function is called. | ||
| 522 | /// `null` means the default for this calling convention. | ||
| 523 | incoming_stack_alignment: ?u64 = null, | ||
| 524 | /// The privilege level. | ||
| 525 | level: PrivilegeLevel = .machine, | ||
| 526 | |||
| 527 | pub const PrivilegeLevel = enum(u2) { | ||
| 528 | user, | ||
| 529 | supervisor, | ||
| 530 | machine, | ||
| 531 | }; | ||
| 532 | }; | ||
| 533 | |||
| 534 | /// Returns the array of `std.Target.Cpu.Arch` to which this `CallingConvention` applies. | ||
| 535 | /// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`. | ||
| 536 | pub const archs = std.Target.Cpu.Arch.fromCallconv; | ||
| 537 | |||
| 538 | pub fn eql(a: NewCallingConvention, b: NewCallingConvention) bool { | ||
| 539 | return std.meta.eql(a, b); | ||
| 540 | } | ||
| 541 | }; | ||
| 542 | |||
| 213 | /// This data structure is used by the Zig language code generation and | 543 | /// This data structure is used by the Zig language code generation and |
| 214 | /// therefore must be kept in sync with the compiler implementation. | 544 | /// therefore must be kept in sync with the compiler implementation. |
| 215 | pub const AddressSpace = enum(u5) { | 545 | pub const AddressSpace = enum(u5) { |
src/InternPool.zig+92-13| ... | @@ -1988,7 +1988,7 @@ pub const Key = union(enum) { | ... | @@ -1988,7 +1988,7 @@ pub const Key = union(enum) { |
| 1988 | /// Tells whether a parameter is noalias. See `paramIsNoalias` helper | 1988 | /// Tells whether a parameter is noalias. See `paramIsNoalias` helper |
| 1989 | /// method for accessing this. | 1989 | /// method for accessing this. |
| 1990 | noalias_bits: u32, | 1990 | noalias_bits: u32, |
| 1991 | cc: std.builtin.CallingConvention, | 1991 | cc: std.builtin.NewCallingConvention, |
| 1992 | is_var_args: bool, | 1992 | is_var_args: bool, |
| 1993 | is_generic: bool, | 1993 | is_generic: bool, |
| 1994 | is_noinline: bool, | 1994 | is_noinline: bool, |
| ... | @@ -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 and | 2011 | a.return_type == b.return_type and |
| 2012 | a.comptime_bits == b.comptime_bits and | 2012 | a.comptime_bits == b.comptime_bits and |
| 2013 | a.noalias_bits == b.noalias_bits and | 2013 | a.noalias_bits == b.noalias_bits and |
| 2014 | a.cc == b.cc and | ||
| 2015 | a.is_var_args == b.is_var_args and | 2014 | a.is_var_args == b.is_var_args and |
| 2016 | a.is_generic == b.is_generic and | 2015 | 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 | } |
| 2019 | 2019 | ||
| 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, |
| 5445 | 5445 | ||
| 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 | }; |
| 5459 | 5459 | ||
| ... | @@ -6912,7 +6912,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke | ... | @@ -6912,7 +6912,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke |
| 6912 | .return_type = type_function.data.return_type, | 6912 | .return_type = type_function.data.return_type, |
| 6913 | .comptime_bits = comptime_bits, | 6913 | .comptime_bits = comptime_bits, |
| 6914 | .noalias_bits = noalias_bits, | 6914 | .noalias_bits = noalias_bits, |
| 6915 | .cc = type_function.data.flags.cc, | 6915 | .cc = type_function.data.flags.cc.unpack(), |
| 6916 | .is_var_args = type_function.data.flags.is_var_args, | 6916 | .is_var_args = type_function.data.flags.is_var_args, |
| 6917 | .is_noinline = type_function.data.flags.is_noinline, | 6917 | .is_noinline = type_function.data.flags.is_noinline, |
| 6918 | .cc_is_generic = type_function.data.flags.cc_is_generic, | 6918 | .cc_is_generic = type_function.data.flags.cc_is_generic, |
| ... | @@ -8526,7 +8526,7 @@ pub const GetFuncTypeKey = struct { | ... | @@ -8526,7 +8526,7 @@ pub const GetFuncTypeKey = struct { |
| 8526 | comptime_bits: u32 = 0, | 8526 | comptime_bits: u32 = 0, |
| 8527 | noalias_bits: u32 = 0, | 8527 | noalias_bits: u32 = 0, |
| 8528 | /// `null` means generic. | 8528 | /// `null` means generic. |
| 8529 | cc: ?std.builtin.CallingConvention = .Unspecified, | 8529 | cc: ?std.builtin.NewCallingConvention = .auto, |
| 8530 | is_var_args: bool = false, | 8530 | is_var_args: bool = false, |
| 8531 | is_generic: bool = false, | 8531 | is_generic: bool = false, |
| 8532 | is_noinline: bool = false, | 8532 | is_noinline: bool = false, |
| ... | @@ -8564,7 +8564,7 @@ pub fn getFuncType( | ... | @@ -8564,7 +8564,7 @@ pub fn getFuncType( |
| 8564 | .params_len = params_len, | 8564 | .params_len = params_len, |
| 8565 | .return_type = key.return_type, | 8565 | .return_type = key.return_type, |
| 8566 | .flags = .{ | 8566 | .flags = .{ |
| 8567 | .cc = key.cc orelse .Unspecified, | 8567 | .cc = .pack(key.cc orelse .auto), |
| 8568 | .is_var_args = key.is_var_args, | 8568 | .is_var_args = key.is_var_args, |
| 8569 | .has_comptime_bits = key.comptime_bits != 0, | 8569 | .has_comptime_bits = key.comptime_bits != 0, |
| 8570 | .has_noalias_bits = key.noalias_bits != 0, | 8570 | .has_noalias_bits = key.noalias_bits != 0, |
| ... | @@ -8668,7 +8668,7 @@ pub const GetFuncDeclKey = struct { | ... | @@ -8668,7 +8668,7 @@ pub const GetFuncDeclKey = struct { |
| 8668 | rbrace_line: u32, | 8668 | rbrace_line: u32, |
| 8669 | lbrace_column: u32, | 8669 | lbrace_column: u32, |
| 8670 | rbrace_column: u32, | 8670 | rbrace_column: u32, |
| 8671 | cc: ?std.builtin.CallingConvention, | 8671 | cc: ?std.builtin.NewCallingConvention, |
| 8672 | is_noinline: bool, | 8672 | is_noinline: bool, |
| 8673 | }; | 8673 | }; |
| 8674 | 8674 | ||
| ... | @@ -8733,7 +8733,7 @@ pub const GetFuncDeclIesKey = struct { | ... | @@ -8733,7 +8733,7 @@ pub const GetFuncDeclIesKey = struct { |
| 8733 | comptime_bits: u32, | 8733 | comptime_bits: u32, |
| 8734 | bare_return_type: Index, | 8734 | bare_return_type: Index, |
| 8735 | /// null means generic. | 8735 | /// null means generic. |
| 8736 | cc: ?std.builtin.CallingConvention, | 8736 | cc: ?std.builtin.NewCallingConvention, |
| 8737 | /// null means generic. | 8737 | /// null means generic. |
| 8738 | alignment: ?Alignment, | 8738 | alignment: ?Alignment, |
| 8739 | section_is_generic: bool, | 8739 | section_is_generic: bool, |
| ... | @@ -8818,7 +8818,7 @@ pub fn getFuncDeclIes( | ... | @@ -8818,7 +8818,7 @@ pub fn getFuncDeclIes( |
| 8818 | .params_len = params_len, | 8818 | .params_len = params_len, |
| 8819 | .return_type = error_union_type, | 8819 | .return_type = error_union_type, |
| 8820 | .flags = .{ | 8820 | .flags = .{ |
| 8821 | .cc = key.cc orelse .Unspecified, | 8821 | .cc = .pack(key.cc orelse .auto), |
| 8822 | .is_var_args = key.is_var_args, | 8822 | .is_var_args = key.is_var_args, |
| 8823 | .has_comptime_bits = key.comptime_bits != 0, | 8823 | .has_comptime_bits = key.comptime_bits != 0, |
| 8824 | .has_noalias_bits = key.noalias_bits != 0, | 8824 | .has_noalias_bits = key.noalias_bits != 0, |
| ... | @@ -8948,7 +8948,7 @@ pub const GetFuncInstanceKey = struct { | ... | @@ -8948,7 +8948,7 @@ pub const GetFuncInstanceKey = struct { |
| 8948 | comptime_args: []const Index, | 8948 | comptime_args: []const Index, |
| 8949 | noalias_bits: u32, | 8949 | noalias_bits: u32, |
| 8950 | bare_return_type: Index, | 8950 | bare_return_type: Index, |
| 8951 | cc: std.builtin.CallingConvention, | 8951 | cc: std.builtin.NewCallingConvention, |
| 8952 | alignment: Alignment, | 8952 | alignment: Alignment, |
| 8953 | section: OptionalNullTerminatedString, | 8953 | section: OptionalNullTerminatedString, |
| 8954 | is_noinline: bool, | 8954 | is_noinline: bool, |
| ... | @@ -9110,7 +9110,7 @@ pub fn getFuncInstanceIes( | ... | @@ -9110,7 +9110,7 @@ pub fn getFuncInstanceIes( |
| 9110 | .params_len = params_len, | 9110 | .params_len = params_len, |
| 9111 | .return_type = error_union_type, | 9111 | .return_type = error_union_type, |
| 9112 | .flags = .{ | 9112 | .flags = .{ |
| 9113 | .cc = arg.cc, | 9113 | .cc = .pack(arg.cc), |
| 9114 | .is_var_args = false, | 9114 | .is_var_args = false, |
| 9115 | .has_comptime_bits = false, | 9115 | .has_comptime_bits = false, |
| 9116 | .has_noalias_bits = arg.noalias_bits != 0, | 9116 | .has_noalias_bits = arg.noalias_bits != 0, |
| ... | @@ -12224,3 +12224,82 @@ pub fn getErrorValue( | ... | @@ -12224,3 +12224,82 @@ pub fn getErrorValue( |
| 12224 | pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { | 12224 | pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { |
| 12225 | return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null); | 12225 | return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null); |
| 12226 | } | 12226 | } |
| 12227 | |||
| 12228 | const PackedCallingConvention = packed struct(u18) { | ||
| 12229 | tag: std.builtin.NewCallingConvention.Tag, | ||
| 12230 | /// May be ignored depending on `tag`. | ||
| 12231 | incoming_stack_alignment: Alignment, | ||
| 12232 | /// Interpretation depends on `tag`. | ||
| 12233 | extra: u4, | ||
| 12234 | |||
| 12235 | fn pack(cc: std.builtin.NewCallingConvention) PackedCallingConvention { | ||
| 12236 | return switch (cc) { | ||
| 12237 | inline else => |pl, tag| switch (@TypeOf(pl)) { | ||
| 12238 | void => .{ | ||
| 12239 | .tag = tag, | ||
| 12240 | .incoming_stack_alignment = .none, // unused | ||
| 12241 | .extra = 0, // unused | ||
| 12242 | }, | ||
| 12243 | std.builtin.NewCallingConvention.CommonOptions => .{ | ||
| 12244 | .tag = tag, | ||
| 12245 | .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), | ||
| 12246 | .extra = 0, // unused | ||
| 12247 | }, | ||
| 12248 | std.builtin.NewCallingConvention.X86RegparmOptions => .{ | ||
| 12249 | .tag = tag, | ||
| 12250 | .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), | ||
| 12251 | .extra = pl.register_params, | ||
| 12252 | }, | ||
| 12253 | std.builtin.NewCallingConvention.ArmInterruptOptions => .{ | ||
| 12254 | .tag = tag, | ||
| 12255 | .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), | ||
| 12256 | .extra = @intFromEnum(pl.type), | ||
| 12257 | }, | ||
| 12258 | std.builtin.NewCallingConvention.MipsInterruptOptions => .{ | ||
| 12259 | .tag = tag, | ||
| 12260 | .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), | ||
| 12261 | .extra = @intFromEnum(pl.mode), | ||
| 12262 | }, | ||
| 12263 | std.builtin.NewCallingConvention.RiscvInterruptOptions => .{ | ||
| 12264 | .tag = tag, | ||
| 12265 | .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), | ||
| 12266 | .extra = @intFromEnum(pl.level), | ||
| 12267 | }, | ||
| 12268 | else => comptime unreachable, | ||
| 12269 | }, | ||
| 12270 | }; | ||
| 12271 | } | ||
| 12272 | |||
| 12273 | fn unpack(cc: PackedCallingConvention) std.builtin.NewCallingConvention { | ||
| 12274 | @setEvalBranchQuota(400_000); | ||
| 12275 | return switch (cc.tag) { | ||
| 12276 | inline else => |tag| @unionInit( | ||
| 12277 | std.builtin.NewCallingConvention, | ||
| 12278 | @tagName(tag), | ||
| 12279 | switch (std.meta.FieldType(std.builtin.NewCallingConvention, tag)) { | ||
| 12280 | void => {}, | ||
| 12281 | std.builtin.NewCallingConvention.CommonOptions => .{ | ||
| 12282 | .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), | ||
| 12283 | }, | ||
| 12284 | std.builtin.NewCallingConvention.X86RegparmOptions => .{ | ||
| 12285 | .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), | ||
| 12286 | .register_params = @intCast(cc.extra), | ||
| 12287 | }, | ||
| 12288 | std.builtin.NewCallingConvention.ArmInterruptOptions => .{ | ||
| 12289 | .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), | ||
| 12290 | .type = @enumFromInt(cc.extra), | ||
| 12291 | }, | ||
| 12292 | std.builtin.NewCallingConvention.MipsInterruptOptions => .{ | ||
| 12293 | .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), | ||
| 12294 | .mode = @enumFromInt(cc.extra), | ||
| 12295 | }, | ||
| 12296 | std.builtin.NewCallingConvention.RiscvInterruptOptions => .{ | ||
| 12297 | .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), | ||
| 12298 | .level = @enumFromInt(cc.extra), | ||
| 12299 | }, | ||
| 12300 | else => comptime unreachable, | ||
| 12301 | }, | ||
| 12302 | ), | ||
| 12303 | }; | ||
| 12304 | } | ||
| 12305 | }; |
src/Sema.zig+236-102| ... | @@ -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`. |
| 28 | func_index: InternPool.Index, | 28 | func_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`. |
| 30 | func_is_naked: bool, | 30 | func_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. |
| 32 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, | 32 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| ... | @@ -1355,7 +1355,7 @@ fn analyzeBodyInner( | ... | @@ -1355,7 +1355,7 @@ fn analyzeBodyInner( |
| 1355 | }, | 1355 | }, |
| 1356 | .value_placeholder => unreachable, // never appears in a body | 1356 | .value_placeholder => unreachable, // never appears in a body |
| 1357 | .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), | 1357 | .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), |
| 1358 | .builtin_value => try sema.zirBuiltinValue(extended), | 1358 | .builtin_value => try sema.zirBuiltinValue(block, extended), |
| 1359 | .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended), | 1359 | .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended), |
| 1360 | }; | 1360 | }; |
| 1361 | }, | 1361 | }, |
| ... | @@ -2698,6 +2698,20 @@ fn analyzeAsInt( | ... | @@ -2698,6 +2698,20 @@ fn analyzeAsInt( |
| 2698 | return try val.toUnsignedIntSema(sema.pt); | 2698 | return try val.toUnsignedIntSema(sema.pt); |
| 2699 | } | 2699 | } |
| 2700 | 2700 | ||
| 2701 | fn analyzeValueAsCallconv( | ||
| 2702 | sema: *Sema, | ||
| 2703 | block: *Block, | ||
| 2704 | src: LazySrcLoc, | ||
| 2705 | unresolved_val: Value, | ||
| 2706 | ) !std.builtin.NewCallingConvention { | ||
| 2707 | const resolved_val = try sema.resolveLazyValue(unresolved_val); | ||
| 2708 | return resolved_val.interpret(std.builtin.NewCallingConvention, sema.pt) catch |err| switch (err) { | ||
| 2709 | error.OutOfMemory => |e| return e, | ||
| 2710 | error.UndefinedValue => return sema.failWithUseOfUndef(block, src), | ||
| 2711 | error.TypeMismatch => @panic("std.builtin is corrupt"), | ||
| 2712 | }; | ||
| 2713 | } | ||
| 2714 | |||
| 2701 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, | 2715 | /// 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`. | 2716 | /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. |
| 2703 | fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { | 2717 | fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { |
| ... | @@ -6516,8 +6530,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -6516,8 +6530,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 6516 | } | 6530 | } |
| 6517 | 6531 | ||
| 6518 | switch (Value.fromInterned(func).typeOf(zcu).fnCallingConvention(zcu)) { | 6532 | switch (Value.fromInterned(func).typeOf(zcu).fnCallingConvention(zcu)) { |
| 6519 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), | 6533 | .naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), |
| 6520 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), | 6534 | .@"inline" => return sema.fail(block, src, "@setAlignStack in inline function", .{}), |
| 6521 | else => {}, | 6535 | else => {}, |
| 6522 | } | 6536 | } |
| 6523 | 6537 | ||
| ... | @@ -7554,7 +7568,7 @@ fn analyzeCall( | ... | @@ -7554,7 +7568,7 @@ fn analyzeCall( |
| 7554 | if (try sema.resolveValue(func)) |func_val| | 7568 | if (try sema.resolveValue(func)) |func_val| |
| 7555 | if (func_val.isUndef(zcu)) | 7569 | if (func_val.isUndef(zcu)) |
| 7556 | return sema.failWithUseOfUndef(block, call_src); | 7570 | return sema.failWithUseOfUndef(block, call_src); |
| 7557 | if (cc == .Naked) { | 7571 | if (cc == .naked) { |
| 7558 | const maybe_func_inst = try sema.funcDeclSrcInst(func); | 7572 | const maybe_func_inst = try sema.funcDeclSrcInst(func); |
| 7559 | const msg = msg: { | 7573 | const msg = msg: { |
| 7560 | const msg = try sema.errMsg( | 7574 | const msg = try sema.errMsg( |
| ... | @@ -7587,7 +7601,7 @@ fn analyzeCall( | ... | @@ -7587,7 +7601,7 @@ fn analyzeCall( |
| 7587 | .async_kw => return sema.failWithUseOfAsync(block, call_src), | 7601 | .async_kw => return sema.failWithUseOfAsync(block, call_src), |
| 7588 | }; | 7602 | }; |
| 7589 | 7603 | ||
| 7590 | if (modifier == .never_inline and func_ty_info.cc == .Inline) { | 7604 | if (modifier == .never_inline and func_ty_info.cc == .@"inline") { |
| 7591 | return sema.fail(block, call_src, "'never_inline' call of inline function", .{}); | 7605 | return sema.fail(block, call_src, "'never_inline' call of inline function", .{}); |
| 7592 | } | 7606 | } |
| 7593 | if (modifier == .always_inline and func_ty_info.is_noinline) { | 7607 | if (modifier == .always_inline and func_ty_info.is_noinline) { |
| ... | @@ -7598,7 +7612,7 @@ fn analyzeCall( | ... | @@ -7598,7 +7612,7 @@ fn analyzeCall( |
| 7598 | 7612 | ||
| 7599 | const is_generic_call = func_ty_info.is_generic; | 7613 | const is_generic_call = func_ty_info.is_generic; |
| 7600 | var is_comptime_call = block.is_comptime or modifier == .compile_time; | 7614 | 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; | 7615 | 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; | 7616 | var comptime_reason: ?*const Block.ComptimeReason = null; |
| 7603 | if (!is_inline_call and !is_comptime_call) { | 7617 | if (!is_inline_call and !is_comptime_call) { |
| 7604 | if (try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) { | 7618 | if (try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) { |
| ... | @@ -8455,7 +8469,7 @@ fn instantiateGenericCall( | ... | @@ -8455,7 +8469,7 @@ fn instantiateGenericCall( |
| 8455 | } | 8469 | } |
| 8456 | // Similarly, if the call evaluated to a generic type we need to instead | 8470 | // Similarly, if the call evaluated to a generic type we need to instead |
| 8457 | // call it inline. | 8471 | // call it inline. |
| 8458 | if (func_ty_info.is_generic or func_ty_info.cc == .Inline) { | 8472 | if (func_ty_info.is_generic or func_ty_info.cc == .@"inline") { |
| 8459 | return error.GenericPoison; | 8473 | return error.GenericPoison; |
| 8460 | } | 8474 | } |
| 8461 | 8475 | ||
| ... | @@ -9505,8 +9519,8 @@ fn zirFunc( | ... | @@ -9505,8 +9519,8 @@ fn zirFunc( |
| 9505 | 9519 | ||
| 9506 | // If this instruction has a body, then it's a function declaration, and we decide | 9520 | // 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 defaults | 9521 | // the callconv based on whether it is exported. Otherwise, the callconv defaults |
| 9508 | // to `.Unspecified`. | 9522 | // to `.auto`. |
| 9509 | const cc: std.builtin.CallingConvention = if (has_body) cc: { | 9523 | const cc: std.builtin.NewCallingConvention = if (has_body) cc: { |
| 9510 | const func_decl_cau = if (sema.generic_owner != .none) cau: { | 9524 | const func_decl_cau = if (sema.generic_owner != .none) cau: { |
| 9511 | const generic_owner_fn = zcu.funcInfo(sema.generic_owner); | 9525 | const generic_owner_fn = zcu.funcInfo(sema.generic_owner); |
| 9512 | // The generic owner definitely has a `Cau` for the corresponding function declaration. | 9526 | // The generic owner definitely has a `Cau` for the corresponding function declaration. |
| ... | @@ -9518,8 +9532,26 @@ fn zirFunc( | ... | @@ -9518,8 +9532,26 @@ fn zirFunc( |
| 9518 | const zir_decl = sema.code.getDeclaration(decl_inst)[0]; | 9532 | const zir_decl = sema.code.getDeclaration(decl_inst)[0]; |
| 9519 | break :exported zir_decl.flags.is_export; | 9533 | break :exported zir_decl.flags.is_export; |
| 9520 | }; | 9534 | }; |
| 9521 | break :cc if (fn_is_exported) .C else .Unspecified; | 9535 | if (fn_is_exported) { |
| 9522 | } else .Unspecified; | 9536 | break :cc target.defaultCCallingConvention() orelse { |
| 9537 | // This target has no default C calling convention. We sometimes trigger a similar | ||
| 9538 | // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency, | ||
| 9539 | // let's eval that now and just get the transitive error. (It's guaranteed to error | ||
| 9540 | // because it does the exact `defaultCCallingConvention` call we just did.) | ||
| 9541 | const cc_type = try sema.getBuiltinType("CallingConvention"); | ||
| 9542 | _ = try sema.namespaceLookupVal( | ||
| 9543 | block, | ||
| 9544 | LazySrcLoc.unneeded, | ||
| 9545 | cc_type.getNamespaceIndex(zcu), | ||
| 9546 | try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls), | ||
| 9547 | ); | ||
| 9548 | // The above should have errored. | ||
| 9549 | @panic("std.builtin is corrupt"); | ||
| 9550 | }; | ||
| 9551 | } else { | ||
| 9552 | break :cc .auto; | ||
| 9553 | } | ||
| 9554 | } else .auto; | ||
| 9523 | 9555 | ||
| 9524 | return sema.funcCommon( | 9556 | return sema.funcCommon( |
| 9525 | block, | 9557 | block, |
| ... | @@ -9654,15 +9686,64 @@ fn handleExternLibName( | ... | @@ -9654,15 +9686,64 @@ fn handleExternLibName( |
| 9654 | /// These are calling conventions that are confirmed to work with variadic functions. | 9686 | /// 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 variadic | 9687 | /// 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. | 9688 | /// functions or there are no more other calling conventions that support variadic functions. |
| 9657 | const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention{ | 9689 | const calling_conventions_supporting_var_args = [_]std.builtin.NewCallingConvention.Tag{ |
| 9658 | .C, | 9690 | .x86_64_sysv, |
| 9691 | .x86_64_win, | ||
| 9692 | .x86_sysv, | ||
| 9693 | .x86_win, | ||
| 9694 | .aarch64_aapcs, | ||
| 9695 | .aarch64_aapcs_darwin, | ||
| 9696 | .aarch64_aapcs_win, | ||
| 9697 | .aarch64_vfabi, | ||
| 9698 | .aarch64_vfabi_sve, | ||
| 9699 | .arm_apcs, | ||
| 9700 | .arm_aapcs, | ||
| 9701 | .arm_aapcs_vfp, | ||
| 9702 | .arm_aapcs16_vfp, | ||
| 9703 | .mips64_n64, | ||
| 9704 | .mips64_n32, | ||
| 9705 | .mips_o32, | ||
| 9706 | .riscv64_lp64, | ||
| 9707 | .riscv64_lp64_v, | ||
| 9708 | .riscv32_ilp32, | ||
| 9709 | .riscv32_ilp32_v, | ||
| 9710 | .sparc64_sysv, | ||
| 9711 | .sparc_sysv, | ||
| 9712 | .powerpc64_elf, | ||
| 9713 | .powerpc64_elf_altivec, | ||
| 9714 | .powerpc64_elf_v2, | ||
| 9715 | .powerpc_sysv, | ||
| 9716 | .powerpc_sysv_altivec, | ||
| 9717 | .powerpc_aix, | ||
| 9718 | .powerpc_aix_altivec, | ||
| 9719 | .wasm_watc, | ||
| 9720 | .arc_sysv, | ||
| 9721 | .avr_gnu, | ||
| 9722 | .bpf_std, | ||
| 9723 | .csky_sysv, | ||
| 9724 | .hexagon_sysv, | ||
| 9725 | .hexagon_sysv_hvx, | ||
| 9726 | .lanai_sysv, | ||
| 9727 | .loongarch64_lp64, | ||
| 9728 | .loongarch32_ilp32, | ||
| 9729 | .m68k_sysv, | ||
| 9730 | .m68k_gnu, | ||
| 9731 | .m68k_rtd, | ||
| 9732 | .msp430_eabi, | ||
| 9733 | .s390x_sysv, | ||
| 9734 | .s390x_sysv_vx, | ||
| 9735 | .ve_sysv, | ||
| 9736 | .xcore_xs1, | ||
| 9737 | .xcore_xs2, | ||
| 9738 | .xtensa_call0, | ||
| 9739 | .xtensa_windowed, | ||
| 9659 | }; | 9740 | }; |
| 9660 | fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention) bool { | 9741 | fn callConvSupportsVarArgs(cc: std.builtin.NewCallingConvention.Tag) bool { |
| 9661 | return for (calling_conventions_supporting_var_args) |supported_cc| { | 9742 | return for (calling_conventions_supporting_var_args) |supported_cc| { |
| 9662 | if (cc == supported_cc) return true; | 9743 | if (cc == supported_cc) return true; |
| 9663 | } else false; | 9744 | } else false; |
| 9664 | } | 9745 | } |
| 9665 | fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention) CompileError!void { | 9746 | fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.NewCallingConvention.Tag) CompileError!void { |
| 9666 | const CallingConventionsSupportingVarArgsList = struct { | 9747 | const CallingConventionsSupportingVarArgsList = struct { |
| 9667 | pub fn format(_: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | 9748 | pub fn format(_: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| 9668 | _ = fmt; | 9749 | _ = fmt; |
| ... | @@ -9703,7 +9784,7 @@ fn funcCommon( | ... | @@ -9703,7 +9784,7 @@ fn funcCommon( |
| 9703 | address_space: ?std.builtin.AddressSpace, | 9784 | address_space: ?std.builtin.AddressSpace, |
| 9704 | section: Section, | 9785 | section: Section, |
| 9705 | /// null means generic poison | 9786 | /// null means generic poison |
| 9706 | cc: ?std.builtin.CallingConvention, | 9787 | cc: ?std.builtin.NewCallingConvention, |
| 9707 | /// this might be Type.generic_poison | 9788 | /// this might be Type.generic_poison |
| 9708 | bare_return_type: Type, | 9789 | bare_return_type: Type, |
| 9709 | var_args: bool, | 9790 | var_args: bool, |
| ... | @@ -9743,7 +9824,7 @@ fn funcCommon( | ... | @@ -9743,7 +9824,7 @@ fn funcCommon( |
| 9743 | // default values which are only meaningful for the generic function, *not* | 9824 | // default values which are only meaningful for the generic function, *not* |
| 9744 | // the instantiation, which can depend on comptime parameters. | 9825 | // the instantiation, which can depend on comptime parameters. |
| 9745 | // Related proposal: https://github.com/ziglang/zig/issues/11834 | 9826 | // Related proposal: https://github.com/ziglang/zig/issues/11834 |
| 9746 | const cc_resolved = cc orelse .Unspecified; | 9827 | const cc_resolved = cc orelse .auto; |
| 9747 | var comptime_bits: u32 = 0; | 9828 | var comptime_bits: u32 = 0; |
| 9748 | for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { | 9829 | 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); | 9830 | const param_ty = Type.fromInterned(param_ty_ip); |
| ... | @@ -9761,10 +9842,10 @@ fn funcCommon( | ... | @@ -9761,10 +9842,10 @@ fn funcCommon( |
| 9761 | } | 9842 | } |
| 9762 | const this_generic = param_ty.isGenericPoison(); | 9843 | const this_generic = param_ty.isGenericPoison(); |
| 9763 | is_generic = is_generic or this_generic; | 9844 | is_generic = is_generic or this_generic; |
| 9764 | if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) { | 9845 | 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)}); | 9846 | return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); |
| 9766 | } | 9847 | } |
| 9767 | if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) { | 9848 | 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)}); | 9849 | return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); |
| 9769 | } | 9850 | } |
| 9770 | if (!param_ty.isValidParamType(zcu)) { | 9851 | if (!param_ty.isValidParamType(zcu)) { |
| ... | @@ -9773,7 +9854,7 @@ fn funcCommon( | ... | @@ -9773,7 +9854,7 @@ fn funcCommon( |
| 9773 | opaque_str, param_ty.fmt(pt), | 9854 | opaque_str, param_ty.fmt(pt), |
| 9774 | }); | 9855 | }); |
| 9775 | } | 9856 | } |
| 9776 | if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { | 9857 | if (!this_generic and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { |
| 9777 | const msg = msg: { | 9858 | const msg = msg: { |
| 9778 | const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ | 9859 | 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), | 9860 | param_ty.fmt(pt), @tagName(cc_resolved), |
| ... | @@ -9807,15 +9888,24 @@ fn funcCommon( | ... | @@ -9807,15 +9888,24 @@ fn funcCommon( |
| 9807 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); | 9888 | return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); |
| 9808 | } | 9889 | } |
| 9809 | switch (cc_resolved) { | 9890 | switch (cc_resolved) { |
| 9810 | .Interrupt => if (target.cpu.arch.isX86()) { | 9891 | .x86_64_interrupt, .x86_interrupt => { |
| 9811 | const err_code_size = target.ptrBitWidth(); | 9892 | const err_code_size = target.ptrBitWidth(); |
| 9812 | switch (i) { | 9893 | 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", .{}), | 9894 | 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with 'Interrupt' calling convention must be a pointer type", .{}), |
| 9814 | 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with 'Interrupt' calling convention must be a {d}-bit integer", .{err_code_size}), | 9895 | 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with 'Interrupt' calling convention must be a {d}-bit integer", .{err_code_size}), |
| 9815 | else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}), | 9896 | else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}), |
| 9816 | } | 9897 | } |
| 9817 | } else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}), | 9898 | }, |
| 9818 | .Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}), | 9899 | .arm_interrupt, |
| 9900 | .mips64_interrupt, | ||
| 9901 | .mips_interrupt, | ||
| 9902 | .riscv64_interrupt, | ||
| 9903 | .riscv32_interrupt, | ||
| 9904 | .avr_interrupt, | ||
| 9905 | .csky_interrupt, | ||
| 9906 | .m68k_interrupt, | ||
| 9907 | => return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}), | ||
| 9908 | .avr_signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}), | ||
| 9819 | else => {}, | 9909 | else => {}, |
| 9820 | } | 9910 | } |
| 9821 | } | 9911 | } |
| ... | @@ -10051,7 +10141,7 @@ fn finishFunc( | ... | @@ -10051,7 +10141,7 @@ fn finishFunc( |
| 10051 | ret_poison: bool, | 10141 | ret_poison: bool, |
| 10052 | bare_return_type: Type, | 10142 | bare_return_type: Type, |
| 10053 | ret_ty_src: LazySrcLoc, | 10143 | ret_ty_src: LazySrcLoc, |
| 10054 | cc_resolved: std.builtin.CallingConvention, | 10144 | cc_resolved: std.builtin.NewCallingConvention, |
| 10055 | is_source_decl: bool, | 10145 | is_source_decl: bool, |
| 10056 | ret_ty_requires_comptime: bool, | 10146 | ret_ty_requires_comptime: bool, |
| 10057 | func_inst: Zir.Inst.Index, | 10147 | func_inst: Zir.Inst.Index, |
| ... | @@ -10064,7 +10154,6 @@ fn finishFunc( | ... | @@ -10064,7 +10154,6 @@ fn finishFunc( |
| 10064 | const zcu = pt.zcu; | 10154 | const zcu = pt.zcu; |
| 10065 | const ip = &zcu.intern_pool; | 10155 | const ip = &zcu.intern_pool; |
| 10066 | const gpa = sema.gpa; | 10156 | const gpa = sema.gpa; |
| 10067 | const target = zcu.getTarget(); | ||
| 10068 | 10157 | ||
| 10069 | const return_type: Type = if (opt_func_index == .none or ret_poison) | 10158 | const return_type: Type = if (opt_func_index == .none or ret_poison) |
| 10070 | bare_return_type | 10159 | bare_return_type |
| ... | @@ -10077,7 +10166,7 @@ fn finishFunc( | ... | @@ -10077,7 +10166,7 @@ fn finishFunc( |
| 10077 | opaque_str, return_type.fmt(pt), | 10166 | opaque_str, return_type.fmt(pt), |
| 10078 | }); | 10167 | }); |
| 10079 | } | 10168 | } |
| 10080 | if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and | 10169 | if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and |
| 10081 | !try sema.validateExternType(return_type, .ret_ty)) | 10170 | !try sema.validateExternType(return_type, .ret_ty)) |
| 10082 | { | 10171 | { |
| 10083 | const msg = msg: { | 10172 | const msg = msg: { |
| ... | @@ -10134,56 +10223,50 @@ fn finishFunc( | ... | @@ -10134,56 +10223,50 @@ fn finishFunc( |
| 10134 | } | 10223 | } |
| 10135 | 10224 | ||
| 10136 | switch (cc_resolved) { | 10225 | switch (cc_resolved) { |
| 10137 | .Interrupt, .Signal => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) { | 10226 | .x86_64_interrupt, |
| 10227 | .x86_interrupt, | ||
| 10228 | .arm_interrupt, | ||
| 10229 | .mips64_interrupt, | ||
| 10230 | .mips_interrupt, | ||
| 10231 | .riscv64_interrupt, | ||
| 10232 | .riscv32_interrupt, | ||
| 10233 | .avr_interrupt, | ||
| 10234 | .csky_interrupt, | ||
| 10235 | .m68k_interrupt, | ||
| 10236 | .avr_signal, | ||
| 10237 | => 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)}); | 10238 | return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)}); |
| 10139 | }, | 10239 | }, |
| 10140 | .Inline => if (is_noinline) { | 10240 | .@"inline" => if (is_noinline) { |
| 10141 | return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); | 10241 | return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'inline'", .{}); |
| 10142 | }, | 10242 | }, |
| 10143 | else => {}, | 10243 | else => {}, |
| 10144 | } | 10244 | } |
| 10145 | 10245 | ||
| 10146 | const arch = target.cpu.arch; | 10246 | switch (zcu.callconvSupported(cc_resolved)) { |
| 10147 | if (@as(?[]const u8, switch (cc_resolved) { | 10247 | .ok => {}, |
| 10148 | .Unspecified, .C, .Naked, .Async, .Inline => null, | 10248 | .bad_arch => |allowed_archs| { |
| 10149 | .Interrupt => switch (arch) { | 10249 | const ArchListFormatter = struct { |
| 10150 | .x86, .x86_64, .avr, .msp430 => null, | 10250 | archs: []const std.Target.Cpu.Arch, |
| 10151 | else => "x86, x86_64, AVR, and MSP430", | 10251 | pub fn format(formatter: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| 10152 | }, | 10252 | _ = fmt; |
| 10153 | .Signal => switch (arch) { | 10253 | _ = options; |
| 10154 | .avr => null, | 10254 | for (formatter.archs, 0..) |arch, i| { |
| 10155 | else => "AVR", | 10255 | if (i != 0) |
| 10156 | }, | 10256 | try writer.writeAll(", "); |
| 10157 | .Stdcall, .Fastcall, .Thiscall => switch (arch) { | 10257 | try writer.print("'.{s}'", .{@tagName(arch)}); |
| 10158 | .x86 => null, | 10258 | } |
| 10159 | else => "x86", | 10259 | } |
| 10160 | }, | 10260 | }; |
| 10161 | .Vectorcall => switch (arch) { | 10261 | return sema.fail(block, cc_src, "callconv '{s}' only available on architectures {}", .{ |
| 10162 | .x86, .aarch64, .aarch64_be => null, | 10262 | @tagName(cc_resolved), |
| 10163 | else => "x86 and AArch64", | 10263 | ArchListFormatter{ .archs = allowed_archs }, |
| 10164 | }, | 10264 | }); |
| 10165 | .APCS, .AAPCS, .AAPCSVFP => switch (arch) { | 10265 | }, |
| 10166 | .arm, .armeb, .aarch64, .aarch64_be, .thumb, .thumbeb => null, | 10266 | .bad_backend => |bad_backend| return sema.fail(block, cc_src, "callconv '{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), | 10267 | @tagName(cc_resolved), |
| 10184 | allowed_platform, | 10268 | @tagName(bad_backend), |
| 10185 | @tagName(arch), | 10269 | }), |
| 10186 | }); | ||
| 10187 | } | 10270 | } |
| 10188 | 10271 | ||
| 10189 | if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; | 10272 | if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; |
| ... | @@ -18342,10 +18425,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18342,10 +18425,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18342 | } }); | 18425 | } }); |
| 18343 | 18426 | ||
| 18344 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 18427 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); |
| 18428 | const callconv_val = Value.uninterpret(func_ty_info.cc, callconv_ty, pt) catch |err| switch (err) { | ||
| 18429 | error.TypeMismatch => @panic("std.builtin is corrupt"), | ||
| 18430 | error.OutOfMemory => |e| return e, | ||
| 18431 | }; | ||
| 18345 | 18432 | ||
| 18346 | const field_values = .{ | 18433 | const field_values: [5]InternPool.Index = .{ |
| 18347 | // calling_convention: CallingConvention, | 18434 | // calling_convention: CallingConvention, |
| 18348 | (try pt.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(), | 18435 | callconv_val.toIntern(), |
| 18349 | // is_generic: bool, | 18436 | // is_generic: bool, |
| 18350 | Value.makeBool(func_ty_info.is_generic).toIntern(), | 18437 | Value.makeBool(func_ty_info.is_generic).toIntern(), |
| 18351 | // is_var_args: bool, | 18438 | // is_var_args: bool, |
| ... | @@ -22171,7 +22258,7 @@ fn zirReify( | ... | @@ -22171,7 +22258,7 @@ fn zirReify( |
| 22171 | } | 22258 | } |
| 22172 | 22259 | ||
| 22173 | const is_var_args = is_var_args_val.toBool(); | 22260 | const is_var_args = is_var_args_val.toBool(); |
| 22174 | const cc = zcu.toEnum(std.builtin.CallingConvention, calling_convention_val); | 22261 | const cc = try sema.analyzeValueAsCallconv(block, src, calling_convention_val); |
| 22175 | if (is_var_args) { | 22262 | if (is_var_args) { |
| 22176 | try sema.checkCallConvSupportsVarArgs(block, src, cc); | 22263 | try sema.checkCallConvSupportsVarArgs(block, src, cc); |
| 22177 | } | 22264 | } |
| ... | @@ -26657,7 +26744,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -26657,7 +26744,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26657 | break :blk .{ .explicit = section_name }; | 26744 | break :blk .{ .explicit = section_name }; |
| 26658 | } else .default; | 26745 | } else .default; |
| 26659 | 26746 | ||
| 26660 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { | 26747 | const cc: ?std.builtin.NewCallingConvention = if (extra.data.bits.has_cc_body) blk: { |
| 26661 | const body_len = sema.code.extra[extra_index]; | 26748 | const body_len = sema.code.extra[extra_index]; |
| 26662 | extra_index += 1; | 26749 | extra_index += 1; |
| 26663 | const body = sema.code.bodySlice(extra_index, body_len); | 26750 | const body = sema.code.bodySlice(extra_index, body_len); |
| ... | @@ -26670,7 +26757,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -26670,7 +26757,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26670 | if (val.isGenericPoison()) { | 26757 | if (val.isGenericPoison()) { |
| 26671 | break :blk null; | 26758 | break :blk null; |
| 26672 | } | 26759 | } |
| 26673 | break :blk zcu.toEnum(std.builtin.CallingConvention, val); | 26760 | break :blk try sema.analyzeValueAsCallconv(block, cc_src, val); |
| 26674 | } else if (extra.data.bits.has_cc_ref) blk: { | 26761 | } else if (extra.data.bits.has_cc_ref) blk: { |
| 26675 | const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | 26762 | const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 26676 | extra_index += 1; | 26763 | extra_index += 1; |
| ... | @@ -26689,7 +26776,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -26689,7 +26776,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26689 | error.GenericPoison => break :blk null, | 26776 | error.GenericPoison => break :blk null, |
| 26690 | else => |e| return e, | 26777 | else => |e| return e, |
| 26691 | }; | 26778 | }; |
| 26692 | break :blk zcu.toEnum(std.builtin.CallingConvention, cc_val); | 26779 | break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val); |
| 26693 | } else cc: { | 26780 | } else cc: { |
| 26694 | if (has_body) { | 26781 | if (has_body) { |
| 26695 | const decl_inst = if (sema.generic_owner != .none) decl_inst: { | 26782 | const decl_inst = if (sema.generic_owner != .none) decl_inst: { |
| ... | @@ -26705,7 +26792,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -26705,7 +26792,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26705 | break :cc .C; | 26792 | break :cc .C; |
| 26706 | } | 26793 | } |
| 26707 | } | 26794 | } |
| 26708 | break :cc .Unspecified; | 26795 | break :cc .auto; |
| 26709 | }; | 26796 | }; |
| 26710 | 26797 | ||
| 26711 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { | 26798 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { |
| ... | @@ -27132,9 +27219,15 @@ fn zirInComptime( | ... | @@ -27132,9 +27219,15 @@ fn zirInComptime( |
| 27132 | return if (block.is_comptime) .bool_true else .bool_false; | 27219 | return if (block.is_comptime) .bool_true else .bool_false; |
| 27133 | } | 27220 | } |
| 27134 | 27221 | ||
| 27135 | fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 27222 | fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 27136 | const pt = sema.pt; | 27223 | const pt = sema.pt; |
| 27224 | const zcu = pt.zcu; | ||
| 27225 | const gpa = zcu.gpa; | ||
| 27226 | const ip = &zcu.intern_pool; | ||
| 27227 | |||
| 27228 | const src = block.nodeOffset(@bitCast(extended.operand)); | ||
| 27137 | const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); | 27229 | const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); |
| 27230 | |||
| 27138 | const type_name = switch (value) { | 27231 | const type_name = switch (value) { |
| 27139 | .atomic_order => "AtomicOrder", | 27232 | .atomic_order => "AtomicOrder", |
| 27140 | .atomic_rmw_op => "AtomicRmwOp", | 27233 | .atomic_rmw_op => "AtomicRmwOp", |
| ... | @@ -27152,21 +27245,25 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr | ... | @@ -27152,21 +27245,25 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr |
| 27152 | // Values are handled here. | 27245 | // Values are handled here. |
| 27153 | .calling_convention_c => { | 27246 | .calling_convention_c => { |
| 27154 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 27247 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); |
| 27155 | comptime assert(@intFromEnum(std.builtin.CallingConvention.C) == 1); | 27248 | return try sema.namespaceLookupVal( |
| 27156 | const val = try pt.intern(.{ .enum_tag = .{ | 27249 | block, |
| 27157 | .ty = callconv_ty.toIntern(), | 27250 | src, |
| 27158 | .int = .one_u8, | 27251 | callconv_ty.getNamespaceIndex(zcu), |
| 27159 | } }); | 27252 | try ip.getOrPutString(gpa, pt.tid, "c", .no_embedded_nulls), |
| 27160 | return Air.internedToRef(val); | 27253 | ) orelse @panic("std.builtin is corrupt"); |
| 27161 | }, | 27254 | }, |
| 27162 | .calling_convention_inline => { | 27255 | .calling_convention_inline => { |
| 27256 | comptime assert(@typeInfo(std.builtin.NewCallingConvention.Tag).@"enum".tag_type == u8); | ||
| 27163 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 27257 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); |
| 27164 | comptime assert(@intFromEnum(std.builtin.CallingConvention.Inline) == 4); | 27258 | const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt"); |
| 27165 | const val = try pt.intern(.{ .enum_tag = .{ | 27259 | const inline_tag_val = try pt.enumValue( |
| 27166 | .ty = callconv_ty.toIntern(), | 27260 | callconv_tag_ty, |
| 27167 | .int = .four_u8, | 27261 | (try pt.intValue( |
| 27168 | } }); | 27262 | Type.u8, |
| 27169 | return Air.internedToRef(val); | 27263 | @intFromEnum(std.builtin.NewCallingConvention.@"inline"), |
| 27264 | )).toIntern(), | ||
| 27265 | ); | ||
| 27266 | return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src); | ||
| 27170 | }, | 27267 | }, |
| 27171 | }; | 27268 | }; |
| 27172 | const ty = try sema.getBuiltinType(type_name); | 27269 | const ty = try sema.getBuiltinType(type_name); |
| ... | @@ -27353,7 +27450,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -27353,7 +27450,7 @@ fn explainWhyTypeIsComptimeInner( |
| 27353 | try sema.errNote(src_loc, msg, "function is generic", .{}); | 27450 | try sema.errNote(src_loc, msg, "function is generic", .{}); |
| 27354 | } | 27451 | } |
| 27355 | switch (fn_info.cc) { | 27452 | switch (fn_info.cc) { |
| 27356 | .Inline => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}), | 27453 | .@"inline" => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}), |
| 27357 | else => {}, | 27454 | else => {}, |
| 27358 | } | 27455 | } |
| 27359 | if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) { | 27456 | if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) { |
| ... | @@ -27461,13 +27558,12 @@ fn validateExternType( | ... | @@ -27461,13 +27558,12 @@ fn validateExternType( |
| 27461 | }, | 27558 | }, |
| 27462 | .@"fn" => { | 27559 | .@"fn" => { |
| 27463 | if (position != .other) return false; | 27560 | 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. | 27561 | // 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. | 27562 | // 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)) { | 27563 | if (ty.fnCallingConvention(zcu) == .nvptx_kernel) { |
| 27468 | return true; | 27564 | return true; |
| 27469 | } | 27565 | } |
| 27470 | return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(zcu)); | 27566 | return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); |
| 27471 | }, | 27567 | }, |
| 27472 | .@"enum" => { | 27568 | .@"enum" => { |
| 27473 | return sema.validateExternType(ty.intTagType(zcu), position); | 27569 | return sema.validateExternType(ty.intTagType(zcu), position); |
| ... | @@ -27547,9 +27643,9 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -27547,9 +27643,9 @@ fn explainWhyTypeIsNotExtern( |
| 27547 | return; | 27643 | return; |
| 27548 | } | 27644 | } |
| 27549 | switch (ty.fnCallingConvention(zcu)) { | 27645 | switch (ty.fnCallingConvention(zcu)) { |
| 27550 | .Unspecified => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), | 27646 | .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", .{}), | 27647 | .@"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", .{}), | 27648 | .@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}), |
| 27553 | else => return, | 27649 | else => return, |
| 27554 | } | 27650 | } |
| 27555 | }, | 27651 | }, |
| ... | @@ -30525,8 +30621,8 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -30525,8 +30621,8 @@ const InMemoryCoercionResult = union(enum) { |
| 30525 | }; | 30621 | }; |
| 30526 | 30622 | ||
| 30527 | const CC = struct { | 30623 | const CC = struct { |
| 30528 | actual: std.builtin.CallingConvention, | 30624 | actual: std.builtin.NewCallingConvention, |
| 30529 | wanted: std.builtin.CallingConvention, | 30625 | wanted: std.builtin.NewCallingConvention, |
| 30530 | }; | 30626 | }; |
| 30531 | 30627 | ||
| 30532 | const BitRange = struct { | 30628 | const BitRange = struct { |
| ... | @@ -31176,8 +31272,8 @@ fn coerceInMemoryAllowedFns( | ... | @@ -31176,8 +31272,8 @@ fn coerceInMemoryAllowedFns( |
| 31176 | return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; | 31272 | return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; |
| 31177 | } | 31273 | } |
| 31178 | 31274 | ||
| 31179 | if (dest_info.cc != src_info.cc) { | 31275 | if (!callconvCoerceAllowed(target, src_info.cc, dest_info.cc)) { |
| 31180 | return InMemoryCoercionResult{ .fn_cc = .{ | 31276 | return .{ .fn_cc = .{ |
| 31181 | .actual = src_info.cc, | 31277 | .actual = src_info.cc, |
| 31182 | .wanted = dest_info.cc, | 31278 | .wanted = dest_info.cc, |
| 31183 | } }; | 31279 | } }; |
| ... | @@ -31250,6 +31346,44 @@ fn coerceInMemoryAllowedFns( | ... | @@ -31250,6 +31346,44 @@ fn coerceInMemoryAllowedFns( |
| 31250 | return .ok; | 31346 | return .ok; |
| 31251 | } | 31347 | } |
| 31252 | 31348 | ||
| 31349 | fn callconvCoerceAllowed( | ||
| 31350 | target: std.Target, | ||
| 31351 | src_cc: std.builtin.NewCallingConvention, | ||
| 31352 | dest_cc: std.builtin.NewCallingConvention, | ||
| 31353 | ) bool { | ||
| 31354 | const Tag = std.builtin.NewCallingConvention.Tag; | ||
| 31355 | if (@as(Tag, src_cc) != @as(Tag, dest_cc)) return false; | ||
| 31356 | |||
| 31357 | switch (src_cc) { | ||
| 31358 | inline else => |src_data, tag| { | ||
| 31359 | const dest_data = @field(dest_cc, @tagName(tag)); | ||
| 31360 | if (@TypeOf(src_data) != void) { | ||
| 31361 | const default_stack_align = target.stackAlignment(); | ||
| 31362 | const src_stack_align = src_data.incoming_stack_alignment orelse default_stack_align; | ||
| 31363 | const dest_stack_align = src_data.incoming_stack_alignment orelse default_stack_align; | ||
| 31364 | if (dest_stack_align < src_stack_align) return false; | ||
| 31365 | } | ||
| 31366 | switch (@TypeOf(src_data)) { | ||
| 31367 | void, std.builtin.NewCallingConvention.CommonOptions => {}, | ||
| 31368 | std.builtin.NewCallingConvention.X86RegparmOptions => { | ||
| 31369 | if (src_data.register_params != dest_data.register_params) return false; | ||
| 31370 | }, | ||
| 31371 | std.builtin.NewCallingConvention.ArmInterruptOptions => { | ||
| 31372 | if (src_data.type != dest_data.type) return false; | ||
| 31373 | }, | ||
| 31374 | std.builtin.NewCallingConvention.MipsInterruptOptions => { | ||
| 31375 | if (src_data.mode != dest_data.mode) return false; | ||
| 31376 | }, | ||
| 31377 | std.builtin.NewCallingConvention.RiscvInterruptOptions => { | ||
| 31378 | if (src_data.level != dest_data.level) return false; | ||
| 31379 | }, | ||
| 31380 | else => comptime unreachable, | ||
| 31381 | } | ||
| 31382 | }, | ||
| 31383 | } | ||
| 31384 | return true; | ||
| 31385 | } | ||
| 31386 | |||
| 31253 | fn coerceInMemoryAllowedPtrs( | 31387 | fn coerceInMemoryAllowedPtrs( |
| 31254 | sema: *Sema, | 31388 | sema: *Sema, |
| 31255 | block: *Block, | 31389 | block: *Block, |
| ... | @@ -36306,7 +36440,7 @@ fn resolveInferredErrorSet( | ... | @@ -36306,7 +36440,7 @@ fn resolveInferredErrorSet( |
| 36306 | // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, | 36440 | // 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. | 36441 | // so here we can simply skip this case. |
| 36308 | if (ies_func_info.return_type == .generic_poison_type) { | 36442 | if (ies_func_info.return_type == .generic_poison_type) { |
| 36309 | assert(ies_func_info.cc == .Inline); | 36443 | assert(ies_func_info.cc == .@"inline"); |
| 36310 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { | 36444 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { |
| 36311 | if (ies_func_info.is_generic) { | 36445 | if (ies_func_info.is_generic) { |
| 36312 | return sema.failWithOwnedErrorMsg(block, msg: { | 36446 | return sema.failWithOwnedErrorMsg(block, msg: { |
src/Type.zig+10-6| ... | @@ -390,10 +390,14 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error | ... | @@ -390,10 +390,14 @@ 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().defaultCCallingConvention()) |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 | try writer.print("callconv({any}) ", .{fn_info.cc}); | ||
| 397 | } | 401 | } |
| 398 | if (fn_info.return_type == .generic_poison_type) { | 402 | if (fn_info.return_type == .generic_poison_type) { |
| 399 | try writer.writeAll("anytype"); | 403 | try writer.writeAll("anytype"); |
| ... | @@ -791,7 +795,7 @@ pub fn fnHasRuntimeBitsInner( | ... | @@ -791,7 +795,7 @@ pub fn fnHasRuntimeBitsInner( |
| 791 | const fn_info = zcu.typeToFunc(ty).?; | 795 | const fn_info = zcu.typeToFunc(ty).?; |
| 792 | if (fn_info.is_generic) return false; | 796 | if (fn_info.is_generic) return false; |
| 793 | if (fn_info.is_var_args) return true; | 797 | if (fn_info.is_var_args) return true; |
| 794 | if (fn_info.cc == .Inline) return false; | 798 | if (fn_info.cc == .@"inline") return false; |
| 795 | return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid); | 799 | return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid); |
| 796 | } | 800 | } |
| 797 | 801 | ||
| ... | @@ -2489,7 +2493,7 @@ pub fn fnReturnType(ty: Type, zcu: *const Zcu) Type { | ... | @@ -2489,7 +2493,7 @@ pub fn fnReturnType(ty: Type, zcu: *const Zcu) Type { |
| 2489 | } | 2493 | } |
| 2490 | 2494 | ||
| 2491 | /// Asserts the type is a function. | 2495 | /// Asserts the type is a function. |
| 2492 | pub fn fnCallingConvention(ty: Type, zcu: *const Zcu) std.builtin.CallingConvention { | 2496 | pub fn fnCallingConvention(ty: Type, zcu: *const Zcu) std.builtin.NewCallingConvention { |
| 2493 | return zcu.intern_pool.indexToKey(ty.toIntern()).func_type.cc; | 2497 | return zcu.intern_pool.indexToKey(ty.toIntern()).func_type.cc; |
| 2494 | } | 2498 | } |
| 2495 | 2499 |
src/Value.zig+160| ... | @@ -4490,3 +4490,163 @@ pub fn resolveLazy( | ... | @@ -4490,3 +4490,163 @@ 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. | ||
| 4497 | pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T { | ||
| 4498 | @setEvalBranchQuota(400_000); | ||
| 4499 | |||
| 4500 | const zcu = pt.zcu; | ||
| 4501 | const ip = &zcu.intern_pool; | ||
| 4502 | const ty = val.typeOf(zcu); | ||
| 4503 | if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch; | ||
| 4504 | if (val.isUndef(zcu)) return error.UndefinedValue; | ||
| 4505 | |||
| 4506 | return switch (@typeInfo(T)) { | ||
| 4507 | .type, | ||
| 4508 | .noreturn, | ||
| 4509 | .comptime_float, | ||
| 4510 | .comptime_int, | ||
| 4511 | .undefined, | ||
| 4512 | .null, | ||
| 4513 | .@"fn", | ||
| 4514 | .@"opaque", | ||
| 4515 | .enum_literal, | ||
| 4516 | => comptime unreachable, // comptime-only or otherwise impossible | ||
| 4517 | |||
| 4518 | .pointer, | ||
| 4519 | .array, | ||
| 4520 | .error_union, | ||
| 4521 | .error_set, | ||
| 4522 | .frame, | ||
| 4523 | .@"anyframe", | ||
| 4524 | .vector, | ||
| 4525 | => comptime unreachable, // unsupported | ||
| 4526 | |||
| 4527 | .void => {}, | ||
| 4528 | |||
| 4529 | .bool => switch (val.toIntern()) { | ||
| 4530 | .bool_false => false, | ||
| 4531 | .bool_true => true, | ||
| 4532 | else => unreachable, | ||
| 4533 | }, | ||
| 4534 | |||
| 4535 | .int => switch (ip.indexToKey(val.toIntern()).int.storage) { | ||
| 4536 | .lazy_align, .lazy_size => unreachable, // `val` is fully resolved | ||
| 4537 | inline .u64, .i64 => |x| std.math.cast(T, x) orelse return error.TypeMismatch, | ||
| 4538 | .big_int => |big| big.to(T) catch return error.TypeMismatch, | ||
| 4539 | }, | ||
| 4540 | |||
| 4541 | .float => val.toFloat(T, zcu), | ||
| 4542 | |||
| 4543 | .optional => |opt| if (val.optionalValue(zcu)) |unwrapped| | ||
| 4544 | try unwrapped.interpret(opt.child, pt) | ||
| 4545 | else | ||
| 4546 | null, | ||
| 4547 | |||
| 4548 | .@"enum" => zcu.toEnum(T, val), | ||
| 4549 | |||
| 4550 | .@"union" => |@"union"| { | ||
| 4551 | const union_obj = zcu.typeToUnion(ty) orelse return error.TypeMismatch; | ||
| 4552 | if (union_obj.field_types.len != @"union".fields.len) return error.TypeMismatch; | ||
| 4553 | const tag_val = val.unionTag(zcu) orelse return error.TypeMismatch; | ||
| 4554 | const tag = try tag_val.interpret(@"union".tag_type.?, pt); | ||
| 4555 | switch (tag) { | ||
| 4556 | inline else => |tag_comptime| { | ||
| 4557 | const Payload = std.meta.FieldType(T, tag_comptime); | ||
| 4558 | const payload = try val.unionValue(zcu).interpret(Payload, pt); | ||
| 4559 | return @unionInit(T, @tagName(tag_comptime), payload); | ||
| 4560 | }, | ||
| 4561 | } | ||
| 4562 | }, | ||
| 4563 | |||
| 4564 | .@"struct" => |@"struct"| { | ||
| 4565 | if (ty.structFieldCount(zcu) != @"struct".fields.len) return error.TypeMismatch; | ||
| 4566 | var result: T = undefined; | ||
| 4567 | inline for (@"struct".fields, 0..) |field, field_idx| { | ||
| 4568 | const field_val = try val.fieldValue(pt, field_idx); | ||
| 4569 | @field(result, field.name) = try field_val.interpret(field.type, pt); | ||
| 4570 | } | ||
| 4571 | return result; | ||
| 4572 | }, | ||
| 4573 | }; | ||
| 4574 | } | ||
| 4575 | |||
| 4576 | /// Given any `val` and a `Type` corresponding `@TypeOf(val)`, construct a `Value` representing it which can be used | ||
| 4577 | /// within the compilation. This is useful for passing `std.builtin` structures in the compiler back to the compilation. | ||
| 4578 | /// This is the inverse of `interpret`. | ||
| 4579 | pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory, TypeMismatch }!Value { | ||
| 4580 | @setEvalBranchQuota(400_000); | ||
| 4581 | |||
| 4582 | const T = @TypeOf(val); | ||
| 4583 | |||
| 4584 | const zcu = pt.zcu; | ||
| 4585 | if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch; | ||
| 4586 | |||
| 4587 | return switch (@typeInfo(T)) { | ||
| 4588 | .type, | ||
| 4589 | .noreturn, | ||
| 4590 | .comptime_float, | ||
| 4591 | .comptime_int, | ||
| 4592 | .undefined, | ||
| 4593 | .null, | ||
| 4594 | .@"fn", | ||
| 4595 | .@"opaque", | ||
| 4596 | .enum_literal, | ||
| 4597 | => comptime unreachable, // comptime-only or otherwise impossible | ||
| 4598 | |||
| 4599 | .pointer, | ||
| 4600 | .array, | ||
| 4601 | .error_union, | ||
| 4602 | .error_set, | ||
| 4603 | .frame, | ||
| 4604 | .@"anyframe", | ||
| 4605 | .vector, | ||
| 4606 | => comptime unreachable, // unsupported | ||
| 4607 | |||
| 4608 | .void => .void, | ||
| 4609 | |||
| 4610 | .bool => if (val) .true else .false, | ||
| 4611 | |||
| 4612 | .int => try pt.intValue(ty, val), | ||
| 4613 | |||
| 4614 | .float => try pt.floatValue(ty, val), | ||
| 4615 | |||
| 4616 | .optional => if (val) |some| | ||
| 4617 | .fromInterned(try pt.intern(.{ .opt = .{ | ||
| 4618 | .ty = ty.toIntern(), | ||
| 4619 | .val = (try uninterpret(some, ty.optionalChild(zcu), pt)).toIntern(), | ||
| 4620 | } })) | ||
| 4621 | else | ||
| 4622 | try pt.nullValue(ty), | ||
| 4623 | |||
| 4624 | .@"enum" => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()), | ||
| 4625 | |||
| 4626 | .@"union" => |@"union"| { | ||
| 4627 | const tag: @"union".tag_type.? = val; | ||
| 4628 | const tag_val = try uninterpret(tag, ty.unionTagType(zcu).?, pt); | ||
| 4629 | const field_ty = ty.unionFieldType(tag_val, zcu) orelse return error.TypeMismatch; | ||
| 4630 | return switch (val) { | ||
| 4631 | inline else => |payload| try pt.unionValue( | ||
| 4632 | ty, | ||
| 4633 | tag_val, | ||
| 4634 | try uninterpret(payload, field_ty, pt), | ||
| 4635 | ), | ||
| 4636 | }; | ||
| 4637 | }, | ||
| 4638 | |||
| 4639 | .@"struct" => |@"struct"| { | ||
| 4640 | if (ty.structFieldCount(zcu) != @"struct".fields.len) return error.TypeMismatch; | ||
| 4641 | var field_vals: [@"struct".fields.len]InternPool.Index = undefined; | ||
| 4642 | inline for (&field_vals, @"struct".fields, 0..) |*field_val, field, field_idx| { | ||
| 4643 | const field_ty = ty.fieldType(field_idx, zcu); | ||
| 4644 | field_val.* = (try uninterpret(@field(val, field.name), field_ty, pt)).toIntern(); | ||
| 4645 | } | ||
| 4646 | return .fromInterned(try pt.intern(.{ .aggregate = .{ | ||
| 4647 | .ty = ty.toIntern(), | ||
| 4648 | .storage = .{ .elems = &field_vals }, | ||
| 4649 | } })); | ||
| 4650 | }, | ||
| 4651 | }; | ||
| 4652 | } |
src/Zcu.zig+90| ... | @@ -3539,3 +3539,93 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void { | ... | @@ -3539,3 +3539,93 @@ 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 | |||
| 3543 | pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.NewCallingConvention) 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.defaultCCallingConvention()) |default_c| { | ||
| 3566 | if (cc.eql(default_c)) { | ||
| 3567 | break :ok true; | ||
| 3568 | } | ||
| 3569 | } | ||
| 3570 | break :ok switch (cc) { | ||
| 3571 | .x86_64_vectorcall, | ||
| 3572 | .x86_fastcall, | ||
| 3573 | .x86_thiscall, | ||
| 3574 | .x86_vectorcall, | ||
| 3575 | => |opts| opts.incoming_stack_alignment == null, | ||
| 3576 | |||
| 3577 | .x86_stdcall, | ||
| 3578 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | ||
| 3579 | |||
| 3580 | .naked => true, | ||
| 3581 | |||
| 3582 | else => false, | ||
| 3583 | }; | ||
| 3584 | }, | ||
| 3585 | .stage2_wasm => switch (cc) { | ||
| 3586 | .wasm_watc => |opts| opts.incoming_stack_alignment == null, | ||
| 3587 | else => false, | ||
| 3588 | }, | ||
| 3589 | .stage2_arm => switch (cc) { | ||
| 3590 | .arm_aapcs => |opts| opts.incoming_stack_alignment == null, | ||
| 3591 | .naked => true, | ||
| 3592 | else => false, | ||
| 3593 | }, | ||
| 3594 | .stage2_x86_64 => switch (cc) { | ||
| 3595 | .x86_64_sysv, .x86_64_win, .naked => true, | ||
| 3596 | else => false, | ||
| 3597 | }, | ||
| 3598 | .stage2_aarch64 => switch (cc) { | ||
| 3599 | .aarch64_aapcs => |opts| opts.incoming_stack_alignment == null, | ||
| 3600 | .naked => true, | ||
| 3601 | else => false, | ||
| 3602 | }, | ||
| 3603 | .stage2_x86 => switch (cc) { | ||
| 3604 | .x86_sysv, | ||
| 3605 | .x86_win, | ||
| 3606 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | ||
| 3607 | .naked => true, | ||
| 3608 | else => false, | ||
| 3609 | }, | ||
| 3610 | .stage2_riscv64 => switch (cc) { | ||
| 3611 | .riscv64_lp64 => |opts| opts.incoming_stack_alignment == null, | ||
| 3612 | .naked => true, | ||
| 3613 | else => false, | ||
| 3614 | }, | ||
| 3615 | .stage2_sparc64 => switch (cc) { | ||
| 3616 | .sparc64_sysv => |opts| opts.incoming_stack_alignment == null, | ||
| 3617 | .naked => true, | ||
| 3618 | else => false, | ||
| 3619 | }, | ||
| 3620 | .stage2_spirv64 => switch (cc) { | ||
| 3621 | .spirv_device, | ||
| 3622 | .spirv_kernel, | ||
| 3623 | .spirv_fragment, | ||
| 3624 | .spirv_vertex, | ||
| 3625 | => true, | ||
| 3626 | else => false, | ||
| 3627 | }, | ||
| 3628 | }; | ||
| 3629 | if (!backend_ok) return .{ .bad_backend = backend }; | ||
| 3630 | return .ok; | ||
| 3631 | } |
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); |
| 6230 | 6230 | ||
| 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 Standard | 6240 | // ARM64 Procedure Call Standard |
| 6241 | var ncrn: usize = 0; // Next Core Register Number | 6241 | var ncrn: usize = 0; // Next Core Register Number |
| 6242 | var nsaa: u32 = 0; // Next stacked argument address | 6242 | 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 { |
| 6266 | 6266 | ||
| 6267 | // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned | 6267 | // 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 number | 6270 | // 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(); |
| 481 | 481 | ||
| ... | @@ -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); |
| 6197 | 6197 | ||
| 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.5 | 6207 | // ARM Procedure Call Standard, Chapter 6.5 |
| 6208 | var ncrn: usize = 0; // Next Core Register Number | 6208 | var ncrn: usize = 0; // Next Core Register Number |
| 6209 | var nsaa: u32 = 0; // Next stacked argument address | 6209 | 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+7-7| ... | @@ -977,7 +977,7 @@ pub fn generateLazy( | ... | @@ -977,7 +977,7 @@ pub fn generateLazy( |
| 977 | .pt = pt, | 977 | .pt = pt, |
| 978 | .allocator = gpa, | 978 | .allocator = gpa, |
| 979 | .mir = mir, | 979 | .mir = mir, |
| 980 | .cc = .Unspecified, | 980 | .cc = .auto, |
| 981 | .src_loc = src_loc, | 981 | .src_loc = src_loc, |
| 982 | .output_mode = comp.config.output_mode, | 982 | .output_mode = comp.config.output_mode, |
| 983 | .link_mode = comp.config.link_mode, | 983 | .link_mode = comp.config.link_mode, |
| ... | @@ -1036,7 +1036,7 @@ fn formatWipMir( | ... | @@ -1036,7 +1036,7 @@ fn formatWipMir( |
| 1036 | .instructions = data.func.mir_instructions.slice(), | 1036 | .instructions = data.func.mir_instructions.slice(), |
| 1037 | .frame_locs = data.func.frame_locs.slice(), | 1037 | .frame_locs = data.func.frame_locs.slice(), |
| 1038 | }, | 1038 | }, |
| 1039 | .cc = .Unspecified, | 1039 | .cc = .auto, |
| 1040 | .src_loc = data.func.src_loc, | 1040 | .src_loc = data.func.src_loc, |
| 1041 | .output_mode = comp.config.output_mode, | 1041 | .output_mode = comp.config.output_mode, |
| 1042 | .link_mode = comp.config.link_mode, | 1042 | .link_mode = comp.config.link_mode, |
| ... | @@ -1238,7 +1238,7 @@ fn gen(func: *Func) !void { | ... | @@ -1238,7 +1238,7 @@ fn gen(func: *Func) !void { |
| 1238 | } | 1238 | } |
| 1239 | } | 1239 | } |
| 1240 | 1240 | ||
| 1241 | if (fn_info.cc != .Naked) { | 1241 | if (fn_info.cc != .naked) { |
| 1242 | _ = try func.addPseudo(.pseudo_dbg_prologue_end); | 1242 | _ = try func.addPseudo(.pseudo_dbg_prologue_end); |
| 1243 | 1243 | ||
| 1244 | const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead); | 1244 | const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead); |
| ... | @@ -4894,7 +4894,7 @@ fn genCall( | ... | @@ -4894,7 +4894,7 @@ fn genCall( |
| 4894 | .lib => |lib| try pt.funcType(.{ | 4894 | .lib => |lib| try pt.funcType(.{ |
| 4895 | .param_types = lib.param_types, | 4895 | .param_types = lib.param_types, |
| 4896 | .return_type = lib.return_type, | 4896 | .return_type = lib.return_type, |
| 4897 | .cc = .C, | 4897 | .cc = func.target.defaultCCallingConvention().?, |
| 4898 | }), | 4898 | }), |
| 4899 | }; | 4899 | }; |
| 4900 | 4900 | ||
| ... | @@ -8289,12 +8289,12 @@ fn resolveCallingConventionValues( | ... | @@ -8289,12 +8289,12 @@ fn resolveCallingConventionValues( |
| 8289 | const ret_ty = Type.fromInterned(fn_info.return_type); | 8289 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| 8290 | 8290 | ||
| 8291 | switch (cc) { | 8291 | switch (cc) { |
| 8292 | .Naked => { | 8292 | .naked => { |
| 8293 | assert(result.args.len == 0); | 8293 | assert(result.args.len == 0); |
| 8294 | result.return_value = InstTracking.init(.unreach); | 8294 | result.return_value = InstTracking.init(.unreach); |
| 8295 | result.stack_align = .@"8"; | 8295 | result.stack_align = .@"8"; |
| 8296 | }, | 8296 | }, |
| 8297 | .C, .Unspecified => { | 8297 | .riscv64_lp64, .auto => { |
| 8298 | if (result.args.len > 8) { | 8298 | if (result.args.len > 8) { |
| 8299 | return func.fail("RISC-V calling convention does not support more than 8 arguments", .{}); | 8299 | return func.fail("RISC-V calling convention does not support more than 8 arguments", .{}); |
| 8300 | } | 8300 | } |
| ... | @@ -8359,7 +8359,7 @@ fn resolveCallingConventionValues( | ... | @@ -8359,7 +8359,7 @@ fn resolveCallingConventionValues( |
| 8359 | 8359 | ||
| 8360 | for (param_types, result.args) |ty, *arg| { | 8360 | for (param_types, result.args) |ty, *arg| { |
| 8361 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 8361 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 8362 | assert(cc == .Unspecified); | 8362 | assert(cc == .auto); |
| 8363 | arg.* = .none; | 8363 | arg.* = .none; |
| 8364 | continue; | 8364 | continue; |
| 8365 | } | 8365 | } |
src/arch/riscv64/Lower.zig+1-1| ... | @@ -6,7 +6,7 @@ link_mode: std.builtin.LinkMode, | ... | @@ -6,7 +6,7 @@ link_mode: std.builtin.LinkMode, |
| 6 | pic: bool, | 6 | pic: bool, |
| 7 | allocator: Allocator, | 7 | allocator: Allocator, |
| 8 | mir: Mir, | 8 | mir: Mir, |
| 9 | cc: std.builtin.CallingConvention, | 9 | cc: std.builtin.NewCallingConvention, |
| 10 | err_msg: ?*ErrorMsg = null, | 10 | err_msg: ?*ErrorMsg = null, |
| 11 | src_loc: Zcu.LazySrcLoc, | 11 | src_loc: Zcu.LazySrcLoc, |
| 12 | result_insts_len: u8 = undefined, | 12 | result_insts_len: u8 = undefined, |
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. |
| 371 | 371 | ||
| 372 | // save %sp, stack_reserved_area, %sp | 372 | // 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); |
| 4442 | 4442 | ||
| 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 3 | 4452 | // SPARC Compliance Definition 2.4.1, Chapter 3 |
| 4453 | // Low-Level System Information (64-bit psABI) - Function Calling Sequence | 4453 | // Low-Level System Information (64-bit psABI) - Function Calling Sequence |
| 4454 | 4454 |
src/arch/wasm/CodeGen.zig+18-17| ... | @@ -1145,7 +1145,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -1145,7 +1145,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { |
| 1145 | /// Memory is owned by the caller. | 1145 | /// Memory is owned by the caller. |
| 1146 | fn genFunctype( | 1146 | fn genFunctype( |
| 1147 | gpa: Allocator, | 1147 | gpa: Allocator, |
| 1148 | cc: std.builtin.CallingConvention, | 1148 | cc: std.builtin.NewCallingConvention, |
| 1149 | params: []const InternPool.Index, | 1149 | params: []const InternPool.Index, |
| 1150 | return_type: Type, | 1150 | return_type: Type, |
| 1151 | pt: Zcu.PerThread, | 1151 | pt: Zcu.PerThread, |
| ... | @@ -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 handle | 1161 | 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; |
| 1179 | 1179 | ||
| 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; |
| 1371 | 1371 | ||
| 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 | } |
| 1383 | 1383 | ||
| 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| { |
| ... | @@ -1408,10 +1408,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV | ... | @@ -1408,10 +1408,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV |
| 1408 | return result; | 1408 | return result; |
| 1409 | } | 1409 | } |
| 1410 | 1410 | ||
| 1411 | fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu.PerThread, target: std.Target) bool { | 1411 | fn firstParamSRet(cc: std.builtin.NewCallingConvention, 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; |
| ... | @@ -1423,8 +1424,8 @@ fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu. | ... | @@ -1423,8 +1424,8 @@ fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, pt: Zcu. |
| 1423 | 1424 | ||
| 1424 | /// Lowers a Zig type and its value based on a given calling convention to ensure | 1425 | /// 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. |
| 1426 | fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void { | 1427 | fn lowerArg(func: *CodeGen, cc: std.builtin.NewCallingConvention, 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 | } |
| 1430 | 1431 | ||
| ... | @@ -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 instead | 2109 | // 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 value | 2114 | // 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 optimize | 2289 | // 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-ABI | 7176 | // 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); |
| 7182 | 7183 | ||
| 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 argument | 7186 | // 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 | } |
| 7198 | 7199 | ||
| 7199 | // Actually call our intrinsic | 7200 | // Actually call our intrinsic |
src/arch/x86_64/CodeGen.zig+32-33| ... | @@ -918,13 +918,13 @@ pub fn generate( | ... | @@ -918,13 +918,13 @@ pub fn generate( |
| 918 | ); | 918 | ); |
| 919 | function.va_info = switch (cc) { | 919 | function.va_info = switch (cc) { |
| 920 | else => undefined, | 920 | else => undefined, |
| 921 | .SysV => .{ .sysv = .{ | 921 | .x86_64_sysv => .{ .sysv = .{ |
| 922 | .gp_count = call_info.gp_count, | 922 | .gp_count = call_info.gp_count, |
| 923 | .fp_count = call_info.fp_count, | 923 | .fp_count = call_info.fp_count, |
| 924 | .overflow_arg_area = .{ .index = .args_frame, .off = call_info.stack_byte_count }, | 924 | .overflow_arg_area = .{ .index = .args_frame, .off = call_info.stack_byte_count }, |
| 925 | .reg_save_area = undefined, | 925 | .reg_save_area = undefined, |
| 926 | } }, | 926 | } }, |
| 927 | .Win64 => .{ .win64 = .{} }, | 927 | .x86_64_win => .{ .win64 = .{} }, |
| 928 | }; | 928 | }; |
| 929 | 929 | ||
| 930 | function.gen() catch |err| switch (err) { | 930 | function.gen() catch |err| switch (err) { |
| ... | @@ -1053,7 +1053,7 @@ pub fn generateLazy( | ... | @@ -1053,7 +1053,7 @@ pub fn generateLazy( |
| 1053 | .bin_file = bin_file, | 1053 | .bin_file = bin_file, |
| 1054 | .allocator = gpa, | 1054 | .allocator = gpa, |
| 1055 | .mir = mir, | 1055 | .mir = mir, |
| 1056 | .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), | 1056 | .cc = abi.resolveCallingConvention(.auto, function.target.*), |
| 1057 | .src_loc = src_loc, | 1057 | .src_loc = src_loc, |
| 1058 | .output_mode = comp.config.output_mode, | 1058 | .output_mode = comp.config.output_mode, |
| 1059 | .link_mode = comp.config.link_mode, | 1059 | .link_mode = comp.config.link_mode, |
| ... | @@ -1159,7 +1159,7 @@ fn formatWipMir( | ... | @@ -1159,7 +1159,7 @@ fn formatWipMir( |
| 1159 | .extra = data.self.mir_extra.items, | 1159 | .extra = data.self.mir_extra.items, |
| 1160 | .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(), | 1160 | .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(), |
| 1161 | }, | 1161 | }, |
| 1162 | .cc = .Unspecified, | 1162 | .cc = .auto, |
| 1163 | .src_loc = data.self.src_loc, | 1163 | .src_loc = data.self.src_loc, |
| 1164 | .output_mode = comp.config.output_mode, | 1164 | .output_mode = comp.config.output_mode, |
| 1165 | .link_mode = comp.config.link_mode, | 1165 | .link_mode = comp.config.link_mode, |
| ... | @@ -2023,7 +2023,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -2023,7 +2023,7 @@ fn gen(self: *Self) InnerError!void { |
| 2023 | const zcu = pt.zcu; | 2023 | const zcu = pt.zcu; |
| 2024 | const fn_info = zcu.typeToFunc(self.fn_type).?; | 2024 | const fn_info = zcu.typeToFunc(self.fn_type).?; |
| 2025 | const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); | 2025 | const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); |
| 2026 | if (cc != .Naked) { | 2026 | if (cc != .naked) { |
| 2027 | try self.asmRegister(.{ ._, .push }, .rbp); | 2027 | try self.asmRegister(.{ ._, .push }, .rbp); |
| 2028 | try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8)); | 2028 | 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)); | 2029 | try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0)); |
| ... | @@ -2056,7 +2056,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -2056,7 +2056,7 @@ fn gen(self: *Self) InnerError!void { |
| 2056 | } | 2056 | } |
| 2057 | 2057 | ||
| 2058 | if (fn_info.is_var_args) switch (cc) { | 2058 | if (fn_info.is_var_args) switch (cc) { |
| 2059 | .SysV => { | 2059 | .x86_64_sysv => { |
| 2060 | const info = &self.va_info.sysv; | 2060 | const info = &self.va_info.sysv; |
| 2061 | const reg_save_area_fi = try self.allocFrameIndex(FrameAlloc.init(.{ | 2061 | const reg_save_area_fi = try self.allocFrameIndex(FrameAlloc.init(.{ |
| 2062 | .size = abi.SysV.c_abi_int_param_regs.len * 8 + | 2062 | .size = abi.SysV.c_abi_int_param_regs.len * 8 + |
| ... | @@ -2089,7 +2089,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -2089,7 +2089,7 @@ fn gen(self: *Self) InnerError!void { |
| 2089 | 2089 | ||
| 2090 | self.performReloc(skip_sse_reloc); | 2090 | self.performReloc(skip_sse_reloc); |
| 2091 | }, | 2091 | }, |
| 2092 | .Win64 => return self.fail("TODO implement gen var arg function for Win64", .{}), | 2092 | .x86_64_win => return self.fail("TODO implement gen var arg function for Win64", .{}), |
| 2093 | else => unreachable, | 2093 | else => unreachable, |
| 2094 | }; | 2094 | }; |
| 2095 | 2095 | ||
| ... | @@ -2541,7 +2541,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { | ... | @@ -2541,7 +2541,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2541 | const enum_ty = Type.fromInterned(lazy_sym.ty); | 2541 | const enum_ty = Type.fromInterned(lazy_sym.ty); |
| 2542 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)}); | 2542 | wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)}); |
| 2543 | 2543 | ||
| 2544 | const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*); | 2544 | const resolved_cc = abi.resolveCallingConvention(.auto, self.target.*); |
| 2545 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); | 2545 | const param_regs = abi.getCAbiIntParamRegs(resolved_cc); |
| 2546 | const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*); | 2546 | const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*); |
| 2547 | defer for (param_locks) |lock| self.register_manager.unlockReg(lock); | 2547 | defer for (param_locks) |lock| self.register_manager.unlockReg(lock); |
| ... | @@ -2694,7 +2694,7 @@ fn setFrameLoc( | ... | @@ -2694,7 +2694,7 @@ fn setFrameLoc( |
| 2694 | offset.* += self.frame_allocs.items(.abi_size)[frame_i]; | 2694 | offset.* += self.frame_allocs.items(.abi_size)[frame_i]; |
| 2695 | } | 2695 | } |
| 2696 | 2696 | ||
| 2697 | fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayout { | 2697 | fn computeFrameLayout(self: *Self, cc: std.builtin.NewCallingConvention) !FrameLayout { |
| 2698 | const frame_allocs_len = self.frame_allocs.len; | 2698 | const frame_allocs_len = self.frame_allocs.len; |
| 2699 | try self.frame_locs.resize(self.gpa, frame_allocs_len); | 2699 | try self.frame_locs.resize(self.gpa, frame_allocs_len); |
| 2700 | const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count); | 2700 | const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count); |
| ... | @@ -3006,11 +3006,10 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { | ... | @@ -3006,11 +3006,10 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 3006 | } | 3006 | } |
| 3007 | } | 3007 | } |
| 3008 | 3008 | ||
| 3009 | pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void { | 3009 | pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.NewCallingConvention) !void { |
| 3010 | switch (cc) { | 3010 | switch (cc) { |
| 3011 | inline .SysV, .Win64 => |known_cc| try self.spillRegisters( | 3011 | .x86_64_sysv => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_sysv = .{} })), |
| 3012 | comptime abi.getCallerPreservedRegs(known_cc), | 3012 | .x86_64_win => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_win = .{} })), |
| 3013 | ), | ||
| 3014 | else => unreachable, | 3013 | else => unreachable, |
| 3015 | } | 3014 | } |
| 3016 | } | 3015 | } |
| ... | @@ -12384,7 +12383,7 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -12384,7 +12383,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12384 | .lib => |lib| try pt.funcType(.{ | 12383 | .lib => |lib| try pt.funcType(.{ |
| 12385 | .param_types = lib.param_types, | 12384 | .param_types = lib.param_types, |
| 12386 | .return_type = lib.return_type, | 12385 | .return_type = lib.return_type, |
| 12387 | .cc = .C, | 12386 | .cc = self.target.defaultCCallingConvention().?, |
| 12388 | }), | 12387 | }), |
| 12389 | }; | 12388 | }; |
| 12390 | const fn_info = zcu.typeToFunc(fn_ty).?; | 12389 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| ... | @@ -12543,7 +12542,7 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -12543,7 +12542,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12543 | src_arg, | 12542 | src_arg, |
| 12544 | .{}, | 12543 | .{}, |
| 12545 | ), | 12544 | ), |
| 12546 | .C, .SysV, .Win64 => { | 12545 | .x86_64_sysv, .x86_64_win => { |
| 12547 | const promoted_ty = self.promoteInt(arg_ty); | 12546 | const promoted_ty = self.promoteInt(arg_ty); |
| 12548 | const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu)); | 12547 | const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(zcu)); |
| 12549 | const dst_alias = registerAlias(dst_reg, promoted_abi_size); | 12548 | const dst_alias = registerAlias(dst_reg, promoted_abi_size); |
| ... | @@ -16822,7 +16821,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -16822,7 +16821,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 16822 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 16821 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 16823 | const inst_ty = self.typeOfIndex(inst); | 16822 | const inst_ty = self.typeOfIndex(inst); |
| 16824 | const enum_ty = self.typeOf(un_op); | 16823 | const enum_ty = self.typeOf(un_op); |
| 16825 | const resolved_cc = abi.resolveCallingConvention(.Unspecified, self.target.*); | 16824 | const resolved_cc = abi.resolveCallingConvention(.auto, self.target.*); |
| 16826 | 16825 | ||
| 16827 | // We need a properly aligned and sized call frame to be able to call this function. | 16826 | // We need a properly aligned and sized call frame to be able to call this function. |
| 16828 | { | 16827 | { |
| ... | @@ -18915,7 +18914,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -18915,7 +18914,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 18915 | self.fn_type.fnCallingConvention(zcu), | 18914 | self.fn_type.fnCallingConvention(zcu), |
| 18916 | self.target.*, | 18915 | self.target.*, |
| 18917 | )) { | 18916 | )) { |
| 18918 | .SysV => result: { | 18917 | .x86_64_sysv => result: { |
| 18919 | const info = self.va_info.sysv; | 18918 | const info = self.va_info.sysv; |
| 18920 | const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, zcu)); | 18919 | const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, zcu)); |
| 18921 | var field_off: u31 = 0; | 18920 | var field_off: u31 = 0; |
| ... | @@ -18957,7 +18956,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -18957,7 +18956,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 18957 | field_off += @intCast(ptr_anyopaque_ty.abiSize(zcu)); | 18956 | field_off += @intCast(ptr_anyopaque_ty.abiSize(zcu)); |
| 18958 | break :result .{ .load_frame = .{ .index = dst_fi } }; | 18957 | break :result .{ .load_frame = .{ .index = dst_fi } }; |
| 18959 | }, | 18958 | }, |
| 18960 | .Win64 => return self.fail("TODO implement c_va_start for Win64", .{}), | 18959 | .x86_64_win => return self.fail("TODO implement c_va_start for Win64", .{}), |
| 18961 | else => unreachable, | 18960 | else => unreachable, |
| 18962 | }; | 18961 | }; |
| 18963 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 18962 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| ... | @@ -18976,7 +18975,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -18976,7 +18975,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 18976 | self.fn_type.fnCallingConvention(zcu), | 18975 | self.fn_type.fnCallingConvention(zcu), |
| 18977 | self.target.*, | 18976 | self.target.*, |
| 18978 | )) { | 18977 | )) { |
| 18979 | .SysV => result: { | 18978 | .x86_64_sysv => result: { |
| 18980 | try self.spillEflagsIfOccupied(); | 18979 | try self.spillEflagsIfOccupied(); |
| 18981 | 18980 | ||
| 18982 | const tmp_regs = | 18981 | const tmp_regs = |
| ... | @@ -19155,7 +19154,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -19155,7 +19154,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 19155 | ); | 19154 | ); |
| 19156 | break :result promote_mcv; | 19155 | break :result promote_mcv; |
| 19157 | }, | 19156 | }, |
| 19158 | .Win64 => return self.fail("TODO implement c_va_arg for Win64", .{}), | 19157 | .x86_64_win => return self.fail("TODO implement c_va_arg for Win64", .{}), |
| 19159 | else => unreachable, | 19158 | else => unreachable, |
| 19160 | }; | 19159 | }; |
| 19161 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 19160 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | @@ -19324,12 +19323,12 @@ fn resolveCallingConventionValues( | ... | @@ -19324,12 +19323,12 @@ fn resolveCallingConventionValues( |
| 19324 | 19323 | ||
| 19325 | const resolved_cc = abi.resolveCallingConvention(cc, self.target.*); | 19324 | const resolved_cc = abi.resolveCallingConvention(cc, self.target.*); |
| 19326 | switch (cc) { | 19325 | switch (cc) { |
| 19327 | .Naked => { | 19326 | .naked => { |
| 19328 | assert(result.args.len == 0); | 19327 | assert(result.args.len == 0); |
| 19329 | result.return_value = InstTracking.init(.unreach); | 19328 | result.return_value = InstTracking.init(.unreach); |
| 19330 | result.stack_align = .@"8"; | 19329 | result.stack_align = .@"8"; |
| 19331 | }, | 19330 | }, |
| 19332 | .C, .SysV, .Win64 => { | 19331 | .x86_64_sysv, .x86_64_win => { |
| 19333 | var ret_int_reg_i: u32 = 0; | 19332 | var ret_int_reg_i: u32 = 0; |
| 19334 | var ret_sse_reg_i: u32 = 0; | 19333 | var ret_sse_reg_i: u32 = 0; |
| 19335 | var param_int_reg_i: u32 = 0; | 19334 | var param_int_reg_i: u32 = 0; |
| ... | @@ -19337,8 +19336,8 @@ fn resolveCallingConventionValues( | ... | @@ -19337,8 +19336,8 @@ fn resolveCallingConventionValues( |
| 19337 | result.stack_align = .@"16"; | 19336 | result.stack_align = .@"16"; |
| 19338 | 19337 | ||
| 19339 | switch (resolved_cc) { | 19338 | switch (resolved_cc) { |
| 19340 | .SysV => {}, | 19339 | .x86_64_sysv => {}, |
| 19341 | .Win64 => { | 19340 | .x86_64_win => { |
| 19342 | // Align the stack to 16bytes before allocating shadow stack space (if any). | 19341 | // Align the stack to 16bytes before allocating shadow stack space (if any). |
| 19343 | result.stack_byte_count += @intCast(4 * Type.usize.abiSize(zcu)); | 19342 | result.stack_byte_count += @intCast(4 * Type.usize.abiSize(zcu)); |
| 19344 | }, | 19343 | }, |
| ... | @@ -19356,8 +19355,8 @@ fn resolveCallingConventionValues( | ... | @@ -19356,8 +19355,8 @@ fn resolveCallingConventionValues( |
| 19356 | var ret_tracking_i: usize = 0; | 19355 | var ret_tracking_i: usize = 0; |
| 19357 | 19356 | ||
| 19358 | const classes = switch (resolved_cc) { | 19357 | const classes = switch (resolved_cc) { |
| 19359 | .SysV => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none), | 19358 | .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none), |
| 19360 | .Win64 => &.{abi.classifyWindows(ret_ty, zcu)}, | 19359 | .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)}, |
| 19361 | else => unreachable, | 19360 | else => unreachable, |
| 19362 | }; | 19361 | }; |
| 19363 | for (classes) |class| switch (class) { | 19362 | for (classes) |class| switch (class) { |
| ... | @@ -19419,8 +19418,8 @@ fn resolveCallingConventionValues( | ... | @@ -19419,8 +19418,8 @@ fn resolveCallingConventionValues( |
| 19419 | for (param_types, result.args) |ty, *arg| { | 19418 | for (param_types, result.args) |ty, *arg| { |
| 19420 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); | 19419 | assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); |
| 19421 | switch (resolved_cc) { | 19420 | switch (resolved_cc) { |
| 19422 | .SysV => {}, | 19421 | .x86_64_sysv => {}, |
| 19423 | .Win64 => { | 19422 | .x86_64_win => { |
| 19424 | param_int_reg_i = @max(param_int_reg_i, param_sse_reg_i); | 19423 | param_int_reg_i = @max(param_int_reg_i, param_sse_reg_i); |
| 19425 | param_sse_reg_i = param_int_reg_i; | 19424 | param_sse_reg_i = param_int_reg_i; |
| 19426 | }, | 19425 | }, |
| ... | @@ -19431,8 +19430,8 @@ fn resolveCallingConventionValues( | ... | @@ -19431,8 +19430,8 @@ fn resolveCallingConventionValues( |
| 19431 | var arg_mcv_i: usize = 0; | 19430 | var arg_mcv_i: usize = 0; |
| 19432 | 19431 | ||
| 19433 | const classes = switch (resolved_cc) { | 19432 | const classes = switch (resolved_cc) { |
| 19434 | .SysV => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none), | 19433 | .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none), |
| 19435 | .Win64 => &.{abi.classifyWindows(ty, zcu)}, | 19434 | .x86_64_win => &.{abi.classifyWindows(ty, zcu)}, |
| 19436 | else => unreachable, | 19435 | else => unreachable, |
| 19437 | }; | 19436 | }; |
| 19438 | for (classes) |class| switch (class) { | 19437 | for (classes) |class| switch (class) { |
| ... | @@ -19464,11 +19463,11 @@ fn resolveCallingConventionValues( | ... | @@ -19464,11 +19463,11 @@ fn resolveCallingConventionValues( |
| 19464 | }, | 19463 | }, |
| 19465 | .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse), | 19464 | .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse), |
| 19466 | .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) { | 19465 | .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) { |
| 19467 | .SysV => switch (class) { | 19466 | .x86_64_sysv => switch (class) { |
| 19468 | .x87, .x87up, .complex_x87, .memory => break, | 19467 | .x87, .x87up, .complex_x87, .memory => break, |
| 19469 | else => unreachable, | 19468 | else => unreachable, |
| 19470 | }, | 19469 | }, |
| 19471 | .Win64 => if (ty.abiSize(zcu) > 8) { | 19470 | .x86_64_win => if (ty.abiSize(zcu) > 8) { |
| 19472 | const param_int_reg = | 19471 | const param_int_reg = |
| 19473 | abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64(); | 19472 | abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64(); |
| 19474 | param_int_reg_i += 1; | 19473 | param_int_reg_i += 1; |
| ... | @@ -19530,7 +19529,7 @@ fn resolveCallingConventionValues( | ... | @@ -19530,7 +19529,7 @@ fn resolveCallingConventionValues( |
| 19530 | assert(param_sse_reg_i <= 16); | 19529 | assert(param_sse_reg_i <= 16); |
| 19531 | result.fp_count = param_sse_reg_i; | 19530 | result.fp_count = param_sse_reg_i; |
| 19532 | }, | 19531 | }, |
| 19533 | .Unspecified => { | 19532 | .auto => { |
| 19534 | result.stack_align = .@"16"; | 19533 | result.stack_align = .@"16"; |
| 19535 | 19534 | ||
| 19536 | // Return values | 19535 | // Return values |
src/arch/x86_64/Lower.zig+1-1| ... | @@ -6,7 +6,7 @@ link_mode: std.builtin.LinkMode, | ... | @@ -6,7 +6,7 @@ link_mode: std.builtin.LinkMode, |
| 6 | pic: bool, | 6 | pic: bool, |
| 7 | allocator: std.mem.Allocator, | 7 | allocator: std.mem.Allocator, |
| 8 | mir: Mir, | 8 | mir: Mir, |
| 9 | cc: std.builtin.CallingConvention, | 9 | cc: std.builtin.NewCallingConvention, |
| 10 | err_msg: ?*Zcu.ErrorMsg = null, | 10 | err_msg: ?*Zcu.ErrorMsg = null, |
| 11 | src_loc: Zcu.LazySrcLoc, | 11 | src_loc: Zcu.LazySrcLoc, |
| 12 | result_insts_len: u8 = undefined, | 12 | result_insts_len: u8 = undefined, |
src/arch/x86_64/abi.zig+23-23| ... | @@ -436,62 +436,62 @@ pub const Win64 = struct { | ... | @@ -436,62 +436,62 @@ pub const Win64 = struct { |
| 436 | }; | 436 | }; |
| 437 | 437 | ||
| 438 | pub fn resolveCallingConvention( | 438 | pub fn resolveCallingConvention( |
| 439 | cc: std.builtin.CallingConvention, | 439 | cc: std.builtin.NewCallingConvention, |
| 440 | target: std.Target, | 440 | target: std.Target, |
| 441 | ) std.builtin.CallingConvention { | 441 | ) std.builtin.NewCallingConvention { |
| 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 | }; |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | pub fn getCalleePreservedRegs(cc: std.builtin.CallingConvention) []const Register { | 451 | pub fn getCalleePreservedRegs(cc: std.builtin.NewCallingConvention) []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 | } |
| 458 | 458 | ||
| 459 | pub fn getCallerPreservedRegs(cc: std.builtin.CallingConvention) []const Register { | 459 | pub fn getCallerPreservedRegs(cc: std.builtin.NewCallingConvention) []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 | } |
| 466 | 466 | ||
| 467 | pub fn getCAbiIntParamRegs(cc: std.builtin.CallingConvention) []const Register { | 467 | pub fn getCAbiIntParamRegs(cc: std.builtin.NewCallingConvention) []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 | } |
| 474 | 474 | ||
| 475 | pub fn getCAbiSseParamRegs(cc: std.builtin.CallingConvention) []const Register { | 475 | pub fn getCAbiSseParamRegs(cc: std.builtin.NewCallingConvention) []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 | } |
| 482 | 482 | ||
| 483 | pub fn getCAbiIntReturnRegs(cc: std.builtin.CallingConvention) []const Register { | 483 | pub fn getCAbiIntReturnRegs(cc: std.builtin.NewCallingConvention) []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 | } |
| 490 | 490 | ||
| 491 | pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention) []const Register { | 491 | pub fn getCAbiSseReturnRegs(cc: std.builtin.NewCallingConvention) []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+13-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); |
| 1784 | 1784 | ||
| 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 { |
| 1796 | 1796 | ||
| 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, .{}); |
| 1798 | 1798 | ||
| 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,17 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void { | ... | @@ -7604,12 +7604,17 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void { |
| 7604 | return w.writeAll(toMemoryOrder(order)); | 7604 | return w.writeAll(toMemoryOrder(order)); |
| 7605 | } | 7605 | } |
| 7606 | 7606 | ||
| 7607 | fn toCallingConvention(call_conv: std.builtin.CallingConvention) ?[]const u8 { | 7607 | fn toCallingConvention(cc: std.builtin.NewCallingConvention, zcu: *Zcu) ?[]const u8 { |
| 7608 | return switch (call_conv) { | 7608 | return switch (cc) { |
| 7609 | .Stdcall => "stdcall", | 7609 | .auto, .naked => null, |
| 7610 | .Fastcall => "fastcall", | 7610 | .x86_stdcall => "stdcall", |
| 7611 | .Vectorcall => "vectorcall", | 7611 | .x86_fastcall => "fastcall", |
| 7612 | else => null, | 7612 | .x86_vectorcall, .x86_64_vectorcall => "vectorcall", |
| 7613 | else => { | ||
| 7614 | // `Zcu.callconvSupported` means this must be the C callconv. | ||
| 7615 | assert(cc.eql(zcu.getTarget().defaultCCallingConvention().?)); | ||
| 7616 | return null; | ||
| 7617 | }, | ||
| 7613 | }; | 7618 | }; |
| 7614 | } | 7619 | } |
| 7615 | 7620 |
src/codegen/llvm.zig+351-243| ... | @@ -1159,7 +1159,7 @@ pub const Object = struct { | ... | @@ -1159,7 +1159,7 @@ pub const Object = struct { |
| 1159 | } | 1159 | } |
| 1160 | 1160 | ||
| 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(); |
| 1164 | 1164 | ||
| 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 | } |
| 1235 | 1235 | ||
| 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 | } |
| 1238 | 1250 | ||
| ... | @@ -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 | } |
| 1469 | 1481 | ||
| 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 | } |
| 3040 | 3044 | ||
| 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 | } |
| 3050 | 3073 | ||
| 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 the | 3084 | // 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 at | 3085 | // 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 | ); |
| 3066 | 3089 | ||
| 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,16 @@ pub const Object = struct { | ... | @@ -4618,9 +4641,16 @@ 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 | .avr_interrupt, | ||
| 4649 | .m68k_interrupt, | ||
| 4650 | => { | ||
| 4651 | const child_type = try lowerType(o, Type.fromInterned(ptr_info.child)); | ||
| 4652 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder); | ||
| 4653 | }, | ||
| 4624 | } | 4654 | } |
| 4625 | if (ptr_info.flags.is_const) { | 4655 | if (ptr_info.flags.is_const) { |
| 4626 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); | 4656 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| ... | @@ -5677,7 +5707,7 @@ pub const FuncGen = struct { | ... | @@ -5677,7 +5707,7 @@ pub const FuncGen = struct { |
| 5677 | .always_tail => .musttail, | 5707 | .always_tail => .musttail, |
| 5678 | .async_kw, .no_async, .always_inline, .compile_time => unreachable, | 5708 | .async_kw, .no_async, .always_inline, .compile_time => unreachable, |
| 5679 | }, | 5709 | }, |
| 5680 | toLlvmCallConv(fn_info.cc, target), | 5710 | toLlvmCallConvTag(fn_info.cc, target).?, |
| 5681 | try attributes.finish(&o.builder), | 5711 | try attributes.finish(&o.builder), |
| 5682 | try o.lowerType(zig_fn_ty), | 5712 | try o.lowerType(zig_fn_ty), |
| 5683 | llvm_fn, | 5713 | llvm_fn, |
| ... | @@ -5756,7 +5786,7 @@ pub const FuncGen = struct { | ... | @@ -5756,7 +5786,7 @@ pub const FuncGen = struct { |
| 5756 | _ = try fg.wip.callIntrinsicAssumeCold(); | 5786 | _ = try fg.wip.callIntrinsicAssumeCold(); |
| 5757 | _ = try fg.wip.call( | 5787 | _ = try fg.wip.call( |
| 5758 | .normal, | 5788 | .normal, |
| 5759 | toLlvmCallConv(fn_info.cc, target), | 5789 | toLlvmCallConvTag(fn_info.cc, target).?, |
| 5760 | .none, | 5790 | .none, |
| 5761 | panic_global.typeOf(&o.builder), | 5791 | panic_global.typeOf(&o.builder), |
| 5762 | panic_global.toValue(&o.builder), | 5792 | panic_global.toValue(&o.builder), |
| ... | @@ -11554,36 +11584,146 @@ fn toLlvmAtomicRmwBinOp( | ... | @@ -11554,36 +11584,146 @@ fn toLlvmAtomicRmwBinOp( |
| 11554 | }; | 11584 | }; |
| 11555 | } | 11585 | } |
| 11556 | 11586 | ||
| 11557 | fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) Builder.CallConv { | 11587 | const CallingConventionInfo = struct { |
| 11558 | return switch (cc) { | 11588 | /// The LLVM calling convention to use. |
| 11559 | .Unspecified, .Inline, .Async => .fastcc, | 11589 | llvm_cc: Builder.CallConv, |
| 11560 | .C, .Naked => .ccc, | 11590 | /// Whether to use an `alignstack` attribute to forcibly re-align the stack pointer in the function's prologue. |
| 11561 | .Stdcall => .x86_stdcallcc, | 11591 | align_stack: bool, |
| 11562 | .Fastcall => .x86_fastcallcc, | 11592 | /// Whether the function needs a `naked` attribute. |
| 11563 | .Vectorcall => return switch (target.cpu.arch) { | 11593 | naked: bool, |
| 11564 | .x86, .x86_64 => .x86_vectorcallcc, | 11594 | /// How many leading parameters to apply the `inreg` attribute to. |
| 11565 | .aarch64, .aarch64_be => .aarch64_vector_pcs, | 11595 | inreg_param_count: u2 = 0, |
| 11566 | else => unreachable, | 11596 | }; |
| 11567 | }, | 11597 | |
| 11568 | .Thiscall => .x86_thiscallcc, | 11598 | pub fn toLlvmCallConv(cc: std.builtin.NewCallingConvention, target: std.Target) ?CallingConventionInfo { |
| 11569 | .APCS => .arm_apcscc, | 11599 | const llvm_cc = toLlvmCallConvTag(cc, target) orelse return null; |
| 11570 | .AAPCS => .arm_aapcscc, | 11600 | const incoming_stack_alignment: ?u64, const register_params: u2 = switch (cc) { |
| 11571 | .AAPCSVFP => .arm_aapcs_vfpcc, | 11601 | inline else => |pl| switch (@TypeOf(pl)) { |
| 11572 | .Interrupt => return switch (target.cpu.arch) { | 11602 | void => .{ null, 0 }, |
| 11573 | .x86, .x86_64 => .x86_intrcc, | 11603 | std.builtin.NewCallingConvention.CommonOptions => .{ pl.incoming_stack_alignment, 0 }, |
| 11574 | .avr => .avr_intrcc, | 11604 | std.builtin.NewCallingConvention.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, | 11605 | else => unreachable, |
| 11585 | }, | 11606 | }, |
| 11586 | .Vertex, .Fragment => unreachable, | 11607 | }; |
| 11608 | return .{ | ||
| 11609 | .llvm_cc = llvm_cc, | ||
| 11610 | .align_stack = if (incoming_stack_alignment) |a| need_align: { | ||
| 11611 | const normal_stack_align = target.stackAlignment(); | ||
| 11612 | break :need_align a < normal_stack_align; | ||
| 11613 | } else false, | ||
| 11614 | .naked = cc == .naked, | ||
| 11615 | .inreg_param_count = register_params, | ||
| 11616 | }; | ||
| 11617 | } | ||
| 11618 | fn toLlvmCallConvTag(cc_tag: std.builtin.NewCallingConvention.Tag, target: std.Target) ?Builder.CallConv { | ||
| 11619 | if (target.defaultCCallingConvention()) |default_c| { | ||
| 11620 | if (cc_tag == default_c) { | ||
| 11621 | return .ccc; | ||
| 11622 | } | ||
| 11623 | } | ||
| 11624 | return switch (cc_tag) { | ||
| 11625 | .@"inline" => unreachable, | ||
| 11626 | .auto, .@"async" => .fastcc, | ||
| 11627 | .naked => .ccc, | ||
| 11628 | .x86_64_sysv => .x86_64_sysvcc, | ||
| 11629 | .x86_64_win => .win64cc, | ||
| 11630 | .x86_64_regcall_v3_sysv => if (target.cpu.arch == .x86_64 and target.os.tag != .windows) | ||
| 11631 | .x86_regcallcc | ||
| 11632 | else | ||
| 11633 | null, | ||
| 11634 | .x86_64_regcall_v4_win => if (target.cpu.arch == .x86_64 and target.os.tag == .windows) | ||
| 11635 | .x86_regcallcc // we use the "RegCallv4" module flag to make this correct | ||
| 11636 | else | ||
| 11637 | null, | ||
| 11638 | .x86_64_vectorcall => .x86_vectorcallcc, | ||
| 11639 | .x86_64_interrupt => .x86_intrcc, | ||
| 11640 | .x86_stdcall => .x86_stdcallcc, | ||
| 11641 | .x86_fastcall => .x86_fastcallcc, | ||
| 11642 | .x86_thiscall => .x86_thiscallcc, | ||
| 11643 | .x86_regcall_v3 => if (target.cpu.arch == .x86 and target.os.tag != .windows) | ||
| 11644 | .x86_regcallcc | ||
| 11645 | else | ||
| 11646 | null, | ||
| 11647 | .x86_regcall_v4_win => if (target.cpu.arch == .x86 and target.os.tag == .windows) | ||
| 11648 | .x86_regcallcc // we use the "RegCallv4" module flag to make this correct | ||
| 11649 | else | ||
| 11650 | null, | ||
| 11651 | .x86_vectorcall => .x86_vectorcallcc, | ||
| 11652 | .x86_interrupt => .x86_intrcc, | ||
| 11653 | .aarch64_vfabi => .aarch64_vector_pcs, | ||
| 11654 | .aarch64_vfabi_sve => .aarch64_sve_vector_pcs, | ||
| 11655 | .arm_apcs => .arm_apcscc, | ||
| 11656 | .arm_aapcs => .arm_aapcscc, | ||
| 11657 | .arm_aapcs_vfp => .arm_aapcs_vfpcc, | ||
| 11658 | .riscv64_lp64_v => .riscv_vectorcallcc, | ||
| 11659 | .riscv32_ilp32_v => .riscv_vectorcallcc, | ||
| 11660 | .avr_builtin => .avr_builtincc, | ||
| 11661 | .avr_signal => .avr_signalcc, | ||
| 11662 | .avr_interrupt => .avr_intrcc, | ||
| 11663 | .m68k_rtd => .m68k_rtdcc, | ||
| 11664 | .m68k_interrupt => .m68k_intrcc, | ||
| 11665 | .amdgcn_kernel => .amdgpu_kernel, | ||
| 11666 | .amdgcn_cs => .amdgpu_cs, | ||
| 11667 | .nvptx_device => .ptx_device, | ||
| 11668 | .nvptx_kernel => .ptx_kernel, | ||
| 11669 | |||
| 11670 | // All the calling conventions which LLVM does not have a general representation for. | ||
| 11671 | // Note that these are often still supported through the `defaultCCallingConvention` path above via `ccc`. | ||
| 11672 | .x86_sysv, | ||
| 11673 | .x86_win, | ||
| 11674 | .x86_thiscall_mingw, | ||
| 11675 | .aarch64_aapcs, | ||
| 11676 | .aarch64_aapcs_darwin, | ||
| 11677 | .aarch64_aapcs_win, | ||
| 11678 | .arm_aapcs16_vfp, | ||
| 11679 | .arm_interrupt, | ||
| 11680 | .mips64_n64, | ||
| 11681 | .mips64_n32, | ||
| 11682 | .mips64_interrupt, | ||
| 11683 | .mips_o32, | ||
| 11684 | .mips_interrupt, | ||
| 11685 | .riscv64_lp64, | ||
| 11686 | .riscv64_interrupt, | ||
| 11687 | .riscv32_ilp32, | ||
| 11688 | .riscv32_interrupt, | ||
| 11689 | .sparc64_sysv, | ||
| 11690 | .sparc_sysv, | ||
| 11691 | .powerpc64_elf, | ||
| 11692 | .powerpc64_elf_altivec, | ||
| 11693 | .powerpc64_elf_v2, | ||
| 11694 | .powerpc_sysv, | ||
| 11695 | .powerpc_sysv_altivec, | ||
| 11696 | .powerpc_aix, | ||
| 11697 | .powerpc_aix_altivec, | ||
| 11698 | .wasm_watc, | ||
| 11699 | .arc_sysv, | ||
| 11700 | .avr_gnu, | ||
| 11701 | .bpf_std, | ||
| 11702 | .csky_sysv, | ||
| 11703 | .csky_interrupt, | ||
| 11704 | .hexagon_sysv, | ||
| 11705 | .hexagon_sysv_hvx, | ||
| 11706 | .lanai_sysv, | ||
| 11707 | .loongarch64_lp64, | ||
| 11708 | .loongarch32_ilp32, | ||
| 11709 | .m68k_sysv, | ||
| 11710 | .m68k_gnu, | ||
| 11711 | .msp430_eabi, | ||
| 11712 | .propeller1_sysv, | ||
| 11713 | .propeller2_sysv, | ||
| 11714 | .s390x_sysv, | ||
| 11715 | .s390x_sysv_vx, | ||
| 11716 | .ve_sysv, | ||
| 11717 | .xcore_xs1, | ||
| 11718 | .xcore_xs2, | ||
| 11719 | .xtensa_call0, | ||
| 11720 | .xtensa_windowed, | ||
| 11721 | .amdgcn_device, | ||
| 11722 | .spirv_device, | ||
| 11723 | .spirv_kernel, | ||
| 11724 | .spirv_fragment, | ||
| 11725 | .spirv_vertex, | ||
| 11726 | => null, | ||
| 11587 | }; | 11727 | }; |
| 11588 | } | 11728 | } |
| 11589 | 11729 | ||
| ... | @@ -11711,31 +11851,27 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe | ... | @@ -11711,31 +11851,27 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe |
| 11711 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; | 11851 | if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; |
| 11712 | 11852 | ||
| 11713 | return switch (fn_info.cc) { | 11853 | return switch (fn_info.cc) { |
| 11714 | .Unspecified, .Inline => returnTypeByRef(zcu, target, return_type), | 11854 | .auto => returnTypeByRef(zcu, target, return_type), |
| 11715 | .C => switch (target.cpu.arch) { | 11855 | .x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target), |
| 11716 | .mips, .mipsel => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) { | 11856 | .x86_64_win => x86_64_abi.classifyWindows(return_type, zcu) == .memory, |
| 11717 | .memory, .i32_array => true, | 11857 | .x86_sysv, .x86_win => isByRef(return_type, zcu), |
| 11718 | .byval => false, | 11858 | .x86_stdcall => !isScalar(zcu, return_type), |
| 11719 | }, | 11859 | .wasm_watc => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect, |
| 11720 | .x86 => isByRef(return_type, zcu), | 11860 | .aarch64_aapcs, |
| 11721 | .x86_64 => switch (target.os.tag) { | 11861 | .aarch64_aapcs_darwin, |
| 11722 | .windows => x86_64_abi.classifyWindows(return_type, zcu) == .memory, | 11862 | .aarch64_aapcs_win, |
| 11723 | else => firstParamSRetSystemV(return_type, zcu, target), | 11863 | => aarch64_c_abi.classifyType(return_type, zcu) == .memory, |
| 11724 | }, | 11864 | .arm_aapcs => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { |
| 11725 | .wasm32 => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect, | 11865 | .memory, .i64_array => true, |
| 11726 | .aarch64, .aarch64_be => aarch64_c_abi.classifyType(return_type, zcu) == .memory, | 11866 | .i32_array => |size| size != 1, |
| 11727 | .arm, .armeb => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { | 11867 | .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 | }, | 11868 | }, |
| 11735 | .SysV => firstParamSRetSystemV(return_type, zcu, target), | 11869 | .riscv64_lp64, .riscv32_ilp32 => riscv_c_abi.classifyType(return_type, zcu) == .memory, |
| 11736 | .Win64 => x86_64_abi.classifyWindows(return_type, zcu) == .memory, | 11870 | .mips64_n64, .mips64_n32, .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) { |
| 11737 | .Stdcall => !isScalar(zcu, return_type), | 11871 | .memory, .i32_array => true, |
| 11738 | else => false, | 11872 | .byval => false, |
| 11873 | }, | ||
| 11874 | else => false, // TODO: investigate other targets/callconvs | ||
| 11739 | }; | 11875 | }; |
| 11740 | } | 11876 | } |
| 11741 | 11877 | ||
| ... | @@ -11761,82 +11897,64 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu | ... | @@ -11761,82 +11897,64 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu |
| 11761 | } | 11897 | } |
| 11762 | const target = zcu.getTarget(); | 11898 | const target = zcu.getTarget(); |
| 11763 | switch (fn_info.cc) { | 11899 | switch (fn_info.cc) { |
| 11764 | .Unspecified, | 11900 | .@"inline" => unreachable, |
| 11765 | .Inline, | 11901 | .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), | 11902 | |
| 11767 | 11903 | .x86_64_sysv => return lowerSystemVFnRetTy(o, fn_info), | |
| 11768 | .C => { | 11904 | .x86_64_win => return lowerWin64FnRetTy(o, fn_info), |
| 11769 | switch (target.cpu.arch) { | 11905 | .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void, |
| 11770 | .mips, .mipsel => { | 11906 | .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)) { | 11907 | .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(return_type, zcu)) { |
| 11772 | .memory, .i32_array => return .void, | 11908 | .memory => return .void, |
| 11773 | .byval => return o.lowerType(return_type), | 11909 | .float_array => return o.lowerType(return_type), |
| 11774 | } | 11910 | .byval => return o.lowerType(return_type), |
| 11775 | }, | 11911 | .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), |
| 11776 | .x86 => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type), | 11912 | .double_integer => return o.builder.arrayType(2, .i64), |
| 11777 | .x86_64 => switch (target.os.tag) { | 11913 | }, |
| 11778 | .windows => return lowerWin64FnRetTy(o, fn_info), | 11914 | .arm_aapcs => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { |
| 11779 | else => return lowerSystemVFnRetTy(o, fn_info), | 11915 | .memory, .i64_array => return .void, |
| 11780 | }, | 11916 | .i32_array => |len| return if (len == 1) .i32 else .void, |
| 11781 | .wasm32 => { | 11917 | .byval => return o.lowerType(return_type), |
| 11782 | if (isScalar(zcu, return_type)) { | 11918 | }, |
| 11783 | return o.lowerType(return_type); | 11919 | .mips64_n64, .mips64_n32, .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) { |
| 11784 | } | 11920 | .memory, .i32_array => return .void, |
| 11785 | const classes = wasm_c_abi.classifyType(return_type, zcu); | 11921 | .byval => return o.lowerType(return_type), |
| 11786 | if (classes[0] == .indirect or classes[0] == .none) { | 11922 | }, |
| 11787 | return .void; | 11923 | .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(return_type, zcu)) { |
| 11788 | } | 11924 | .memory => return .void, |
| 11789 | 11925 | .integer => { | |
| 11790 | assert(classes[0] == .direct and classes[1] == .none); | 11926 | return o.builder.intType(@intCast(return_type.bitSize(zcu))); |
| 11791 | const scalar_type = wasm_c_abi.scalarType(return_type, zcu); | 11927 | }, |
| 11792 | return o.builder.intType(@intCast(scalar_type.abiSize(zcu) * 8)); | 11928 | .double_integer => { |
| 11793 | }, | 11929 | return o.builder.structType(.normal, &.{ .i64, .i64 }); |
| 11794 | .aarch64, .aarch64_be => { | 11930 | }, |
| 11795 | switch (aarch64_c_abi.classifyType(return_type, zcu)) { | 11931 | .byval => return o.lowerType(return_type), |
| 11796 | .memory => return .void, | 11932 | .fields => { |
| 11797 | .float_array => return o.lowerType(return_type), | 11933 | var types_len: usize = 0; |
| 11798 | .byval => return o.lowerType(return_type), | 11934 | var types: [8]Builder.Type = undefined; |
| 11799 | .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), | 11935 | for (0..return_type.structFieldCount(zcu)) |field_index| { |
| 11800 | .double_integer => return o.builder.arrayType(2, .i64), | 11936 | const field_ty = return_type.fieldType(field_index, zcu); |
| 11801 | } | 11937 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 11802 | }, | 11938 | types[types_len] = try o.lowerType(field_ty); |
| 11803 | .arm, .armeb => { | 11939 | types_len += 1; |
| 11804 | switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { | 11940 | } |
| 11805 | .memory, .i64_array => return .void, | 11941 | return o.builder.structType(.normal, types[0..types_len]); |
| 11806 | .i32_array => |len| return if (len == 1) .i32 else .void, | 11942 | }, |
| 11807 | .byval => return o.lowerType(return_type), | 11943 | }, |
| 11808 | } | 11944 | .wasm_watc => { |
| 11809 | }, | 11945 | if (isScalar(zcu, return_type)) { |
| 11810 | .riscv32, .riscv64 => { | 11946 | return o.lowerType(return_type); |
| 11811 | switch (riscv_c_abi.classifyType(return_type, zcu)) { | 11947 | } |
| 11812 | .memory => return .void, | 11948 | const classes = wasm_c_abi.classifyType(return_type, zcu); |
| 11813 | .integer => { | 11949 | if (classes[0] == .indirect or classes[0] == .none) { |
| 11814 | return o.builder.intType(@intCast(return_type.bitSize(zcu))); | 11950 | 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 | } | 11951 | } |
| 11952 | |||
| 11953 | assert(classes[0] == .direct and classes[1] == .none); | ||
| 11954 | const scalar_type = wasm_c_abi.scalarType(return_type, zcu); | ||
| 11955 | return o.builder.intType(@intCast(scalar_type.abiSize(zcu) * 8)); | ||
| 11836 | }, | 11956 | }, |
| 11837 | .Win64 => return lowerWin64FnRetTy(o, fn_info), | 11957 | // 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), | 11958 | else => return o.lowerType(return_type), |
| 11841 | } | 11959 | } |
| 11842 | } | 11960 | } |
| ... | @@ -11989,7 +12107,8 @@ const ParamTypeIterator = struct { | ... | @@ -11989,7 +12107,8 @@ const ParamTypeIterator = struct { |
| 11989 | return .no_bits; | 12107 | return .no_bits; |
| 11990 | } | 12108 | } |
| 11991 | switch (it.fn_info.cc) { | 12109 | switch (it.fn_info.cc) { |
| 11992 | .Unspecified, .Inline => { | 12110 | .@"inline" => unreachable, |
| 12111 | .auto => { | ||
| 11993 | it.zig_index += 1; | 12112 | it.zig_index += 1; |
| 11994 | it.llvm_index += 1; | 12113 | it.llvm_index += 1; |
| 11995 | if (ty.isSlice(zcu) or | 12114 | if (ty.isSlice(zcu) or |
| ... | @@ -12010,97 +12129,12 @@ const ParamTypeIterator = struct { | ... | @@ -12010,97 +12129,12 @@ const ParamTypeIterator = struct { |
| 12010 | return .byval; | 12129 | return .byval; |
| 12011 | } | 12130 | } |
| 12012 | }, | 12131 | }, |
| 12013 | .Async => { | 12132 | .@"async" => { |
| 12014 | @panic("TODO implement async function lowering in the LLVM backend"); | 12133 | @panic("TODO implement async function lowering in the LLVM backend"); |
| 12015 | }, | 12134 | }, |
| 12016 | .C => switch (target.cpu.arch) { | 12135 | .x86_64_sysv => return it.nextSystemV(ty), |
| 12017 | .mips, .mipsel => { | 12136 | .x86_64_win => return it.nextWin64(ty), |
| 12018 | it.zig_index += 1; | 12137 | .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; | 12138 | it.zig_index += 1; |
| 12105 | it.llvm_index += 1; | 12139 | it.llvm_index += 1; |
| 12106 | 12140 | ||
| ... | @@ -12111,6 +12145,80 @@ const ParamTypeIterator = struct { | ... | @@ -12111,6 +12145,80 @@ const ParamTypeIterator = struct { |
| 12111 | return .byref; | 12145 | return .byref; |
| 12112 | } | 12146 | } |
| 12113 | }, | 12147 | }, |
| 12148 | .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => { | ||
| 12149 | it.zig_index += 1; | ||
| 12150 | it.llvm_index += 1; | ||
| 12151 | switch (aarch64_c_abi.classifyType(ty, zcu)) { | ||
| 12152 | .memory => return .byref_mut, | ||
| 12153 | .float_array => |len| return Lowering{ .float_array = len }, | ||
| 12154 | .byval => return .byval, | ||
| 12155 | .integer => { | ||
| 12156 | it.types_len = 1; | ||
| 12157 | it.types_buffer[0] = .i64; | ||
| 12158 | return .multiple_llvm_types; | ||
| 12159 | }, | ||
| 12160 | .double_integer => return Lowering{ .i64_array = 2 }, | ||
| 12161 | } | ||
| 12162 | }, | ||
| 12163 | .arm_aapcs => { | ||
| 12164 | it.zig_index += 1; | ||
| 12165 | it.llvm_index += 1; | ||
| 12166 | switch (arm_c_abi.classifyType(ty, zcu, .arg)) { | ||
| 12167 | .memory => { | ||
| 12168 | it.byval_attr = true; | ||
| 12169 | return .byref; | ||
| 12170 | }, | ||
| 12171 | .byval => return .byval, | ||
| 12172 | .i32_array => |size| return Lowering{ .i32_array = size }, | ||
| 12173 | .i64_array => |size| return Lowering{ .i64_array = size }, | ||
| 12174 | } | ||
| 12175 | }, | ||
| 12176 | .mips64_n64, .mips64_n32, .mips_o32 => { | ||
| 12177 | it.zig_index += 1; | ||
| 12178 | it.llvm_index += 1; | ||
| 12179 | switch (mips_c_abi.classifyType(ty, zcu, .arg)) { | ||
| 12180 | .memory => { | ||
| 12181 | it.byval_attr = true; | ||
| 12182 | return .byref; | ||
| 12183 | }, | ||
| 12184 | .byval => return .byval, | ||
| 12185 | .i32_array => |size| return Lowering{ .i32_array = size }, | ||
| 12186 | } | ||
| 12187 | }, | ||
| 12188 | .riscv64_lp64, .riscv32_ilp32 => { | ||
| 12189 | it.zig_index += 1; | ||
| 12190 | it.llvm_index += 1; | ||
| 12191 | switch (riscv_c_abi.classifyType(ty, zcu)) { | ||
| 12192 | .memory => return .byref_mut, | ||
| 12193 | .byval => return .byval, | ||
| 12194 | .integer => return .abi_sized_int, | ||
| 12195 | .double_integer => return Lowering{ .i64_array = 2 }, | ||
| 12196 | .fields => { | ||
| 12197 | it.types_len = 0; | ||
| 12198 | for (0..ty.structFieldCount(zcu)) |field_index| { | ||
| 12199 | const field_ty = ty.fieldType(field_index, zcu); | ||
| 12200 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 12201 | it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); | ||
| 12202 | it.types_len += 1; | ||
| 12203 | } | ||
| 12204 | it.llvm_index += it.types_len - 1; | ||
| 12205 | return .multiple_llvm_types; | ||
| 12206 | }, | ||
| 12207 | } | ||
| 12208 | }, | ||
| 12209 | .wasm_watc => { | ||
| 12210 | it.zig_index += 1; | ||
| 12211 | it.llvm_index += 1; | ||
| 12212 | if (isScalar(zcu, ty)) { | ||
| 12213 | return .byval; | ||
| 12214 | } | ||
| 12215 | const classes = wasm_c_abi.classifyType(ty, zcu); | ||
| 12216 | if (classes[0] == .indirect) { | ||
| 12217 | return .byref; | ||
| 12218 | } | ||
| 12219 | return .abi_sized_int; | ||
| 12220 | }, | ||
| 12221 | // TODO investigate other callconvs | ||
| 12114 | else => { | 12222 | else => { |
| 12115 | it.zig_index += 1; | 12223 | it.zig_index += 1; |
| 12116 | it.llvm_index += 1; | 12224 | it.llvm_index += 1; |
| ... | @@ -12263,13 +12371,13 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp | ... | @@ -12263,13 +12371,13 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp |
| 12263 | } | 12371 | } |
| 12264 | 12372 | ||
| 12265 | fn ccAbiPromoteInt( | 12373 | fn ccAbiPromoteInt( |
| 12266 | cc: std.builtin.CallingConvention, | 12374 | cc: std.builtin.NewCallingConvention, |
| 12267 | zcu: *Zcu, | 12375 | zcu: *Zcu, |
| 12268 | ty: Type, | 12376 | ty: Type, |
| 12269 | ) ?std.builtin.Signedness { | 12377 | ) ?std.builtin.Signedness { |
| 12270 | const target = zcu.getTarget(); | 12378 | const target = zcu.getTarget(); |
| 12271 | switch (cc) { | 12379 | switch (cc) { |
| 12272 | .Unspecified, .Inline, .Async => return null, | 12380 | .auto, .@"inline", .@"async" => return null, |
| 12273 | else => {}, | 12381 | else => {}, |
| 12274 | } | 12382 | } |
| 12275 | const int_info = switch (ty.zigTypeTag(zcu)) { | 12383 | 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, | ||
| 2055 | 2056 | ||
| 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, | ||
| 2063 | 2065 | ||
| 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) { |
| 2068 | 2070 | ||
| 2069 | amdgpu_gfx = 100, | 2071 | amdgpu_gfx = 100, |
| 2070 | 2072 | ||
| 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, |
| 2073 | 2077 | ||
| 2078 | m68k_rtdcc = 106, | ||
| 2079 | |||
| 2080 | riscv_vectorcallcc = 110, | ||
| 2081 | |||
| 2074 | _, | 2082 | _, |
| 2075 | 2083 | ||
| 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 { |
| 1640 | 1640 | ||
| 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, // TODO | 1644 | else => @panic("TODO"), |
| 1645 | } | 1645 | } |
| 1646 | 1646 | ||
| 1647 | // TODO: Put this somewhere in Sema.zig | 1647 | // 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+7-5| ... | @@ -1484,14 +1484,16 @@ pub fn updateExports( | ... | @@ -1484,14 +1484,16 @@ pub fn updateExports( |
| 1484 | const exported_nav = ip.getNav(exported_nav_index); | 1484 | const exported_nav = ip.getNav(exported_nav_index); |
| 1485 | const exported_ty = exported_nav.typeOf(ip); | 1485 | const exported_ty = exported_nav.typeOf(ip); |
| 1486 | if (!ip.isFunctionType(exported_ty)) continue; | 1486 | if (!ip.isFunctionType(exported_ty)) continue; |
| 1487 | const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) { | 1487 | const c_cc = target.defaultCCallingConvention().?; |
| 1488 | .x86 => .Stdcall, | 1488 | const winapi_cc: std.builtin.NewCallingConvention = switch (target.cpu.arch) { |
| 1489 | else => .C, | 1489 | .x86 => .{ .x86_stdcall = .{} }, |
| 1490 | else => c_cc, | ||
| 1490 | }; | 1491 | }; |
| 1491 | const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu); | 1492 | const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu); |
| 1492 | if (exported_cc == .C and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) { | 1493 | const CcTag = std.builtin.NewCallingConvention.Tag; |
| 1494 | if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) { | ||
| 1493 | zcu.stage1_flags.have_c_main = true; | 1495 | zcu.stage1_flags.have_c_main = true; |
| 1494 | } else if (exported_cc == winapi_cc and target.os.tag == .windows) { | 1496 | } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) { |
| 1495 | if (exp.opts.name.eqlSlice("WinMain", ip)) { | 1497 | if (exp.opts.name.eqlSlice("WinMain", ip)) { |
| 1496 | zcu.stage1_flags.have_winmain = true; | 1498 | zcu.stage1_flags.have_winmain = true; |
| 1497 | } else if (exp.opts.name.eqlSlice("wWinMain", ip)) { | 1499 | } else if (exp.opts.name.eqlSlice("wWinMain", ip)) { |
src/link/Dwarf.zig+62-15| ... | @@ -3398,21 +3398,68 @@ fn updateType( | ... | @@ -3398,21 +3398,68 @@ 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().defaultCCallingConvention()) |cc| { |
| 3403 | .Naked, .Async, .Inline => .nocall, | 3403 | if (@as(std.builtin.NewCallingConvention.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 | break :cc switch (func_type.cc) { |
| 3408 | .Thiscall => .BORLAND_thiscall, | 3408 | .@"inline" => unreachable, |
| 3409 | .APCS => .nocall, | 3409 | .@"async", .auto, .naked => .normal, |
| 3410 | .AAPCS => .LLVM_AAPCS, | 3410 | .x86_64_sysv => .LLVM_X86_64SysV, |
| 3411 | .AAPCSVFP => .LLVM_AAPCS_VFP, | 3411 | .x86_64_win => .LLVM_Win64, |
| 3412 | .SysV => .LLVM_X86_64SysV, | 3412 | .x86_64_regcall_v3_sysv => .LLVM_X86RegCall, |
| 3413 | .Win64 => .LLVM_Win64, | 3413 | .x86_64_regcall_v4_win => .LLVM_X86RegCall, |
| 3414 | .Kernel, .Fragment, .Vertex => .nocall, | 3414 | .x86_64_vectorcall => .LLVM_vectorcall, |
| 3415 | }))); | 3415 | .x86_sysv => .nocall, |
| 3416 | .x86_win => .nocall, | ||
| 3417 | .x86_stdcall => .BORLAND_stdcall, | ||
| 3418 | .x86_fastcall => .BORLAND_msfastcall, | ||
| 3419 | .x86_thiscall => .BORLAND_thiscall, | ||
| 3420 | .x86_thiscall_mingw => .BORLAND_thiscall, | ||
| 3421 | .x86_regcall_v3 => .LLVM_X86RegCall, | ||
| 3422 | .x86_regcall_v4_win => .LLVM_X86RegCall, | ||
| 3423 | .x86_vectorcall => .LLVM_vectorcall, | ||
| 3424 | |||
| 3425 | .aarch64_aapcs => .LLVM_AAPCS, | ||
| 3426 | .aarch64_aapcs_darwin => .LLVM_AAPCS, | ||
| 3427 | .aarch64_aapcs_win => .LLVM_AAPCS, | ||
| 3428 | .aarch64_vfabi => .LLVM_AAPCS, | ||
| 3429 | .aarch64_vfabi_sve => .LLVM_AAPCS, | ||
| 3430 | |||
| 3431 | .arm_apcs => .nocall, | ||
| 3432 | .arm_aapcs => .LLVM_AAPCS, | ||
| 3433 | .arm_aapcs_vfp => .LLVM_AAPCS_VFP, | ||
| 3434 | .arm_aapcs16_vfp => .nocall, | ||
| 3435 | |||
| 3436 | .riscv64_lp64_v, | ||
| 3437 | .riscv32_ilp32_v, | ||
| 3438 | => .LLVM_RISCVVectorCall, | ||
| 3439 | |||
| 3440 | .m68k_rtd => .LLVM_M68kRTD, | ||
| 3441 | |||
| 3442 | .amdgcn_kernel, | ||
| 3443 | .nvptx_kernel, | ||
| 3444 | .spirv_kernel, | ||
| 3445 | => .LLVM_OpenCLKernel, | ||
| 3446 | |||
| 3447 | .x86_64_interrupt, | ||
| 3448 | .x86_interrupt, | ||
| 3449 | .arm_interrupt, | ||
| 3450 | .mips64_interrupt, | ||
| 3451 | .mips_interrupt, | ||
| 3452 | .riscv64_interrupt, | ||
| 3453 | .riscv32_interrupt, | ||
| 3454 | .avr_interrupt, | ||
| 3455 | .csky_interrupt, | ||
| 3456 | .m68k_interrupt, | ||
| 3457 | => .normal, | ||
| 3458 | |||
| 3459 | else => .nocall, | ||
| 3460 | }; | ||
| 3461 | }; | ||
| 3462 | try diw.writeByte(@intFromEnum(cc)); | ||
| 3416 | try wip_nav.refType(Type.fromInterned(func_type.return_type)); | 3463 | try wip_nav.refType(Type.fromInterned(func_type.return_type)); |
| 3417 | for (0..func_type.param_types.len) |param_index| { | 3464 | for (0..func_type.param_types.len) |param_index| { |
| 3418 | try wip_nav.abbrevCode(.func_type_param); | 3465 | 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/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 | } |
| 546 | 546 | ||
| 547 | pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConvention) bool { | 547 | pub fn fnCallConvAllowsZigTypes(cc: std.builtin.NewCallingConvention) 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 if | 550 | // 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 more | 551 | // 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+14-14| ... | @@ -4,7 +4,6 @@ const assert = std.debug.assert; | ... | @@ -4,7 +4,6 @@ const assert = std.debug.assert; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const math = std.math; | 5 | const math = std.math; |
| 6 | const meta = std.meta; | 6 | const meta = std.meta; |
| 7 | const CallingConvention = std.builtin.CallingConvention; | ||
| 8 | const clang = @import("clang.zig"); | 7 | const clang = @import("clang.zig"); |
| 9 | const aro = @import("aro"); | 8 | const aro = @import("aro"); |
| 10 | const CToken = aro.Tokenizer.Token; | 9 | const CToken = aro.Tokenizer.Token; |
| ... | @@ -5001,17 +5000,18 @@ fn transCC( | ... | @@ -5001,17 +5000,18 @@ 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 | .X86StdCall => .x86_stdcall, |
| 5010 | .X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall, | 5009 | .X86FastCall => .x86_fastcall, |
| 5011 | .X86ThisCall => return CallingConvention.Thiscall, | 5010 | .X86ThisCall => .x86_thiscall, |
| 5012 | .AAPCS => return CallingConvention.AAPCS, | 5011 | .X86VectorCall => .x86_vectorcall, |
| 5013 | .AAPCS_VFP => return CallingConvention.AAPCSVFP, | 5012 | .AArch64VectorCall => .aarch64_vfabi, |
| 5014 | .X86_64SysV => return CallingConvention.SysV, | 5013 | .AAPCS => .arm_aapcs, |
| 5014 | .AAPCS_VFP => .arm_aapcs_vfp, | ||
| 5015 | else => return fail( | 5015 | else => return fail( |
| 5016 | c, | 5016 | c, |
| 5017 | error.UnsupportedType, | 5017 | error.UnsupportedType, |
| ... | @@ -5019,7 +5019,7 @@ fn transCC( | ... | @@ -5019,7 +5019,7 @@ fn transCC( |
| 5019 | "unsupported calling convention: {s}", | 5019 | "unsupported calling convention: {s}", |
| 5020 | .{@tagName(clang_cc)}, | 5020 | .{@tagName(clang_cc)}, |
| 5021 | ), | 5021 | ), |
| 5022 | } | 5022 | }; |
| 5023 | } | 5023 | } |
| 5024 | 5024 | ||
| 5025 | fn transFnProto( | 5025 | fn transFnProto( |
| ... | @@ -5056,7 +5056,7 @@ fn finishTransFnProto( | ... | @@ -5056,7 +5056,7 @@ fn finishTransFnProto( |
| 5056 | source_loc: clang.SourceLocation, | 5056 | source_loc: clang.SourceLocation, |
| 5057 | fn_decl_context: ?FnDeclContext, | 5057 | fn_decl_context: ?FnDeclContext, |
| 5058 | is_var_args: bool, | 5058 | is_var_args: bool, |
| 5059 | cc: CallingConvention, | 5059 | cc: ast.Payload.Func.CallingConvention, |
| 5060 | is_pub: bool, | 5060 | is_pub: bool, |
| 5061 | ) !*ast.Payload.Func { | 5061 | ) !*ast.Payload.Func { |
| 5062 | const is_export = if (fn_decl_context) |ctx| ctx.is_export else false; | 5062 | const is_export = if (fn_decl_context) |ctx| ctx.is_export else false; |
| ... | @@ -5104,7 +5104,7 @@ fn finishTransFnProto( | ... | @@ -5104,7 +5104,7 @@ fn finishTransFnProto( |
| 5104 | 5104 | ||
| 5105 | const alignment = if (fn_decl) |decl| ClangAlignment.forFunc(c, decl).zigAlignment() else null; | 5105 | const alignment = if (fn_decl) |decl| ClangAlignment.forFunc(c, decl).zigAlignment() else null; |
| 5106 | 5106 | ||
| 5107 | const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .C) null else cc; | 5107 | const explicit_callconv = if ((is_inline or is_export or is_extern) and cc == .c) null else cc; |
| 5108 | 5108 | ||
| 5109 | const return_type_node = blk: { | 5109 | const return_type_node = blk: { |
| 5110 | if (fn_ty.getNoReturnAttr()) { | 5110 | if (fn_ty.getNoReturnAttr()) { |