| author | |
| committer | |
| log | f12fbce0f51d58b429afd8a359aeb8a3b27a4eb0 |
| tree | fbbdda77efc779ee473d898bf34933ee67439440 |
| parent | 4816121e008aa4c28241a94253b0c4a2b7b6ba7c |
4 files changed, 69 insertions(+), 7 deletions(-)
src/all_types.hpp+4| ... | @@ -1067,6 +1067,9 @@ struct BuiltinFnEntry { | ... | @@ -1067,6 +1067,9 @@ struct BuiltinFnEntry { |
| 1067 | LLVMValueRef fn_val; | 1067 | LLVMValueRef fn_val; |
| 1068 | }; | 1068 | }; |
| 1069 | 1069 | ||
| 1070 | uint32_t fn_eval_hash(Scope*); | ||
| 1071 | bool fn_eval_eql(Scope *a, Scope *b); | ||
| 1072 | |||
| 1070 | struct CodeGen { | 1073 | struct CodeGen { |
| 1071 | LLVMModuleRef module; | 1074 | LLVMModuleRef module; |
| 1072 | ZigList<ErrorMsg*> errors; | 1075 | ZigList<ErrorMsg*> errors; |
| ... | @@ -1085,6 +1088,7 @@ struct CodeGen { | ... | @@ -1085,6 +1088,7 @@ struct CodeGen { |
| 1085 | HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table; | 1088 | HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table; |
| 1086 | HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table; | 1089 | HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table; |
| 1087 | HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; | 1090 | HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1091 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; | ||
| 1088 | 1092 | ||
| 1089 | ZigList<ImportTableEntry *> import_queue; | 1093 | ZigList<ImportTableEntry *> import_queue; |
| 1090 | size_t import_queue_index; | 1094 | size_t import_queue_index; |
src/analyze.cpp+48| ... | @@ -2693,6 +2693,54 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { | ... | @@ -2693,6 +2693,54 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { |
| 2693 | return true; | 2693 | return true; |
| 2694 | } | 2694 | } |
| 2695 | 2695 | ||
| 2696 | uint32_t fn_eval_hash(Scope* scope) { | ||
| 2697 | uint32_t result = 0; | ||
| 2698 | while (scope) { | ||
| 2699 | if (scope->id == ScopeIdVarDecl) { | ||
| 2700 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; | ||
| 2701 | result += hash_const_val(var_scope->var->type, var_scope->var->value); | ||
| 2702 | } else if (scope->id == ScopeIdFnDef) { | ||
| 2703 | ScopeFnDef *fn_scope = (ScopeFnDef *)scope; | ||
| 2704 | result += hash_ptr(fn_scope->fn_entry); | ||
| 2705 | return result; | ||
| 2706 | } else { | ||
| 2707 | zig_unreachable(); | ||
| 2708 | } | ||
| 2709 | |||
| 2710 | scope = scope->parent; | ||
| 2711 | } | ||
| 2712 | zig_unreachable(); | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | bool fn_eval_eql(Scope *a, Scope *b) { | ||
| 2716 | while (a && b) { | ||
| 2717 | if (a->id != b->id) | ||
| 2718 | return false; | ||
| 2719 | |||
| 2720 | if (a->id == ScopeIdVarDecl) { | ||
| 2721 | ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; | ||
| 2722 | ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; | ||
| 2723 | if (a_var_scope->var->type != b_var_scope->var->type) | ||
| 2724 | return false; | ||
| 2725 | if (!const_values_equal(a_var_scope->var->value, b_var_scope->var->value, a_var_scope->var->type)) | ||
| 2726 | return false; | ||
| 2727 | } else if (a->id == ScopeIdFnDef) { | ||
| 2728 | ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; | ||
| 2729 | ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; | ||
| 2730 | if (a_fn_scope->fn_entry != b_fn_scope->fn_entry) | ||
| 2731 | return false; | ||
| 2732 | |||
| 2733 | return true; | ||
| 2734 | } else { | ||
| 2735 | zig_unreachable(); | ||
| 2736 | } | ||
| 2737 | |||
| 2738 | a = a->parent; | ||
| 2739 | b = b->parent; | ||
| 2740 | } | ||
| 2741 | return false; | ||
| 2742 | } | ||
| 2743 | |||
| 2696 | bool type_has_bits(TypeTableEntry *type_entry) { | 2744 | bool type_has_bits(TypeTableEntry *type_entry) { |
| 2697 | assert(type_entry); | 2745 | assert(type_entry); |
| 2698 | assert(type_entry->id != TypeTableEntryIdInvalid); | 2746 | assert(type_entry->id != TypeTableEntryIdInvalid); |
src/codegen.cpp+1| ... | @@ -61,6 +61,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { | ... | @@ -61,6 +61,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 61 | g->fn_type_table.init(32); | 61 | g->fn_type_table.init(32); |
| 62 | g->error_table.init(16); | 62 | g->error_table.init(16); |
| 63 | g->generic_table.init(16); | 63 | g->generic_table.init(16); |
| 64 | g->memoized_fn_eval_table.init(16); | ||
| 64 | g->is_release_build = false; | 65 | g->is_release_build = false; |
| 65 | g->is_test_build = false; | 66 | g->is_test_build = false; |
| 66 | g->want_h_file = true; | 67 | g->want_h_file = true; |
src/ir.cpp+16-7| ... | @@ -6049,13 +6049,22 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -6049,13 +6049,22 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 6049 | if (return_type->id == TypeTableEntryIdInvalid) | 6049 | if (return_type->id == TypeTableEntryIdInvalid) |
| 6050 | return ira->codegen->builtin_types.entry_invalid; | 6050 | return ira->codegen->builtin_types.entry_invalid; |
| 6051 | 6051 | ||
| 6052 | // Analyze the fn body block like any other constant expression. | 6052 | IrInstruction *result; |
| 6053 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; | 6053 | |
| 6054 | IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, | 6054 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
| 6055 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, | 6055 | if (entry) { |
| 6056 | nullptr, call_instruction->base.source_node, nullptr); | 6056 | result = entry->value; |
| 6057 | if (result->type_entry->id == TypeTableEntryIdInvalid) | 6057 | } else { |
| 6058 | return ira->codegen->builtin_types.entry_invalid; | 6058 | // Analyze the fn body block like any other constant expression. |
| 6059 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; | ||
| 6060 | result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, | ||
| 6061 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, | ||
| 6062 | nullptr, call_instruction->base.source_node, nullptr); | ||
| 6063 | if (result->type_entry->id == TypeTableEntryIdInvalid) | ||
| 6064 | return ira->codegen->builtin_types.entry_invalid; | ||
| 6065 | |||
| 6066 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); | ||
| 6067 | } | ||
| 6059 | 6068 | ||
| 6060 | ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base, | 6069 | ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base, |
| 6061 | result->static_value.depends_on_compile_var); | 6070 | result->static_value.depends_on_compile_var); |