authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-09-05 12:22:02+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-05 13:04:58-04:00
logfabf45f5fc0a1827913be5675130db5db514c136
treec81705ac2785869cd53a7a2dc758c0b9be38c718
parenta7fd14096c8dbc9cb5ed9a3731753b24e32d5757

Add the noinline keyword for function declarations


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};
605605
606enum FnInline {
607 FnInlineAuto,
608 FnInlineAlways,
609 FnInlineNever,
610};
611
606struct AstNodeFnProto {612struct 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 declaration624 // 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};
14551461
1456enum FnInline {
1457 FnInlineAuto,
1458 FnInlineAlways,
1459 FnInlineNever,
1460};
1461
1462struct GlobalExport {1462struct 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;
30683068
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);
30713070
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//}
126126
127static const char *inline_string(bool is_inline) {127static 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}
130135
131static const char *const_or_var_string(bool is_const) {136static 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}
579579
580// TopLevelDecl580// 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? VarDecl582// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
583// / KEYWORD_use Expr SEMICOLON583// / KEYWORD_use Expr SEMICOLON
584static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {584static 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);
594596
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?
437437
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}
202202
203/// TopLevelDecl203/// 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? VarDecl205/// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
206/// / KEYWORD_usingnamespace Expr SEMICOLON206/// / KEYWORD_usingnamespace Expr SEMICOLON
207fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {207fn 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 };
218219
...@@ -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 }
233234
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,