From 563d9ebfe597b313b265a5a30296c081fe35d87a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 23 Dec 2019 21:52:06 +0100 Subject: Implement the callconv() annotation --- src/parser.cpp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index a0c5cf794b..65ea9ac203 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -92,6 +92,7 @@ static Token *ast_parse_block_label(ParseContext *pc); static AstNode *ast_parse_field_init(ParseContext *pc); static AstNode *ast_parse_while_continue_expr(ParseContext *pc); static AstNode *ast_parse_link_section(ParseContext *pc); +static AstNode *ast_parse_callconv(ParseContext *pc); static Optional ast_parse_fn_cc(ParseContext *pc); static AstNode *ast_parse_param_decl(ParseContext *pc); static AstNode *ast_parse_param_type(ParseContext *pc); @@ -676,7 +677,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B fn_proto->column = first->start_column; fn_proto->data.fn_proto.visib_mod = visib_mod; fn_proto->data.fn_proto.doc_comments = *doc_comments; - fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; + // ast_parse_fn_cc may set it + if (!fn_proto->data.fn_proto.is_extern) + fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; switch (first->id) { case TokenIdKeywordInline: @@ -761,7 +764,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { // The extern keyword for fn CC is also used for container decls. // We therefore put it back, as allow container decl to consume it // later. - if (fn_cc.cc == CallingConventionC) { + if (fn_cc.is_extern) { fn = eat_token_if(pc, TokenIdKeywordFn); if (fn == nullptr) { put_back_token(pc); @@ -784,6 +787,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { AstNode *align_expr = ast_parse_byte_align(pc); AstNode *section_expr = ast_parse_link_section(pc); + AstNode *callconv_expr = ast_parse_callconv(pc); Token *var = eat_token_if(pc, TokenIdKeywordVar); Token *exmark = nullptr; AstNode *return_type = nullptr; @@ -798,6 +802,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { res->data.fn_proto.params = params; res->data.fn_proto.align_expr = align_expr; res->data.fn_proto.section_expr = section_expr; + res->data.fn_proto.callconv_expr = callconv_expr; res->data.fn_proto.return_var_token = var; res->data.fn_proto.auto_err_set = exmark != nullptr; res->data.fn_proto.return_type = return_type; @@ -2099,6 +2104,18 @@ static AstNode *ast_parse_link_section(ParseContext *pc) { return res; } +// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN +static AstNode *ast_parse_callconv(ParseContext *pc) { + Token *first = eat_token_if(pc, TokenIdKeywordCallconv); + if (first == nullptr) + return nullptr; + + expect_token(pc, TokenIdLParen); + AstNode *res = ast_expect(pc, ast_parse_expr); + expect_token(pc, TokenIdRParen); + return res; +} + // FnCC // <- KEYWORD_nakedcc // / KEYWORD_stdcallcc @@ -2107,19 +2124,19 @@ static AstNode *ast_parse_link_section(ParseContext *pc) { static Optional ast_parse_fn_cc(ParseContext *pc) { AstNodeFnProto res = {}; if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) { - res.cc = CallingConventionNaked; + res.is_nakedcc = true; return Optional::some(res); } if (eat_token_if(pc, TokenIdKeywordStdcallCC) != nullptr) { - res.cc = CallingConventionStdcall; + res.is_stdcallcc = true; return Optional::some(res); } - if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) { - res.cc = CallingConventionC; + if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) { + res.is_async = true; return Optional::some(res); } - if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) { - res.cc = CallingConventionAsync; + if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) { + res.is_extern = true; return Optional::some(res); } -- cgit v1.2.3 From 5951b79af40212754071157596b8aebbe2414ffb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 6 Jan 2020 15:23:05 -0500 Subject: remove stdcallcc, extern, nakedcc from stage1; zig fmt rewrites --- lib/std/builtin.zig | 1 - lib/std/zig/parser_test.zig | 4 +++- lib/std/zig/render.zig | 15 ++++++++++----- src/all_types.hpp | 3 --- src/analyze.cpp | 22 ++++++++++------------ src/codegen.cpp | 2 +- src/ir.cpp | 18 ++++++------------ src/parser.cpp | 12 +----------- src/tokenizer.cpp | 4 ---- src/tokenizer.hpp | 2 -- 10 files changed, 31 insertions(+), 52 deletions(-) (limited to 'src/parser.cpp') diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 9b3be8f424..288e8f8897 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -322,7 +322,6 @@ pub const TypeInfo = union(enum) { pub const FnDecl = struct { fn_type: type, inline_type: Inline, - calling_convention: CallingConvention, is_var_args: bool, is_extern: bool, is_export: bool, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 018ba9653f..97df2dff15 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -10,13 +10,15 @@ test "zig fmt: change @typeOf to @TypeOf" { } // TODO: Remove nakedcc/stdcallcc once zig 0.6.0 is released. See https://github.com/ziglang/zig/pull/3977 -test "zig fmt: convert nakedcc/stdcallcc into callconv(...)" { +test "zig fmt: convert extern/nakedcc/stdcallcc into callconv(...)" { try testTransform( \\nakedcc fn foo1() void {} \\stdcallcc fn foo2() void {} + \\extern fn foo3() void {} , \\fn foo1() callconv(.Naked) void {} \\fn foo2() callconv(.Stdcall) void {} + \\fn foo3() callconv(.C) void {} \\ ); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 626017dd66..2b1a739186 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1311,17 +1311,22 @@ fn renderExpression( try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub } + // Some extra machinery is needed to rewrite the old-style cc + // notation to the new callconv one + var cc_rewrite_str: ?[*:0]const u8 = null; if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export + const tok = tree.tokens.at(extern_export_inline_token); + if (tok.id != .Keyword_extern or fn_proto.body_node == null) { + try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export + } else { + cc_rewrite_str = ".C"; + } } if (fn_proto.lib_name) |lib_name| { try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); } - // Some extra machinery is needed to rewrite the old-style cc - // notation to the new callconv one - var cc_rewrite_str: ?[*:0]const u8 = null; if (fn_proto.cc_token) |cc_token| { var str = tree.tokenSlicePtr(tree.tokens.at(cc_token)); if (mem.eql(u8, str, "stdcallcc")) { @@ -1405,7 +1410,7 @@ fn renderExpression( const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); const callconv_kw = tree.prevToken(callconv_lparen); - try renderToken(tree, stream, callconv_kw, indent, start_col, Space.None); // section + try renderToken(tree, stream, callconv_kw, indent, start_col, Space.None); // callconv try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) diff --git a/src/all_types.hpp b/src/all_types.hpp index 3e8516529a..fe77d3db3b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -653,8 +653,6 @@ struct AstNodeFnProto { Buf doc_comments; FnInline fn_inline; - bool is_nakedcc; - bool is_stdcallcc; bool is_async; VisibMod visib_mod; @@ -1610,7 +1608,6 @@ struct ZigFn { Buf **param_names; IrInstruction *err_code_spill; AstNode *assumed_non_async; - CallingConvention cc; AstNode *fn_no_inline_set_node; AstNode *fn_static_eval_set_node; diff --git a/src/analyze.cpp b/src/analyze.cpp index 5fb99ef1f3..a7763fea61 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1451,8 +1451,6 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { ZigType *fn_type = new_type_table_entry(ZigTypeIdFn); buf_resize(&fn_type->name, 0); - if (fn_type->data.fn.fn_type_id.cc == CallingConventionC) - buf_append_str(&fn_type->name, "extern "); buf_appendf(&fn_type->name, "fn("); size_t i = 0; for (; i < fn_type_id->next_param_index; i += 1) { @@ -1465,7 +1463,7 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { buf_appendf(&fn_type->name, "%svar", comma_str); } buf_append_str(&fn_type->name, ")"); - if (fn_type_id->cc != CallingConventionUnspecified && fn_type_id->cc != CallingConventionC) { + if (fn_type_id->cc != CallingConventionUnspecified) { buf_appendf(&fn_type->name, " callconv(%s)", calling_convention_name(fn_type_id->cc)); } buf_append_str(&fn_type->name, " var"); @@ -1479,10 +1477,6 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { } CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto) { - if (fn_proto->is_nakedcc) - return CallingConventionNaked; - if (fn_proto->is_stdcallcc) - return CallingConventionStdcall; if (fn_proto->is_async) return CallingConventionAsync; // Compatible with the C ABI @@ -1764,13 +1758,15 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) { return err_set_type; } -static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, ZigFn *fn_entry) { +static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, ZigFn *fn_entry, + CallingConvention cc) +{ assert(proto_node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; Error err; FnTypeId fn_type_id = {0}; - init_fn_type_id(&fn_type_id, proto_node, fn_entry->cc, proto_node->data.fn_proto.params.length); + init_fn_type_id(&fn_type_id, proto_node, cc, proto_node->data.fn_proto.params.length); for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index); @@ -3432,7 +3428,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; - fn_table_entry->cc = cc_from_fn_proto(fn_proto); + CallingConvention cc; if (fn_proto->callconv_expr != nullptr) { ZigType *cc_enum_value = get_builtin_type(g, "CallingConvention"); @@ -3444,7 +3440,9 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { return; } - fn_table_entry->cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag); + cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag); + } else { + cc = cc_from_fn_proto(fn_proto); } if (fn_proto->section_expr != nullptr) { @@ -3455,7 +3453,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { } } - fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry); + fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry, cc); if (type_is_invalid(fn_table_entry->type_entry)) { tld_fn->base.resolution = TldResolutionInvalid; diff --git a/src/codegen.cpp b/src/codegen.cpp index cbb5e35a57..59f69539bc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -519,7 +519,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { if (cc == CallingConventionNaked) { addLLVMFnAttr(llvm_fn, "naked"); } else { - ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); + ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, cc)); } bool want_cold = fn->is_cold || cc == CallingConventionCold; diff --git a/src/ir.cpp b/src/ir.cpp index 78be3256c0..4a91046b7c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18263,7 +18263,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn); impl_fn->child_scope = &impl_fn->fndef_scope->base; - impl_fn->cc = fn_entry->cc; FnTypeId inst_fn_type_id = {0}; init_fn_type_id(&inst_fn_type_id, fn_proto_node, fn_type_id->cc, new_fn_arg_count); inst_fn_type_id.param_count = 0; @@ -22599,29 +22598,24 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_decl_fields[1]->special = ConstValSpecialStatic; fn_decl_fields[1]->type = type_info_fn_decl_inline_type; bigint_init_unsigned(&fn_decl_fields[1]->data.x_enum_tag, fn_entry->fn_inline); - // calling_convention: TypeInfo.CallingConvention - ensure_field_index(fn_decl_val->type, "calling_convention", 2); - fn_decl_fields[2]->special = ConstValSpecialStatic; - fn_decl_fields[2]->type = get_builtin_type(ira->codegen, "CallingConvention"); - bigint_init_unsigned(&fn_decl_fields[2]->data.x_enum_tag, fn_entry->cc); // is_var_args: bool - ensure_field_index(fn_decl_val->type, "is_var_args", 3); + ensure_field_index(fn_decl_val->type, "is_var_args", 2); bool is_varargs = fn_node->is_var_args; fn_decl_fields[3]->special = ConstValSpecialStatic; fn_decl_fields[3]->type = ira->codegen->builtin_types.entry_bool; fn_decl_fields[3]->data.x_bool = is_varargs; // is_extern: bool - ensure_field_index(fn_decl_val->type, "is_extern", 4); + ensure_field_index(fn_decl_val->type, "is_extern", 3); fn_decl_fields[4]->special = ConstValSpecialStatic; fn_decl_fields[4]->type = ira->codegen->builtin_types.entry_bool; fn_decl_fields[4]->data.x_bool = fn_node->is_extern; // is_export: bool - ensure_field_index(fn_decl_val->type, "is_export", 5); + ensure_field_index(fn_decl_val->type, "is_export", 4); fn_decl_fields[5]->special = ConstValSpecialStatic; fn_decl_fields[5]->type = ira->codegen->builtin_types.entry_bool; fn_decl_fields[5]->data.x_bool = fn_node->is_export; // lib_name: ?[]const u8 - ensure_field_index(fn_decl_val->type, "lib_name", 6); + ensure_field_index(fn_decl_val->type, "lib_name", 5); fn_decl_fields[6]->special = ConstValSpecialStatic; ZigType *u8_ptr = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, @@ -22637,12 +22631,12 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_decl_fields[6]->data.x_optional = nullptr; } // return_type: type - ensure_field_index(fn_decl_val->type, "return_type", 7); + ensure_field_index(fn_decl_val->type, "return_type", 6); fn_decl_fields[7]->special = ConstValSpecialStatic; fn_decl_fields[7]->type = ira->codegen->builtin_types.entry_type; fn_decl_fields[7]->data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; // arg_names: [][] const u8 - ensure_field_index(fn_decl_val->type, "arg_names", 8); + ensure_field_index(fn_decl_val->type, "arg_names", 7); size_t fn_arg_count = fn_entry->variable_list.length; ZigValue *fn_arg_name_array = create_const_vals(1); fn_arg_name_array->special = ConstValSpecialStatic; diff --git a/src/parser.cpp b/src/parser.cpp index 65ea9ac203..f6f5811e63 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2117,20 +2117,10 @@ static AstNode *ast_parse_callconv(ParseContext *pc) { } // FnCC -// <- KEYWORD_nakedcc -// / KEYWORD_stdcallcc -// / KEYWORD_extern +// <- KEYWORD_extern // / KEYWORD_async static Optional ast_parse_fn_cc(ParseContext *pc) { AstNodeFnProto res = {}; - if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) { - res.is_nakedcc = true; - return Optional::some(res); - } - if (eat_token_if(pc, TokenIdKeywordStdcallCC) != nullptr) { - res.is_stdcallcc = true; - return Optional::some(res); - } if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) { res.is_async = true; return Optional::some(res); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index fb58bc19bb..9182c5227a 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -127,7 +127,6 @@ static const struct ZigKeyword zig_keywords[] = { {"for", TokenIdKeywordFor}, {"if", TokenIdKeywordIf}, {"inline", TokenIdKeywordInline}, - {"nakedcc", TokenIdKeywordNakedCC}, {"noalias", TokenIdKeywordNoAlias}, {"noasync", TokenIdKeywordNoAsync}, {"noinline", TokenIdKeywordNoInline}, @@ -139,7 +138,6 @@ static const struct ZigKeyword zig_keywords[] = { {"resume", TokenIdKeywordResume}, {"return", TokenIdKeywordReturn}, {"linksection", TokenIdKeywordLinkSection}, - {"stdcallcc", TokenIdKeywordStdcallCC}, {"struct", TokenIdKeywordStruct}, {"suspend", TokenIdKeywordSuspend}, {"switch", TokenIdKeywordSwitch}, @@ -1562,7 +1560,6 @@ const char * token_name(TokenId id) { case TokenIdKeywordFor: return "for"; case TokenIdKeywordIf: return "if"; case TokenIdKeywordInline: return "inline"; - case TokenIdKeywordNakedCC: return "nakedcc"; case TokenIdKeywordNoAlias: return "noalias"; case TokenIdKeywordNoAsync: return "noasync"; case TokenIdKeywordNoInline: return "noinline"; @@ -1573,7 +1570,6 @@ const char * token_name(TokenId id) { case TokenIdKeywordPub: return "pub"; case TokenIdKeywordReturn: return "return"; case TokenIdKeywordLinkSection: return "linksection"; - case TokenIdKeywordStdcallCC: return "stdcallcc"; case TokenIdKeywordStruct: return "struct"; case TokenIdKeywordSwitch: return "switch"; case TokenIdKeywordTest: return "test"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index eacdaad98d..a893cc2373 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -77,7 +77,6 @@ enum TokenId { TokenIdKeywordInline, TokenIdKeywordNoInline, TokenIdKeywordLinkSection, - TokenIdKeywordNakedCC, TokenIdKeywordNoAlias, TokenIdKeywordNoAsync, TokenIdKeywordNull, @@ -87,7 +86,6 @@ enum TokenId { TokenIdKeywordPub, TokenIdKeywordResume, TokenIdKeywordReturn, - TokenIdKeywordStdcallCC, TokenIdKeywordStruct, TokenIdKeywordSuspend, TokenIdKeywordSwitch, -- cgit v1.2.3