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
786786 .Keyword_for,
787787 .Keyword_if,
788788 .Keyword_inline,
789 .Keyword_noinline,
789790 .Keyword_nakedcc,
790791 .Keyword_noalias,
791792 .Keyword_or,
src/all_types.hpp+7-7
......@@ -603,6 +603,12 @@ enum CallingConvention {
603603 CallingConventionAsync,
604604};
605605
606enum FnInline {
607 FnInlineAuto,
608 FnInlineAlways,
609 FnInlineNever,
610};
611
606612struct AstNodeFnProto {
607613 VisibMod visib_mod;
608614 Buf *name;
......@@ -612,7 +618,7 @@ struct AstNodeFnProto {
612618 bool is_var_args;
613619 bool is_extern;
614620 bool is_export;
615 bool is_inline;
621 FnInline fn_inline;
616622 CallingConvention cc;
617623 AstNode *fn_def_node;
618624 // populated if this is an extern declaration
......@@ -1453,12 +1459,6 @@ enum FnAnalState {
14531459 FnAnalStateInvalid,
14541460};
14551461
1456enum FnInline {
1457 FnInlineAuto,
1458 FnInlineAlways,
1459 FnInlineNever,
1460};
1461
14621462struct GlobalExport {
14631463 Buf name;
14641464 GlobalLinkageId linkage;
src/analyze.cpp+1-2
......@@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
30663066 assert(proto_node->type == NodeTypeFnProto);
30673067 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
30683068
3069 FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto;
3070 ZigFn *fn_entry = create_fn_raw(g, inline_value);
3069 ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline);
30713070
30723071 fn_entry->proto_node = proto_node;
30733072 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) {
124124// zig_unreachable();
125125//}
126126
127static const char *inline_string(bool is_inline) {
128 return is_inline ? "inline " : "";
127static const char *inline_string(FnInline fn_inline) {
128 switch (fn_inline) {
129 case FnInlineAlways: return "inline ";
130 case FnInlineNever: return "noinline ";
131 case FnInlineAuto: return "";
132 }
133 zig_unreachable();
129134}
130135
131136static const char *const_or_var_string(bool is_const) {
......@@ -436,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
436441 const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
437442 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
438443 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);
440445 fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
441446 if (node->data.fn_proto.name != nullptr) {
442447 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) {
578578}
579579
580580// 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)
582582// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
583583// / KEYWORD_use Expr SEMICOLON
584584static 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) {
587587 first = eat_token_if(pc, TokenIdKeywordExtern);
588588 if (first == nullptr)
589589 first = eat_token_if(pc, TokenIdKeywordInline);
590 if (first == nullptr)
591 first = eat_token_if(pc, TokenIdKeywordNoInline);
590592 if (first != nullptr) {
591593 Token *lib_name = nullptr;
592594 if (first->id == TokenIdKeywordExtern)
593595 lib_name = eat_token_if(pc, TokenIdStringLiteral);
594596
595 if (first->id != TokenIdKeywordInline) {
597 if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) {
596598 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
597599 AstNode *var_decl = ast_parse_var_decl(pc);
598600 if (var_decl != nullptr) {
......@@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
623625 fn_proto->data.fn_proto.visib_mod = visib_mod;
624626 fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
625627 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 }
627639 fn_proto->data.fn_proto.lib_name = token_buf(lib_name);
640
628641 AstNode *res = fn_proto;
629642 if (body != nullptr) {
630643 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[] = {
130130 {"for", TokenIdKeywordFor},
131131 {"if", TokenIdKeywordIf},
132132 {"inline", TokenIdKeywordInline},
133 {"noinline", TokenIdKeywordNoInline},
133134 {"nakedcc", TokenIdKeywordNakedCC},
134135 {"noalias", TokenIdKeywordNoAlias},
135136 {"null", TokenIdKeywordNull},
......@@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) {
15511552 case TokenIdKeywordFor: return "for";
15521553 case TokenIdKeywordIf: return "if";
15531554 case TokenIdKeywordInline: return "inline";
1555 case TokenIdKeywordNoInline: return "noinline";
15541556 case TokenIdKeywordNakedCC: return "nakedcc";
15551557 case TokenIdKeywordNoAlias: return "noalias";
15561558 case TokenIdKeywordNull: return "null";
src/tokenizer.hpp+1
......@@ -74,6 +74,7 @@ enum TokenId {
7474 TokenIdKeywordFor,
7575 TokenIdKeywordIf,
7676 TokenIdKeywordInline,
77 TokenIdKeywordNoInline,
7778 TokenIdKeywordLinkSection,
7879 TokenIdKeywordNakedCC,
7980 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
432432 AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
433433 fn_proto->data.fn_proto.visib_mod = c->visib_mod;
434434 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;
436436 fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
437437
438438 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) !?*
201201}
202202
203203/// 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)
205205/// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
206206/// / KEYWORD_usingnamespace Expr SEMICOLON
207207fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
......@@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
213213 break :blk token;
214214 }
215215 if (eatToken(it, .Keyword_inline)) |token| break :blk token;
216 if (eatToken(it, .Keyword_noinline)) |token| break :blk token;
216217 break :blk null;
217218 };
218219
......@@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
232233 }
233234
234235 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) {
236238 putBackToken(it, token);
237239 return null;
238240 }
std/zig/parser_test.zig+3
......@@ -1677,14 +1677,17 @@ test "zig fmt: functions" {
16771677 \\extern "c" fn puts(s: *const u8) c_int;
16781678 \\export fn puts(s: *const u8) c_int;
16791679 \\inline fn puts(s: *const u8) c_int;
1680 \\noinline fn puts(s: *const u8) c_int;
16801681 \\pub extern fn puts(s: *const u8) c_int;
16811682 \\pub extern "c" fn puts(s: *const u8) c_int;
16821683 \\pub export fn puts(s: *const u8) c_int;
16831684 \\pub inline fn puts(s: *const u8) c_int;
1685 \\pub noinline fn puts(s: *const u8) c_int;
16841686 \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
16851687 \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
16861688 \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
16871689 \\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;
16881691 \\
16891692 );
16901693}
std/zig/tokenizer.zig+2
......@@ -36,6 +36,7 @@ pub const Token = struct {
3636 Keyword{ .bytes = "for", .id = Id.Keyword_for },
3737 Keyword{ .bytes = "if", .id = Id.Keyword_if },
3838 Keyword{ .bytes = "inline", .id = Id.Keyword_inline },
39 Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline },
3940 Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc },
4041 Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias },
4142 Keyword{ .bytes = "null", .id = Id.Keyword_null },
......@@ -166,6 +167,7 @@ pub const Token = struct {
166167 Keyword_for,
167168 Keyword_if,
168169 Keyword_inline,
170 Keyword_noinline,
169171 Keyword_nakedcc,
170172 Keyword_noalias,
171173 Keyword_null,