authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-03 13:40:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-03 13:40:40-04:00
log4bae87764fc455f4df8b9d96be856921b0dd97db
tree194da04d4f7cf3be9795e8d2edab96ac1c1a31af
parent9da054095cdc6d428c645c37189730c5e689964d
signaturelock-open Commit is signed but in an unrecognized format.

update `@unionInit` to integrate with result location semantics


4 files changed, 118 insertions(+), 73 deletions(-)

doc/langref.html.in+17
......@@ -5065,6 +5065,12 @@ test "@intToPtr for pointer to zero bit type" {
50655065 {#header_close#}
50665066 {#header_close#}
50675067
5068 {#header_open|Result Location Semantics#}
5069 <p>
5070 <a href="https://github.com/ziglang/zig/issues/2809">TODO add documentation for this</a>
5071 </p>
5072 {#header_close#}
5073
50685074 {#header_open|comptime#}
50695075 <p>
50705076 Zig places importance on the concept of whether an expression is known at compile-time.
......@@ -7809,6 +7815,17 @@ pub const TypeInfo = union(TypeId) {
78097815
78107816 {#header_close#}
78117817
7818 {#header_open|@unionInit#}
7819 <pre>{#syntax#}@unionInit(comptime Union: type, comptime active_field_name: []const u8, init_expr) Union{#endsyntax#}</pre>
7820 <p>
7821 This is the same thing as {#link|union#} initialization syntax, except that the field name is a
7822 {#link|comptime#}-known value rather than an identifier token.
7823 </p>
7824 <p>
7825 {#syntax#}@unionInit{#endsyntax#} forwards its {#link|result location|Result Location Semantics#} to {#syntax#}init_expr{#endsyntax#}.
7826 </p>
7827 {#header_close#}
7828
78127829 {#header_open|@Vector#}
78137830 <pre>{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}</pre>
78147831 <p>
src/all_types.hpp+2-1
......@@ -3610,7 +3610,8 @@ struct IrInstructionUnionInitNamedField {
36103610
36113611 IrInstruction *union_type;
36123612 IrInstruction *field_name;
3613 IrInstruction *value;
3613 IrInstruction *field_result_loc;
3614 IrInstruction *result_loc;
36143615};
36153616
36163617struct IrInstructionHasDecl {
src/ir.cpp+96-71
......@@ -198,6 +198,9 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *
198198 IrInstruction *base_ptr, bool initializing);
199199static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
200200 IrInstruction *ptr, IrInstruction *uncasted_value);
201static 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);
201204
202205static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
203206 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -1069,7 +1072,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)
10691072 return IrInstructionIdAssertNonNull;
10701073}
10711074
1072<<<<<<< HEAD
10731075static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {
10741076 return IrInstructionIdHasDecl;
10751077}
......@@ -1357,12 +1359,13 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s
13571359}
13581360
13591361static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node,
1360 IrInstruction *container_ptr, IrInstruction *field_name_expr)
1362 IrInstruction *container_ptr, IrInstruction *field_name_expr, bool initializing)
13611363{
13621364 IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node);
13631365 instruction->container_ptr = container_ptr;
13641366 instruction->field_name_buffer = nullptr;
13651367 instruction->field_name_expr = field_name_expr;
1368 instruction->initializing = initializing;
13661369
13671370 ir_ref_instruction(container_ptr, irb->current_basic_block);
13681371 ir_ref_instruction(field_name_expr, irb->current_basic_block);
......@@ -3329,16 +3332,19 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
33293332 return &instruction->base;
33303333}
33313334
3332static IrInstruction *ir_build_union_init_2(IrBuilder *irb, Scope *scope, AstNode *source_node,
3333 IrInstruction *union_type_value, IrInstruction *field_name_expr, IrInstruction *value) {
3334 IrInstructionUnionInit2 *instruction = ir_build_instruction<IrInstructionUnionInit2>(irb, scope, source_node);
3335 instruction->union_type_value = union_type_value;
3336 instruction->field_name_expr = field_name_expr;
3337 instruction->value = value;
3335static 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;
33383343
3339 ir_ref_instruction(union_type_value, irb->current_basic_block);
3340 ir_ref_instruction(field_name_expr, irb->current_basic_block);
3341 ir_ref_instruction(value, irb->current_basic_block);
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);
33423348
33433349 return &instruction->base;
33443350}
......@@ -5130,7 +5136,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
51305136 if (arg1_value == irb->codegen->invalid_instruction)
51315137 return arg1_value;
51325138
5133 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);
51345141
51355142 if (lval == LValPtr)
51365143 return ptr_instruction;
......@@ -5673,26 +5680,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
56735680 }
56745681 case BuiltinFnIdUnionInit:
56755682 {
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;
56765687
5677 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5678 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5679 if (arg0_value == irb->codegen->invalid_instruction)
5680 return arg0_value;
5681
5682 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5683 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5684 if (arg1_value == irb->codegen->invalid_instruction)
5685 return arg1_value;
5686
5687 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5688 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
5689 if (arg2_value == irb->codegen->invalid_instruction)
5690 return arg2_value;
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;
56915692
5692 IrInstruction *result = ir_build_union_init_2(irb, scope, node, arg0_value, arg1_value, arg2_value);
5693 AstNode *init_node = node->data.fn_call_expr.params.at(2);
56935694
5694 // TODO: Not sure if we need ir_lval_wrap or not.
5695 return result;
5695 return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
5696 lval, result_loc);
56965697 }
56975698 }
56985699 zig_unreachable();
......@@ -5972,6 +5973,31 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
59725973 zig_unreachable();
59735974}
59745975
5976static 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
59756001static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
59766002 ResultLoc *parent_result_loc)
59776003{
......@@ -19451,32 +19477,21 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
1945119477 return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile);
1945219478}
1945319479
19454static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
19455 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
19456 IrInstruction *result_loc)
19480static 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)
1945719483{
1945819484 Error err;
19459 assert(container_type->id == ZigTypeIdUnion);
19460
19461 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
19462 return ira->codegen->invalid_instruction;
19463
19464 if (instr_field_count != 1) {
19465 ir_add_error(ira, instruction,
19466 buf_sprintf("union initialization expects exactly one field"));
19467 return ira->codegen->invalid_instruction;
19468 }
19485 assert(union_type->id == ZigTypeIdUnion);
1946919486
19470 IrInstructionContainerInitFieldsField *field = &fields[0];
19471 IrInstruction *field_result_loc = field->result_loc->child;
19472 if (type_is_invalid(field_result_loc->value.type))
19487 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
1947319488 return ira->codegen->invalid_instruction;
1947419489
19475 TypeUnionField *type_field = find_union_type_field(container_type, field->name);
19490 TypeUnionField *type_field = find_union_type_field(union_type, field_name);
1947619491 if (type_field == nullptr) {
19477 ir_add_error_node(ira, field->source_node,
19492 ir_add_error_node(ira, field_source_node,
1947819493 buf_sprintf("no member named '%s' in union '%s'",
19479 buf_ptr(field->name), buf_ptr(&container_type->name)));
19494 buf_ptr(field_name), buf_ptr(&union_type->name)));
1948019495 return ira->codegen->invalid_instruction;
1948119496 }
1948219497
......@@ -19493,12 +19508,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1949319508 }
1949419509 }
1949519510
19496 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
19497 || 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;
1949819513
19499 IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
19514 IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr);
1950019515 if (is_comptime && !instr_is_comptime(result)) {
19501 ir_add_error(ira, field->result_loc,
19516 ir_add_error(ira, field_result_loc,
1950219517 buf_sprintf("unable to evaluate constant expression"));
1950319518 return ira->codegen->invalid_instruction;
1950419519 }
......@@ -19511,8 +19526,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1951119526{
1951219527 Error err;
1951319528 if (container_type->id == ZigTypeIdUnion) {
19514 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
19515 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);
1951619541 }
1951719542 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
1951819543 ir_add_error(ira, instruction,
......@@ -25369,33 +25394,33 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
2536925394 return instruction->result_loc_bit_cast->parent->gen_instruction;
2537025395}
2537125396
25372static IrInstruction *ir_analyze_instruction_union_init_2(IrAnalyze *ira, IrInstructionUnionInit2 *union_init_instruction)
25397static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira,
25398 IrInstructionUnionInitNamedField *instruction)
2537325399{
25374 Error err;
25375 IrInstruction *union_type_value = union_init_instruction->union_type_value->child;
25376 ZigType *union_type = ir_resolve_type(ira, union_type_value);
25377 if (type_is_invalid(union_type)) {
25400 ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child);
25401 if (type_is_invalid(union_type))
2537825402 return ira->codegen->invalid_instruction;
25379 }
2538025403
25381 if (union_type->id != ZigTypeIdUnion)
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)));
2538225407 return ira->codegen->invalid_instruction;
25408 }
2538325409
25384 if ((err = ensure_complete_type(ira->codegen, union_type)))
25410 Buf *field_name = ir_resolve_str(ira, instruction->field_name->child);
25411 if (field_name == nullptr)
2538525412 return ira->codegen->invalid_instruction;
2538625413
25387 IrInstruction *field_name_expr = union_init_instruction->field_name_expr->child;
25388 Buf *field_name = ir_resolve_str(ira, field_name_expr);
25389 if (!field_name)
25414 IrInstruction *field_result_loc = instruction->field_result_loc->child;
25415 if (type_is_invalid(field_result_loc->value.type))
2539025416 return ira->codegen->invalid_instruction;
2539125417
25392 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(1);
25393
25394 fields[0].name = field_name;
25395 fields[0].value = union_init_instruction->value;
25396 fields[0].source_node = union_init_instruction->base.source_node;
25418 IrInstruction *result_loc = instruction->result_loc->child;
25419 if (type_is_invalid(result_loc->value.type))
25420 return ira->codegen->invalid_instruction;
2539725421
25398 return ir_analyze_container_init_fields_union(ira, &union_init_instruction->base, union_type, 1, fields);
25422 return ir_analyze_union_init(ira, &instruction->base, instruction->base.source_node,
25423 union_type, field_name, field_result_loc, result_loc);
2539925424}
2540025425
2540125426static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
src/ir_print.cpp+3-1
......@@ -1632,7 +1632,9 @@ static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInit
16321632 fprintf(irp->f, ", ");
16331633 ir_print_other_instruction(irp, instruction->field_name);
16341634 fprintf(irp->f, ", ");
1635 ir_print_other_instruction(irp, instruction->value);
1635 ir_print_other_instruction(irp, instruction->field_result_loc);
1636 fprintf(irp->f, ", ");
1637 ir_print_other_instruction(irp, instruction->result_loc);
16361638 fprintf(irp->f, ")");
16371639}
16381640