| author | |
| committer | |
| log | 1c15091bc8d83b9464082afbdb62ecd9c9176cd6 |
| tree | 8cd175ded0ee4737d45ef5411263059622ea9e26 |
| parent | 5dfe0e7e8fabd3cfc3fdf5c7099791da98899903 |
| signature | Commit is signed but in an unrecognized format. |
7 files changed, 56 insertions(+), 84 deletions(-)
lib/std/builtin.zig+2-9| ... | ... | @@ -155,6 +155,7 @@ pub const CallingConvention = enum { |
| 155 | 155 | C, |
| 156 | 156 | Naked, |
| 157 | 157 | Async, |
| 158 | Inline, | |
| 158 | 159 | Interrupt, |
| 159 | 160 | Signal, |
| 160 | 161 | Stdcall, |
| ... | ... | @@ -404,21 +405,13 @@ pub const TypeInfo = union(enum) { |
| 404 | 405 | /// therefore must be kept in sync with the compiler implementation. |
| 405 | 406 | pub const FnDecl = struct { |
| 406 | 407 | fn_type: type, |
| 407 | inline_type: Inline, | |
| 408 | is_noinline: bool, | |
| 408 | 409 | is_var_args: bool, |
| 409 | 410 | is_extern: bool, |
| 410 | 411 | is_export: bool, |
| 411 | 412 | lib_name: ?[]const u8, |
| 412 | 413 | return_type: type, |
| 413 | 414 | arg_names: []const []const u8, |
| 414 | ||
| 415 | /// This data structure is used by the Zig language code generation and | |
| 416 | /// therefore must be kept in sync with the compiler implementation. | |
| 417 | pub const Inline = enum { | |
| 418 | Auto, | |
| 419 | Always, | |
| 420 | Never, | |
| 421 | }; | |
| 422 | 415 | }; |
| 423 | 416 | }; |
| 424 | 417 | }; |
src/stage1/all_types.hpp+3-9| ... | ... | @@ -74,6 +74,7 @@ enum CallingConvention { |
| 74 | 74 | CallingConventionC, |
| 75 | 75 | CallingConventionNaked, |
| 76 | 76 | CallingConventionAsync, |
| 77 | CallingConventionInline, | |
| 77 | 78 | CallingConventionInterrupt, |
| 78 | 79 | CallingConventionSignal, |
| 79 | 80 | CallingConventionStdcall, |
| ... | ... | @@ -703,12 +704,6 @@ enum NodeType { |
| 703 | 704 | NodeTypeAnyTypeField, |
| 704 | 705 | }; |
| 705 | 706 | |
| 706 | enum FnInline { | |
| 707 | FnInlineAuto, | |
| 708 | FnInlineAlways, | |
| 709 | FnInlineNever, | |
| 710 | }; | |
| 711 | ||
| 712 | 707 | struct AstNodeFnProto { |
| 713 | 708 | Buf *name; |
| 714 | 709 | ZigList<AstNode *> params; |
| ... | ... | @@ -725,13 +720,12 @@ struct AstNodeFnProto { |
| 725 | 720 | AstNode *callconv_expr; |
| 726 | 721 | Buf doc_comments; |
| 727 | 722 | |
| 728 | FnInline fn_inline; | |
| 729 | ||
| 730 | 723 | VisibMod visib_mod; |
| 731 | 724 | bool auto_err_set; |
| 732 | 725 | bool is_var_args; |
| 733 | 726 | bool is_extern; |
| 734 | 727 | bool is_export; |
| 728 | bool is_noinline; | |
| 735 | 729 | }; |
| 736 | 730 | |
| 737 | 731 | struct AstNodeFnDef { |
| ... | ... | @@ -1719,7 +1713,6 @@ struct ZigFn { |
| 1719 | 1713 | |
| 1720 | 1714 | LLVMValueRef valgrind_client_request_array; |
| 1721 | 1715 | |
| 1722 | FnInline fn_inline; | |
| 1723 | 1716 | FnAnalState anal_state; |
| 1724 | 1717 | |
| 1725 | 1718 | uint32_t align_bytes; |
| ... | ... | @@ -1728,6 +1721,7 @@ struct ZigFn { |
| 1728 | 1721 | bool calls_or_awaits_errorable_fn; |
| 1729 | 1722 | bool is_cold; |
| 1730 | 1723 | bool is_test; |
| 1724 | bool is_noinline; | |
| 1731 | 1725 | }; |
| 1732 | 1726 | |
| 1733 | 1727 | uint32_t fn_table_entry_hash(ZigFn*); |
src/stage1/analyze.cpp+15-5| ... | ... | @@ -973,6 +973,7 @@ const char *calling_convention_name(CallingConvention cc) { |
| 973 | 973 | case CallingConventionAPCS: return "APCS"; |
| 974 | 974 | case CallingConventionAAPCS: return "AAPCS"; |
| 975 | 975 | case CallingConventionAAPCSVFP: return "AAPCSVFP"; |
| 976 | case CallingConventionInline: return "Inline"; | |
| 976 | 977 | } |
| 977 | 978 | zig_unreachable(); |
| 978 | 979 | } |
| ... | ... | @@ -981,6 +982,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) { |
| 981 | 982 | switch (cc) { |
| 982 | 983 | case CallingConventionUnspecified: |
| 983 | 984 | case CallingConventionAsync: |
| 985 | case CallingConventionInline: | |
| 984 | 986 | return true; |
| 985 | 987 | case CallingConventionC: |
| 986 | 988 | case CallingConventionNaked: |
| ... | ... | @@ -1007,7 +1009,8 @@ ZigType *get_stack_trace_type(CodeGen *g) { |
| 1007 | 1009 | } |
| 1008 | 1010 | |
| 1009 | 1011 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 1010 | if (fn_type_id->cc == CallingConventionUnspecified) { | |
| 1012 | if (fn_type_id->cc == CallingConventionUnspecified | |
| 1013 | || fn_type_id->cc == CallingConventionInline) { | |
| 1011 | 1014 | return handle_is_ptr(g, fn_type_id->return_type); |
| 1012 | 1015 | } |
| 1013 | 1016 | if (fn_type_id->cc != CallingConventionC) { |
| ... | ... | @@ -1888,6 +1891,7 @@ Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_ |
| 1888 | 1891 | case CallingConventionC: |
| 1889 | 1892 | case CallingConventionNaked: |
| 1890 | 1893 | case CallingConventionAsync: |
| 1894 | case CallingConventionInline: | |
| 1891 | 1895 | break; |
| 1892 | 1896 | case CallingConventionInterrupt: |
| 1893 | 1897 | if (g->zig_target->arch != ZigLLVM_x86 |
| ... | ... | @@ -3587,7 +3591,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i |
| 3587 | 3591 | } |
| 3588 | 3592 | } |
| 3589 | 3593 | |
| 3590 | static ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { | |
| 3594 | static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { | |
| 3591 | 3595 | ZigFn *fn_entry = heap::c_allocator.create<ZigFn>(); |
| 3592 | 3596 | fn_entry->ir_executable = heap::c_allocator.create<IrExecutableSrc>(); |
| 3593 | 3597 | |
| ... | ... | @@ -3597,7 +3601,7 @@ static ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { |
| 3597 | 3601 | fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota; |
| 3598 | 3602 | fn_entry->analyzed_executable.fn_entry = fn_entry; |
| 3599 | 3603 | fn_entry->ir_executable->fn_entry = fn_entry; |
| 3600 | fn_entry->fn_inline = inline_value; | |
| 3604 | fn_entry->is_noinline = is_noinline; | |
| 3601 | 3605 | |
| 3602 | 3606 | return fn_entry; |
| 3603 | 3607 | } |
| ... | ... | @@ -3606,7 +3610,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) { |
| 3606 | 3610 | assert(proto_node->type == NodeTypeFnProto); |
| 3607 | 3611 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 3608 | 3612 | |
| 3609 | ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline); | |
| 3613 | ZigFn *fn_entry = create_fn_raw(g, fn_proto->is_noinline); | |
| 3610 | 3614 | |
| 3611 | 3615 | fn_entry->proto_node = proto_node; |
| 3612 | 3616 | fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : |
| ... | ... | @@ -3739,6 +3743,12 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3739 | 3743 | fn_table_entry->type_entry = g->builtin_types.entry_invalid; |
| 3740 | 3744 | tld_fn->base.resolution = TldResolutionInvalid; |
| 3741 | 3745 | return; |
| 3746 | case CallingConventionInline: | |
| 3747 | add_node_error(g, fn_def_node, | |
| 3748 | buf_sprintf("exported function cannot be inline")); | |
| 3749 | fn_table_entry->type_entry = g->builtin_types.entry_invalid; | |
| 3750 | tld_fn->base.resolution = TldResolutionInvalid; | |
| 3751 | return; | |
| 3742 | 3752 | case CallingConventionC: |
| 3743 | 3753 | case CallingConventionNaked: |
| 3744 | 3754 | case CallingConventionInterrupt: |
| ... | ... | @@ -3774,7 +3784,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3774 | 3784 | fn_table_entry->inferred_async_node = fn_table_entry->proto_node; |
| 3775 | 3785 | } |
| 3776 | 3786 | } else if (source_node->type == NodeTypeTestDecl) { |
| 3777 | ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto); | |
| 3787 | ZigFn *fn_table_entry = create_fn_raw(g, false); | |
| 3778 | 3788 | |
| 3779 | 3789 | get_fully_qualified_decl_name(g, &fn_table_entry->symbol_name, &tld_fn->base, true); |
| 3780 | 3790 |
src/stage1/ast_render.cpp+3-8| ... | ... | @@ -123,13 +123,8 @@ static const char *export_string(bool is_export) { |
| 123 | 123 | // zig_unreachable(); |
| 124 | 124 | //} |
| 125 | 125 | |
| 126 | static const char *inline_string(FnInline fn_inline) { | |
| 127 | switch (fn_inline) { | |
| 128 | case FnInlineAlways: return "inline "; | |
| 129 | case FnInlineNever: return "noinline "; | |
| 130 | case FnInlineAuto: return ""; | |
| 131 | } | |
| 132 | zig_unreachable(); | |
| 126 | static const char *inline_string(bool is_inline) { | |
| 127 | return is_inline ? "inline" : ""; | |
| 133 | 128 | } |
| 134 | 129 | |
| 135 | 130 | static const char *const_or_var_string(bool is_const) { |
| ... | ... | @@ -446,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 446 | 441 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); |
| 447 | 442 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); |
| 448 | 443 | const char *export_str = export_string(node->data.fn_proto.is_export); |
| 449 | const char *inline_str = inline_string(node->data.fn_proto.fn_inline); | |
| 444 | const char *inline_str = inline_string(node->data.fn_proto.is_noinline); | |
| 450 | 445 | fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); |
| 451 | 446 | if (node->data.fn_proto.name != nullptr) { |
| 452 | 447 | print_symbol(ar, node->data.fn_proto.name); |
src/stage1/codegen.cpp+18-28| ... | ... | @@ -159,6 +159,7 @@ static const char *get_mangled_name(CodeGen *g, const char *original_name) { |
| 159 | 159 | static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 160 | 160 | switch (cc) { |
| 161 | 161 | case CallingConventionUnspecified: |
| 162 | case CallingConventionInline: | |
| 162 | 163 | return ZigLLVM_Fast; |
| 163 | 164 | case CallingConventionC: |
| 164 | 165 | return ZigLLVM_C; |
| ... | ... | @@ -350,6 +351,7 @@ static bool cc_want_sret_attr(CallingConvention cc) { |
| 350 | 351 | return true; |
| 351 | 352 | case CallingConventionAsync: |
| 352 | 353 | case CallingConventionUnspecified: |
| 354 | case CallingConventionInline: | |
| 353 | 355 | return false; |
| 354 | 356 | } |
| 355 | 357 | zig_unreachable(); |
| ... | ... | @@ -452,20 +454,11 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 452 | 454 | } |
| 453 | 455 | } |
| 454 | 456 | |
| 455 | switch (fn->fn_inline) { | |
| 456 | case FnInlineAlways: | |
| 457 | addLLVMFnAttr(llvm_fn, "alwaysinline"); | |
| 458 | g->inline_fns.append(fn); | |
| 459 | break; | |
| 460 | case FnInlineNever: | |
| 461 | addLLVMFnAttr(llvm_fn, "noinline"); | |
| 462 | break; | |
| 463 | case FnInlineAuto: | |
| 464 | if (fn->alignstack_value != 0) { | |
| 465 | addLLVMFnAttr(llvm_fn, "noinline"); | |
| 466 | } | |
| 467 | break; | |
| 468 | } | |
| 457 | if (cc == CallingConventionInline) | |
| 458 | addLLVMFnAttr(llvm_fn, "alwaysinline"); | |
| 459 | ||
| 460 | if (fn->is_noinline || (cc != CallingConventionInline && fn->alignstack_value != 0)) | |
| 461 | addLLVMFnAttr(llvm_fn, "noinline"); | |
| 469 | 462 | |
| 470 | 463 | if (cc == CallingConventionNaked) { |
| 471 | 464 | addLLVMFnAttr(llvm_fn, "naked"); |
| ... | ... | @@ -532,7 +525,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 532 | 525 | addLLVMFnAttr(llvm_fn, "nounwind"); |
| 533 | 526 | add_uwtable_attr(g, llvm_fn); |
| 534 | 527 | addLLVMFnAttr(llvm_fn, "nobuiltin"); |
| 535 | if (codegen_have_frame_pointer(g) && fn->fn_inline != FnInlineAlways) { | |
| 528 | if (codegen_have_frame_pointer(g) && cc != CallingConventionInline) { | |
| 536 | 529 | ZigLLVMAddFunctionAttr(llvm_fn, "frame-pointer", "all"); |
| 537 | 530 | } |
| 538 | 531 | if (fn->section_name) { |
| ... | ... | @@ -9043,19 +9036,16 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 9043 | 9036 | static_assert(CallingConventionC == 1, ""); |
| 9044 | 9037 | static_assert(CallingConventionNaked == 2, ""); |
| 9045 | 9038 | static_assert(CallingConventionAsync == 3, ""); |
| 9046 | static_assert(CallingConventionInterrupt == 4, ""); | |
| 9047 | static_assert(CallingConventionSignal == 5, ""); | |
| 9048 | static_assert(CallingConventionStdcall == 6, ""); | |
| 9049 | static_assert(CallingConventionFastcall == 7, ""); | |
| 9050 | static_assert(CallingConventionVectorcall == 8, ""); | |
| 9051 | static_assert(CallingConventionThiscall == 9, ""); | |
| 9052 | static_assert(CallingConventionAPCS == 10, ""); | |
| 9053 | static_assert(CallingConventionAAPCS == 11, ""); | |
| 9054 | static_assert(CallingConventionAAPCSVFP == 12, ""); | |
| 9055 | ||
| 9056 | static_assert(FnInlineAuto == 0, ""); | |
| 9057 | static_assert(FnInlineAlways == 1, ""); | |
| 9058 | static_assert(FnInlineNever == 2, ""); | |
| 9039 | static_assert(CallingConventionInline == 4, ""); | |
| 9040 | static_assert(CallingConventionInterrupt == 5, ""); | |
| 9041 | static_assert(CallingConventionSignal == 6, ""); | |
| 9042 | static_assert(CallingConventionStdcall == 7, ""); | |
| 9043 | static_assert(CallingConventionFastcall == 8, ""); | |
| 9044 | static_assert(CallingConventionVectorcall == 9, ""); | |
| 9045 | static_assert(CallingConventionThiscall == 10, ""); | |
| 9046 | static_assert(CallingConventionAPCS == 11, ""); | |
| 9047 | static_assert(CallingConventionAAPCS == 12, ""); | |
| 9048 | static_assert(CallingConventionAAPCSVFP == 13, ""); | |
| 9059 | 9049 | |
| 9060 | 9050 | static_assert(BuiltinPtrSizeOne == 0, ""); |
| 9061 | 9051 | static_assert(BuiltinPtrSizeMany == 1, ""); |
src/stage1/ir.cpp+12-11| ... | ... | @@ -19000,7 +19000,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV |
| 19000 | 19000 | } else if (init_val->type->id == ZigTypeIdFn && |
| 19001 | 19001 | init_val->special != ConstValSpecialUndef && |
| 19002 | 19002 | init_val->data.x_ptr.special == ConstPtrSpecialFunction && |
| 19003 | init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) | |
| 19003 | init_val->data.x_ptr.data.fn.fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionInline) | |
| 19004 | 19004 | { |
| 19005 | 19005 | var_class_requires_const = true; |
| 19006 | 19006 | if (!var->src_is_const && !is_comptime_var) { |
| ... | ... | @@ -19182,6 +19182,11 @@ static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport |
| 19182 | 19182 | buf_sprintf("exported function cannot be async")); |
| 19183 | 19183 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); |
| 19184 | 19184 | } break; |
| 19185 | case CallingConventionInline: { | |
| 19186 | ErrorMsg *msg = ir_add_error(ira, &target->base, | |
| 19187 | buf_sprintf("exported function cannot be inline")); | |
| 19188 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); | |
| 19189 | } break; | |
| 19185 | 19190 | case CallingConventionC: |
| 19186 | 19191 | case CallingConventionNaked: |
| 19187 | 19192 | case CallingConventionInterrupt: |
| ... | ... | @@ -21120,7 +21125,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 21120 | 21125 | if (type_is_invalid(return_type)) |
| 21121 | 21126 | return ira->codegen->invalid_inst_gen; |
| 21122 | 21127 | |
| 21123 | if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && modifier == CallModifierNeverInline) { | |
| 21128 | if (fn_entry != nullptr && fn_type_id->cc == CallingConventionInline && modifier == CallModifierNeverInline) { | |
| 21124 | 21129 | ir_add_error(ira, source_instr, |
| 21125 | 21130 | buf_sprintf("no-inline call of inline function")); |
| 21126 | 21131 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -25219,10 +25224,6 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa |
| 25219 | 25224 | if ((err = type_resolve(ira->codegen, type_info_fn_decl_type, ResolveStatusSizeKnown))) |
| 25220 | 25225 | return err; |
| 25221 | 25226 | |
| 25222 | ZigType *type_info_fn_decl_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_decl_type); | |
| 25223 | if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown))) | |
| 25224 | return err; | |
| 25225 | ||
| 25226 | 25227 | resolve_container_usingnamespace_decls(ira->codegen, decls_scope); |
| 25227 | 25228 | |
| 25228 | 25229 | // The unresolved declarations are collected in a separate queue to avoid |
| ... | ... | @@ -25365,11 +25366,11 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa |
| 25365 | 25366 | fn_decl_fields[0]->special = ConstValSpecialStatic; |
| 25366 | 25367 | fn_decl_fields[0]->type = ira->codegen->builtin_types.entry_type; |
| 25367 | 25368 | fn_decl_fields[0]->data.x_type = fn_entry->type_entry; |
| 25368 | // inline_type: Data.FnDecl.Inline | |
| 25369 | ensure_field_index(fn_decl_val->type, "inline_type", 1); | |
| 25369 | // is_noinline: bool | |
| 25370 | ensure_field_index(fn_decl_val->type, "is_noinline", 1); | |
| 25370 | 25371 | fn_decl_fields[1]->special = ConstValSpecialStatic; |
| 25371 | fn_decl_fields[1]->type = type_info_fn_decl_inline_type; | |
| 25372 | bigint_init_unsigned(&fn_decl_fields[1]->data.x_enum_tag, fn_entry->fn_inline); | |
| 25372 | fn_decl_fields[1]->type = ira->codegen->builtin_types.entry_bool; | |
| 25373 | fn_decl_fields[1]->data.x_bool = fn_entry->is_noinline; | |
| 25373 | 25374 | // is_var_args: bool |
| 25374 | 25375 | ensure_field_index(fn_decl_val->type, "is_var_args", 2); |
| 25375 | 25376 | bool is_varargs = fn_node->is_var_args; |
| ... | ... | @@ -30957,7 +30958,7 @@ static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstS |
| 30957 | 30958 | return ira->codegen->invalid_inst_gen; |
| 30958 | 30959 | } |
| 30959 | 30960 | |
| 30960 | if (fn_entry->fn_inline == FnInlineAlways) { | |
| 30961 | if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionInline) { | |
| 30961 | 30962 | ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack in inline function")); |
| 30962 | 30963 | return ira->codegen->invalid_inst_gen; |
| 30963 | 30964 | } |
src/stage1/parser.cpp+3-14| ... | ... | @@ -693,8 +693,6 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 693 | 693 | Token *first = eat_token_if(pc, TokenIdKeywordExport); |
| 694 | 694 | if (first == nullptr) |
| 695 | 695 | first = eat_token_if(pc, TokenIdKeywordExtern); |
| 696 | if (first == nullptr) | |
| 697 | first = eat_token_if(pc, TokenIdKeywordInline); | |
| 698 | 696 | if (first == nullptr) |
| 699 | 697 | first = eat_token_if(pc, TokenIdKeywordNoInline); |
| 700 | 698 | if (first != nullptr) { |
| ... | ... | @@ -702,7 +700,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 702 | 700 | if (first->id == TokenIdKeywordExtern) |
| 703 | 701 | lib_name = eat_token_if(pc, TokenIdStringLiteral); |
| 704 | 702 | |
| 705 | if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) { | |
| 703 | if (first->id != TokenIdKeywordNoInline) { | |
| 706 | 704 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 707 | 705 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 708 | 706 | if (var_decl != nullptr) { |
| ... | ... | @@ -739,17 +737,8 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 739 | 737 | if (!fn_proto->data.fn_proto.is_extern) |
| 740 | 738 | fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; |
| 741 | 739 | fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; |
| 742 | switch (first->id) { | |
| 743 | case TokenIdKeywordInline: | |
| 744 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; | |
| 745 | break; | |
| 746 | case TokenIdKeywordNoInline: | |
| 747 | fn_proto->data.fn_proto.fn_inline = FnInlineNever; | |
| 748 | break; | |
| 749 | default: | |
| 750 | fn_proto->data.fn_proto.fn_inline = FnInlineAuto; | |
| 751 | break; | |
| 752 | } | |
| 740 | if (first->id == TokenIdKeywordNoInline) | |
| 741 | fn_proto->data.fn_proto.is_noinline = true; | |
| 753 | 742 | fn_proto->data.fn_proto.lib_name = token_buf(lib_name); |
| 754 | 743 | |
| 755 | 744 | AstNode *res = fn_proto; |