| author | |
| committer | |
| log | fabf45f5fc0a1827913be5675130db5db514c136 |
| tree | c81705ac2785869cd53a7a2dc758c0b9be38c718 |
| parent | a7fd14096c8dbc9cb5ed9a3731753b24e32d5757 |
11 files changed, 46 insertions(+), 18 deletions(-)
doc/docgen.zig+1| ... | @@ -786,6 +786,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -786,6 +786,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 786 | .Keyword_for, | 786 | .Keyword_for, |
| 787 | .Keyword_if, | 787 | .Keyword_if, |
| 788 | .Keyword_inline, | 788 | .Keyword_inline, |
| 789 | .Keyword_noinline, | ||
| 789 | .Keyword_nakedcc, | 790 | .Keyword_nakedcc, |
| 790 | .Keyword_noalias, | 791 | .Keyword_noalias, |
| 791 | .Keyword_or, | 792 | .Keyword_or, |
src/all_types.hpp+7-7| ... | @@ -603,6 +603,12 @@ enum CallingConvention { | ... | @@ -603,6 +603,12 @@ enum CallingConvention { |
| 603 | CallingConventionAsync, | 603 | CallingConventionAsync, |
| 604 | }; | 604 | }; |
| 605 | 605 | ||
| 606 | enum FnInline { | ||
| 607 | FnInlineAuto, | ||
| 608 | FnInlineAlways, | ||
| 609 | FnInlineNever, | ||
| 610 | }; | ||
| 611 | |||
| 606 | struct AstNodeFnProto { | 612 | struct AstNodeFnProto { |
| 607 | VisibMod visib_mod; | 613 | VisibMod visib_mod; |
| 608 | Buf *name; | 614 | Buf *name; |
| ... | @@ -612,7 +618,7 @@ struct AstNodeFnProto { | ... | @@ -612,7 +618,7 @@ struct AstNodeFnProto { |
| 612 | bool is_var_args; | 618 | bool is_var_args; |
| 613 | bool is_extern; | 619 | bool is_extern; |
| 614 | bool is_export; | 620 | bool is_export; |
| 615 | bool is_inline; | 621 | FnInline fn_inline; |
| 616 | CallingConvention cc; | 622 | CallingConvention cc; |
| 617 | AstNode *fn_def_node; | 623 | AstNode *fn_def_node; |
| 618 | // populated if this is an extern declaration | 624 | // populated if this is an extern declaration |
| ... | @@ -1453,12 +1459,6 @@ enum FnAnalState { | ... | @@ -1453,12 +1459,6 @@ enum FnAnalState { |
| 1453 | FnAnalStateInvalid, | 1459 | FnAnalStateInvalid, |
| 1454 | }; | 1460 | }; |
| 1455 | 1461 | ||
| 1456 | enum FnInline { | ||
| 1457 | FnInlineAuto, | ||
| 1458 | FnInlineAlways, | ||
| 1459 | FnInlineNever, | ||
| 1460 | }; | ||
| 1461 | |||
| 1462 | struct GlobalExport { | 1462 | struct GlobalExport { |
| 1463 | Buf name; | 1463 | Buf name; |
| 1464 | GlobalLinkageId linkage; | 1464 | GlobalLinkageId linkage; |
src/analyze.cpp+1-2| ... | @@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) { | ... | @@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) { |
| 3066 | assert(proto_node->type == NodeTypeFnProto); | 3066 | assert(proto_node->type == NodeTypeFnProto); |
| 3067 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; | 3067 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 3068 | 3068 | ||
| 3069 | FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; | 3069 | ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline); |
| 3070 | ZigFn *fn_entry = create_fn_raw(g, inline_value); | ||
| 3071 | 3070 | ||
| 3072 | fn_entry->proto_node = proto_node; | 3071 | fn_entry->proto_node = proto_node; |
| 3073 | fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : | 3072 | fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : |
src/ast_render.cpp+8-3| ... | @@ -124,8 +124,13 @@ static const char *export_string(bool is_export) { | ... | @@ -124,8 +124,13 @@ static const char *export_string(bool is_export) { |
| 124 | // zig_unreachable(); | 124 | // zig_unreachable(); |
| 125 | //} | 125 | //} |
| 126 | 126 | ||
| 127 | static const char *inline_string(bool is_inline) { | 127 | static const char *inline_string(FnInline fn_inline) { |
| 128 | return is_inline ? "inline " : ""; | 128 | switch (fn_inline) { |
| 129 | case FnInlineAlways: return "inline "; | ||
| 130 | case FnInlineNever: return "noinline "; | ||
| 131 | case FnInlineAuto: return ""; | ||
| 132 | } | ||
| 133 | zig_unreachable(); | ||
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | static const char *const_or_var_string(bool is_const) { | 136 | static const char *const_or_var_string(bool is_const) { |
| ... | @@ -436,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -436,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 436 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); | 441 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); |
| 437 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); | 442 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); |
| 438 | const char *export_str = export_string(node->data.fn_proto.is_export); | 443 | const char *export_str = export_string(node->data.fn_proto.is_export); |
| 439 | const char *inline_str = inline_string(node->data.fn_proto.is_inline); | 444 | const char *inline_str = inline_string(node->data.fn_proto.fn_inline); |
| 440 | fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); | 445 | fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); |
| 441 | if (node->data.fn_proto.name != nullptr) { | 446 | if (node->data.fn_proto.name != nullptr) { |
| 442 | print_symbol(ar, node->data.fn_proto.name); | 447 | print_symbol(ar, node->data.fn_proto.name); |
src/parser.cpp+16-3| ... | @@ -578,7 +578,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { | ... | @@ -578,7 +578,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | // TopLevelDecl | 580 | // TopLevelDecl |
| 581 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) | 581 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 582 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl | 582 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl |
| 583 | // / KEYWORD_use Expr SEMICOLON | 583 | // / KEYWORD_use Expr SEMICOLON |
| 584 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { | 584 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| ... | @@ -587,12 +587,14 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { | ... | @@ -587,12 +587,14 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 587 | first = eat_token_if(pc, TokenIdKeywordExtern); | 587 | first = eat_token_if(pc, TokenIdKeywordExtern); |
| 588 | if (first == nullptr) | 588 | if (first == nullptr) |
| 589 | first = eat_token_if(pc, TokenIdKeywordInline); | 589 | first = eat_token_if(pc, TokenIdKeywordInline); |
| 590 | if (first == nullptr) | ||
| 591 | first = eat_token_if(pc, TokenIdKeywordNoInline); | ||
| 590 | if (first != nullptr) { | 592 | if (first != nullptr) { |
| 591 | Token *lib_name = nullptr; | 593 | Token *lib_name = nullptr; |
| 592 | if (first->id == TokenIdKeywordExtern) | 594 | if (first->id == TokenIdKeywordExtern) |
| 593 | lib_name = eat_token_if(pc, TokenIdStringLiteral); | 595 | lib_name = eat_token_if(pc, TokenIdStringLiteral); |
| 594 | 596 | ||
| 595 | if (first->id != TokenIdKeywordInline) { | 597 | if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) { |
| 596 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | 598 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 597 | AstNode *var_decl = ast_parse_var_decl(pc); | 599 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 598 | if (var_decl != nullptr) { | 600 | if (var_decl != nullptr) { |
| ... | @@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { | ... | @@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 623 | fn_proto->data.fn_proto.visib_mod = visib_mod; | 625 | fn_proto->data.fn_proto.visib_mod = visib_mod; |
| 624 | fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; | 626 | fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; |
| 625 | fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; | 627 | fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; |
| 626 | fn_proto->data.fn_proto.is_inline = first->id == TokenIdKeywordInline; | 628 | switch (first->id) { |
| 629 | case TokenIdKeywordInline: | ||
| 630 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; | ||
| 631 | break; | ||
| 632 | case TokenIdKeywordNoInline: | ||
| 633 | fn_proto->data.fn_proto.fn_inline = FnInlineNever; | ||
| 634 | break; | ||
| 635 | default: | ||
| 636 | fn_proto->data.fn_proto.fn_inline = FnInlineAuto; | ||
| 637 | break; | ||
| 638 | } | ||
| 627 | fn_proto->data.fn_proto.lib_name = token_buf(lib_name); | 639 | fn_proto->data.fn_proto.lib_name = token_buf(lib_name); |
| 640 | |||
| 628 | AstNode *res = fn_proto; | 641 | AstNode *res = fn_proto; |
| 629 | if (body != nullptr) { | 642 | if (body != nullptr) { |
| 630 | res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); | 643 | res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); |
src/tokenizer.cpp+2| ... | @@ -130,6 +130,7 @@ static const struct ZigKeyword zig_keywords[] = { | ... | @@ -130,6 +130,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 130 | {"for", TokenIdKeywordFor}, | 130 | {"for", TokenIdKeywordFor}, |
| 131 | {"if", TokenIdKeywordIf}, | 131 | {"if", TokenIdKeywordIf}, |
| 132 | {"inline", TokenIdKeywordInline}, | 132 | {"inline", TokenIdKeywordInline}, |
| 133 | {"noinline", TokenIdKeywordNoInline}, | ||
| 133 | {"nakedcc", TokenIdKeywordNakedCC}, | 134 | {"nakedcc", TokenIdKeywordNakedCC}, |
| 134 | {"noalias", TokenIdKeywordNoAlias}, | 135 | {"noalias", TokenIdKeywordNoAlias}, |
| 135 | {"null", TokenIdKeywordNull}, | 136 | {"null", TokenIdKeywordNull}, |
| ... | @@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) { | ... | @@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) { |
| 1551 | case TokenIdKeywordFor: return "for"; | 1552 | case TokenIdKeywordFor: return "for"; |
| 1552 | case TokenIdKeywordIf: return "if"; | 1553 | case TokenIdKeywordIf: return "if"; |
| 1553 | case TokenIdKeywordInline: return "inline"; | 1554 | case TokenIdKeywordInline: return "inline"; |
| 1555 | case TokenIdKeywordNoInline: return "noinline"; | ||
| 1554 | case TokenIdKeywordNakedCC: return "nakedcc"; | 1556 | case TokenIdKeywordNakedCC: return "nakedcc"; |
| 1555 | case TokenIdKeywordNoAlias: return "noalias"; | 1557 | case TokenIdKeywordNoAlias: return "noalias"; |
| 1556 | case TokenIdKeywordNull: return "null"; | 1558 | case TokenIdKeywordNull: return "null"; |
src/tokenizer.hpp+1| ... | @@ -74,6 +74,7 @@ enum TokenId { | ... | @@ -74,6 +74,7 @@ enum TokenId { |
| 74 | TokenIdKeywordFor, | 74 | TokenIdKeywordFor, |
| 75 | TokenIdKeywordIf, | 75 | TokenIdKeywordIf, |
| 76 | TokenIdKeywordInline, | 76 | TokenIdKeywordInline, |
| 77 | TokenIdKeywordNoInline, | ||
| 77 | TokenIdKeywordLinkSection, | 78 | TokenIdKeywordLinkSection, |
| 78 | TokenIdKeywordNakedCC, | 79 | TokenIdKeywordNakedCC, |
| 79 | TokenIdKeywordNoAlias, | 80 | TokenIdKeywordNoAlias, |
src/translate_c.cpp+1-1| ... | @@ -432,7 +432,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r | ... | @@ -432,7 +432,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r |
| 432 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); | 432 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); |
| 433 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; | 433 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; |
| 434 | fn_proto->data.fn_proto.name = fn_name; | 434 | fn_proto->data.fn_proto.name = fn_name; |
| 435 | fn_proto->data.fn_proto.is_inline = true; | 435 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; |
| 436 | fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? | 436 | fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? |
| 437 | 437 | ||
| 438 | fn_def->data.fn_def.fn_proto = fn_proto; | 438 | fn_def->data.fn_def.fn_proto = fn_proto; |
std/zig/parse.zig+4-2| ... | @@ -201,7 +201,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* | ... | @@ -201,7 +201,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | /// TopLevelDecl | 203 | /// TopLevelDecl |
| 204 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) | 204 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 205 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl | 205 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl |
| 206 | /// / KEYWORD_usingnamespace Expr SEMICOLON | 206 | /// / KEYWORD_usingnamespace Expr SEMICOLON |
| 207 | fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 207 | fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| ... | @@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 213 | break :blk token; | 213 | break :blk token; |
| 214 | } | 214 | } |
| 215 | if (eatToken(it, .Keyword_inline)) |token| break :blk token; | 215 | if (eatToken(it, .Keyword_inline)) |token| break :blk token; |
| 216 | if (eatToken(it, .Keyword_noinline)) |token| break :blk token; | ||
| 216 | break :blk null; | 217 | break :blk null; |
| 217 | }; | 218 | }; |
| 218 | 219 | ||
| ... | @@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 232 | } | 233 | } |
| 233 | 234 | ||
| 234 | if (extern_export_inline_token) |token| { | 235 | if (extern_export_inline_token) |token| { |
| 235 | if (tree.tokens.at(token).id == .Keyword_inline) { | 236 | if (tree.tokens.at(token).id == .Keyword_inline or |
| 237 | tree.tokens.at(token).id == .Keyword_noinline) { | ||
| 236 | putBackToken(it, token); | 238 | putBackToken(it, token); |
| 237 | return null; | 239 | return null; |
| 238 | } | 240 | } |
std/zig/parser_test.zig+3| ... | @@ -1677,14 +1677,17 @@ test "zig fmt: functions" { | ... | @@ -1677,14 +1677,17 @@ test "zig fmt: functions" { |
| 1677 | \\extern "c" fn puts(s: *const u8) c_int; | 1677 | \\extern "c" fn puts(s: *const u8) c_int; |
| 1678 | \\export fn puts(s: *const u8) c_int; | 1678 | \\export fn puts(s: *const u8) c_int; |
| 1679 | \\inline fn puts(s: *const u8) c_int; | 1679 | \\inline fn puts(s: *const u8) c_int; |
| 1680 | \\noinline fn puts(s: *const u8) c_int; | ||
| 1680 | \\pub extern fn puts(s: *const u8) c_int; | 1681 | \\pub extern fn puts(s: *const u8) c_int; |
| 1681 | \\pub extern "c" fn puts(s: *const u8) c_int; | 1682 | \\pub extern "c" fn puts(s: *const u8) c_int; |
| 1682 | \\pub export fn puts(s: *const u8) c_int; | 1683 | \\pub export fn puts(s: *const u8) c_int; |
| 1683 | \\pub inline fn puts(s: *const u8) c_int; | 1684 | \\pub inline fn puts(s: *const u8) c_int; |
| 1685 | \\pub noinline fn puts(s: *const u8) c_int; | ||
| 1684 | \\pub extern fn puts(s: *const u8) align(2 + 2) c_int; | 1686 | \\pub extern fn puts(s: *const u8) align(2 + 2) c_int; |
| 1685 | \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int; | 1687 | \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int; |
| 1686 | \\pub export fn puts(s: *const u8) align(2 + 2) c_int; | 1688 | \\pub export fn puts(s: *const u8) align(2 + 2) c_int; |
| 1687 | \\pub inline fn puts(s: *const u8) align(2 + 2) c_int; | 1689 | \\pub inline fn puts(s: *const u8) align(2 + 2) c_int; |
| 1690 | \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int; | ||
| 1688 | \\ | 1691 | \\ |
| 1689 | ); | 1692 | ); |
| 1690 | } | 1693 | } |
std/zig/tokenizer.zig+2| ... | @@ -36,6 +36,7 @@ pub const Token = struct { | ... | @@ -36,6 +36,7 @@ pub const Token = struct { |
| 36 | Keyword{ .bytes = "for", .id = Id.Keyword_for }, | 36 | Keyword{ .bytes = "for", .id = Id.Keyword_for }, |
| 37 | Keyword{ .bytes = "if", .id = Id.Keyword_if }, | 37 | Keyword{ .bytes = "if", .id = Id.Keyword_if }, |
| 38 | Keyword{ .bytes = "inline", .id = Id.Keyword_inline }, | 38 | Keyword{ .bytes = "inline", .id = Id.Keyword_inline }, |
| 39 | Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline }, | ||
| 39 | Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc }, | 40 | Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc }, |
| 40 | Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias }, | 41 | Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias }, |
| 41 | Keyword{ .bytes = "null", .id = Id.Keyword_null }, | 42 | Keyword{ .bytes = "null", .id = Id.Keyword_null }, |
| ... | @@ -166,6 +167,7 @@ pub const Token = struct { | ... | @@ -166,6 +167,7 @@ pub const Token = struct { |
| 166 | Keyword_for, | 167 | Keyword_for, |
| 167 | Keyword_if, | 168 | Keyword_if, |
| 168 | Keyword_inline, | 169 | Keyword_inline, |
| 170 | Keyword_noinline, | ||
| 169 | Keyword_nakedcc, | 171 | Keyword_nakedcc, |
| 170 | Keyword_noalias, | 172 | Keyword_noalias, |
| 171 | Keyword_null, | 173 | Keyword_null, |