| ... | @@ -49,6 +49,7 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); | ... | @@ -49,6 +49,7 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 49 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); | 49 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 50 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); | 50 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 51 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); | 51 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); |
| | 52 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr); |
| 52 | | 53 | |
| 53 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { | 54 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 54 | assert(const_val->type->id == TypeTableEntryIdPointer); | 55 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | @@ -6292,7 +6293,26 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -6292,7 +6293,26 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6292 | } | 6293 | } |
| 6293 | } | 6294 | } |
| 6294 | | 6295 | |
| 6295 | // implicit [N]T to &const []const N | 6296 | // implicit &const [N]T to []const T |
| | 6297 | if (expected_type->id == TypeTableEntryIdStruct && |
| | 6298 | expected_type->data.structure.is_slice && |
| | 6299 | actual_type->id == TypeTableEntryIdPointer && |
| | 6300 | actual_type->data.pointer.is_const && |
| | 6301 | actual_type->data.pointer.child_type->id == TypeTableEntryIdArray) |
| | 6302 | { |
| | 6303 | TypeTableEntry *ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry; |
| | 6304 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 6305 | |
| | 6306 | TypeTableEntry *array_type = actual_type->data.pointer.child_type; |
| | 6307 | |
| | 6308 | if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| | 6309 | types_match_const_cast_only(ptr_type->data.pointer.child_type, array_type->data.array.child_type)) |
| | 6310 | { |
| | 6311 | return ImplicitCastMatchResultYes; |
| | 6312 | } |
| | 6313 | } |
| | 6314 | |
| | 6315 | // implicit [N]T to &const []const T |
| 6296 | if (expected_type->id == TypeTableEntryIdPointer && | 6316 | if (expected_type->id == TypeTableEntryIdPointer && |
| 6297 | expected_type->data.pointer.is_const && | 6317 | expected_type->data.pointer.is_const && |
| 6298 | is_slice(expected_type->data.pointer.child_type) && | 6318 | is_slice(expected_type->data.pointer.child_type) && |
| ... | @@ -6308,7 +6328,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -6308,7 +6328,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6308 | } | 6328 | } |
| 6309 | } | 6329 | } |
| 6310 | | 6330 | |
| 6311 | // implicit [N]T to ?[]const N | 6331 | // implicit [N]T to ?[]const T |
| 6312 | if (expected_type->id == TypeTableEntryIdMaybe && | 6332 | if (expected_type->id == TypeTableEntryIdMaybe && |
| 6313 | is_slice(expected_type->data.maybe.child_type) && | 6333 | is_slice(expected_type->data.maybe.child_type) && |
| 6314 | actual_type->id == TypeTableEntryIdArray) | 6334 | actual_type->id == TypeTableEntryIdArray) |
| ... | @@ -7069,12 +7089,20 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi | ... | @@ -7069,12 +7089,20 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 7069 | } | 7089 | } |
| 7070 | | 7090 | |
| 7071 | static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, | 7091 | static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, |
| 7072 | IrInstruction *array, TypeTableEntry *wanted_type) | 7092 | IrInstruction *array_arg, TypeTableEntry *wanted_type) |
| 7073 | { | 7093 | { |
| 7074 | assert(is_slice(wanted_type)); | 7094 | assert(is_slice(wanted_type)); |
| 7075 | // In this function we honor the const-ness of wanted_type, because | 7095 | // In this function we honor the const-ness of wanted_type, because |
| 7076 | // we may be casting [0]T to []const T which is perfectly valid. | 7096 | // we may be casting [0]T to []const T which is perfectly valid. |
| 7077 | | 7097 | |
| | 7098 | IrInstruction *array_ptr = nullptr; |
| | 7099 | IrInstruction *array; |
| | 7100 | if (array_arg->value.type->id == TypeTableEntryIdPointer) { |
| | 7101 | array = ir_get_deref(ira, source_instr, array_arg); |
| | 7102 | array_ptr = array_arg; |
| | 7103 | } else { |
| | 7104 | array = array_arg; |
| | 7105 | } |
| 7078 | TypeTableEntry *array_type = array->value.type; | 7106 | TypeTableEntry *array_type = array->value.type; |
| 7079 | assert(array_type->id == TypeTableEntryIdArray); | 7107 | assert(array_type->id == TypeTableEntryIdArray); |
| 7080 | | 7108 | |
| ... | @@ -7094,7 +7122,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s | ... | @@ -7094,7 +7122,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 7094 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | 7122 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); |
| 7095 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); | 7123 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); |
| 7096 | | 7124 | |
| 7097 | IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false); | 7125 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 7098 | | 7126 | |
| 7099 | IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, | 7127 | IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, |
| 7100 | source_instr->source_node, array_ptr, start, end, false); | 7128 | source_instr->source_node, array_ptr, start, end, false); |
| ... | @@ -7374,6 +7402,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7374,6 +7402,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7374 | } | 7402 | } |
| 7375 | } | 7403 | } |
| 7376 | | 7404 | |
| | 7405 | // expliict cast from &const [N]T to []const T |
| | 7406 | if (is_slice(wanted_type) && |
| | 7407 | actual_type->id == TypeTableEntryIdPointer && |
| | 7408 | actual_type->data.pointer.is_const && |
| | 7409 | actual_type->data.pointer.child_type->id == TypeTableEntryIdArray) |
| | 7410 | { |
| | 7411 | TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; |
| | 7412 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 7413 | |
| | 7414 | TypeTableEntry *array_type = actual_type->data.pointer.child_type; |
| | 7415 | |
| | 7416 | if ((ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && |
| | 7417 | types_match_const_cast_only(ptr_type->data.pointer.child_type, array_type->data.array.child_type)) |
| | 7418 | { |
| | 7419 | return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type); |
| | 7420 | } |
| | 7421 | } |
| | 7422 | |
| 7377 | // explicit cast from [N]T to &const []const N | 7423 | // explicit cast from [N]T to &const []const N |
| 7378 | if (wanted_type->id == TypeTableEntryIdPointer && | 7424 | if (wanted_type->id == TypeTableEntryIdPointer && |
| 7379 | wanted_type->data.pointer.is_const && | 7425 | wanted_type->data.pointer.is_const && |
| ... | @@ -7674,6 +7720,13 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ | ... | @@ -7674,6 +7720,13 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ |
| 7674 | zig_unreachable(); | 7720 | zig_unreachable(); |
| 7675 | } | 7721 | } |
| 7676 | | 7722 | |
| | 7723 | static IrInstruction *ir_implicit_byval_const_ref_cast(IrAnalyze *ira, IrInstruction *inst) { |
| | 7724 | if (type_is_copyable(ira->codegen, inst->value.type)) |
| | 7725 | return inst; |
| | 7726 | TypeTableEntry *const_ref_type = get_pointer_to_type(ira->codegen, inst->value.type, true); |
| | 7727 | return ir_implicit_cast(ira, inst, const_ref_type); |
| | 7728 | } |
| | 7729 | |
| 7677 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { | 7730 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { |
| 7678 | TypeTableEntry *type_entry = ptr->value.type; | 7731 | TypeTableEntry *type_entry = ptr->value.type; |
| 7679 | if (type_is_invalid(type_entry)) { | 7732 | if (type_is_invalid(type_entry)) { |
| ... | @@ -8816,7 +8869,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -8816,7 +8869,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 8816 | IrInstruction *casted_arg; | 8869 | IrInstruction *casted_arg; |
| 8817 | if (is_var_args) { | 8870 | if (is_var_args) { |
| 8818 | arg_part_of_generic_id = true; | 8871 | arg_part_of_generic_id = true; |
| 8819 | casted_arg = arg; | 8872 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); |
| 8820 | } else { | 8873 | } else { |
| 8821 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | 8874 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 8822 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); | 8875 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); |
| ... | @@ -8826,7 +8879,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -8826,7 +8879,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 8826 | bool is_var_type = (param_type->id == TypeTableEntryIdVar); | 8879 | bool is_var_type = (param_type->id == TypeTableEntryIdVar); |
| 8827 | if (is_var_type) { | 8880 | if (is_var_type) { |
| 8828 | arg_part_of_generic_id = true; | 8881 | arg_part_of_generic_id = true; |
| 8829 | casted_arg = arg; | 8882 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); |
| 8830 | } else { | 8883 | } else { |
| 8831 | casted_arg = ir_implicit_cast(ira, arg, param_type); | 8884 | casted_arg = ir_implicit_cast(ira, arg, param_type); |
| 8832 | if (type_is_invalid(casted_arg->value.type)) | 8885 | if (type_is_invalid(casted_arg->value.type)) |