mirror of
https://github.com/ziglang/zig.git
synced 2024-11-30 17:12:31 +00:00
Add the noinline keyword for function declarations
This commit is contained in:
parent
a7fd14096c
commit
fabf45f5fc
@ -786,6 +786,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
|
|||||||
.Keyword_for,
|
.Keyword_for,
|
||||||
.Keyword_if,
|
.Keyword_if,
|
||||||
.Keyword_inline,
|
.Keyword_inline,
|
||||||
|
.Keyword_noinline,
|
||||||
.Keyword_nakedcc,
|
.Keyword_nakedcc,
|
||||||
.Keyword_noalias,
|
.Keyword_noalias,
|
||||||
.Keyword_or,
|
.Keyword_or,
|
||||||
|
@ -603,6 +603,12 @@ enum CallingConvention {
|
|||||||
CallingConventionAsync,
|
CallingConventionAsync,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FnInline {
|
||||||
|
FnInlineAuto,
|
||||||
|
FnInlineAlways,
|
||||||
|
FnInlineNever,
|
||||||
|
};
|
||||||
|
|
||||||
struct AstNodeFnProto {
|
struct AstNodeFnProto {
|
||||||
VisibMod visib_mod;
|
VisibMod visib_mod;
|
||||||
Buf *name;
|
Buf *name;
|
||||||
@ -612,7 +618,7 @@ struct AstNodeFnProto {
|
|||||||
bool is_var_args;
|
bool is_var_args;
|
||||||
bool is_extern;
|
bool is_extern;
|
||||||
bool is_export;
|
bool is_export;
|
||||||
bool is_inline;
|
FnInline fn_inline;
|
||||||
CallingConvention cc;
|
CallingConvention cc;
|
||||||
AstNode *fn_def_node;
|
AstNode *fn_def_node;
|
||||||
// populated if this is an extern declaration
|
// populated if this is an extern declaration
|
||||||
@ -1453,12 +1459,6 @@ enum FnAnalState {
|
|||||||
FnAnalStateInvalid,
|
FnAnalStateInvalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FnInline {
|
|
||||||
FnInlineAuto,
|
|
||||||
FnInlineAlways,
|
|
||||||
FnInlineNever,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GlobalExport {
|
struct GlobalExport {
|
||||||
Buf name;
|
Buf name;
|
||||||
GlobalLinkageId linkage;
|
GlobalLinkageId linkage;
|
||||||
|
@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
|
|||||||
assert(proto_node->type == NodeTypeFnProto);
|
assert(proto_node->type == NodeTypeFnProto);
|
||||||
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
||||||
|
|
||||||
FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto;
|
ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline);
|
||||||
ZigFn *fn_entry = create_fn_raw(g, inline_value);
|
|
||||||
|
|
||||||
fn_entry->proto_node = proto_node;
|
fn_entry->proto_node = proto_node;
|
||||||
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
|
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
|
||||||
|
@ -124,8 +124,13 @@ static const char *export_string(bool is_export) {
|
|||||||
// zig_unreachable();
|
// zig_unreachable();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
static const char *inline_string(bool is_inline) {
|
static const char *inline_string(FnInline fn_inline) {
|
||||||
return is_inline ? "inline " : "";
|
switch (fn_inline) {
|
||||||
|
case FnInlineAlways: return "inline ";
|
||||||
|
case FnInlineNever: return "noinline ";
|
||||||
|
case FnInlineAuto: return "";
|
||||||
|
}
|
||||||
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const_or_var_string(bool is_const) {
|
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) {
|
|||||||
const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
|
const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
|
||||||
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
|
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
|
||||||
const char *export_str = export_string(node->data.fn_proto.is_export);
|
const char *export_str = export_string(node->data.fn_proto.is_export);
|
||||||
const char *inline_str = inline_string(node->data.fn_proto.is_inline);
|
const char *inline_str = inline_string(node->data.fn_proto.fn_inline);
|
||||||
fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
|
fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
|
||||||
if (node->data.fn_proto.name != nullptr) {
|
if (node->data.fn_proto.name != nullptr) {
|
||||||
print_symbol(ar, node->data.fn_proto.name);
|
print_symbol(ar, node->data.fn_proto.name);
|
||||||
|
@ -578,7 +578,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TopLevelDecl
|
// TopLevelDecl
|
||||||
// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
|
// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
|
||||||
// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
|
// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
|
||||||
// / KEYWORD_use Expr SEMICOLON
|
// / KEYWORD_use Expr SEMICOLON
|
||||||
static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
|
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) {
|
|||||||
first = eat_token_if(pc, TokenIdKeywordExtern);
|
first = eat_token_if(pc, TokenIdKeywordExtern);
|
||||||
if (first == nullptr)
|
if (first == nullptr)
|
||||||
first = eat_token_if(pc, TokenIdKeywordInline);
|
first = eat_token_if(pc, TokenIdKeywordInline);
|
||||||
|
if (first == nullptr)
|
||||||
|
first = eat_token_if(pc, TokenIdKeywordNoInline);
|
||||||
if (first != nullptr) {
|
if (first != nullptr) {
|
||||||
Token *lib_name = nullptr;
|
Token *lib_name = nullptr;
|
||||||
if (first->id == TokenIdKeywordExtern)
|
if (first->id == TokenIdKeywordExtern)
|
||||||
lib_name = eat_token_if(pc, TokenIdStringLiteral);
|
lib_name = eat_token_if(pc, TokenIdStringLiteral);
|
||||||
|
|
||||||
if (first->id != TokenIdKeywordInline) {
|
if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) {
|
||||||
Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
|
Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
|
||||||
AstNode *var_decl = ast_parse_var_decl(pc);
|
AstNode *var_decl = ast_parse_var_decl(pc);
|
||||||
if (var_decl != nullptr) {
|
if (var_decl != nullptr) {
|
||||||
@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
|
|||||||
fn_proto->data.fn_proto.visib_mod = visib_mod;
|
fn_proto->data.fn_proto.visib_mod = visib_mod;
|
||||||
fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
|
fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
|
||||||
fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
|
fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
|
||||||
fn_proto->data.fn_proto.is_inline = first->id == TokenIdKeywordInline;
|
switch (first->id) {
|
||||||
|
case TokenIdKeywordInline:
|
||||||
|
fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
|
||||||
|
break;
|
||||||
|
case TokenIdKeywordNoInline:
|
||||||
|
fn_proto->data.fn_proto.fn_inline = FnInlineNever;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fn_proto->data.fn_proto.fn_inline = FnInlineAuto;
|
||||||
|
break;
|
||||||
|
}
|
||||||
fn_proto->data.fn_proto.lib_name = token_buf(lib_name);
|
fn_proto->data.fn_proto.lib_name = token_buf(lib_name);
|
||||||
|
|
||||||
AstNode *res = fn_proto;
|
AstNode *res = fn_proto;
|
||||||
if (body != nullptr) {
|
if (body != nullptr) {
|
||||||
res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
|
res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
|
||||||
|
@ -130,6 +130,7 @@ static const struct ZigKeyword zig_keywords[] = {
|
|||||||
{"for", TokenIdKeywordFor},
|
{"for", TokenIdKeywordFor},
|
||||||
{"if", TokenIdKeywordIf},
|
{"if", TokenIdKeywordIf},
|
||||||
{"inline", TokenIdKeywordInline},
|
{"inline", TokenIdKeywordInline},
|
||||||
|
{"noinline", TokenIdKeywordNoInline},
|
||||||
{"nakedcc", TokenIdKeywordNakedCC},
|
{"nakedcc", TokenIdKeywordNakedCC},
|
||||||
{"noalias", TokenIdKeywordNoAlias},
|
{"noalias", TokenIdKeywordNoAlias},
|
||||||
{"null", TokenIdKeywordNull},
|
{"null", TokenIdKeywordNull},
|
||||||
@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) {
|
|||||||
case TokenIdKeywordFor: return "for";
|
case TokenIdKeywordFor: return "for";
|
||||||
case TokenIdKeywordIf: return "if";
|
case TokenIdKeywordIf: return "if";
|
||||||
case TokenIdKeywordInline: return "inline";
|
case TokenIdKeywordInline: return "inline";
|
||||||
|
case TokenIdKeywordNoInline: return "noinline";
|
||||||
case TokenIdKeywordNakedCC: return "nakedcc";
|
case TokenIdKeywordNakedCC: return "nakedcc";
|
||||||
case TokenIdKeywordNoAlias: return "noalias";
|
case TokenIdKeywordNoAlias: return "noalias";
|
||||||
case TokenIdKeywordNull: return "null";
|
case TokenIdKeywordNull: return "null";
|
||||||
|
@ -74,6 +74,7 @@ enum TokenId {
|
|||||||
TokenIdKeywordFor,
|
TokenIdKeywordFor,
|
||||||
TokenIdKeywordIf,
|
TokenIdKeywordIf,
|
||||||
TokenIdKeywordInline,
|
TokenIdKeywordInline,
|
||||||
|
TokenIdKeywordNoInline,
|
||||||
TokenIdKeywordLinkSection,
|
TokenIdKeywordLinkSection,
|
||||||
TokenIdKeywordNakedCC,
|
TokenIdKeywordNakedCC,
|
||||||
TokenIdKeywordNoAlias,
|
TokenIdKeywordNoAlias,
|
||||||
|
@ -432,7 +432,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r
|
|||||||
AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
|
AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
|
||||||
fn_proto->data.fn_proto.visib_mod = c->visib_mod;
|
fn_proto->data.fn_proto.visib_mod = c->visib_mod;
|
||||||
fn_proto->data.fn_proto.name = fn_name;
|
fn_proto->data.fn_proto.name = fn_name;
|
||||||
fn_proto->data.fn_proto.is_inline = true;
|
fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
|
||||||
fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
|
fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
|
||||||
|
|
||||||
fn_def->data.fn_def.fn_proto = fn_proto;
|
fn_def->data.fn_def.fn_proto = fn_proto;
|
||||||
|
@ -201,7 +201,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TopLevelDecl
|
/// TopLevelDecl
|
||||||
/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
|
/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
|
||||||
/// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
|
/// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
|
||||||
/// / KEYWORD_usingnamespace Expr SEMICOLON
|
/// / KEYWORD_usingnamespace Expr SEMICOLON
|
||||||
fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||||
@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
|
|||||||
break :blk token;
|
break :blk token;
|
||||||
}
|
}
|
||||||
if (eatToken(it, .Keyword_inline)) |token| break :blk token;
|
if (eatToken(it, .Keyword_inline)) |token| break :blk token;
|
||||||
|
if (eatToken(it, .Keyword_noinline)) |token| break :blk token;
|
||||||
break :blk null;
|
break :blk null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (extern_export_inline_token) |token| {
|
if (extern_export_inline_token) |token| {
|
||||||
if (tree.tokens.at(token).id == .Keyword_inline) {
|
if (tree.tokens.at(token).id == .Keyword_inline or
|
||||||
|
tree.tokens.at(token).id == .Keyword_noinline) {
|
||||||
putBackToken(it, token);
|
putBackToken(it, token);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1677,14 +1677,17 @@ test "zig fmt: functions" {
|
|||||||
\\extern "c" fn puts(s: *const u8) c_int;
|
\\extern "c" fn puts(s: *const u8) c_int;
|
||||||
\\export fn puts(s: *const u8) c_int;
|
\\export fn puts(s: *const u8) c_int;
|
||||||
\\inline fn puts(s: *const u8) c_int;
|
\\inline fn puts(s: *const u8) c_int;
|
||||||
|
\\noinline fn puts(s: *const u8) c_int;
|
||||||
\\pub extern fn puts(s: *const u8) c_int;
|
\\pub extern fn puts(s: *const u8) c_int;
|
||||||
\\pub extern "c" fn puts(s: *const u8) c_int;
|
\\pub extern "c" fn puts(s: *const u8) c_int;
|
||||||
\\pub export fn puts(s: *const u8) c_int;
|
\\pub export fn puts(s: *const u8) c_int;
|
||||||
\\pub inline fn puts(s: *const u8) c_int;
|
\\pub inline fn puts(s: *const u8) c_int;
|
||||||
|
\\pub noinline fn puts(s: *const u8) c_int;
|
||||||
\\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
|
\\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
|
||||||
\\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
|
\\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
|
||||||
\\pub export fn puts(s: *const u8) align(2 + 2) c_int;
|
\\pub export fn puts(s: *const u8) align(2 + 2) c_int;
|
||||||
\\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
|
\\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
|
||||||
|
\\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
|
||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ pub const Token = struct {
|
|||||||
Keyword{ .bytes = "for", .id = Id.Keyword_for },
|
Keyword{ .bytes = "for", .id = Id.Keyword_for },
|
||||||
Keyword{ .bytes = "if", .id = Id.Keyword_if },
|
Keyword{ .bytes = "if", .id = Id.Keyword_if },
|
||||||
Keyword{ .bytes = "inline", .id = Id.Keyword_inline },
|
Keyword{ .bytes = "inline", .id = Id.Keyword_inline },
|
||||||
|
Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline },
|
||||||
Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc },
|
Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc },
|
||||||
Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias },
|
Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias },
|
||||||
Keyword{ .bytes = "null", .id = Id.Keyword_null },
|
Keyword{ .bytes = "null", .id = Id.Keyword_null },
|
||||||
@ -166,6 +167,7 @@ pub const Token = struct {
|
|||||||
Keyword_for,
|
Keyword_for,
|
||||||
Keyword_if,
|
Keyword_if,
|
||||||
Keyword_inline,
|
Keyword_inline,
|
||||||
|
Keyword_noinline,
|
||||||
Keyword_nakedcc,
|
Keyword_nakedcc,
|
||||||
Keyword_noalias,
|
Keyword_noalias,
|
||||||
Keyword_null,
|
Keyword_null,
|
||||||
|
Loading…
Reference in New Issue
Block a user