| ... | @@ -790,16 +790,6 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so | ... | @@ -790,16 +790,6 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so |
| 790 | return &instruction->base; | 790 | return &instruction->base; |
| 791 | } | 791 | } |
| 792 | | 792 | |
| 793 | static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, | | |
| 794 | VariableTableEntry *var, bool is_const, bool is_volatile) | | |
| 795 | { | | |
| 796 | IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->scope, | | |
| 797 | old_instruction->source_node, var, is_const, is_volatile); | | |
| 798 | ir_link_new_instruction(new_instruction, old_instruction); | | |
| 799 | return new_instruction; | | |
| 800 | | | |
| 801 | } | | |
| 802 | | | |
| 803 | static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, | 793 | static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, |
| 804 | IrInstruction *elem_index, bool safety_check_on) | 794 | IrInstruction *elem_index, bool safety_check_on) |
| 805 | { | 795 | { |
| ... | @@ -8048,6 +8038,65 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -8048,6 +8038,65 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 8048 | return true; | 8038 | return true; |
| 8049 | } | 8039 | } |
| 8050 | | 8040 | |
| | 8041 | static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t index) { |
| | 8042 | size_t next_var_i = 0; |
| | 8043 | FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info; |
| | 8044 | for (size_t param_i = 0; param_i < index; param_i += 1) { |
| | 8045 | FnGenParamInfo *info = &gen_param_info[param_i]; |
| | 8046 | if (info->gen_index == SIZE_MAX) |
| | 8047 | continue; |
| | 8048 | |
| | 8049 | next_var_i += 1; |
| | 8050 | } |
| | 8051 | FnGenParamInfo *info = &gen_param_info[index]; |
| | 8052 | if (info->gen_index == SIZE_MAX) |
| | 8053 | return nullptr; |
| | 8054 | |
| | 8055 | return fn_entry->variable_list.at(next_var_i); |
| | 8056 | } |
| | 8057 | |
| | 8058 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| | 8059 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) |
| | 8060 | { |
| | 8061 | assert(var->value->type); |
| | 8062 | if (type_is_invalid(var->value->type)) |
| | 8063 | return ira->codegen->invalid_instruction; |
| | 8064 | |
| | 8065 | bool comptime_var_mem = ir_get_var_is_comptime(var); |
| | 8066 | |
| | 8067 | ConstExprValue *mem_slot = nullptr; |
| | 8068 | FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope); |
| | 8069 | if (var->value->special == ConstValSpecialStatic) { |
| | 8070 | mem_slot = var->value; |
| | 8071 | } else if (fn_entry) { |
| | 8072 | // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing. |
| | 8073 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) |
| | 8074 | mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| | 8075 | } |
| | 8076 | |
| | 8077 | bool is_const = (var->value->type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| | 8078 | bool is_volatile = (var->value->type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false; |
| | 8079 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| | 8080 | ConstPtrMut ptr_mut; |
| | 8081 | if (comptime_var_mem) { |
| | 8082 | ptr_mut = ConstPtrMutComptimeVar; |
| | 8083 | } else if (var->gen_is_const) { |
| | 8084 | ptr_mut = ConstPtrMutComptimeConst; |
| | 8085 | } else { |
| | 8086 | assert(!comptime_var_mem); |
| | 8087 | ptr_mut = ConstPtrMutRuntimeVar; |
| | 8088 | } |
| | 8089 | return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, |
| | 8090 | ptr_mut, is_const, is_volatile); |
| | 8091 | } else { |
| | 8092 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, |
| | 8093 | instruction->scope, instruction->source_node, var, is_const, is_volatile); |
| | 8094 | var_ptr_instruction->value.type = get_pointer_to_type(ira->codegen, var->value->type, var->src_is_const); |
| | 8095 | type_ensure_zero_bits_known(ira->codegen, var->value->type); |
| | 8096 | return var_ptr_instruction; |
| | 8097 | } |
| | 8098 | } |
| | 8099 | |
| 8051 | static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, | 8100 | static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| 8052 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, | 8101 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, |
| 8053 | IrInstruction *first_arg_ptr, bool inline_fn_call) | 8102 | IrInstruction *first_arg_ptr, bool inline_fn_call) |
| ... | @@ -8149,17 +8198,31 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -8149,17 +8198,31 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8149 | if (fn_type->data.fn.is_generic) { | 8198 | if (fn_type->data.fn.is_generic) { |
| 8150 | assert(fn_entry); | 8199 | assert(fn_entry); |
| 8151 | | 8200 | |
| 8152 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); | 8201 | // Count the arguments of the function type id we are creating |
| | 8202 | size_t new_fn_arg_count = 0; |
| | 8203 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| | 8204 | IrInstruction *arg = call_instruction->args[call_i]->other; |
| | 8205 | if (type_is_invalid(arg->value.type)) |
| | 8206 | return ira->codegen->builtin_types.entry_invalid; |
| | 8207 | |
| | 8208 | if (arg->value.type->id == TypeTableEntryIdArgTuple) { |
| | 8209 | new_fn_arg_count += arg->value.data.x_arg_tuple.end_index - arg->value.data.x_arg_tuple.start_index; |
| | 8210 | } else { |
| | 8211 | new_fn_arg_count += 1; |
| | 8212 | } |
| | 8213 | } |
| | 8214 | |
| | 8215 | IrInstruction **casted_args = allocate<IrInstruction *>(new_fn_arg_count); |
| 8153 | | 8216 | |
| 8154 | // Fork a scope of the function with known values for the parameters. | 8217 | // Fork a scope of the function with known values for the parameters. |
| 8155 | Scope *parent_scope = fn_entry->fndef_scope->base.parent; | 8218 | Scope *parent_scope = fn_entry->fndef_scope->base.parent; |
| 8156 | FnTableEntry *impl_fn = create_fn(fn_proto_node); | 8219 | FnTableEntry *impl_fn = create_fn(fn_proto_node); |
| 8157 | impl_fn->param_source_nodes = allocate<AstNode *>(call_param_count); | 8220 | impl_fn->param_source_nodes = allocate<AstNode *>(new_fn_arg_count); |
| 8158 | buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); | 8221 | buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); |
| 8159 | impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn); | 8222 | impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn); |
| 8160 | impl_fn->child_scope = &impl_fn->fndef_scope->base; | 8223 | impl_fn->child_scope = &impl_fn->fndef_scope->base; |
| 8161 | FnTypeId inst_fn_type_id = {0}; | 8224 | FnTypeId inst_fn_type_id = {0}; |
| 8162 | init_fn_type_id(&inst_fn_type_id, fn_proto_node, call_param_count); | 8225 | init_fn_type_id(&inst_fn_type_id, fn_proto_node, new_fn_arg_count); |
| 8163 | inst_fn_type_id.param_count = 0; | 8226 | inst_fn_type_id.param_count = 0; |
| 8164 | inst_fn_type_id.is_var_args = false; | 8227 | inst_fn_type_id.is_var_args = false; |
| 8165 | | 8228 | |
| ... | @@ -8168,7 +8231,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -8168,7 +8231,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8168 | GenericFnTypeId *generic_id = allocate<GenericFnTypeId>(1); | 8231 | GenericFnTypeId *generic_id = allocate<GenericFnTypeId>(1); |
| 8169 | generic_id->fn_entry = fn_entry; | 8232 | generic_id->fn_entry = fn_entry; |
| 8170 | generic_id->param_count = 0; | 8233 | generic_id->param_count = 0; |
| 8171 | generic_id->params = allocate<ConstExprValue>(call_param_count); | 8234 | generic_id->params = allocate<ConstExprValue>(new_fn_arg_count); |
| 8172 | size_t next_proto_i = 0; | 8235 | size_t next_proto_i = 0; |
| 8173 | | 8236 | |
| 8174 | if (first_arg_ptr) { | 8237 | if (first_arg_ptr) { |
| ... | @@ -8191,6 +8254,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -8191,6 +8254,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8191 | | 8254 | |
| 8192 | bool found_first_var_arg = false; | 8255 | bool found_first_var_arg = false; |
| 8193 | size_t first_var_arg = inst_fn_type_id.param_count; | 8256 | size_t first_var_arg = inst_fn_type_id.param_count; |
| | 8257 | |
| | 8258 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); |
| | 8259 | assert(parent_fn_entry); |
| 8194 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { | 8260 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| 8195 | IrInstruction *arg = call_instruction->args[call_i]->other; | 8261 | IrInstruction *arg = call_instruction->args[call_i]->other; |
| 8196 | if (type_is_invalid(arg->value.type)) | 8262 | if (type_is_invalid(arg->value.type)) |
| ... | @@ -8204,7 +8270,27 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -8204,7 +8270,27 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8204 | found_first_var_arg = true; | 8270 | found_first_var_arg = true; |
| 8205 | } | 8271 | } |
| 8206 | | 8272 | |
| 8207 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, | 8273 | if (arg->value.type->id == TypeTableEntryIdArgTuple) { |
| | 8274 | for (size_t arg_tuple_i = arg->value.data.x_arg_tuple.start_index; |
| | 8275 | arg_tuple_i < arg->value.data.x_arg_tuple.end_index; arg_tuple_i += 1) |
| | 8276 | { |
| | 8277 | VariableTableEntry *arg_var = get_fn_var_by_index(parent_fn_entry, arg_tuple_i); |
| | 8278 | assert(arg_var != nullptr); |
| | 8279 | IrInstruction *arg_var_ptr_inst = ir_get_var_ptr(ira, arg, arg_var, true, false); |
| | 8280 | if (type_is_invalid(arg_var_ptr_inst->value.type)) |
| | 8281 | return ira->codegen->builtin_types.entry_invalid; |
| | 8282 | |
| | 8283 | IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst); |
| | 8284 | if (type_is_invalid(arg_tuple_arg->value.type)) |
| | 8285 | return ira->codegen->builtin_types.entry_invalid; |
| | 8286 | |
| | 8287 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg_tuple_arg, &impl_fn->child_scope, |
| | 8288 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) |
| | 8289 | { |
| | 8290 | return ira->codegen->builtin_types.entry_invalid; |
| | 8291 | } |
| | 8292 | } |
| | 8293 | } else if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, |
| 8208 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) | 8294 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) |
| 8209 | { | 8295 | { |
| 8210 | return ira->codegen->builtin_types.entry_invalid; | 8296 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -8769,40 +8855,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP | ... | @@ -8769,40 +8855,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 8769 | static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | 8855 | static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 8770 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) | 8856 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) |
| 8771 | { | 8857 | { |
| 8772 | assert(var->value->type); | 8858 | IrInstruction *result = ir_get_var_ptr(ira, instruction, var, is_const_ptr, is_volatile_ptr); |
| 8773 | if (type_is_invalid(var->value->type)) | 8859 | ir_link_new_instruction(result, instruction); |
| 8774 | return var->value->type; | 8860 | return result->value.type; |
| 8775 | | | |
| 8776 | bool comptime_var_mem = ir_get_var_is_comptime(var); | | |
| 8777 | | | |
| 8778 | ConstExprValue *mem_slot = nullptr; | | |
| 8779 | FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope); | | |
| 8780 | if (var->value->special == ConstValSpecialStatic) { | | |
| 8781 | mem_slot = var->value; | | |
| 8782 | } else if (fn_entry) { | | |
| 8783 | // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing. | | |
| 8784 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) | | |
| 8785 | mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | | |
| 8786 | } | | |
| 8787 | | | |
| 8788 | bool is_const = (var->value->type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; | | |
| 8789 | bool is_volatile = (var->value->type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false; | | |
| 8790 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { | | |
| 8791 | ConstPtrMut ptr_mut; | | |
| 8792 | if (comptime_var_mem) { | | |
| 8793 | ptr_mut = ConstPtrMutComptimeVar; | | |
| 8794 | } else if (var->gen_is_const) { | | |
| 8795 | ptr_mut = ConstPtrMutComptimeConst; | | |
| 8796 | } else { | | |
| 8797 | assert(!comptime_var_mem); | | |
| 8798 | ptr_mut = ConstPtrMutRuntimeVar; | | |
| 8799 | } | | |
| 8800 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value->type, ptr_mut, is_const, is_volatile); | | |
| 8801 | } else { | | |
| 8802 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, is_const, is_volatile); | | |
| 8803 | type_ensure_zero_bits_known(ira->codegen, var->value->type); | | |
| 8804 | return get_pointer_to_type(ira->codegen, var->value->type, var->src_is_const); | | |
| 8805 | } | | |
| 8806 | } | 8861 | } |
| 8807 | | 8862 | |
| 8808 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { | 8863 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { |
| ... | @@ -8811,23 +8866,6 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -8811,23 +8866,6 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 8811 | var_ptr_instruction->is_volatile); | 8866 | var_ptr_instruction->is_volatile); |
| 8812 | } | 8867 | } |
| 8813 | | 8868 | |
| 8814 | static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t index) { | | |
| 8815 | size_t next_var_i = 0; | | |
| 8816 | FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info; | | |
| 8817 | for (size_t param_i = 0; param_i < index; param_i += 1) { | | |
| 8818 | FnGenParamInfo *info = &gen_param_info[param_i]; | | |
| 8819 | if (info->gen_index == SIZE_MAX) | | |
| 8820 | continue; | | |
| 8821 | | | |
| 8822 | next_var_i += 1; | | |
| 8823 | } | | |
| 8824 | FnGenParamInfo *info = &gen_param_info[index]; | | |
| 8825 | if (info->gen_index == SIZE_MAX) | | |
| 8826 | return nullptr; | | |
| 8827 | | | |
| 8828 | return fn_entry->variable_list.at(next_var_i); | | |
| 8829 | } | | |
| 8830 | | | |
| 8831 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { | 8869 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| 8832 | IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other; | 8870 | IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other; |
| 8833 | if (type_is_invalid(array_ptr->value.type)) | 8871 | if (type_is_invalid(array_ptr->value.type)) |