| ... | ... | @@ -2307,6 +2307,12 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode |
| 2307 | 2307 | return ir_build_const_null(irb, scope, node); |
| 2308 | 2308 | } |
| 2309 | 2309 | |
| 2310 | static 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 | |
| 2310 | 2316 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld, |
| 2311 | 2317 | LValPurpose lval, Scope *scope) |
| 2312 | 2318 | { |
| ... | ... | @@ -3927,6 +3933,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3927 | 3933 | return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval); |
| 3928 | 3934 | case NodeTypeNullLiteral: |
| 3929 | 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 | 3938 | case NodeTypeIfVarExpr: |
| 3931 | 3939 | return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval); |
| 3932 | 3940 | case NodeTypeSwitchExpr: |
| ... | ... | @@ -3949,8 +3957,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3949 | 3957 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); |
| 3950 | 3958 | case NodeTypeUnwrapErrorExpr: |
| 3951 | 3959 | return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); |
| 3952 | | case NodeTypeZeroesLiteral: |
| 3953 | | case NodeTypeVarLiteral: |
| 3954 | 3960 | case NodeTypeFnProto: |
| 3955 | 3961 | case NodeTypeFnDef: |
| 3956 | 3962 | case NodeTypeFnDecl: |
| ... | ... | @@ -3959,6 +3965,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3959 | 3965 | case NodeTypeErrorValueDecl: |
| 3960 | 3966 | case NodeTypeTypeDecl: |
| 3961 | 3967 | zig_panic("TODO more IR gen for node types"); |
| 3968 | case NodeTypeZeroesLiteral: |
| 3969 | zig_panic("TODO zeroes is deprecated"); |
| 3962 | 3970 | } |
| 3963 | 3971 | zig_unreachable(); |
| 3964 | 3972 | } |
| ... | ... | @@ -4065,17 +4073,18 @@ static IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 4065 | 4073 | return nullptr; |
| 4066 | 4074 | |
| 4067 | 4075 | IrBasicBlock *bb = exec->basic_block_list.at(0); |
| 4068 | | if (bb->instruction_list.length != 1) |
| 4069 | | return nullptr; |
| 4070 | | |
| 4071 | | IrInstruction *only_inst = bb->instruction_list.at(0); |
| 4072 | | if (only_inst->id != IrInstructionIdReturn) |
| 4073 | | return nullptr; |
| 4074 | | |
| 4075 | | IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst; |
| 4076 | | IrInstruction *value = ret_inst->value; |
| 4077 | | assert(value->static_value.special != ConstValSpecialRuntime); |
| 4078 | | return value; |
| 4076 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { |
| 4077 | IrInstruction *instruction = bb->instruction_list.at(i); |
| 4078 | if (instruction->id == IrInstructionIdReturn) { |
| 4079 | IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction; |
| 4080 | IrInstruction *value = ret_inst->value; |
| 4081 | assert(value->static_value.special != ConstValSpecialRuntime); |
| 4082 | return value; |
| 4083 | } else if (ir_has_side_effects(instruction)) { |
| 4084 | return nullptr; |
| 4085 | } |
| 4086 | } |
| 4087 | return nullptr; |
| 4079 | 4088 | } |
| 4080 | 4089 | |
| 4081 | 4090 | static 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 | 4132 | return false; |
| 4124 | 4133 | } |
| 4125 | 4134 | |
| 4126 | | static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_node, |
| 4127 | | IrInstruction **instructions, size_t instruction_count) |
| 4135 | enum ImplicitCastMatchResult { |
| 4136 | ImplicitCastMatchResultNo, |
| 4137 | ImplicitCastMatchResultYes, |
| 4138 | ImplicitCastMatchResultReportedError, |
| 4139 | }; |
| 4140 | |
| 4141 | static 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 | |
| 4237 | static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) { |
| 4129 | 4238 | assert(instruction_count >= 1); |
| 4130 | 4239 | IrInstruction *prev_inst = instructions[0]; |
| 4131 | 4240 | if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) { |
| ... | ... | @@ -4241,109 +4350,6 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_n |
| 4241 | 4350 | } |
| 4242 | 4351 | } |
| 4243 | 4352 | |
| 4244 | | enum ImplicitCastMatchResult { |
| 4245 | | ImplicitCastMatchResultNo, |
| 4246 | | ImplicitCastMatchResultYes, |
| 4247 | | ImplicitCastMatchResultReportedError, |
| 4248 | | }; |
| 4249 | | |
| 4250 | | static 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 | | |
| 4341 | | static 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 | | |
| 4347 | 4353 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *type_entry) { |
| 4348 | 4354 | if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) { |
| 4349 | 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 | 4752 | return ira->codegen->invalid_instruction; |
| 4747 | 4753 | } |
| 4748 | 4754 | |
| 4755 | if (wanted_type->id == TypeTableEntryIdVar) |
| 4756 | return value; |
| 4757 | |
| 4749 | 4758 | // explicit match or non-const to const |
| 4750 | 4759 | if (types_match_const_cast_only(wanted_type, actual_type)) { |
| 4751 | 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 | 5842 | |
| 5834 | 5843 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 5835 | 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 | 5846 | *exec_scope = var->child_scope; |
| 5838 | 5847 | *next_proto_i += 1; |
| 5839 | 5848 | |
| ... | ... | @@ -5852,38 +5861,49 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 5852 | 5861 | if (param_type->id == TypeTableEntryIdInvalid) |
| 5853 | 5862 | return false; |
| 5854 | 5863 | |
| 5855 | | bool is_var_type = (param_type->id == TypeTableEntryIdVar); |
| 5856 | | IrInstruction *casted_arg; |
| 5857 | | if (is_var_type) { |
| 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 | | } |
| 5864 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg, param_type); |
| 5865 | if (casted_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 5866 | return false; |
| 5864 | 5867 | |
| 5865 | 5868 | bool inline_arg = param_decl_node->data.param_decl.is_inline; |
| 5866 | | if (inline_arg || is_var_type) { |
| 5867 | | ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad); |
| 5869 | bool is_var_type = (param_type->id == TypeTableEntryIdVar); |
| 5870 | |
| 5871 | ConstExprValue *arg_val; |
| 5872 | |
| 5873 | if (inline_arg) { |
| 5874 | arg_val = ir_resolve_const(ira, casted_arg, UndefBad); |
| 5868 | 5875 | if (!arg_val) |
| 5869 | 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 | 5877 | // This generic function instance could be called with anything, so when this variable is read it |
| 5876 | 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; |
| 5878 | 5888 | |
| 5889 | if (inline_arg || is_var_type) { |
| 5879 | 5890 | GenericParamValue *generic_param = &generic_id->params[generic_id->param_count]; |
| 5880 | 5891 | generic_param->type = casted_arg->type_entry; |
| 5881 | 5892 | generic_param->value = arg_val; |
| 5882 | 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 | 5904 | casted_args[fn_type_id->param_count] = casted_arg; |
| 5885 | 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 | 5907 | param_info->is_noalias = param_decl_node->data.param_decl.is_noalias; |
| 5888 | 5908 | impl_fn->param_source_nodes[fn_type_id->param_count] = param_decl_node; |
| 5889 | 5909 | fn_type_id->param_count += 1; |
| ... | ... | @@ -6475,12 +6495,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 6475 | 6495 | return ira->codegen->builtin_types.entry_invalid; |
| 6476 | 6496 | } |
| 6477 | 6497 | |
| 6478 | | // cast all literal values to the resolved type |
| 6498 | // 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 | 6502 | for (size_t i = 0; i < new_incoming_values.length; i += 1) { |
| 6480 | 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 | 6507 | IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type); |
| 6482 | 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); |
| 6484 | 6512 | |
| 6485 | 6513 | ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length, |
| 6486 | 6514 | new_incoming_blocks.items, new_incoming_values.items); |