authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-18 00:09:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-18 00:09:43-05:00
log85b6d1463792a321832ff79b81d5ba51c324d7fa
tree1a9d6779ce2bcda6d18c4f724b19dbcddc502ff9
parente73faf9a9efad4c3a8deb1ae8a21302f4366c0ac

IR: support var type args and fix phi peer type resolution


3 files changed, 259 insertions(+), 189 deletions(-)

src/analyze.cpp+91-50
...@@ -723,6 +723,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -723,6 +723,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
723 fn_type->data.fn.calling_convention = LLVMFastCallConv;723 fn_type->data.fn.calling_convention = LLVMFastCallConv;
724 }724 }
725725
726 bool skip_debug_info = false;
727
726 // populate the name of the type728 // populate the name of the type
727 buf_resize(&fn_type->name, 0);729 buf_resize(&fn_type->name, 0);
728 const char *extern_str = fn_type_id->is_extern ? "extern " : "";730 const char *extern_str = fn_type_id->is_extern ? "extern " : "";
...@@ -736,6 +738,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -736,6 +738,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
736 const char *comma = (i == 0) ? "" : ", ";738 const char *comma = (i == 0) ? "" : ", ";
737 const char *noalias_str = param_info->is_noalias ? "noalias " : "";739 const char *noalias_str = param_info->is_noalias ? "noalias " : "";
738 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));740 buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(&param_type->name));
741
742 skip_debug_info = skip_debug_info || !param_type->di_type;
739 }743 }
740744
741 if (fn_type_id->is_var_args) {745 if (fn_type_id->is_var_args) {
...@@ -746,66 +750,69 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -746,66 +750,69 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
746 if (fn_type_id->return_type->id != TypeTableEntryIdVoid) {750 if (fn_type_id->return_type->id != TypeTableEntryIdVoid) {
747 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));751 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));
748 }752 }
753 skip_debug_info = skip_debug_info || !fn_type_id->return_type->di_type;
749754
750 // next, loop over the parameters again and compute debug information755 // next, loop over the parameters again and compute debug information
751 // and codegen information756 // and codegen information
752 bool first_arg_return = !fn_type_id->is_extern && handle_is_ptr(fn_type_id->return_type);757 if (!skip_debug_info) {
753 // +1 for maybe making the first argument the return value758 bool first_arg_return = !fn_type_id->is_extern && handle_is_ptr(fn_type_id->return_type);
754 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);759 // +1 for maybe making the first argument the return value
755 // +1 because 0 is the return type and +1 for maybe making first arg ret val760 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);
756 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(2 + fn_type_id->param_count);761 // +1 because 0 is the return type and +1 for maybe making first arg ret val
757 param_di_types[0] = fn_type_id->return_type->di_type;762 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(2 + fn_type_id->param_count);
758 size_t gen_param_index = 0;763 param_di_types[0] = fn_type_id->return_type->di_type;
759 TypeTableEntry *gen_return_type;764 size_t gen_param_index = 0;
760 if (!type_has_bits(fn_type_id->return_type)) {765 TypeTableEntry *gen_return_type;
761 gen_return_type = g->builtin_types.entry_void;766 if (!type_has_bits(fn_type_id->return_type)) {
762 } else if (first_arg_return) {767 gen_return_type = g->builtin_types.entry_void;
763 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);768 } else if (first_arg_return) {
764 gen_param_types[gen_param_index] = gen_type->type_ref;769 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
765 gen_param_index += 1;
766 // after the gen_param_index += 1 because 0 is the return type
767 param_di_types[gen_param_index] = gen_type->di_type;
768 gen_return_type = g->builtin_types.entry_void;
769 } else {
770 gen_return_type = fn_type_id->return_type;
771 }
772 fn_type->data.fn.gen_return_type = gen_return_type;
773
774 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
775 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
776 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
777 TypeTableEntry *type_entry = src_param_info->type;
778 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];
779
780 gen_param_info->src_index = i;
781 gen_param_info->gen_index = SIZE_MAX;
782
783 assert(type_is_complete(type_entry));
784 if (type_has_bits(type_entry)) {
785 TypeTableEntry *gen_type;
786 if (handle_is_ptr(type_entry)) {
787 gen_type = get_pointer_to_type(g, type_entry, true);
788 gen_param_info->is_byval = true;
789 } else {
790 gen_type = type_entry;
791 }
792 gen_param_types[gen_param_index] = gen_type->type_ref;770 gen_param_types[gen_param_index] = gen_type->type_ref;
793 gen_param_info->gen_index = gen_param_index;
794 gen_param_info->type = gen_type;
795
796 gen_param_index += 1;771 gen_param_index += 1;
797
798 // after the gen_param_index += 1 because 0 is the return type772 // after the gen_param_index += 1 because 0 is the return type
799 param_di_types[gen_param_index] = gen_type->di_type;773 param_di_types[gen_param_index] = gen_type->di_type;
774 gen_return_type = g->builtin_types.entry_void;
775 } else {
776 gen_return_type = fn_type_id->return_type;
800 }777 }
801 }778 fn_type->data.fn.gen_return_type = gen_return_type;
779
780 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
781 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
782 FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
783 TypeTableEntry *type_entry = src_param_info->type;
784 FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i];
785
786 gen_param_info->src_index = i;
787 gen_param_info->gen_index = SIZE_MAX;
788
789 assert(type_is_complete(type_entry));
790 if (type_has_bits(type_entry)) {
791 TypeTableEntry *gen_type;
792 if (handle_is_ptr(type_entry)) {
793 gen_type = get_pointer_to_type(g, type_entry, true);
794 gen_param_info->is_byval = true;
795 } else {
796 gen_type = type_entry;
797 }
798 gen_param_types[gen_param_index] = gen_type->type_ref;
799 gen_param_info->gen_index = gen_param_index;
800 gen_param_info->type = gen_type;
801
802 gen_param_index += 1;
802803
803 fn_type->data.fn.gen_param_count = gen_param_index;804 // after the gen_param_index += 1 because 0 is the return type
805 param_di_types[gen_param_index] = gen_type->di_type;
806 }
807 }
804808
805 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,809 fn_type->data.fn.gen_param_count = gen_param_index;
806 gen_param_types, gen_param_index, fn_type_id->is_var_args);810
807 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);811 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
808 fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types, gen_param_index + 1, 0);812 gen_param_types, gen_param_index, fn_type_id->is_var_args);
813 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
814 fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types, gen_param_index + 1, 0);
815 }
809816
810 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);817 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
811818
...@@ -2765,6 +2772,40 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)...@@ -2765,6 +2772,40 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
2765 zig_unreachable();2772 zig_unreachable();
2766}2773}
27672774
2775bool type_requires_comptime(TypeTableEntry *type_entry) {
2776 switch (type_entry->id) {
2777 case TypeTableEntryIdInvalid:
2778 case TypeTableEntryIdUnreachable:
2779 case TypeTableEntryIdVar:
2780 zig_unreachable();
2781 case TypeTableEntryIdNumLitFloat:
2782 case TypeTableEntryIdNumLitInt:
2783 case TypeTableEntryIdUndefLit:
2784 case TypeTableEntryIdNullLit:
2785 case TypeTableEntryIdMetaType:
2786 case TypeTableEntryIdVoid:
2787 case TypeTableEntryIdNamespace:
2788 case TypeTableEntryIdBlock:
2789 case TypeTableEntryIdBoundFn:
2790 return true;
2791 case TypeTableEntryIdArray:
2792 case TypeTableEntryIdStruct:
2793 case TypeTableEntryIdUnion:
2794 case TypeTableEntryIdMaybe:
2795 case TypeTableEntryIdErrorUnion:
2796 case TypeTableEntryIdTypeDecl:
2797 case TypeTableEntryIdEnum:
2798 case TypeTableEntryIdPureError:
2799 case TypeTableEntryIdFn:
2800 case TypeTableEntryIdBool:
2801 case TypeTableEntryIdInt:
2802 case TypeTableEntryIdFloat:
2803 case TypeTableEntryIdPointer:
2804 return false;
2805 }
2806 zig_unreachable();
2807}
2808
2768uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {2809uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
2769 TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);2810 TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);
2770 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);2811 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
src/analyze.hpp+1
...@@ -75,6 +75,7 @@ FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage);...@@ -75,6 +75,7 @@ FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage);
75void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node);75void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node);
76AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);76AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);
77FnTableEntry *scope_get_fn_if_root(Scope *scope);77FnTableEntry *scope_get_fn_if_root(Scope *scope);
78bool type_requires_comptime(TypeTableEntry *type_entry);
7879
79ScopeBlock *create_block_scope(AstNode *node, Scope *parent);80ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
80ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);81ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
src/ir.cpp+167-139
...@@ -2307,6 +2307,12 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode...@@ -2307,6 +2307,12 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode
2307 return ir_build_const_null(irb, scope, node);2307 return ir_build_const_null(irb, scope, node);
2308}2308}
23092309
2310static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
2311 assert(node->type == NodeTypeVarLiteral);
2312
2313 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var);
2314}
2315
2310static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld,2316static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld,
2311 LValPurpose lval, Scope *scope)2317 LValPurpose lval, Scope *scope)
2312{2318{
...@@ -3927,6 +3933,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -3927,6 +3933,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
3927 return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval);3933 return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval);
3928 case NodeTypeNullLiteral:3934 case NodeTypeNullLiteral:
3929 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);3935 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
3936 case NodeTypeVarLiteral:
3937 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
3930 case NodeTypeIfVarExpr:3938 case NodeTypeIfVarExpr:
3931 return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);3939 return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);
3932 case NodeTypeSwitchExpr:3940 case NodeTypeSwitchExpr:
...@@ -3949,8 +3957,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -3949,8 +3957,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
3949 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);3957 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
3950 case NodeTypeUnwrapErrorExpr:3958 case NodeTypeUnwrapErrorExpr:
3951 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);3959 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);
3952 case NodeTypeZeroesLiteral:
3953 case NodeTypeVarLiteral:
3954 case NodeTypeFnProto:3960 case NodeTypeFnProto:
3955 case NodeTypeFnDef:3961 case NodeTypeFnDef:
3956 case NodeTypeFnDecl:3962 case NodeTypeFnDecl:
...@@ -3959,6 +3965,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -3959,6 +3965,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
3959 case NodeTypeErrorValueDecl:3965 case NodeTypeErrorValueDecl:
3960 case NodeTypeTypeDecl:3966 case NodeTypeTypeDecl:
3961 zig_panic("TODO more IR gen for node types");3967 zig_panic("TODO more IR gen for node types");
3968 case NodeTypeZeroesLiteral:
3969 zig_panic("TODO zeroes is deprecated");
3962 }3970 }
3963 zig_unreachable();3971 zig_unreachable();
3964}3972}
...@@ -4065,17 +4073,18 @@ static IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -4065,17 +4073,18 @@ static IrInstruction *ir_exec_const_result(IrExecutable *exec) {
4065 return nullptr;4073 return nullptr;
40664074
4067 IrBasicBlock *bb = exec->basic_block_list.at(0);4075 IrBasicBlock *bb = exec->basic_block_list.at(0);
4068 if (bb->instruction_list.length != 1)4076 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
4069 return nullptr;4077 IrInstruction *instruction = bb->instruction_list.at(i);
40704078 if (instruction->id == IrInstructionIdReturn) {
4071 IrInstruction *only_inst = bb->instruction_list.at(0);4079 IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction;
4072 if (only_inst->id != IrInstructionIdReturn)4080 IrInstruction *value = ret_inst->value;
4073 return nullptr;4081 assert(value->static_value.special != ConstValSpecialRuntime);
40744082 return value;
4075 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;4083 } else if (ir_has_side_effects(instruction)) {
4076 IrInstruction *value = ret_inst->value;4084 return nullptr;
4077 assert(value->static_value.special != ConstValSpecialRuntime);4085 }
4078 return value;4086 }
4087 return nullptr;
4079}4088}
40804089
4081static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {4090static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
...@@ -4123,9 +4132,109 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -4123,9 +4132,109 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
4123 return false;4132 return false;
4124}4133}
41254134
4126static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_node,4135enum ImplicitCastMatchResult {
4127 IrInstruction **instructions, size_t instruction_count)4136 ImplicitCastMatchResultNo,
4137 ImplicitCastMatchResultYes,
4138 ImplicitCastMatchResultReportedError,
4139};
4140
4141static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, TypeTableEntry *expected_type,
4142 TypeTableEntry *actual_type, IrInstruction *value)
4128{4143{
4144 if (types_match_const_cast_only(expected_type, actual_type)) {
4145 return ImplicitCastMatchResultYes;
4146 }
4147
4148 // implicit conversion from anything to var
4149 if (expected_type->id == TypeTableEntryIdVar) {
4150 return ImplicitCastMatchResultYes;
4151 }
4152
4153 // implicit conversion from non maybe type to maybe type
4154 if (expected_type->id == TypeTableEntryIdMaybe &&
4155 ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value))
4156 {
4157 return ImplicitCastMatchResultYes;
4158 }
4159
4160 // implicit conversion from null literal to maybe type
4161 if (expected_type->id == TypeTableEntryIdMaybe &&
4162 actual_type->id == TypeTableEntryIdNullLit)
4163 {
4164 return ImplicitCastMatchResultYes;
4165 }
4166
4167 // implicit conversion from error child type to error type
4168 if (expected_type->id == TypeTableEntryIdErrorUnion &&
4169 ir_types_match_with_implicit_cast(ira, expected_type->data.error.child_type, actual_type, value))
4170 {
4171 return ImplicitCastMatchResultYes;
4172 }
4173
4174 // implicit conversion from pure error to error union type
4175 if (expected_type->id == TypeTableEntryIdErrorUnion &&
4176 actual_type->id == TypeTableEntryIdPureError)
4177 {
4178 return ImplicitCastMatchResultYes;
4179 }
4180
4181 // implicit widening conversion
4182 if (expected_type->id == TypeTableEntryIdInt &&
4183 actual_type->id == TypeTableEntryIdInt &&
4184 expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
4185 expected_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
4186 {
4187 return ImplicitCastMatchResultYes;
4188 }
4189
4190 // small enough unsigned ints can get casted to large enough signed ints
4191 if (expected_type->id == TypeTableEntryIdInt && expected_type->data.integral.is_signed &&
4192 actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
4193 expected_type->data.integral.bit_count > actual_type->data.integral.bit_count)
4194 {
4195 return ImplicitCastMatchResultYes;
4196 }
4197
4198 // implicit float widening conversion
4199 if (expected_type->id == TypeTableEntryIdFloat &&
4200 actual_type->id == TypeTableEntryIdFloat &&
4201 expected_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
4202 {
4203 return ImplicitCastMatchResultYes;
4204 }
4205
4206 // implicit array to slice conversion
4207 if (expected_type->id == TypeTableEntryIdStruct &&
4208 expected_type->data.structure.is_slice &&
4209 actual_type->id == TypeTableEntryIdArray &&
4210 types_match_const_cast_only(
4211 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
4212 actual_type->data.array.child_type))
4213 {
4214 return ImplicitCastMatchResultYes;
4215 }
4216
4217 // implicit number literal to typed number
4218 if ((actual_type->id == TypeTableEntryIdNumLitFloat ||
4219 actual_type->id == TypeTableEntryIdNumLitInt))
4220 {
4221 if (ir_num_lit_fits_in_other_type(ira, value, expected_type)) {
4222 return ImplicitCastMatchResultYes;
4223 } else {
4224 return ImplicitCastMatchResultReportedError;
4225 }
4226 }
4227
4228 // implicit undefined literal to anything
4229 if (actual_type->id == TypeTableEntryIdUndefLit) {
4230 return ImplicitCastMatchResultYes;
4231 }
4232
4233
4234 return ImplicitCastMatchResultNo;
4235}
4236
4237static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
4129 assert(instruction_count >= 1);4238 assert(instruction_count >= 1);
4130 IrInstruction *prev_inst = instructions[0];4239 IrInstruction *prev_inst = instructions[0];
4131 if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) {4240 if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) {
...@@ -4241,109 +4350,6 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_n...@@ -4241,109 +4350,6 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_n
4241 }4350 }
4242}4351}
42434352
4244enum ImplicitCastMatchResult {
4245 ImplicitCastMatchResultNo,
4246 ImplicitCastMatchResultYes,
4247 ImplicitCastMatchResultReportedError,
4248};
4249
4250static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, TypeTableEntry *expected_type,
4251 TypeTableEntry *actual_type, IrInstruction *value)
4252{
4253 if (types_match_const_cast_only(expected_type, actual_type)) {
4254 return ImplicitCastMatchResultYes;
4255 }
4256
4257 // implicit conversion from non maybe type to maybe type
4258 if (expected_type->id == TypeTableEntryIdMaybe &&
4259 ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value))
4260 {
4261 return ImplicitCastMatchResultYes;
4262 }
4263
4264 // implicit conversion from null literal to maybe type
4265 if (expected_type->id == TypeTableEntryIdMaybe &&
4266 actual_type->id == TypeTableEntryIdNullLit)
4267 {
4268 return ImplicitCastMatchResultYes;
4269 }
4270
4271 // implicit conversion from error child type to error type
4272 if (expected_type->id == TypeTableEntryIdErrorUnion &&
4273 ir_types_match_with_implicit_cast(ira, expected_type->data.error.child_type, actual_type, value))
4274 {
4275 return ImplicitCastMatchResultYes;
4276 }
4277
4278 // implicit conversion from pure error to error union type
4279 if (expected_type->id == TypeTableEntryIdErrorUnion &&
4280 actual_type->id == TypeTableEntryIdPureError)
4281 {
4282 return ImplicitCastMatchResultYes;
4283 }
4284
4285 // implicit widening conversion
4286 if (expected_type->id == TypeTableEntryIdInt &&
4287 actual_type->id == TypeTableEntryIdInt &&
4288 expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
4289 expected_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
4290 {
4291 return ImplicitCastMatchResultYes;
4292 }
4293
4294 // small enough unsigned ints can get casted to large enough signed ints
4295 if (expected_type->id == TypeTableEntryIdInt && expected_type->data.integral.is_signed &&
4296 actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
4297 expected_type->data.integral.bit_count > actual_type->data.integral.bit_count)
4298 {
4299 return ImplicitCastMatchResultYes;
4300 }
4301
4302 // implicit float widening conversion
4303 if (expected_type->id == TypeTableEntryIdFloat &&
4304 actual_type->id == TypeTableEntryIdFloat &&
4305 expected_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
4306 {
4307 return ImplicitCastMatchResultYes;
4308 }
4309
4310 // implicit array to slice conversion
4311 if (expected_type->id == TypeTableEntryIdStruct &&
4312 expected_type->data.structure.is_slice &&
4313 actual_type->id == TypeTableEntryIdArray &&
4314 types_match_const_cast_only(
4315 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
4316 actual_type->data.array.child_type))
4317 {
4318 return ImplicitCastMatchResultYes;
4319 }
4320
4321 // implicit number literal to typed number
4322 if ((actual_type->id == TypeTableEntryIdNumLitFloat ||
4323 actual_type->id == TypeTableEntryIdNumLitInt))
4324 {
4325 if (ir_num_lit_fits_in_other_type(ira, value, expected_type)) {
4326 return ImplicitCastMatchResultYes;
4327 } else {
4328 return ImplicitCastMatchResultReportedError;
4329 }
4330 }
4331
4332 // implicit undefined literal to anything
4333 if (actual_type->id == TypeTableEntryIdUndefLit) {
4334 return ImplicitCastMatchResultYes;
4335 }
4336
4337
4338 return ImplicitCastMatchResultNo;
4339}
4340
4341static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node,
4342 IrInstruction **instructions, size_t instruction_count)
4343{
4344 return ir_determine_peer_types(ira, source_node, instructions, instruction_count);
4345}
4346
4347static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *type_entry) {4353static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *type_entry) {
4348 if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {4354 if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {
4349 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);4355 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
...@@ -4746,6 +4752,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -4746,6 +4752,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
4746 return ira->codegen->invalid_instruction;4752 return ira->codegen->invalid_instruction;
4747 }4753 }
47484754
4755 if (wanted_type->id == TypeTableEntryIdVar)
4756 return value;
4757
4749 // explicit match or non-const to const4758 // explicit match or non-const to const
4750 if (types_match_const_cast_only(wanted_type, actual_type)) {4759 if (types_match_const_cast_only(wanted_type, actual_type)) {
4751 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);4760 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
...@@ -5833,7 +5842,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node...@@ -5833,7 +5842,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
58335842
5834 Buf *param_name = param_decl_node->data.param_decl.name;5843 Buf *param_name = param_decl_node->data.param_decl.name;
5835 VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,5844 VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
5836 *exec_scope, param_name, param_type, true, first_arg_val);5845 *exec_scope, param_name, casted_arg->type_entry, true, first_arg_val);
5837 *exec_scope = var->child_scope;5846 *exec_scope = var->child_scope;
5838 *next_proto_i += 1;5847 *next_proto_i += 1;
58395848
...@@ -5852,38 +5861,49 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -5852,38 +5861,49 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
5852 if (param_type->id == TypeTableEntryIdInvalid)5861 if (param_type->id == TypeTableEntryIdInvalid)
5853 return false;5862 return false;
58545863
5855 bool is_var_type = (param_type->id == TypeTableEntryIdVar);5864 IrInstruction *casted_arg = ir_implicit_cast(ira, arg, param_type);
5856 IrInstruction *casted_arg;5865 if (casted_arg->type_entry->id == TypeTableEntryIdInvalid)
5857 if (is_var_type) {5866 return false;
5858 casted_arg = arg;
5859 } else {
5860 casted_arg = ir_implicit_cast(ira, arg, param_type);
5861 if (casted_arg->type_entry->id == TypeTableEntryIdInvalid)
5862 return false;
5863 }
58645867
5865 bool inline_arg = param_decl_node->data.param_decl.is_inline;5868 bool inline_arg = param_decl_node->data.param_decl.is_inline;
5866 if (inline_arg || is_var_type) {5869 bool is_var_type = (param_type->id == TypeTableEntryIdVar);
5867 ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad);5870
5871 ConstExprValue *arg_val;
5872
5873 if (inline_arg) {
5874 arg_val = ir_resolve_const(ira, casted_arg, UndefBad);
5868 if (!arg_val)5875 if (!arg_val)
5869 return false;5876 return false;
5870
5871 Buf *param_name = param_decl_node->data.param_decl.name;
5872 VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
5873 *child_scope, param_name, param_type, true, arg_val);
5874 *child_scope = var->child_scope;
5875 // This generic function instance could be called with anything, so when this variable is read it5877 // This generic function instance could be called with anything, so when this variable is read it
5876 // needs to know that it depends on compile time variable data.5878 // needs to know that it depends on compile time variable data.
5877 var->value->depends_on_compile_var = true;5879 arg_val->depends_on_compile_var = true;
5880 } else {
5881 arg_val = nullptr;
5882 }
5883
5884 Buf *param_name = param_decl_node->data.param_decl.name;
5885 VariableTableEntry *var = add_variable(ira->codegen, param_decl_node,
5886 *child_scope, param_name, casted_arg->type_entry, true, arg_val);
5887 *child_scope = var->child_scope;
58785888
5889 if (inline_arg || is_var_type) {
5879 GenericParamValue *generic_param = &generic_id->params[generic_id->param_count];5890 GenericParamValue *generic_param = &generic_id->params[generic_id->param_count];
5880 generic_param->type = casted_arg->type_entry;5891 generic_param->type = casted_arg->type_entry;
5881 generic_param->value = arg_val;5892 generic_param->value = arg_val;
5882 generic_id->param_count += 1;5893 generic_id->param_count += 1;
5883 } else {5894 }
5895 if (!inline_arg) {
5896 if (type_requires_comptime(var->type)) {
5897 ir_add_error(ira, arg,
5898 buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&var->type->name)));
5899 return false;
5900 }
5901
5902 var->shadowable = true;
5903
5884 casted_args[fn_type_id->param_count] = casted_arg;5904 casted_args[fn_type_id->param_count] = casted_arg;
5885 FnTypeParamInfo *param_info = &fn_type_id->param_info[fn_type_id->param_count];5905 FnTypeParamInfo *param_info = &fn_type_id->param_info[fn_type_id->param_count];
5886 param_info->type = param_type;5906 param_info->type = casted_arg->type_entry;
5887 param_info->is_noalias = param_decl_node->data.param_decl.is_noalias;5907 param_info->is_noalias = param_decl_node->data.param_decl.is_noalias;
5888 impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node;5908 impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node;
5889 fn_type_id->param_count += 1;5909 fn_type_id->param_count += 1;
...@@ -6475,12 +6495,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -6475,12 +6495,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
6475 return ira->codegen->builtin_types.entry_invalid;6495 return ira->codegen->builtin_types.entry_invalid;
6476 }6496 }
64776497
6478 // cast all literal values to the resolved type6498 // cast all values to the resolved type. however we can't put cast instructions in front of the phi instruction.
6499 // so we go back and insert the casts as the last instruction in the corresponding predecessor blocks, and
6500 // then make sure the branch instruction is preserved.
6501 IrBasicBlock *cur_bb = ira->new_irb.current_basic_block;
6479 for (size_t i = 0; i < new_incoming_values.length; i += 1) {6502 for (size_t i = 0; i < new_incoming_values.length; i += 1) {
6480 IrInstruction *new_value = new_incoming_values.at(i);6503 IrInstruction *new_value = new_incoming_values.at(i);
6504 IrBasicBlock *predecessor = new_incoming_blocks.at(i);
6505 IrInstruction *branch_instruction = predecessor->instruction_list.pop();
6506 ir_set_cursor_at_end(&ira->new_irb, predecessor);
6481 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);6507 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
6482 new_incoming_values.items[i] = casted_value;6508 new_incoming_values.items[i] = casted_value;
6509 predecessor->instruction_list.append(branch_instruction);
6483 }6510 }
6511 ir_set_cursor_at_end(&ira->new_irb, cur_bb);
64846512
6485 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,6513 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
6486 new_incoming_blocks.items, new_incoming_values.items);6514 new_incoming_blocks.items, new_incoming_values.items);