authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-05-20 14:08:57+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-05-20 14:54:44+02:00
log3fd8ac092e88ac4bc604afcdd3fcb33249dba967
tree7e0cb16071c65746f7fcf86bdaa0f3c67eded508
parent569525f03e17ba32204733108a950a5170662299
signaturelock-open Commit is signed but in an unrecognized format.

stage2: support inline keyword on function decls

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 {
18331833 var result: full.FnProto = .{
18341834 .ast = info,
18351835 .visib_token = null,
1836 .extern_export_token = null,
1836 .extern_export_inline_token = null,
18371837 .lib_name = null,
18381838 .name_token = null,
18391839 .lparen = undefined,
......@@ -1842,7 +1842,11 @@ pub const Tree = struct {
18421842 while (i > 0) {
18431843 i -= 1;
18441844 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,
18461850 .keyword_pub => result.visib_token = i,
18471851 .string_literal => result.lib_name = i,
18481852 else => break,
......@@ -2123,7 +2127,7 @@ pub const full = struct {
21232127
21242128 pub const FnProto = struct {
21252129 visib_token: ?TokenIndex,
2126 extern_export_token: ?TokenIndex,
2130 extern_export_inline_token: ?TokenIndex,
21272131 lib_name: ?TokenIndex,
21282132 name_token: ?TokenIndex,
21292133 lparen: TokenIndex,
src/AstGen.zig+32-14
......@@ -995,7 +995,7 @@ fn fnProtoExpr(
995995 const token_tags = tree.tokens.items(.tag);
996996
997997 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;
999999 break :blk token_tags[maybe_extern_token] == .keyword_extern;
10001000 };
10011001 assert(!is_extern);
......@@ -2735,15 +2735,20 @@ fn fnDecl(
27352735 };
27362736 defer decl_gz.instructions.deinit(gpa);
27372737
2738 // TODO: support noinline
27382739 const is_pub = fn_proto.visib_token != null;
27392740 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;
27412742 break :blk token_tags[maybe_export_token] == .keyword_export;
27422743 };
27432744 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;
27452746 break :blk token_tags[maybe_extern_token] == .keyword_extern;
27462747 };
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 };
27472752 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
27482753 break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr);
27492754 };
......@@ -2812,17 +2817,30 @@ fn fnDecl(
28122817 fn_proto.ast.return_type,
28132818 );
28142819
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 };
28262844
28272845 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
28282846 if (!is_extern) {
src/Zir.zig+13
......@@ -1687,6 +1687,8 @@ pub const Inst = struct {
16871687 one_usize,
16881688 /// `std.builtin.CallingConvention.C`
16891689 calling_convention_c,
1690 /// `std.builtin.CallingConvention.Inline`
1691 calling_convention_inline,
16901692
16911693 _,
16921694
......@@ -1954,6 +1956,10 @@ pub const Inst = struct {
19541956 .ty = Type.initTag(.calling_convention),
19551957 .val = .{ .ptr_otherwise = &calling_convention_c_payload.base },
19561958 },
1959 .calling_convention_inline = .{
1960 .ty = Type.initTag(.calling_convention),
1961 .val = .{ .ptr_otherwise = &calling_convention_inline_payload.base },
1962 },
19571963 });
19581964 };
19591965
......@@ -1964,6 +1970,13 @@ pub const Inst = struct {
19641970 .data = @enumToInt(std.builtin.CallingConvention.C),
19651971 };
19661972
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
19671980 /// All instructions have an 8-byte payload, which is contained within
19681981 /// this union. `Tag` determines which union field is active, as well as
19691982 /// how to interpret the data within.