| ... | @@ -541,18 +541,21 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry * | ... | @@ -541,18 +541,21 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry * |
| 541 | } | 541 | } |
| 542 | | 542 | |
| 543 | // accepts ownership of fn_type_id memory | 543 | // accepts ownership of fn_type_id memory |
| 544 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { | 544 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 545 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); | 545 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); |
| 546 | if (table_entry) { | 546 | if (table_entry) { |
| 547 | return table_entry->value; | 547 | return table_entry->value; |
| 548 | } | 548 | } |
| 549 | | 549 | |
| 550 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); | 550 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); |
| 551 | fn_type->data.fn.fn_type_id = fn_type_id; | 551 | fn_type->data.fn.fn_type_id = *fn_type_id; |
| | 552 | if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) { |
| | 553 | fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0]; |
| | 554 | } |
| 552 | | 555 | |
| 553 | if (fn_type_id.is_cold) { | 556 | if (fn_type_id->is_cold) { |
| 554 | fn_type->data.fn.calling_convention = LLVMColdCallConv; | 557 | fn_type->data.fn.calling_convention = LLVMColdCallConv; |
| 555 | } else if (fn_type_id.is_extern) { | 558 | } else if (fn_type_id->is_extern) { |
| 556 | fn_type->data.fn.calling_convention = LLVMCCallConv; | 559 | fn_type->data.fn.calling_convention = LLVMCCallConv; |
| 557 | } else { | 560 | } else { |
| 558 | fn_type->data.fn.calling_convention = LLVMFastCallConv; | 561 | fn_type->data.fn.calling_convention = LLVMFastCallConv; |
| ... | @@ -560,12 +563,12 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { | ... | @@ -560,12 +563,12 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { |
| 560 | | 563 | |
| 561 | // populate the name of the type | 564 | // populate the name of the type |
| 562 | buf_resize(&fn_type->name, 0); | 565 | buf_resize(&fn_type->name, 0); |
| 563 | const char *extern_str = fn_type_id.is_extern ? "extern " : ""; | 566 | const char *extern_str = fn_type_id->is_extern ? "extern " : ""; |
| 564 | const char *naked_str = fn_type_id.is_naked ? "naked " : ""; | 567 | const char *naked_str = fn_type_id->is_naked ? "naked " : ""; |
| 565 | const char *cold_str = fn_type_id.is_cold ? "cold " : ""; | 568 | const char *cold_str = fn_type_id->is_cold ? "cold " : ""; |
| 566 | buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str); | 569 | buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str); |
| 567 | for (int i = 0; i < fn_type_id.param_count; i += 1) { | 570 | for (int i = 0; i < fn_type_id->param_count; i += 1) { |
| 568 | FnTypeParamInfo *param_info = &fn_type_id.param_info[i]; | 571 | FnTypeParamInfo *param_info = &fn_type_id->param_info[i]; |
| 569 | | 572 | |
| 570 | TypeTableEntry *param_type = param_info->type; | 573 | TypeTableEntry *param_type = param_info->type; |
| 571 | const char *comma = (i == 0) ? "" : ", "; | 574 | const char *comma = (i == 0) ? "" : ", "; |
| ... | @@ -573,42 +576,42 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { | ... | @@ -573,42 +576,42 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { |
| 573 | buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name)); | 576 | buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name)); |
| 574 | } | 577 | } |
| 575 | | 578 | |
| 576 | if (fn_type_id.is_var_args) { | 579 | if (fn_type_id->is_var_args) { |
| 577 | const char *comma = (fn_type_id.param_count == 0) ? "" : ", "; | 580 | const char *comma = (fn_type_id->param_count == 0) ? "" : ", "; |
| 578 | buf_appendf(&fn_type->name, "%s...", comma); | 581 | buf_appendf(&fn_type->name, "%s...", comma); |
| 579 | } | 582 | } |
| 580 | buf_appendf(&fn_type->name, ")"); | 583 | buf_appendf(&fn_type->name, ")"); |
| 581 | if (fn_type_id.return_type->id != TypeTableEntryIdVoid) { | 584 | if (fn_type_id->return_type->id != TypeTableEntryIdVoid) { |
| 582 | buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id.return_type->name)); | 585 | buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name)); |
| 583 | } | 586 | } |
| 584 | | 587 | |
| 585 | | 588 | |
| 586 | // next, loop over the parameters again and compute debug information | 589 | // next, loop over the parameters again and compute debug information |
| 587 | // and codegen information | 590 | // and codegen information |
| 588 | bool first_arg_return = handle_is_ptr(fn_type_id.return_type); | 591 | bool first_arg_return = handle_is_ptr(fn_type_id->return_type); |
| 589 | // +1 for maybe making the first argument the return value | 592 | // +1 for maybe making the first argument the return value |
| 590 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id.param_count); | 593 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count); |
| 591 | // +1 because 0 is the return type and +1 for maybe making first arg ret val | 594 | // +1 because 0 is the return type and +1 for maybe making first arg ret val |
| 592 | LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id.param_count); | 595 | LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(2 + fn_type_id->param_count); |
| 593 | param_di_types[0] = fn_type_id.return_type->di_type; | 596 | param_di_types[0] = fn_type_id->return_type->di_type; |
| 594 | int gen_param_index = 0; | 597 | int gen_param_index = 0; |
| 595 | TypeTableEntry *gen_return_type; | 598 | TypeTableEntry *gen_return_type; |
| 596 | if (first_arg_return) { | 599 | if (first_arg_return) { |
| 597 | TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id.return_type, false); | 600 | TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false); |
| 598 | gen_param_types[gen_param_index] = gen_type->type_ref; | 601 | gen_param_types[gen_param_index] = gen_type->type_ref; |
| 599 | gen_param_index += 1; | 602 | gen_param_index += 1; |
| 600 | // after the gen_param_index += 1 because 0 is the return type | 603 | // after the gen_param_index += 1 because 0 is the return type |
| 601 | param_di_types[gen_param_index] = gen_type->di_type; | 604 | param_di_types[gen_param_index] = gen_type->di_type; |
| 602 | gen_return_type = g->builtin_types.entry_void; | 605 | gen_return_type = g->builtin_types.entry_void; |
| 603 | } else if (!type_has_bits(fn_type_id.return_type)) { | 606 | } else if (!type_has_bits(fn_type_id->return_type)) { |
| 604 | gen_return_type = g->builtin_types.entry_void; | 607 | gen_return_type = g->builtin_types.entry_void; |
| 605 | } else { | 608 | } else { |
| 606 | gen_return_type = fn_type_id.return_type; | 609 | gen_return_type = fn_type_id->return_type; |
| 607 | } | 610 | } |
| 608 | fn_type->data.fn.gen_return_type = gen_return_type; | 611 | fn_type->data.fn.gen_return_type = gen_return_type; |
| 609 | | 612 | |
| 610 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id.param_count); | 613 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count); |
| 611 | for (int i = 0; i < fn_type_id.param_count; i += 1) { | 614 | for (int i = 0; i < fn_type_id->param_count; i += 1) { |
| 612 | FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; | 615 | FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; |
| 613 | TypeTableEntry *type_entry = src_param_info->type; | 616 | TypeTableEntry *type_entry = src_param_info->type; |
| 614 | FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i]; | 617 | FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i]; |
| ... | @@ -639,13 +642,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { | ... | @@ -639,13 +642,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) { |
| 639 | fn_type->data.fn.gen_param_count = gen_param_index; | 642 | fn_type->data.fn.gen_param_count = gen_param_index; |
| 640 | | 643 | |
| 641 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, | 644 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, |
| 642 | gen_param_types, gen_param_index, fn_type_id.is_var_args); | 645 | gen_param_types, gen_param_index, fn_type_id->is_var_args); |
| 643 | fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); | 646 | fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); |
| 644 | LLVMZigDIFile *di_file = nullptr; | 647 | LLVMZigDIFile *di_file = nullptr; |
| 645 | fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, di_file, | 648 | fn_type->di_type = LLVMZigCreateSubroutineType(g->dbuilder, di_file, |
| 646 | param_di_types, gen_param_index + 1, 0); | 649 | param_di_types, gen_param_index + 1, 0); |
| 647 | | 650 | |
| 648 | g->fn_type_table.put(fn_type_id, fn_type); | 651 | g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); |
| 649 | | 652 | |
| 650 | return fn_type; | 653 | return fn_type; |
| 651 | } | 654 | } |
| ... | @@ -747,7 +750,13 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -747,7 +750,13 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 747 | fn_type_id.is_naked = is_naked; | 750 | fn_type_id.is_naked = is_naked; |
| 748 | fn_type_id.is_cold = is_cold; | 751 | fn_type_id.is_cold = is_cold; |
| 749 | fn_type_id.param_count = node->data.fn_proto.params.length; | 752 | fn_type_id.param_count = node->data.fn_proto.params.length; |
| 750 | fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count); | 753 | |
| | 754 | if (fn_type_id.param_count > fn_type_id_prealloc_param_info_count) { |
| | 755 | fn_type_id.param_info = allocate_nonzero<FnTypeParamInfo>(fn_type_id.param_count); |
| | 756 | } else { |
| | 757 | fn_type_id.param_info = &fn_type_id.prealloc_param_info[0]; |
| | 758 | } |
| | 759 | |
| 751 | fn_type_id.is_var_args = fn_proto->is_var_args; | 760 | fn_type_id.is_var_args = fn_proto->is_var_args; |
| 752 | fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type); | 761 | fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type); |
| 753 | | 762 | |
| ... | @@ -800,7 +809,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -800,7 +809,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 800 | return g->builtin_types.entry_invalid; | 809 | return g->builtin_types.entry_invalid; |
| 801 | } | 810 | } |
| 802 | | 811 | |
| 803 | return get_fn_type(g, fn_type_id); | 812 | return get_fn_type(g, &fn_type_id); |
| 804 | } | 813 | } |
| 805 | | 814 | |
| 806 | | 815 | |
| ... | @@ -5855,35 +5864,35 @@ static uint32_t hash_ptr(void *ptr) { | ... | @@ -5855,35 +5864,35 @@ static uint32_t hash_ptr(void *ptr) { |
| 5855 | return a ^ b; | 5864 | return a ^ b; |
| 5856 | } | 5865 | } |
| 5857 | | 5866 | |
| 5858 | uint32_t fn_type_id_hash(FnTypeId id) { | 5867 | uint32_t fn_type_id_hash(FnTypeId *id) { |
| 5859 | uint32_t result = 0; | 5868 | uint32_t result = 0; |
| 5860 | result += id.is_extern ? 3349388391 : 0; | 5869 | result += id->is_extern ? 3349388391 : 0; |
| 5861 | result += id.is_naked ? 608688877 : 0; | 5870 | result += id->is_naked ? 608688877 : 0; |
| 5862 | result += id.is_cold ? 3605523458 : 0; | 5871 | result += id->is_cold ? 3605523458 : 0; |
| 5863 | result += id.is_var_args ? 1931444534 : 0; | 5872 | result += id->is_var_args ? 1931444534 : 0; |
| 5864 | result += hash_ptr(id.return_type); | 5873 | result += hash_ptr(id->return_type); |
| 5865 | result += id.param_count; | 5874 | result += id->param_count; |
| 5866 | for (int i = 0; i < id.param_count; i += 1) { | 5875 | for (int i = 0; i < id->param_count; i += 1) { |
| 5867 | FnTypeParamInfo *info = &id.param_info[i]; | 5876 | FnTypeParamInfo *info = &id->param_info[i]; |
| 5868 | result += info->is_noalias ? 892356923 : 0; | 5877 | result += info->is_noalias ? 892356923 : 0; |
| 5869 | result += hash_ptr(info->type); | 5878 | result += hash_ptr(info->type); |
| 5870 | } | 5879 | } |
| 5871 | return result; | 5880 | return result; |
| 5872 | } | 5881 | } |
| 5873 | | 5882 | |
| 5874 | bool fn_type_id_eql(FnTypeId a, FnTypeId b) { | 5883 | bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { |
| 5875 | if (a.is_extern != b.is_extern || | 5884 | if (a->is_extern != b->is_extern || |
| 5876 | a.is_naked != b.is_naked || | 5885 | a->is_naked != b->is_naked || |
| 5877 | a.is_cold != b.is_cold || | 5886 | a->is_cold != b->is_cold || |
| 5878 | a.return_type != b.return_type || | 5887 | a->return_type != b->return_type || |
| 5879 | a.is_var_args != b.is_var_args || | 5888 | a->is_var_args != b->is_var_args || |
| 5880 | a.param_count != b.param_count) | 5889 | a->param_count != b->param_count) |
| 5881 | { | 5890 | { |
| 5882 | return false; | 5891 | return false; |
| 5883 | } | 5892 | } |
| 5884 | for (int i = 0; i < a.param_count; i += 1) { | 5893 | for (int i = 0; i < a->param_count; i += 1) { |
| 5885 | FnTypeParamInfo *a_param_info = &a.param_info[i]; | 5894 | FnTypeParamInfo *a_param_info = &a->param_info[i]; |
| 5886 | FnTypeParamInfo *b_param_info = &b.param_info[i]; | 5895 | FnTypeParamInfo *b_param_info = &b->param_info[i]; |
| 5887 | | 5896 | |
| 5888 | if (a_param_info->type != b_param_info->type) { | 5897 | if (a_param_info->type != b_param_info->type) { |
| 5889 | return false; | 5898 | return false; |