| ... | ... | @@ -14,6 +14,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 14 | 14 | TypeTableEntry *expected_type, AstNode *node); |
| 15 | 15 | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 16 | 16 | AstNode *node, AstNodeNumberLiteral *out_number_literal); |
| 17 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node); |
| 18 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 19 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); |
| 17 | 20 | |
| 18 | 21 | static AstNode *first_executing_node(AstNode *node) { |
| 19 | 22 | switch (node->type) { |
| ... | ... | @@ -438,6 +441,9 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 438 | 441 | { |
| 439 | 442 | Buf *name = &node->data.type.primitive_name; |
| 440 | 443 | auto table_entry = import->type_table.maybe_get(name); |
| 444 | if (!table_entry) { |
| 445 | table_entry = g->primitive_type_table.maybe_get(name); |
| 446 | } |
| 441 | 447 | if (table_entry) { |
| 442 | 448 | type_node->entry = table_entry->value; |
| 443 | 449 | } else { |
| ... | ... | @@ -716,10 +722,19 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 716 | 722 | } |
| 717 | 723 | } |
| 718 | 724 | |
| 719 | | static void preview_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node, TypeTableEntry *struct_type) { |
| 720 | | assert(node->type == NodeTypeFnDef); |
| 721 | | AstNode *proto_node = node->data.fn_def.fn_proto; |
| 722 | | assert(proto_node->type == NodeTypeFnProto); |
| 725 | static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 726 | AstNode *proto_node) |
| 727 | { |
| 728 | AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node; |
| 729 | AstNode *extern_node = proto_node->data.fn_proto.extern_node; |
| 730 | AstNode *struct_node = proto_node->data.fn_proto.struct_node; |
| 731 | TypeTableEntry *struct_type; |
| 732 | if (struct_node) { |
| 733 | struct_type = struct_node->codegen_node->data.struct_decl_node.type_entry; |
| 734 | } else { |
| 735 | struct_type = nullptr; |
| 736 | } |
| 737 | |
| 723 | 738 | Buf *proto_name = &proto_node->data.fn_proto.name; |
| 724 | 739 | |
| 725 | 740 | auto fn_table = struct_type ? &struct_type->data.structure.fn_table : &import->fn_table; |
| ... | ... | @@ -727,69 +742,74 @@ static void preview_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node, |
| 727 | 742 | auto entry = fn_table->maybe_get(proto_name); |
| 728 | 743 | bool skip = false; |
| 729 | 744 | bool is_internal = (proto_node->data.fn_proto.visib_mod != VisibModExport); |
| 745 | bool is_c_compat = !is_internal || extern_node; |
| 730 | 746 | bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate); |
| 731 | 747 | if (entry) { |
| 732 | | add_node_error(g, node, |
| 748 | add_node_error(g, proto_node, |
| 733 | 749 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 734 | | alloc_codegen_node(node); |
| 735 | | node->codegen_node->data.fn_def_node.skip = true; |
| 750 | proto_node->codegen_node->data.fn_proto_node.skip = true; |
| 736 | 751 | skip = true; |
| 737 | 752 | } else if (is_pub) { |
| 738 | 753 | auto entry = fn_table->maybe_get(proto_name); |
| 739 | 754 | if (entry) { |
| 740 | | add_node_error(g, node, |
| 741 | | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 742 | | alloc_codegen_node(node); |
| 743 | | node->codegen_node->data.fn_def_node.skip = true; |
| 755 | add_node_error(g, proto_node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 756 | proto_node->codegen_node->data.fn_proto_node.skip = true; |
| 744 | 757 | skip = true; |
| 745 | 758 | } |
| 746 | 759 | } |
| 747 | | if (proto_node->data.fn_proto.is_var_args) { |
| 748 | | add_node_error(g, node, |
| 760 | if (!extern_node && proto_node->data.fn_proto.is_var_args) { |
| 761 | add_node_error(g, proto_node, |
| 749 | 762 | buf_sprintf("variadic arguments only allowed in extern functions")); |
| 750 | 763 | } |
| 751 | | if (!skip) { |
| 752 | | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 753 | | fn_table_entry->import_entry = import; |
| 754 | | fn_table_entry->proto_node = proto_node; |
| 755 | | fn_table_entry->fn_def_node = node; |
| 756 | | fn_table_entry->internal_linkage = is_internal; |
| 757 | | fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; |
| 758 | | fn_table_entry->label_table.init(8); |
| 759 | | fn_table_entry->member_of_struct = struct_type; |
| 764 | if (skip) { |
| 765 | return; |
| 766 | } |
| 760 | 767 | |
| 761 | | if (struct_type) { |
| 762 | | buf_resize(&fn_table_entry->symbol_name, 0); |
| 763 | | buf_appendf(&fn_table_entry->symbol_name, "%s_%s", |
| 764 | | buf_ptr(&struct_type->name), |
| 765 | | buf_ptr(proto_name)); |
| 766 | | } else { |
| 767 | | buf_init_from_buf(&fn_table_entry->symbol_name, proto_name); |
| 768 | | } |
| 768 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 769 | fn_table_entry->import_entry = import; |
| 770 | fn_table_entry->proto_node = proto_node; |
| 771 | fn_table_entry->fn_def_node = fn_def_node; |
| 772 | fn_table_entry->internal_linkage = !is_c_compat; |
| 773 | fn_table_entry->is_extern = extern_node; |
| 774 | fn_table_entry->calling_convention = is_c_compat ? LLVMCCallConv : LLVMFastCallConv; |
| 775 | fn_table_entry->label_table.init(8); |
| 776 | fn_table_entry->member_of_struct = struct_type; |
| 777 | |
| 778 | if (struct_type) { |
| 779 | buf_resize(&fn_table_entry->symbol_name, 0); |
| 780 | buf_appendf(&fn_table_entry->symbol_name, "%s_%s", |
| 781 | buf_ptr(&struct_type->name), |
| 782 | buf_ptr(proto_name)); |
| 783 | } else { |
| 784 | buf_init_from_buf(&fn_table_entry->symbol_name, proto_name); |
| 785 | } |
| 786 | |
| 787 | g->fn_protos.append(fn_table_entry); |
| 769 | 788 | |
| 770 | | g->fn_protos.append(fn_table_entry); |
| 789 | if (!extern_node) { |
| 771 | 790 | g->fn_defs.append(fn_table_entry); |
| 791 | } |
| 772 | 792 | |
| 773 | | fn_table->put(proto_name, fn_table_entry); |
| 793 | fn_table->put(proto_name, fn_table_entry); |
| 774 | 794 | |
| 775 | | if (!struct_type && |
| 776 | | g->bootstrap_import && |
| 777 | | import == g->root_import && buf_eql_str(proto_name, "main")) |
| 778 | | { |
| 779 | | g->bootstrap_import->fn_table.put(proto_name, fn_table_entry); |
| 780 | | } |
| 795 | if (!struct_type && |
| 796 | g->bootstrap_import && |
| 797 | import == g->root_import && buf_eql_str(proto_name, "main")) |
| 798 | { |
| 799 | g->bootstrap_import->fn_table.put(proto_name, fn_table_entry); |
| 800 | } |
| 781 | 801 | |
| 782 | | resolve_function_proto(g, proto_node, fn_table_entry, import); |
| 802 | resolve_function_proto(g, proto_node, fn_table_entry, import); |
| 783 | 803 | |
| 784 | 804 | |
| 785 | | alloc_codegen_node(proto_node); |
| 786 | | proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 805 | proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 787 | 806 | |
| 788 | | preview_function_labels(g, node->data.fn_def.body, fn_table_entry); |
| 807 | if (fn_def_node) { |
| 808 | preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry); |
| 789 | 809 | } |
| 790 | 810 | } |
| 791 | 811 | |
| 792 | | static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 812 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 793 | 813 | switch (node->type) { |
| 794 | 814 | case NodeTypeExternBlock: |
| 795 | 815 | for (int i = 0; i < node->data.extern_block.directives->length; i += 1) { |
| ... | ... | @@ -803,33 +823,9 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 803 | 823 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); |
| 804 | 824 | } |
| 805 | 825 | } |
| 806 | | |
| 807 | | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { |
| 808 | | AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); |
| 809 | | assert(fn_decl->type == NodeTypeFnDecl); |
| 810 | | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; |
| 811 | | |
| 812 | | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 813 | | fn_table_entry->proto_node = fn_proto; |
| 814 | | fn_table_entry->is_extern = true; |
| 815 | | fn_table_entry->calling_convention = LLVMCCallConv; |
| 816 | | fn_table_entry->import_entry = import; |
| 817 | | fn_table_entry->label_table.init(8); |
| 818 | | |
| 819 | | buf_init_from_buf(&fn_table_entry->symbol_name, &fn_proto->data.fn_proto.name); |
| 820 | | |
| 821 | | resolve_function_proto(g, fn_proto, fn_table_entry, import); |
| 822 | | |
| 823 | | Buf *name = &fn_proto->data.fn_proto.name; |
| 824 | | g->fn_protos.append(fn_table_entry); |
| 825 | | import->fn_table.put(name, fn_table_entry); |
| 826 | | |
| 827 | | alloc_codegen_node(fn_proto); |
| 828 | | fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 829 | | } |
| 830 | 826 | break; |
| 831 | | case NodeTypeFnDef: |
| 832 | | preview_fn_def(g, import, node, nullptr); |
| 827 | case NodeTypeFnProto: |
| 828 | preview_fn_proto(g, import, node); |
| 833 | 829 | break; |
| 834 | 830 | case NodeTypeRootExportDecl: |
| 835 | 831 | if (import == g->root_import) { |
| ... | ... | @@ -881,95 +877,22 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 881 | 877 | |
| 882 | 878 | resolve_struct_type(g, import, type_entry); |
| 883 | 879 | |
| 884 | | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { |
| 885 | | AstNode *fn_def_node = node->data.struct_decl.fns.at(i); |
| 886 | | preview_fn_def(g, import, fn_def_node, type_entry); |
| 887 | | } |
| 880 | // struct member fns will get resolved independently |
| 888 | 881 | break; |
| 889 | 882 | } |
| 890 | | case NodeTypeUse: |
| 891 | 883 | case NodeTypeVariableDeclaration: |
| 892 | | // nothing to do here |
| 893 | | break; |
| 894 | | case NodeTypeDirective: |
| 895 | | case NodeTypeParamDecl: |
| 896 | | case NodeTypeFnProto: |
| 897 | | case NodeTypeType: |
| 898 | | case NodeTypeFnDecl: |
| 899 | | case NodeTypeReturnExpr: |
| 900 | | case NodeTypeRoot: |
| 901 | | case NodeTypeBlock: |
| 902 | | case NodeTypeBinOpExpr: |
| 903 | | case NodeTypeFnCallExpr: |
| 904 | | case NodeTypeArrayAccessExpr: |
| 905 | | case NodeTypeSliceExpr: |
| 906 | | case NodeTypeNumberLiteral: |
| 907 | | case NodeTypeStringLiteral: |
| 908 | | case NodeTypeCharLiteral: |
| 909 | | case NodeTypeUnreachable: |
| 910 | | case NodeTypeVoid: |
| 911 | | case NodeTypeBoolLiteral: |
| 912 | | case NodeTypeNullLiteral: |
| 913 | | case NodeTypeSymbol: |
| 914 | | case NodeTypeCastExpr: |
| 915 | | case NodeTypePrefixOpExpr: |
| 916 | | case NodeTypeIfBoolExpr: |
| 917 | | case NodeTypeIfVarExpr: |
| 918 | | case NodeTypeWhileExpr: |
| 919 | | case NodeTypeLabel: |
| 920 | | case NodeTypeGoto: |
| 921 | | case NodeTypeBreak: |
| 922 | | case NodeTypeContinue: |
| 923 | | case NodeTypeAsmExpr: |
| 924 | | case NodeTypeFieldAccessExpr: |
| 925 | | case NodeTypeStructField: |
| 926 | | case NodeTypeStructValueExpr: |
| 927 | | case NodeTypeStructValueField: |
| 928 | | case NodeTypeCompilerFnExpr: |
| 929 | | case NodeTypeCompilerFnType: |
| 930 | | zig_unreachable(); |
| 931 | | } |
| 932 | | } |
| 933 | | |
| 934 | | static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 935 | | switch (node->type) { |
| 936 | | case NodeTypeStructDecl: |
| 937 | 884 | { |
| 938 | | alloc_codegen_node(node); |
| 939 | | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; |
| 940 | | |
| 941 | | Buf *name = &node->data.struct_decl.name; |
| 942 | | auto table_entry = import->type_table.maybe_get(name); |
| 943 | | if (table_entry) { |
| 944 | | struct_codegen->type_entry = table_entry->value; |
| 945 | | add_node_error(g, node, |
| 946 | | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 947 | | } else { |
| 948 | | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 949 | | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); |
| 950 | | entry->data.structure.decl_node = node; |
| 951 | | entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder, |
| 952 | | LLVMZigTag_DW_structure_type(), buf_ptr(&node->data.struct_decl.name), |
| 953 | | LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1); |
| 954 | | |
| 955 | | buf_init_from_buf(&entry->name, name); |
| 956 | | // put off adding the debug type until we do the full struct body |
| 957 | | // this type is incomplete until we do another pass |
| 958 | | import->type_table.put(&entry->name, entry); |
| 959 | | struct_codegen->type_entry = entry; |
| 960 | | } |
| 885 | VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context, |
| 886 | nullptr, node); |
| 887 | g->global_vars.append(var); |
| 961 | 888 | break; |
| 962 | 889 | } |
| 963 | | case NodeTypeExternBlock: |
| 964 | | case NodeTypeFnDef: |
| 965 | | case NodeTypeRootExportDecl: |
| 966 | 890 | case NodeTypeUse: |
| 967 | | case NodeTypeVariableDeclaration: |
| 968 | | // nothing to do |
| 891 | // nothing to do here |
| 969 | 892 | break; |
| 893 | case NodeTypeFnDef: |
| 970 | 894 | case NodeTypeDirective: |
| 971 | 895 | case NodeTypeParamDecl: |
| 972 | | case NodeTypeFnProto: |
| 973 | 896 | case NodeTypeType: |
| 974 | 897 | case NodeTypeFnDecl: |
| 975 | 898 | case NodeTypeReturnExpr: |
| ... | ... | @@ -2552,15 +2475,15 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2552 | 2475 | static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2553 | 2476 | assert(node->type == NodeTypeFnDef); |
| 2554 | 2477 | |
| 2555 | | if (node->codegen_node && node->codegen_node->data.fn_def_node.skip) { |
| 2478 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; |
| 2479 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 2480 | |
| 2481 | if (fn_proto_node->codegen_node->data.fn_proto_node.skip) { |
| 2556 | 2482 | // we detected an error with this function definition which prevents us |
| 2557 | 2483 | // from further analyzing it. |
| 2558 | 2484 | return; |
| 2559 | 2485 | } |
| 2560 | 2486 | |
| 2561 | | AstNode *fn_proto_node = node->data.fn_def.fn_proto; |
| 2562 | | assert(fn_proto_node->type == NodeTypeFnProto); |
| 2563 | | |
| 2564 | 2487 | alloc_codegen_node(node); |
| 2565 | 2488 | BlockContext *context = new_block_context(node, import->block_context); |
| 2566 | 2489 | node->codegen_node->data.fn_def_node.block_context = context; |
| ... | ... | @@ -2630,7 +2553,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2630 | 2553 | } |
| 2631 | 2554 | } |
| 2632 | 2555 | |
| 2633 | | static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2556 | static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2634 | 2557 | switch (node->type) { |
| 2635 | 2558 | case NodeTypeFnDef: |
| 2636 | 2559 | analyze_top_level_fn_def(g, import, node); |
| ... | ... | @@ -2732,16 +2655,332 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 2732 | 2655 | } |
| 2733 | 2656 | break; |
| 2734 | 2657 | } |
| 2658 | case NodeTypeVariableDeclaration: |
| 2659 | // handled in resolve phase |
| 2660 | break; |
| 2661 | case NodeTypeDirective: |
| 2662 | case NodeTypeParamDecl: |
| 2663 | case NodeTypeFnProto: |
| 2664 | case NodeTypeType: |
| 2665 | case NodeTypeFnDecl: |
| 2666 | case NodeTypeReturnExpr: |
| 2667 | case NodeTypeRoot: |
| 2668 | case NodeTypeBlock: |
| 2669 | case NodeTypeBinOpExpr: |
| 2670 | case NodeTypeFnCallExpr: |
| 2671 | case NodeTypeArrayAccessExpr: |
| 2672 | case NodeTypeSliceExpr: |
| 2673 | case NodeTypeNumberLiteral: |
| 2674 | case NodeTypeStringLiteral: |
| 2675 | case NodeTypeCharLiteral: |
| 2676 | case NodeTypeUnreachable: |
| 2677 | case NodeTypeVoid: |
| 2678 | case NodeTypeBoolLiteral: |
| 2679 | case NodeTypeNullLiteral: |
| 2680 | case NodeTypeSymbol: |
| 2681 | case NodeTypeCastExpr: |
| 2682 | case NodeTypePrefixOpExpr: |
| 2683 | case NodeTypeIfBoolExpr: |
| 2684 | case NodeTypeIfVarExpr: |
| 2685 | case NodeTypeWhileExpr: |
| 2686 | case NodeTypeLabel: |
| 2687 | case NodeTypeGoto: |
| 2688 | case NodeTypeBreak: |
| 2689 | case NodeTypeContinue: |
| 2690 | case NodeTypeAsmExpr: |
| 2691 | case NodeTypeFieldAccessExpr: |
| 2692 | case NodeTypeStructField: |
| 2693 | case NodeTypeStructValueExpr: |
| 2694 | case NodeTypeStructValueField: |
| 2695 | case NodeTypeCompilerFnExpr: |
| 2696 | case NodeTypeCompilerFnType: |
| 2697 | zig_unreachable(); |
| 2698 | } |
| 2699 | } |
| 2700 | |
| 2701 | static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *expr_node, |
| 2702 | DeclNode *decl_node) |
| 2703 | { |
| 2704 | switch (expr_node->type) { |
| 2705 | case NodeTypeNumberLiteral: |
| 2706 | case NodeTypeStringLiteral: |
| 2707 | case NodeTypeCharLiteral: |
| 2708 | case NodeTypeVoid: |
| 2709 | case NodeTypeBoolLiteral: |
| 2710 | case NodeTypeNullLiteral: |
| 2711 | case NodeTypeUnreachable: |
| 2712 | case NodeTypeGoto: |
| 2713 | case NodeTypeBreak: |
| 2714 | case NodeTypeContinue: |
| 2715 | // no dependencies on other top level declarations |
| 2716 | break; |
| 2717 | case NodeTypeSymbol: |
| 2718 | decl_node->deps.put(&expr_node->data.symbol, expr_node); |
| 2719 | break; |
| 2720 | case NodeTypeBinOpExpr: |
| 2721 | collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node); |
| 2722 | collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op2, decl_node); |
| 2723 | break; |
| 2724 | case NodeTypeReturnExpr: |
| 2725 | collect_expr_decl_deps(g, import, expr_node->data.return_expr.expr, decl_node); |
| 2726 | break; |
| 2727 | case NodeTypeCastExpr: |
| 2728 | collect_expr_decl_deps(g, import, expr_node->data.cast_expr.expr, decl_node); |
| 2729 | collect_type_decl_deps(g, import, expr_node->data.cast_expr.type, decl_node); |
| 2730 | break; |
| 2731 | case NodeTypePrefixOpExpr: |
| 2732 | collect_expr_decl_deps(g, import, expr_node->data.prefix_op_expr.primary_expr, decl_node); |
| 2733 | break; |
| 2734 | case NodeTypeFnCallExpr: |
| 2735 | collect_expr_decl_deps(g, import, expr_node->data.fn_call_expr.fn_ref_expr, decl_node); |
| 2736 | for (int i = 0; i < expr_node->data.fn_call_expr.params.length; i += 1) { |
| 2737 | AstNode *arg_node = expr_node->data.fn_call_expr.params.at(i); |
| 2738 | collect_expr_decl_deps(g, import, arg_node, decl_node); |
| 2739 | } |
| 2740 | break; |
| 2741 | case NodeTypeArrayAccessExpr: |
| 2742 | collect_expr_decl_deps(g, import, expr_node->data.array_access_expr.array_ref_expr, decl_node); |
| 2743 | collect_expr_decl_deps(g, import, expr_node->data.array_access_expr.subscript, decl_node); |
| 2744 | break; |
| 2745 | case NodeTypeSliceExpr: |
| 2746 | collect_expr_decl_deps(g, import, expr_node->data.slice_expr.array_ref_expr, decl_node); |
| 2747 | collect_expr_decl_deps(g, import, expr_node->data.slice_expr.start, decl_node); |
| 2748 | if (expr_node->data.slice_expr.end) { |
| 2749 | collect_expr_decl_deps(g, import, expr_node->data.slice_expr.end, decl_node); |
| 2750 | } |
| 2751 | break; |
| 2752 | case NodeTypeFieldAccessExpr: |
| 2753 | collect_expr_decl_deps(g, import, expr_node->data.field_access_expr.struct_expr, decl_node); |
| 2754 | break; |
| 2755 | case NodeTypeIfBoolExpr: |
| 2756 | collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.condition, decl_node); |
| 2757 | collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.then_block, decl_node); |
| 2758 | if (expr_node->data.if_bool_expr.else_node) { |
| 2759 | collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.else_node, decl_node); |
| 2760 | } |
| 2761 | break; |
| 2762 | case NodeTypeIfVarExpr: |
| 2763 | if (expr_node->data.if_var_expr.var_decl.type) { |
| 2764 | collect_type_decl_deps(g, import, expr_node->data.if_var_expr.var_decl.type, decl_node); |
| 2765 | } |
| 2766 | if (expr_node->data.if_var_expr.var_decl.expr) { |
| 2767 | collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.var_decl.expr, decl_node); |
| 2768 | } |
| 2769 | collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.then_block, decl_node); |
| 2770 | if (expr_node->data.if_bool_expr.else_node) { |
| 2771 | collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.else_node, decl_node); |
| 2772 | } |
| 2773 | break; |
| 2774 | case NodeTypeWhileExpr: |
| 2775 | collect_expr_decl_deps(g, import, expr_node->data.while_expr.condition, decl_node); |
| 2776 | collect_expr_decl_deps(g, import, expr_node->data.while_expr.body, decl_node); |
| 2777 | break; |
| 2778 | case NodeTypeBlock: |
| 2779 | for (int i = 0; i < expr_node->data.block.statements.length; i += 1) { |
| 2780 | AstNode *stmt = expr_node->data.block.statements.at(i); |
| 2781 | collect_expr_decl_deps(g, import, stmt, decl_node); |
| 2782 | } |
| 2783 | break; |
| 2784 | case NodeTypeAsmExpr: |
| 2785 | for (int i = 0; i < expr_node->data.asm_expr.output_list.length; i += 1) { |
| 2786 | AsmOutput *asm_output = expr_node->data.asm_expr.output_list.at(i); |
| 2787 | if (asm_output->return_type) { |
| 2788 | collect_type_decl_deps(g, import, asm_output->return_type, decl_node); |
| 2789 | } else { |
| 2790 | decl_node->deps.put(&asm_output->variable_name, expr_node); |
| 2791 | } |
| 2792 | } |
| 2793 | for (int i = 0; i < expr_node->data.asm_expr.input_list.length; i += 1) { |
| 2794 | AsmInput *asm_input = expr_node->data.asm_expr.input_list.at(i); |
| 2795 | collect_expr_decl_deps(g, import, asm_input->expr, decl_node); |
| 2796 | } |
| 2797 | break; |
| 2798 | case NodeTypeStructValueExpr: |
| 2799 | collect_type_decl_deps(g, import, expr_node->data.struct_val_expr.type, decl_node); |
| 2800 | for (int i = 0; i < expr_node->data.struct_val_expr.fields.length; i += 1) { |
| 2801 | AstNode *field_node = expr_node->data.struct_val_expr.fields.at(i); |
| 2802 | assert(field_node->type == NodeTypeStructValueField); |
| 2803 | collect_expr_decl_deps(g, import, field_node->data.struct_val_field.expr, decl_node); |
| 2804 | } |
| 2805 | break; |
| 2806 | case NodeTypeCompilerFnExpr: |
| 2807 | collect_expr_decl_deps(g, import, expr_node->data.compiler_fn_expr.expr, decl_node); |
| 2808 | break; |
| 2809 | case NodeTypeCompilerFnType: |
| 2810 | collect_type_decl_deps(g, import, expr_node->data.compiler_fn_type.type, decl_node); |
| 2811 | break; |
| 2812 | case NodeTypeRoot: |
| 2813 | case NodeTypeRootExportDecl: |
| 2814 | case NodeTypeFnProto: |
| 2815 | case NodeTypeFnDef: |
| 2816 | case NodeTypeFnDecl: |
| 2817 | case NodeTypeParamDecl: |
| 2818 | case NodeTypeType: |
| 2819 | case NodeTypeExternBlock: |
| 2820 | case NodeTypeDirective: |
| 2821 | case NodeTypeVariableDeclaration: |
| 2822 | case NodeTypeUse: |
| 2823 | case NodeTypeLabel: |
| 2824 | case NodeTypeStructDecl: |
| 2825 | case NodeTypeStructField: |
| 2826 | case NodeTypeStructValueField: |
| 2827 | zig_unreachable(); |
| 2828 | } |
| 2829 | } |
| 2830 | |
| 2831 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, DeclNode *decl_node) { |
| 2832 | assert(type_node->type == NodeTypeType); |
| 2833 | switch (type_node->data.type.type) { |
| 2834 | case AstNodeTypeTypePrimitive: |
| 2835 | { |
| 2836 | Buf *name = &type_node->data.type.primitive_name; |
| 2837 | auto table_entry = g->primitive_type_table.maybe_get(name); |
| 2838 | if (!table_entry) { |
| 2839 | table_entry = import->type_table.maybe_get(name); |
| 2840 | } |
| 2841 | if (!table_entry) { |
| 2842 | decl_node->deps.put(name, type_node); |
| 2843 | } |
| 2844 | break; |
| 2845 | } |
| 2846 | case AstNodeTypeTypePointer: |
| 2847 | collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node); |
| 2848 | break; |
| 2849 | case AstNodeTypeTypeArray: |
| 2850 | collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node); |
| 2851 | if (type_node->data.type.array_size) { |
| 2852 | collect_expr_decl_deps(g, import, type_node->data.type.array_size, decl_node); |
| 2853 | } |
| 2854 | break; |
| 2855 | case AstNodeTypeTypeMaybe: |
| 2856 | collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node); |
| 2857 | break; |
| 2858 | case AstNodeTypeTypeCompilerExpr: |
| 2859 | collect_expr_decl_deps(g, import, type_node->data.type.compiler_expr, decl_node); |
| 2860 | break; |
| 2861 | } |
| 2862 | } |
| 2863 | |
| 2864 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2865 | switch (node->type) { |
| 2866 | case NodeTypeStructDecl: |
| 2867 | { |
| 2868 | alloc_codegen_node(node); |
| 2869 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; |
| 2870 | |
| 2871 | Buf *name = &node->data.struct_decl.name; |
| 2872 | auto table_entry = import->type_table.maybe_get(name); |
| 2873 | if (!table_entry) { |
| 2874 | table_entry = g->primitive_type_table.maybe_get(name); |
| 2875 | } |
| 2876 | if (table_entry) { |
| 2877 | struct_codegen->type_entry = table_entry->value; |
| 2878 | add_node_error(g, node, |
| 2879 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 2880 | } else { |
| 2881 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 2882 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); |
| 2883 | entry->data.structure.decl_node = node; |
| 2884 | entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder, |
| 2885 | LLVMZigTag_DW_structure_type(), buf_ptr(&node->data.struct_decl.name), |
| 2886 | LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1); |
| 2887 | |
| 2888 | buf_init_from_buf(&entry->name, name); |
| 2889 | // put off adding the debug type until we do the full struct body |
| 2890 | // this type is incomplete until we do another pass |
| 2891 | import->type_table.put(&entry->name, entry); |
| 2892 | struct_codegen->type_entry = entry; |
| 2893 | } |
| 2894 | |
| 2895 | // determine which other top level declarations this struct depends on. |
| 2896 | DeclNode *decl_node = &node->codegen_node->decl_node; |
| 2897 | for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) { |
| 2898 | AstNode *field_node = node->data.struct_decl.fields.at(i); |
| 2899 | AstNode *type_node = field_node->data.struct_field.type; |
| 2900 | collect_type_decl_deps(g, import, type_node, decl_node); |
| 2901 | } |
| 2902 | node->codegen_node->decl_node.name = name; |
| 2903 | node->codegen_node->decl_node.import = import; |
| 2904 | if (decl_node->deps.size() > 0) { |
| 2905 | g->unresolved_top_level_decls.put(name, node); |
| 2906 | } else { |
| 2907 | resolve_top_level_decl(g, import, node); |
| 2908 | } |
| 2909 | |
| 2910 | // handle the member function definitions independently |
| 2911 | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { |
| 2912 | AstNode *fn_def_node = node->data.struct_decl.fns.at(i); |
| 2913 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; |
| 2914 | fn_proto_node->data.fn_proto.struct_node = node; |
| 2915 | detect_top_level_decl_deps(g, import, fn_def_node); |
| 2916 | } |
| 2917 | |
| 2918 | break; |
| 2919 | } |
| 2920 | case NodeTypeExternBlock: |
| 2921 | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { |
| 2922 | AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); |
| 2923 | assert(fn_decl->type == NodeTypeFnDecl); |
| 2924 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; |
| 2925 | fn_proto->data.fn_proto.extern_node = node; |
| 2926 | detect_top_level_decl_deps(g, import, fn_proto); |
| 2927 | } |
| 2928 | resolve_top_level_decl(g, import, node); |
| 2929 | break; |
| 2930 | case NodeTypeFnDef: |
| 2931 | node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node; |
| 2932 | detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto); |
| 2933 | break; |
| 2735 | 2934 | case NodeTypeVariableDeclaration: |
| 2736 | 2935 | { |
| 2737 | | VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context, |
| 2738 | | nullptr, node); |
| 2739 | | g->global_vars.append(var); |
| 2936 | // determine which other top level declarations this variable declaration depends on. |
| 2937 | alloc_codegen_node(node); |
| 2938 | DeclNode *decl_node = &node->codegen_node->decl_node; |
| 2939 | if (node->data.variable_declaration.type) { |
| 2940 | collect_type_decl_deps(g, import, node->data.variable_declaration.type, decl_node); |
| 2941 | } |
| 2942 | if (node->data.variable_declaration.expr) { |
| 2943 | collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node); |
| 2944 | } |
| 2945 | Buf *name = &node->data.variable_declaration.symbol; |
| 2946 | node->codegen_node->decl_node.name = name; |
| 2947 | node->codegen_node->decl_node.import = import; |
| 2948 | if (decl_node->deps.size() > 0) { |
| 2949 | g->unresolved_top_level_decls.put(name, node); |
| 2950 | } else { |
| 2951 | resolve_top_level_decl(g, import, node); |
| 2952 | } |
| 2740 | 2953 | break; |
| 2741 | 2954 | } |
| 2955 | case NodeTypeFnProto: |
| 2956 | { |
| 2957 | // determine which other top level declarations this function prototype depends on. |
| 2958 | alloc_codegen_node(node); |
| 2959 | DeclNode *decl_node = &node->codegen_node->decl_node; |
| 2960 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 2961 | AstNode *param_node = node->data.fn_proto.params.at(i); |
| 2962 | assert(param_node->type == NodeTypeParamDecl); |
| 2963 | collect_type_decl_deps(g, import, param_node->data.param_decl.type, decl_node); |
| 2964 | } |
| 2965 | |
| 2966 | Buf *name = &node->data.fn_proto.name; |
| 2967 | node->codegen_node->decl_node.name = name; |
| 2968 | node->codegen_node->decl_node.import = import; |
| 2969 | if (decl_node->deps.size() > 0) { |
| 2970 | g->unresolved_top_level_decls.put(name, node); |
| 2971 | } else { |
| 2972 | resolve_top_level_decl(g, import, node); |
| 2973 | } |
| 2974 | break; |
| 2975 | } |
| 2976 | case NodeTypeRootExportDecl: |
| 2977 | resolve_top_level_decl(g, import, node); |
| 2978 | break; |
| 2979 | case NodeTypeUse: |
| 2980 | // nothing to do |
| 2981 | break; |
| 2742 | 2982 | case NodeTypeDirective: |
| 2743 | 2983 | case NodeTypeParamDecl: |
| 2744 | | case NodeTypeFnProto: |
| 2745 | 2984 | case NodeTypeType: |
| 2746 | 2985 | case NodeTypeFnDecl: |
| 2747 | 2986 | case NodeTypeReturnExpr: |
| ... | ... | @@ -2779,24 +3018,69 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 2779 | 3018 | } |
| 2780 | 3019 | } |
| 2781 | 3020 | |
| 2782 | | static void find_function_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2783 | | assert(node->type == NodeTypeRoot); |
| 3021 | static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 3022 | auto it = node->codegen_node->decl_node.deps.entry_iterator(); |
| 3023 | for (;;) { |
| 3024 | auto *entry = it.next(); |
| 3025 | if (!entry) |
| 3026 | break; |
| 2784 | 3027 | |
| 2785 | | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { |
| 2786 | | AstNode *child = node->data.root.top_level_decls.at(i); |
| 2787 | | preview_function_declarations(g, import, child); |
| 3028 | auto unresolved_entry = g->unresolved_top_level_decls.maybe_get(entry->key); |
| 3029 | if (!unresolved_entry) { |
| 3030 | continue; |
| 3031 | } |
| 3032 | |
| 3033 | AstNode *child_node = unresolved_entry->value; |
| 3034 | |
| 3035 | if (child_node->codegen_node->decl_node.in_current_deps) { |
| 3036 | zig_panic("TODO infinite top level decl loop"); |
| 3037 | } |
| 3038 | |
| 3039 | // set temporary flag |
| 3040 | child_node->codegen_node->decl_node.in_current_deps = true; |
| 3041 | |
| 3042 | recursive_resolve_decl(g, child_node->codegen_node->decl_node.import, child_node); |
| 3043 | |
| 3044 | // unset temporary flag |
| 3045 | child_node->codegen_node->decl_node.in_current_deps = false; |
| 2788 | 3046 | } |
| 2789 | 3047 | |
| 3048 | resolve_top_level_decl(g, import, node); |
| 3049 | g->unresolved_top_level_decls.remove(node->codegen_node->decl_node.name); |
| 2790 | 3050 | } |
| 2791 | 3051 | |
| 2792 | | static void preview_types_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 3052 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2793 | 3053 | assert(node->type == NodeTypeRoot); |
| 2794 | 3054 | |
| 2795 | 3055 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { |
| 2796 | 3056 | AstNode *child = node->data.root.top_level_decls.at(i); |
| 2797 | | preview_types(g, import, child); |
| 3057 | detect_top_level_decl_deps(g, import, child); |
| 2798 | 3058 | } |
| 2799 | 3059 | |
| 3060 | while (g->unresolved_top_level_decls.size() > 0) { |
| 3061 | // for the sake of determinism, find the element with the lowest |
| 3062 | // insert index and resolve that one. |
| 3063 | AstNode *decl_node = nullptr; |
| 3064 | auto it = g->unresolved_top_level_decls.entry_iterator(); |
| 3065 | for (;;) { |
| 3066 | auto *entry = it.next(); |
| 3067 | if (!entry) |
| 3068 | break; |
| 3069 | |
| 3070 | AstNode *this_node = entry->value; |
| 3071 | if (!decl_node || this_node->create_index < decl_node->create_index) { |
| 3072 | decl_node = this_node; |
| 3073 | } |
| 3074 | |
| 3075 | } |
| 3076 | // set temporary flag |
| 3077 | decl_node->codegen_node->decl_node.in_current_deps = true; |
| 3078 | |
| 3079 | recursive_resolve_decl(g, decl_node->codegen_node->decl_node.import, decl_node); |
| 3080 | |
| 3081 | // unset temporary flag |
| 3082 | decl_node->codegen_node->decl_node.in_current_deps = false; |
| 3083 | } |
| 2800 | 3084 | } |
| 2801 | 3085 | |
| 2802 | 3086 | static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| ... | ... | @@ -2804,7 +3088,7 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A |
| 2804 | 3088 | |
| 2805 | 3089 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { |
| 2806 | 3090 | AstNode *child = node->data.root.top_level_decls.at(i); |
| 2807 | | analyze_top_level_declaration(g, import, child); |
| 3091 | analyze_top_level_decl(g, import, child); |
| 2808 | 3092 | } |
| 2809 | 3093 | } |
| 2810 | 3094 | |
| ... | ... | @@ -2817,21 +3101,9 @@ void semantic_analyze(CodeGen *g) { |
| 2817 | 3101 | break; |
| 2818 | 3102 | |
| 2819 | 3103 | ImportTableEntry *import = entry->value; |
| 2820 | | preview_types_root(g, import, import->root); |
| 2821 | | } |
| 2822 | | } |
| 2823 | | { |
| 2824 | | auto it = g->import_table.entry_iterator(); |
| 2825 | | for (;;) { |
| 2826 | | auto *entry = it.next(); |
| 2827 | | if (!entry) |
| 2828 | | break; |
| 2829 | | |
| 2830 | | ImportTableEntry *import = entry->value; |
| 2831 | | find_function_declarations_root(g, import, import->root); |
| 3104 | resolve_top_level_declarations_root(g, import, import->root); |
| 2832 | 3105 | } |
| 2833 | 3106 | } |
| 2834 | | |
| 2835 | 3107 | { |
| 2836 | 3108 | auto it = g->import_table.entry_iterator(); |
| 2837 | 3109 | for (;;) { |
| ... | ... | @@ -2844,7 +3116,6 @@ void semantic_analyze(CodeGen *g) { |
| 2844 | 3116 | } |
| 2845 | 3117 | } |
| 2846 | 3118 | |
| 2847 | | |
| 2848 | 3119 | if (!g->root_out_name) { |
| 2849 | 3120 | add_node_error(g, g->root_import->root, |
| 2850 | 3121 | buf_sprintf("missing export declaration and output name not provided")); |
| ... | ... | @@ -2857,5 +3128,6 @@ void semantic_analyze(CodeGen *g) { |
| 2857 | 3128 | void alloc_codegen_node(AstNode *node) { |
| 2858 | 3129 | assert(!node->codegen_node); |
| 2859 | 3130 | node->codegen_node = allocate<CodeGenNode>(1); |
| 3131 | node->codegen_node->decl_node.deps.init(1); |
| 2860 | 3132 | } |
| 2861 | 3133 | |