| author | |
| committer | |
| log | 3fd8ac092e88ac4bc604afcdd3fcb33249dba967 |
| tree | 7e0cb16071c65746f7fcf86bdaa0f3c67eded508 |
| parent | 569525f03e17ba32204733108a950a5170662299 |
| signature |
This is an alternative to callconv(.Inline). Using an inline keyword
as well as an explicit callconv() is a compile error.3 files changed, 52 insertions(+), 17 deletions(-)
lib/std/zig/ast.zig+7-3| ... | ... | @@ -1833,7 +1833,7 @@ pub const Tree = struct { |
| 1833 | 1833 | var result: full.FnProto = .{ |
| 1834 | 1834 | .ast = info, |
| 1835 | 1835 | .visib_token = null, |
| 1836 | .extern_export_token = null, | |
| 1836 | .extern_export_inline_token = null, | |
| 1837 | 1837 | .lib_name = null, |
| 1838 | 1838 | .name_token = null, |
| 1839 | 1839 | .lparen = undefined, |
| ... | ... | @@ -1842,7 +1842,11 @@ pub const Tree = struct { |
| 1842 | 1842 | while (i > 0) { |
| 1843 | 1843 | i -= 1; |
| 1844 | 1844 | switch (token_tags[i]) { |
| 1845 | .keyword_extern, .keyword_export => result.extern_export_token = i, | |
| 1845 | .keyword_extern, | |
| 1846 | .keyword_export, | |
| 1847 | .keyword_inline, | |
| 1848 | .keyword_noinline, | |
| 1849 | => result.extern_export_inline_token = i, | |
| 1846 | 1850 | .keyword_pub => result.visib_token = i, |
| 1847 | 1851 | .string_literal => result.lib_name = i, |
| 1848 | 1852 | else => break, |
| ... | ... | @@ -2123,7 +2127,7 @@ pub const full = struct { |
| 2123 | 2127 | |
| 2124 | 2128 | pub const FnProto = struct { |
| 2125 | 2129 | visib_token: ?TokenIndex, |
| 2126 | extern_export_token: ?TokenIndex, | |
| 2130 | extern_export_inline_token: ?TokenIndex, | |
| 2127 | 2131 | lib_name: ?TokenIndex, |
| 2128 | 2132 | name_token: ?TokenIndex, |
| 2129 | 2133 | lparen: TokenIndex, |
src/AstGen.zig+32-14| ... | ... | @@ -995,7 +995,7 @@ fn fnProtoExpr( |
| 995 | 995 | const token_tags = tree.tokens.items(.tag); |
| 996 | 996 | |
| 997 | 997 | const is_extern = blk: { |
| 998 | const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false; | |
| 998 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; | |
| 999 | 999 | break :blk token_tags[maybe_extern_token] == .keyword_extern; |
| 1000 | 1000 | }; |
| 1001 | 1001 | assert(!is_extern); |
| ... | ... | @@ -2735,15 +2735,20 @@ fn fnDecl( |
| 2735 | 2735 | }; |
| 2736 | 2736 | defer decl_gz.instructions.deinit(gpa); |
| 2737 | 2737 | |
| 2738 | // TODO: support noinline | |
| 2738 | 2739 | const is_pub = fn_proto.visib_token != null; |
| 2739 | 2740 | const is_export = blk: { |
| 2740 | const maybe_export_token = fn_proto.extern_export_token orelse break :blk false; | |
| 2741 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; | |
| 2741 | 2742 | break :blk token_tags[maybe_export_token] == .keyword_export; |
| 2742 | 2743 | }; |
| 2743 | 2744 | const is_extern = blk: { |
| 2744 | const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false; | |
| 2745 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; | |
| 2745 | 2746 | break :blk token_tags[maybe_extern_token] == .keyword_extern; |
| 2746 | 2747 | }; |
| 2748 | const has_inline_keyword = blk: { | |
| 2749 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; | |
| 2750 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | |
| 2751 | }; | |
| 2747 | 2752 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 2748 | 2753 | break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr); |
| 2749 | 2754 | }; |
| ... | ... | @@ -2812,17 +2817,30 @@ fn fnDecl( |
| 2812 | 2817 | fn_proto.ast.return_type, |
| 2813 | 2818 | ); |
| 2814 | 2819 | |
| 2815 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) | |
| 2816 | try AstGen.expr( | |
| 2817 | &decl_gz, | |
| 2818 | &decl_gz.base, | |
| 2819 | .{ .ty = .calling_convention_type }, | |
| 2820 | fn_proto.ast.callconv_expr, | |
| 2821 | ) | |
| 2822 | else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269 | |
| 2823 | Zir.Inst.Ref.calling_convention_c | |
| 2824 | else | |
| 2825 | Zir.Inst.Ref.none; | |
| 2820 | const cc: Zir.Inst.Ref = blk: { | |
| 2821 | if (fn_proto.ast.callconv_expr != 0) { | |
| 2822 | if (has_inline_keyword) { | |
| 2823 | return astgen.failNode( | |
| 2824 | fn_proto.ast.callconv_expr, | |
| 2825 | "explicit callconv incompatible with inline keyword", | |
| 2826 | .{}, | |
| 2827 | ); | |
| 2828 | } | |
| 2829 | break :blk try AstGen.expr( | |
| 2830 | &decl_gz, | |
| 2831 | &decl_gz.base, | |
| 2832 | .{ .ty = .calling_convention_type }, | |
| 2833 | fn_proto.ast.callconv_expr, | |
| 2834 | ); | |
| 2835 | } else if (is_extern) { | |
| 2836 | // note: https://github.com/ziglang/zig/issues/5269 | |
| 2837 | break :blk .calling_convention_c; | |
| 2838 | } else if (has_inline_keyword) { | |
| 2839 | break :blk .calling_convention_inline; | |
| 2840 | } else { | |
| 2841 | break :blk .none; | |
| 2842 | } | |
| 2843 | }; | |
| 2826 | 2844 | |
| 2827 | 2845 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { |
| 2828 | 2846 | if (!is_extern) { |
src/Zir.zig+13| ... | ... | @@ -1687,6 +1687,8 @@ pub const Inst = struct { |
| 1687 | 1687 | one_usize, |
| 1688 | 1688 | /// `std.builtin.CallingConvention.C` |
| 1689 | 1689 | calling_convention_c, |
| 1690 | /// `std.builtin.CallingConvention.Inline` | |
| 1691 | calling_convention_inline, | |
| 1690 | 1692 | |
| 1691 | 1693 | _, |
| 1692 | 1694 | |
| ... | ... | @@ -1954,6 +1956,10 @@ pub const Inst = struct { |
| 1954 | 1956 | .ty = Type.initTag(.calling_convention), |
| 1955 | 1957 | .val = .{ .ptr_otherwise = &calling_convention_c_payload.base }, |
| 1956 | 1958 | }, |
| 1959 | .calling_convention_inline = .{ | |
| 1960 | .ty = Type.initTag(.calling_convention), | |
| 1961 | .val = .{ .ptr_otherwise = &calling_convention_inline_payload.base }, | |
| 1962 | }, | |
| 1957 | 1963 | }); |
| 1958 | 1964 | }; |
| 1959 | 1965 | |
| ... | ... | @@ -1964,6 +1970,13 @@ pub const Inst = struct { |
| 1964 | 1970 | .data = @enumToInt(std.builtin.CallingConvention.C), |
| 1965 | 1971 | }; |
| 1966 | 1972 | |
| 1973 | /// We would like this to be const but `Value` wants a mutable pointer for | |
| 1974 | /// its payload field. Nothing should mutate this though. | |
| 1975 | var calling_convention_inline_payload: Value.Payload.U32 = .{ | |
| 1976 | .base = .{ .tag = .enum_field_index }, | |
| 1977 | .data = @enumToInt(std.builtin.CallingConvention.Inline), | |
| 1978 | }; | |
| 1979 | ||
| 1967 | 1980 | /// All instructions have an 8-byte payload, which is contained within |
| 1968 | 1981 | /// this union. `Tag` determines which union field is active, as well as |
| 1969 | 1982 | /// how to interpret the data within. |