| ... | @@ -198,6 +198,9 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * | ... | @@ -198,6 +198,9 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * |
| 198 | IrInstruction *base_ptr, bool initializing); | 198 | IrInstruction *base_ptr, bool initializing); |
| 199 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, | 199 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 200 | IrInstruction *ptr, IrInstruction *uncasted_value); | 200 | IrInstruction *ptr, IrInstruction *uncasted_value); |
| | 201 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 202 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, |
| | 203 | LVal lval, ResultLoc *parent_result_loc); |
| 201 | | 204 | |
| 202 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 205 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 203 | assert(get_src_ptr_type(const_val->type) != nullptr); | 206 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -1089,6 +1092,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) { | ... | @@ -1089,6 +1092,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) { |
| 1089 | return IrInstructionIdEndExpr; | 1092 | return IrInstructionIdEndExpr; |
| 1090 | } | 1093 | } |
| 1091 | | 1094 | |
| | 1095 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedField *) { |
| | 1096 | return IrInstructionIdUnionInitNamedField; |
| | 1097 | } |
| | 1098 | |
| 1092 | template<typename T> | 1099 | template<typename T> |
| 1093 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 1100 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1094 | T *special_instruction = allocate<T>(1); | 1101 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1352,12 +1359,13 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -1352,12 +1359,13 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s |
| 1352 | } | 1359 | } |
| 1353 | | 1360 | |
| 1354 | static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1361 | static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1355 | IrInstruction *container_ptr, IrInstruction *field_name_expr) | 1362 | IrInstruction *container_ptr, IrInstruction *field_name_expr, bool initializing) |
| 1356 | { | 1363 | { |
| 1357 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); | 1364 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); |
| 1358 | instruction->container_ptr = container_ptr; | 1365 | instruction->container_ptr = container_ptr; |
| 1359 | instruction->field_name_buffer = nullptr; | 1366 | instruction->field_name_buffer = nullptr; |
| 1360 | instruction->field_name_expr = field_name_expr; | 1367 | instruction->field_name_expr = field_name_expr; |
| | 1368 | instruction->initializing = initializing; |
| 1361 | | 1369 | |
| 1362 | ir_ref_instruction(container_ptr, irb->current_basic_block); | 1370 | ir_ref_instruction(container_ptr, irb->current_basic_block); |
| 1363 | ir_ref_instruction(field_name_expr, irb->current_basic_block); | 1371 | ir_ref_instruction(field_name_expr, irb->current_basic_block); |
| ... | @@ -3324,6 +3332,24 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, | ... | @@ -3324,6 +3332,24 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, |
| 3324 | return &instruction->base; | 3332 | return &instruction->base; |
| 3325 | } | 3333 | } |
| 3326 | | 3334 | |
| | 3335 | static IrInstruction *ir_build_union_init_named_field(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 3336 | IrInstruction *union_type, IrInstruction *field_name, IrInstruction *field_result_loc, IrInstruction *result_loc) |
| | 3337 | { |
| | 3338 | IrInstructionUnionInitNamedField *instruction = ir_build_instruction<IrInstructionUnionInitNamedField>(irb, scope, source_node); |
| | 3339 | instruction->union_type = union_type; |
| | 3340 | instruction->field_name = field_name; |
| | 3341 | instruction->field_result_loc = field_result_loc; |
| | 3342 | instruction->result_loc = result_loc; |
| | 3343 | |
| | 3344 | ir_ref_instruction(union_type, irb->current_basic_block); |
| | 3345 | ir_ref_instruction(field_name, irb->current_basic_block); |
| | 3346 | ir_ref_instruction(field_result_loc, irb->current_basic_block); |
| | 3347 | if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); |
| | 3348 | |
| | 3349 | return &instruction->base; |
| | 3350 | } |
| | 3351 | |
| | 3352 | |
| 3327 | static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, | 3353 | static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, |
| 3328 | ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc) | 3354 | ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc) |
| 3329 | { | 3355 | { |
| ... | @@ -5110,7 +5136,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -5110,7 +5136,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 5110 | if (arg1_value == irb->codegen->invalid_instruction) | 5136 | if (arg1_value == irb->codegen->invalid_instruction) |
| 5111 | return arg1_value; | 5137 | return arg1_value; |
| 5112 | | 5138 | |
| 5113 | IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, arg0_value, arg1_value); | 5139 | IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, |
| | 5140 | arg0_value, arg1_value, false); |
| 5114 | | 5141 | |
| 5115 | if (lval == LValPtr) | 5142 | if (lval == LValPtr) |
| 5116 | return ptr_instruction; | 5143 | return ptr_instruction; |
| ... | @@ -5651,6 +5678,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -5651,6 +5678,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 5651 | IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); | 5678 | IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); |
| 5652 | return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); | 5679 | return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); |
| 5653 | } | 5680 | } |
| | 5681 | case BuiltinFnIdUnionInit: |
| | 5682 | { |
| | 5683 | AstNode *union_type_node = node->data.fn_call_expr.params.at(0); |
| | 5684 | IrInstruction *union_type_inst = ir_gen_node(irb, union_type_node, scope); |
| | 5685 | if (union_type_inst == irb->codegen->invalid_instruction) |
| | 5686 | return union_type_inst; |
| | 5687 | |
| | 5688 | AstNode *name_node = node->data.fn_call_expr.params.at(1); |
| | 5689 | IrInstruction *name_inst = ir_gen_node(irb, name_node, scope); |
| | 5690 | if (name_inst == irb->codegen->invalid_instruction) |
| | 5691 | return name_inst; |
| | 5692 | |
| | 5693 | AstNode *init_node = node->data.fn_call_expr.params.at(2); |
| | 5694 | |
| | 5695 | return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node, |
| | 5696 | lval, result_loc); |
| | 5697 | } |
| 5654 | } | 5698 | } |
| 5655 | zig_unreachable(); | 5699 | zig_unreachable(); |
| 5656 | } | 5700 | } |
| ... | @@ -5929,6 +5973,31 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -5929,6 +5973,31 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 5929 | zig_unreachable(); | 5973 | zig_unreachable(); |
| 5930 | } | 5974 | } |
| 5931 | | 5975 | |
| | 5976 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 5977 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, |
| | 5978 | LVal lval, ResultLoc *parent_result_loc) |
| | 5979 | { |
| | 5980 | IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); |
| | 5981 | IrInstruction *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, |
| | 5982 | field_name, true); |
| | 5983 | |
| | 5984 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| | 5985 | result_loc_inst->base.id = ResultLocIdInstruction; |
| | 5986 | result_loc_inst->base.source_instruction = field_ptr; |
| | 5987 | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| | 5988 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| | 5989 | |
| | 5990 | IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, |
| | 5991 | &result_loc_inst->base); |
| | 5992 | if (expr_value == irb->codegen->invalid_instruction) |
| | 5993 | return expr_value; |
| | 5994 | |
| | 5995 | IrInstruction *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, |
| | 5996 | field_name, field_ptr, container_ptr); |
| | 5997 | |
| | 5998 | return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); |
| | 5999 | } |
| | 6000 | |
| 5932 | static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, | 6001 | static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| 5933 | ResultLoc *parent_result_loc) | 6002 | ResultLoc *parent_result_loc) |
| 5934 | { | 6003 | { |
| ... | @@ -19408,32 +19477,21 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe | ... | @@ -19408,32 +19477,21 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe |
| 19408 | return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile); | 19477 | return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile); |
| 19409 | } | 19478 | } |
| 19410 | | 19479 | |
| 19411 | static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction, | 19480 | static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *source_instruction, |
| 19412 | ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, | 19481 | AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstruction *field_result_loc, |
| 19413 | IrInstruction *result_loc) | 19482 | IrInstruction *result_loc) |
| 19414 | { | 19483 | { |
| 19415 | Error err; | 19484 | Error err; |
| 19416 | assert(container_type->id == ZigTypeIdUnion); | 19485 | assert(union_type->id == ZigTypeIdUnion); |
| 19417 | | | |
| 19418 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) | | |
| 19419 | return ira->codegen->invalid_instruction; | | |
| 19420 | | | |
| 19421 | if (instr_field_count != 1) { | | |
| 19422 | ir_add_error(ira, instruction, | | |
| 19423 | buf_sprintf("union initialization expects exactly one field")); | | |
| 19424 | return ira->codegen->invalid_instruction; | | |
| 19425 | } | | |
| 19426 | | 19486 | |
| 19427 | IrInstructionContainerInitFieldsField *field = &fields[0]; | 19487 | if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown))) |
| 19428 | IrInstruction *field_result_loc = field->result_loc->child; | | |
| 19429 | if (type_is_invalid(field_result_loc->value.type)) | | |
| 19430 | return ira->codegen->invalid_instruction; | 19488 | return ira->codegen->invalid_instruction; |
| 19431 | | 19489 | |
| 19432 | TypeUnionField *type_field = find_union_type_field(container_type, field->name); | 19490 | TypeUnionField *type_field = find_union_type_field(union_type, field_name); |
| 19433 | if (type_field == nullptr) { | 19491 | if (type_field == nullptr) { |
| 19434 | ir_add_error_node(ira, field->source_node, | 19492 | ir_add_error_node(ira, field_source_node, |
| 19435 | buf_sprintf("no member named '%s' in union '%s'", | 19493 | buf_sprintf("no member named '%s' in union '%s'", |
| 19436 | buf_ptr(field->name), buf_ptr(&container_type->name))); | 19494 | buf_ptr(field_name), buf_ptr(&union_type->name))); |
| 19437 | return ira->codegen->invalid_instruction; | 19495 | return ira->codegen->invalid_instruction; |
| 19438 | } | 19496 | } |
| 19439 | | 19497 | |
| ... | @@ -19450,12 +19508,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI | ... | @@ -19450,12 +19508,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 19450 | } | 19508 | } |
| 19451 | } | 19509 | } |
| 19452 | | 19510 | |
| 19453 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) | 19511 | bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope) |
| 19454 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; | 19512 | || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; |
| 19455 | | 19513 | |
| 19456 | IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr); | 19514 | IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); |
| 19457 | if (is_comptime && !instr_is_comptime(result)) { | 19515 | if (is_comptime && !instr_is_comptime(result)) { |
| 19458 | ir_add_error(ira, field->result_loc, | 19516 | ir_add_error(ira, field_result_loc, |
| 19459 | buf_sprintf("unable to evaluate constant expression")); | 19517 | buf_sprintf("unable to evaluate constant expression")); |
| 19460 | return ira->codegen->invalid_instruction; | 19518 | return ira->codegen->invalid_instruction; |
| 19461 | } | 19519 | } |
| ... | @@ -19468,8 +19526,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -19468,8 +19526,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19468 | { | 19526 | { |
| 19469 | Error err; | 19527 | Error err; |
| 19470 | if (container_type->id == ZigTypeIdUnion) { | 19528 | if (container_type->id == ZigTypeIdUnion) { |
| 19471 | return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, | 19529 | if (instr_field_count != 1) { |
| 19472 | fields, result_loc); | 19530 | ir_add_error(ira, instruction, |
| | 19531 | buf_sprintf("union initialization expects exactly one field")); |
| | 19532 | return ira->codegen->invalid_instruction; |
| | 19533 | } |
| | 19534 | IrInstructionContainerInitFieldsField *field = &fields[0]; |
| | 19535 | IrInstruction *field_result_loc = field->result_loc->child; |
| | 19536 | if (type_is_invalid(field_result_loc->value.type)) |
| | 19537 | return ira->codegen->invalid_instruction; |
| | 19538 | |
| | 19539 | return ir_analyze_union_init(ira, instruction, field->source_node, container_type, field->name, |
| | 19540 | field_result_loc, result_loc); |
| 19473 | } | 19541 | } |
| 19474 | if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) { | 19542 | if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) { |
| 19475 | ir_add_error(ira, instruction, | 19543 | ir_add_error(ira, instruction, |
| ... | @@ -25326,6 +25394,35 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst | ... | @@ -25326,6 +25394,35 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst |
| 25326 | return instruction->result_loc_bit_cast->parent->gen_instruction; | 25394 | return instruction->result_loc_bit_cast->parent->gen_instruction; |
| 25327 | } | 25395 | } |
| 25328 | | 25396 | |
| | 25397 | static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira, |
| | 25398 | IrInstructionUnionInitNamedField *instruction) |
| | 25399 | { |
| | 25400 | ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child); |
| | 25401 | if (type_is_invalid(union_type)) |
| | 25402 | return ira->codegen->invalid_instruction; |
| | 25403 | |
| | 25404 | if (union_type->id != ZigTypeIdUnion) { |
| | 25405 | ir_add_error(ira, instruction->union_type, |
| | 25406 | buf_sprintf("non-union type '%s' passed to @unionInit", buf_ptr(&union_type->name))); |
| | 25407 | return ira->codegen->invalid_instruction; |
| | 25408 | } |
| | 25409 | |
| | 25410 | Buf *field_name = ir_resolve_str(ira, instruction->field_name->child); |
| | 25411 | if (field_name == nullptr) |
| | 25412 | return ira->codegen->invalid_instruction; |
| | 25413 | |
| | 25414 | IrInstruction *field_result_loc = instruction->field_result_loc->child; |
| | 25415 | if (type_is_invalid(field_result_loc->value.type)) |
| | 25416 | return ira->codegen->invalid_instruction; |
| | 25417 | |
| | 25418 | IrInstruction *result_loc = instruction->result_loc->child; |
| | 25419 | if (type_is_invalid(result_loc->value.type)) |
| | 25420 | return ira->codegen->invalid_instruction; |
| | 25421 | |
| | 25422 | return ir_analyze_union_init(ira, &instruction->base, instruction->base.source_node, |
| | 25423 | union_type, field_name, field_result_loc, result_loc); |
| | 25424 | } |
| | 25425 | |
| 25329 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { | 25426 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { |
| 25330 | switch (instruction->id) { | 25427 | switch (instruction->id) { |
| 25331 | case IrInstructionIdInvalid: | 25428 | case IrInstructionIdInvalid: |
| ... | @@ -25641,6 +25738,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction | ... | @@ -25641,6 +25738,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 25641 | return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction); | 25738 | return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction); |
| 25642 | case IrInstructionIdBitCastSrc: | 25739 | case IrInstructionIdBitCastSrc: |
| 25643 | return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction); | 25740 | return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction); |
| | 25741 | case IrInstructionIdUnionInitNamedField: |
| | 25742 | return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction); |
| 25644 | } | 25743 | } |
| 25645 | zig_unreachable(); | 25744 | zig_unreachable(); |
| 25646 | } | 25745 | } |
| ... | @@ -25794,6 +25893,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -25794,6 +25893,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25794 | case IrInstructionIdCast: | 25893 | case IrInstructionIdCast: |
| 25795 | case IrInstructionIdContainerInitList: | 25894 | case IrInstructionIdContainerInitList: |
| 25796 | case IrInstructionIdContainerInitFields: | 25895 | case IrInstructionIdContainerInitFields: |
| | 25896 | case IrInstructionIdUnionInitNamedField: |
| 25797 | case IrInstructionIdFieldPtr: | 25897 | case IrInstructionIdFieldPtr: |
| 25798 | case IrInstructionIdElemPtr: | 25898 | case IrInstructionIdElemPtr: |
| 25799 | case IrInstructionIdVarPtr: | 25899 | case IrInstructionIdVarPtr: |