| ... | ... | @@ -790,16 +790,6 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so |
| 790 | 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 | 793 | static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, |
| 804 | 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 | 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 | 8100 | static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| 8052 | 8101 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, |
| 8053 | 8102 | IrInstruction *first_arg_ptr, bool inline_fn_call) |
| ... | ... | @@ -8149,17 +8198,31 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8149 | 8198 | if (fn_type->data.fn.is_generic) { |
| 8150 | 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 | 8217 | // Fork a scope of the function with known values for the parameters. |
| 8155 | 8218 | Scope *parent_scope = fn_entry->fndef_scope->base.parent; |
| 8156 | 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 | 8221 | buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); |
| 8159 | 8222 | impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn); |
| 8160 | 8223 | impl_fn->child_scope = &impl_fn->fndef_scope->base; |
| 8161 | 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 | 8226 | inst_fn_type_id.param_count = 0; |
| 8164 | 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 | 8231 | GenericFnTypeId *generic_id = allocate<GenericFnTypeId>(1); |
| 8169 | 8232 | generic_id->fn_entry = fn_entry; |
| 8170 | 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 | 8235 | size_t next_proto_i = 0; |
| 8173 | 8236 | |
| 8174 | 8237 | if (first_arg_ptr) { |
| ... | ... | @@ -8191,6 +8254,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8191 | 8254 | |
| 8192 | 8255 | bool found_first_var_arg = false; |
| 8193 | 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 | 8260 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| 8195 | 8261 | IrInstruction *arg = call_instruction->args[call_i]->other; |
| 8196 | 8262 | if (type_is_invalid(arg->value.type)) |
| ... | ... | @@ -8204,7 +8270,27 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 8204 | 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 | 8294 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) |
| 8209 | 8295 | { |
| 8210 | 8296 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -8769,40 +8855,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 8769 | 8855 | static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 8770 | 8856 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) |
| 8771 | 8857 | { |
| 8772 | | assert(var->value->type); |
| 8773 | | if (type_is_invalid(var->value->type)) |
| 8774 | | return var->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 | | } |
| 8858 | IrInstruction *result = ir_get_var_ptr(ira, instruction, var, is_const_ptr, is_volatile_ptr); |
| 8859 | ir_link_new_instruction(result, instruction); |
| 8860 | return result->value.type; |
| 8806 | 8861 | } |
| 8807 | 8862 | |
| 8808 | 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 | 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 | 8869 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| 8832 | 8870 | IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other; |
| 8833 | 8871 | if (type_is_invalid(array_ptr->value.type)) |