| ... | ... | @@ -198,6 +198,9 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * |
| 198 | 198 | IrInstruction *base_ptr, bool initializing); |
| 199 | 199 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 200 | 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 | 205 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 203 | 206 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | ... | @@ -1089,6 +1092,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) { |
| 1089 | 1092 | return IrInstructionIdEndExpr; |
| 1090 | 1093 | } |
| 1091 | 1094 | |
| 1095 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedField *) { |
| 1096 | return IrInstructionIdUnionInitNamedField; |
| 1097 | } |
| 1098 | |
| 1092 | 1099 | template<typename T> |
| 1093 | 1100 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1094 | 1101 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1352,12 +1359,13 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s |
| 1352 | 1359 | } |
| 1353 | 1360 | |
| 1354 | 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 | 1364 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); |
| 1358 | 1365 | instruction->container_ptr = container_ptr; |
| 1359 | 1366 | instruction->field_name_buffer = nullptr; |
| 1360 | 1367 | instruction->field_name_expr = field_name_expr; |
| 1368 | instruction->initializing = initializing; |
| 1361 | 1369 | |
| 1362 | 1370 | ir_ref_instruction(container_ptr, irb->current_basic_block); |
| 1363 | 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 | 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 | 3353 | static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, |
| 3328 | 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 | 5136 | if (arg1_value == irb->codegen->invalid_instruction) |
| 5111 | 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 | 5142 | if (lval == LValPtr) |
| 5116 | 5143 | return ptr_instruction; |
| ... | ... | @@ -5651,6 +5678,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 5651 | 5678 | IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); |
| 5652 | 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 | 5699 | zig_unreachable(); |
| 5656 | 5700 | } |
| ... | ... | @@ -5929,6 +5973,31 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 5929 | 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 | 6001 | static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| 5933 | 6002 | ResultLoc *parent_result_loc) |
| 5934 | 6003 | { |
| ... | ... | @@ -19408,32 +19477,21 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe |
| 19408 | 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, |
| 19412 | | ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 19413 | | IrInstruction *result_loc) |
| 19480 | static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *source_instruction, |
| 19481 | AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstruction *field_result_loc, |
| 19482 | IrInstruction *result_loc) |
| 19414 | 19483 | { |
| 19415 | 19484 | Error err; |
| 19416 | | assert(container_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 | | } |
| 19485 | assert(union_type->id == ZigTypeIdUnion); |
| 19426 | 19486 | |
| 19427 | | IrInstructionContainerInitFieldsField *field = &fields[0]; |
| 19428 | | IrInstruction *field_result_loc = field->result_loc->child; |
| 19429 | | if (type_is_invalid(field_result_loc->value.type)) |
| 19487 | if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown))) |
| 19430 | 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 | 19491 | if (type_field == nullptr) { |
| 19434 | | ir_add_error_node(ira, field->source_node, |
| 19492 | ir_add_error_node(ira, field_source_node, |
| 19435 | 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 | 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 | 19508 | } |
| 19451 | 19509 | } |
| 19452 | 19510 | |
| 19453 | | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) |
| 19454 | | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; |
| 19511 | bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope) |
| 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 | 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 | 19517 | buf_sprintf("unable to evaluate constant expression")); |
| 19460 | 19518 | return ira->codegen->invalid_instruction; |
| 19461 | 19519 | } |
| ... | ... | @@ -19468,8 +19526,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19468 | 19526 | { |
| 19469 | 19527 | Error err; |
| 19470 | 19528 | if (container_type->id == ZigTypeIdUnion) { |
| 19471 | | return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, |
| 19472 | | fields, result_loc); |
| 19529 | if (instr_field_count != 1) { |
| 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 | 19542 | if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) { |
| 19475 | 19543 | ir_add_error(ira, instruction, |
| ... | ... | @@ -25326,6 +25394,35 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst |
| 25326 | 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 | 25426 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { |
| 25330 | 25427 | switch (instruction->id) { |
| 25331 | 25428 | case IrInstructionIdInvalid: |
| ... | ... | @@ -25641,6 +25738,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 25641 | 25738 | return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction); |
| 25642 | 25739 | case IrInstructionIdBitCastSrc: |
| 25643 | 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 | 25744 | zig_unreachable(); |
| 25646 | 25745 | } |
| ... | ... | @@ -25794,6 +25893,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25794 | 25893 | case IrInstructionIdCast: |
| 25795 | 25894 | case IrInstructionIdContainerInitList: |
| 25796 | 25895 | case IrInstructionIdContainerInitFields: |
| 25896 | case IrInstructionIdUnionInitNamedField: |
| 25797 | 25897 | case IrInstructionIdFieldPtr: |
| 25798 | 25898 | case IrInstructionIdElemPtr: |
| 25799 | 25899 | case IrInstructionIdVarPtr: |