authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-08 18:51:31-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-08 18:51:31-04:00
log771e88951a9af48335abe14e4c44b5c4f5b252de
treec6b4831bd61ba18dc819e6ebce1f50b841b4ad80
parent52eb34718862928b5d83c58990d5d7a6b07e20e2
signaturelock-open Commit is signed but in an unrecognized format.

result location mechanism for struct initialization

```zig export fn entry() void { const static = Foo{ .x = 9, .bar = Bar{ .y = 10 }, }; const runtime = foo(true); } fn foo(c: bool) Foo { return Foo{ .x = 12, .bar = if (c) bar1() else bar2(), }; } fn bar1() Bar { return Bar{ .y = 34 }; } fn bar2() Bar { return Bar{ .y = 56 }; } ``` ```llvm @0 = internal unnamed_addr constant %Foo { i32 9, %Bar { i32 10 } }, align 4 @1 = internal unnamed_addr constant %Bar { i32 34 }, align 4 @2 = internal unnamed_addr constant %Bar { i32 56 }, align 4 define void @entry() #2 !dbg !35 { Entry: %runtime = alloca %Foo, align 4 call void @llvm.dbg.declare(metadata %Foo* @0, metadata !39, metadata !DIExpression()), !dbg !50 call fastcc void @foo(%Foo* sret %runtime, i1 true), !dbg !51 call void @llvm.dbg.declare(metadata %Foo* %runtime, metadata !49, metadata !DIExpression()), !dbg !52 ret void, !dbg !53 } define internal fastcc void @foo(%Foo* nonnull sret, i1) unnamed_addr #2 !dbg !54 { Entry: %c = alloca i1, align 1 store i1 %1, i1* %c, align 1 call void @llvm.dbg.declare(metadata i1* %c, metadata !60, metadata !DIExpression()), !dbg !61 %2 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 0, !dbg !62 store i32 12, i32* %2, align 4, !dbg !62 %3 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 1, !dbg !64 %4 = load i1, i1* %c, align 1, !dbg !65 br i1 %4, label %Then, label %Else, !dbg !65 Then: ; preds = %Entry call fastcc void @bar1(%Bar* sret %3), !dbg !66 br label %EndIf, !dbg !64 Else: ; preds = %Entry call fastcc void @bar2(%Bar* sret %3), !dbg !67 br label %EndIf, !dbg !64 EndIf: ; preds = %Else, %Then ret void, !dbg !68 } define internal fastcc void @bar1(%Bar* nonnull sret) unnamed_addr #2 !dbg !69 { Entry: %1 = bitcast %Bar* %0 to i8*, !dbg !73 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @1 to i8*), i64 4, i1 false), !dbg !73 ret void, !dbg !73 } define internal fastcc void @bar2(%Bar* nonnull sret) unnamed_addr #2 !dbg !75 { Entry: %1 = bitcast %Bar* %0 to i8*, !dbg !76 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @2 to i8*), i64 4, i1 false), !dbg !76 ret void, !dbg !76 } !39 = !DILocalVariable(name: "static", scope: !40, file: !5, line: 2, type: !41) !49 = !DILocalVariable(name: "runtime", scope: !40, file: !5, line: 6, type: !41) ```

7 files changed, 270 insertions(+), 143 deletions(-)

BRANCH_TODO+2-6
......@@ -1,8 +1,8 @@
11Scratch pad for stuff to do before merging master
22=================================================
33
4 * struct initializations
5 * function call parameters
4 * array initializations
5 * union initializations
66 * bitCast
77
88look at all the ir_gen_node ir_gen_node_extra calls and make sure result locations are properly propagated
......@@ -25,7 +25,3 @@ inferred comptime
2525 return ir_build_ref(irb, scope, value->source_node, value, false, false);
2626
2727handle if with no else
28
29
30
31
src/all_types.hpp+34-15
......@@ -1957,6 +1957,7 @@ enum ScopeId {
19571957 ScopeIdCompTime,
19581958 ScopeIdCoroPrelude,
19591959 ScopeIdRuntime,
1960 ScopeIdElide,
19601961};
19611962
19621963struct Scope {
......@@ -1970,6 +1971,14 @@ struct Scope {
19701971 ScopeId id;
19711972};
19721973
1974// This scope, when activated, causes all the instructions in the scope to be omitted
1975// from the generated code.
1976struct ScopeElide {
1977 Scope base;
1978
1979 bool activated;
1980};
1981
19731982// This scope comes from global declarations or from
19741983// declarations in a container declaration
19751984// NodeTypeContainerDecl
......@@ -2189,7 +2198,6 @@ enum IrInstructionId {
21892198 IrInstructionIdResizeSlice,
21902199 IrInstructionIdContainerInitList,
21912200 IrInstructionIdContainerInitFields,
2192 IrInstructionIdStructInit,
21932201 IrInstructionIdUnionInit,
21942202 IrInstructionIdUnreachable,
21952203 IrInstructionIdTypeOf,
......@@ -2279,6 +2287,7 @@ enum IrInstructionId {
22792287 IrInstructionIdPtrType,
22802288 IrInstructionIdAlignCast,
22812289 IrInstructionIdImplicitCast,
2290 IrInstructionIdResolveResult,
22822291 IrInstructionIdOpaqueType,
22832292 IrInstructionIdSetAlignStack,
22842293 IrInstructionIdArgType,
......@@ -2366,6 +2375,7 @@ struct IrInstructionCondBr {
23662375 IrBasicBlock *then_block;
23672376 IrBasicBlock *else_block;
23682377 IrInstruction *is_comptime;
2378 ResultLoc *result_loc;
23692379};
23702380
23712381struct IrInstructionBr {
......@@ -2646,20 +2656,6 @@ struct IrInstructionContainerInitFields {
26462656 IrInstructionContainerInitFieldsField *fields;
26472657};
26482658
2649struct IrInstructionStructInitField {
2650 IrInstruction *value;
2651 TypeStructField *type_struct_field;
2652};
2653
2654struct IrInstructionStructInit {
2655 IrInstruction base;
2656
2657 ZigType *struct_type;
2658 size_t field_count;
2659 IrInstructionStructInitField *fields;
2660 LLVMValueRef tmp_ptr;
2661};
2662
26632659struct IrInstructionUnionInit {
26642660 IrInstruction base;
26652661
......@@ -3581,13 +3577,22 @@ struct IrInstructionImplicitCast {
35813577 IrInstruction *target;
35823578};
35833579
3580struct IrInstructionResolveResult {
3581 IrInstruction base;
3582
3583 ResultLoc *result_loc;
3584 IrInstruction *ty;
3585};
3586
35843587enum ResultLocId {
35853588 ResultLocIdInvalid,
35863589 ResultLocIdNone,
35873590 ResultLocIdVar,
3591 ResultLocIdField,
35883592 ResultLocIdReturn,
35893593 ResultLocIdPeer,
35903594 ResultLocIdPeerParent,
3595 ResultLocIdInstruction,
35913596};
35923597
35933598struct ResultLoc {
......@@ -3597,6 +3602,7 @@ struct ResultLoc {
35973602 IrInstruction *source_instruction;
35983603 IrInstruction *gen_instruction; // value to store to the result loc
35993604 ZigType *implicit_elem_type;
3605 ScopeElide *scope_elide;
36003606};
36013607
36023608struct ResultLocNone {
......@@ -3609,6 +3615,14 @@ struct ResultLocVar {
36093615 ZigVar *var;
36103616};
36113617
3618struct ResultLocField {
3619 ResultLoc base;
3620
3621 ResultLoc *parent;
3622 Buf *name;
3623 IrInstruction *container_type;
3624};
3625
36123626struct ResultLocReturn {
36133627 ResultLoc base;
36143628};
......@@ -3636,6 +3650,11 @@ struct ResultLocPeer {
36363650 IrSuspendPosition suspend_pos;
36373651};
36383652
3653// The result location is the source instruction
3654struct ResultLocInstruction {
3655 ResultLoc base;
3656};
3657
36393658static const size_t slice_ptr_index = 0;
36403659static const size_t slice_len_index = 1;
36413660
src/analyze.cpp+6
......@@ -166,6 +166,12 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct
166166 return &scope->base;
167167}
168168
169ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent) {
170 ScopeElide *scope = allocate<ScopeElide>(1);
171 init_scope(g, &scope->base, ScopeIdElide, node, parent);
172 return scope;
173}
174
169175ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
170176 assert(node->type == NodeTypeSuspend);
171177 ScopeSuspend *scope = allocate<ScopeSuspend>(1);
src/analyze.hpp+1
......@@ -121,6 +121,7 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *
121121Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
122122Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
123123Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
124ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent);
124125
125126void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
126127ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
src/codegen.cpp+39-34
......@@ -715,6 +715,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
715715 case ScopeIdCompTime:
716716 case ScopeIdCoroPrelude:
717717 case ScopeIdRuntime:
718 case ScopeIdElide:
718719 return get_di_scope(g, scope->parent);
719720 }
720721 zig_unreachable();
......@@ -2383,7 +2384,6 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
23832384}
23842385
23852386static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2386 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
23872387 ZigType *return_type = return_instruction->value->value.type;
23882388
23892389 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
......@@ -2391,13 +2391,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
23912391 if (return_instruction->value->value.special != ConstValSpecialRuntime) {
23922392 // if it's comptime we have to do this but if it's runtime trust that
23932393 // result location mechanism took care of it.
2394 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
23942395 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
23952396 }
23962397 LLVMBuildRetVoid(g->builder);
23972398 } else if (handle_is_ptr(return_type)) {
2399 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
23982400 LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
23992401 LLVMBuildRet(g->builder, by_val_value);
24002402 } else {
2403 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
24012404 LLVMBuildRet(g->builder, value);
24022405 }
24032406 return nullptr;
......@@ -5032,29 +5035,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
50325035 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
50335036}
50345037
5035static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
5036 for (size_t i = 0; i < instruction->field_count; i += 1) {
5037 IrInstructionStructInitField *field = &instruction->fields[i];
5038 TypeStructField *type_struct_field = field->type_struct_field;
5039 if (!type_has_bits(type_struct_field->type_entry))
5040 continue;
5041
5042 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
5043 (unsigned)type_struct_field->gen_index, "");
5044 LLVMValueRef value = ir_llvm_value(g, field->value);
5045
5046 uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
5047 uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
5048
5049 ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
5050 false, false, PtrLenSingle, field_align_bytes,
5051 (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
5052
5053 gen_assign_raw(g, field_ptr, ptr_type, value);
5054 }
5055 return instruction->tmp_ptr;
5056}
5057
50585038static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
50595039 TypeUnionField *type_union_field = instruction->field;
50605040
......@@ -5531,10 +5511,6 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
55315511}
55325512
55335513static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
5534 if (!g->strip_debug_symbols) {
5535 set_debug_location(g, instruction);
5536 }
5537
55385514 switch (instruction->id) {
55395515 case IrInstructionIdInvalid:
55405516 case IrInstructionIdConst:
......@@ -5609,6 +5585,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
56095585 case IrInstructionIdEndExpr:
56105586 case IrInstructionIdAllocaGen:
56115587 case IrInstructionIdImplicitCast:
5588 case IrInstructionIdResolveResult:
56125589 zig_unreachable();
56135590
56145591 case IrInstructionIdDeclVarGen:
......@@ -5705,8 +5682,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
57055682 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
57065683 case IrInstructionIdUnionTag:
57075684 return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
5708 case IrInstructionIdStructInit:
5709 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
57105685 case IrInstructionIdUnionInit:
57115686 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
57125687 case IrInstructionIdPtrCastGen:
......@@ -5791,6 +5766,34 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
57915766 zig_unreachable();
57925767}
57935768
5769static bool scope_is_elided(Scope *scope) {
5770 for (;;) {
5771 switch (scope->id) {
5772 case ScopeIdDecls:
5773 case ScopeIdCompTime:
5774 case ScopeIdCImport:
5775 zig_unreachable();
5776 case ScopeIdElide:
5777 if (reinterpret_cast<ScopeElide *>(scope)->activated)
5778 return true;
5779 // fallthrough
5780 case ScopeIdBlock:
5781 case ScopeIdDefer:
5782 case ScopeIdDeferExpr:
5783 case ScopeIdVarDecl:
5784 case ScopeIdLoop:
5785 case ScopeIdSuspend:
5786 case ScopeIdCoroPrelude:
5787 case ScopeIdRuntime:
5788 scope = scope->parent;
5789 continue;
5790 case ScopeIdFnDef:
5791 return false;
5792 }
5793 zig_unreachable();
5794 }
5795}
5796
57945797static void ir_render(CodeGen *g, ZigFn *fn_entry) {
57955798 assert(fn_entry);
57965799
......@@ -5806,7 +5809,12 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
58065809 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
58075810 continue;
58085811
5809 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5812 if (!scope_is_elided(instruction->scope)) {
5813 if (!g->strip_debug_symbols) {
5814 set_debug_location(g, instruction);
5815 }
5816 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5817 }
58105818 }
58115819 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
58125820 }
......@@ -6891,9 +6899,6 @@ static void do_code_gen(CodeGen *g) {
68916899 } else if (instruction->id == IrInstructionIdContainerInitList) {
68926900 IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
68936901 slot = &container_init_list_instruction->tmp_ptr;
6894 } else if (instruction->id == IrInstructionIdStructInit) {
6895 IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
6896 slot = &struct_init_instruction->tmp_ptr;
68976902 } else if (instruction->id == IrInstructionIdUnionInit) {
68986903 IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
68996904 slot = &union_init_instruction->tmp_ptr;
src/ir.cpp+163-73
......@@ -616,10 +616,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
616616 return IrInstructionIdRef;
617617}
618618
619static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {
620 return IrInstructionIdStructInit;
621}
622
623619static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
624620 return IrInstructionIdUnionInit;
625621}
......@@ -888,6 +884,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *)
888884 return IrInstructionIdImplicitCast;
889885}
890886
887static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) {
888 return IrInstructionIdResolveResult;
889}
890
891891static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
892892 return IrInstructionIdOpaqueType;
893893}
......@@ -1517,20 +1517,6 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
15171517 return &container_init_fields_instruction->base;
15181518}
15191519
1520static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
1521 ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields)
1522{
1523 IrInstructionStructInit *struct_init_instruction = ir_build_instruction<IrInstructionStructInit>(irb, scope, source_node);
1524 struct_init_instruction->struct_type = struct_type;
1525 struct_init_instruction->field_count = field_count;
1526 struct_init_instruction->fields = fields;
1527
1528 for (size_t i = 0; i < field_count; i += 1)
1529 ir_ref_instruction(fields[i].value, irb->current_basic_block);
1530
1531 return &struct_init_instruction->base;
1532}
1533
15341520static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
15351521 ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
15361522{
......@@ -2764,6 +2750,18 @@ static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNo
27642750 return &instruction->base;
27652751}
27662752
2753static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
2754 ResultLoc *result_loc, IrInstruction *ty)
2755{
2756 IrInstructionResolveResult *instruction = ir_build_instruction<IrInstructionResolveResult>(irb, scope, source_node);
2757 instruction->result_loc = result_loc;
2758 instruction->ty = ty;
2759
2760 ir_ref_instruction(ty, irb->current_basic_block);
2761
2762 return &instruction->base;
2763}
2764
27672765static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
27682766 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
27692767
......@@ -3220,6 +3218,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
32203218 case ScopeIdSuspend:
32213219 case ScopeIdCompTime:
32223220 case ScopeIdRuntime:
3221 case ScopeIdElide:
32233222 scope = scope->parent;
32243223 continue;
32253224 case ScopeIdDeferExpr:
......@@ -3276,6 +3275,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
32763275 case ScopeIdSuspend:
32773276 case ScopeIdCompTime:
32783277 case ScopeIdRuntime:
3278 case ScopeIdElide:
32793279 scope = scope->parent;
32803280 continue;
32813281 case ScopeIdDeferExpr:
......@@ -5549,7 +5549,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
55495549 zig_unreachable();
55505550}
55515551
5552static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5552static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5553 ResultLoc *result_loc)
5554{
55535555 assert(node->type == NodeTypeContainerInitExpr);
55545556
55555557 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
......@@ -5559,39 +5561,61 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
55595561 if (container_type == irb->codegen->invalid_instruction)
55605562 return container_type;
55615563
5562 if (kind == ContainerInitKindStruct) {
5563 size_t field_count = container_init_expr->entries.length;
5564 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
5565 for (size_t i = 0; i < field_count; i += 1) {
5566 AstNode *entry_node = container_init_expr->entries.at(i);
5567 assert(entry_node->type == NodeTypeStructValueField);
5568
5569 Buf *name = entry_node->data.struct_val_field.name;
5570 AstNode *expr_node = entry_node->data.struct_val_field.expr;
5571 IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
5572 if (expr_value == irb->codegen->invalid_instruction)
5573 return expr_value;
5574
5575 fields[i].name = name;
5576 fields[i].value = expr_value;
5577 fields[i].source_node = entry_node;
5578 }
5579 return ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);
5580 } else if (kind == ContainerInitKindArray) {
5581 size_t item_count = container_init_expr->entries.length;
5582 IrInstruction **values = allocate<IrInstruction *>(item_count);
5583 for (size_t i = 0; i < item_count; i += 1) {
5584 AstNode *expr_node = container_init_expr->entries.at(i);
5585 IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
5586 if (expr_value == irb->codegen->invalid_instruction)
5587 return expr_value;
5588
5589 values[i] = expr_value;
5590 }
5591 return ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
5592 } else {
5593 zig_unreachable();
5564 switch (kind) {
5565 case ContainerInitKindStruct: {
5566 src_assert(result_loc->scope_elide == nullptr, node);
5567 result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
5568 size_t field_count = container_init_expr->entries.length;
5569 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
5570 for (size_t i = 0; i < field_count; i += 1) {
5571 AstNode *entry_node = container_init_expr->entries.at(i);
5572 assert(entry_node->type == NodeTypeStructValueField);
5573
5574 Buf *name = entry_node->data.struct_val_field.name;
5575 AstNode *expr_node = entry_node->data.struct_val_field.expr;
5576
5577 ResultLoc *child_result_loc = nullptr;
5578 if (result_loc != nullptr) {
5579 IrInstruction *container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
5580 expr_node, result_loc, container_type);
5581 IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node,
5582 container_ptr, name);
5583 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5584 result_loc_inst->base.id = ResultLocIdInstruction;
5585 result_loc_inst->base.source_instruction = field_ptr;
5586 ir_ref_instruction(field_ptr, irb->current_basic_block);
5587 child_result_loc = &result_loc_inst->base;
5588 }
5589
5590 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, &result_loc->scope_elide->base,
5591 LValNone, child_result_loc);
5592 if (expr_value == irb->codegen->invalid_instruction)
5593 return expr_value;
5594
5595 fields[i].name = name;
5596 fields[i].value = expr_value;
5597 fields[i].source_node = entry_node;
5598 }
5599 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);
5600
5601 return ir_lval_wrap(irb, scope, init_fields, lval, result_loc);
5602 }
5603 case ContainerInitKindArray: {
5604 size_t item_count = container_init_expr->entries.length;
5605 IrInstruction **values = allocate<IrInstruction *>(item_count);
5606 for (size_t i = 0; i < item_count; i += 1) {
5607 AstNode *expr_node = container_init_expr->entries.at(i);
5608 IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);
5609 if (expr_value == irb->codegen->invalid_instruction)
5610 return expr_value;
5611
5612 values[i] = expr_value;
5613 }
5614 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
5615 return ir_lval_wrap(irb, scope, init_list, lval, result_loc);
5616 }
55945617 }
5618 zig_unreachable();
55955619}
55965620
55975621static ResultLocVar *create_var_result_loc(IrInstruction *alloca, ZigVar *var) {
......@@ -7885,7 +7909,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
78857909 case NodeTypePrefixOpExpr:
78867910 return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc);
78877911 case NodeTypeContainerInitExpr:
7888 return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval, result_loc);
7912 return ir_gen_container_init_expr(irb, scope, node, lval, result_loc);
78897913 case NodeTypeVariableDeclaration:
78907914 return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc);
78917915 case NodeTypeWhileExpr:
......@@ -14468,7 +14492,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
1446814492 return &result->base;
1446914493}
1447014494
14471static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_loc) {
14495static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr,
14496 ResultLoc *result_loc)
14497{
1447214498 switch (result_loc->id) {
1447314499 case ResultLocIdInvalid:
1447414500 case ResultLocIdPeerParent:
......@@ -14476,6 +14502,30 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_lo
1447614502 case ResultLocIdNone:
1447714503 case ResultLocIdVar:
1447814504 return nullptr;
14505 case ResultLocIdInstruction:
14506 return result_loc->source_instruction->child->value.type;
14507 case ResultLocIdField: {
14508 if (result_loc->resolved_loc != nullptr) {
14509 ZigType *ptr_type = result_loc->resolved_loc->value.type;
14510 assert(ptr_type->id == ZigTypeIdPointer);
14511 return ptr_type->data.pointer.child_type;
14512 }
14513 ResultLocField *result_loc_field = reinterpret_cast<ResultLocField *>(result_loc);
14514 ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child);
14515 if (type_is_invalid(container_type))
14516 return ira->codegen->builtin_types.entry_invalid;
14517 if (container_type->id == ZigTypeIdStruct) {
14518 TypeStructField *field = find_struct_type_field(container_type, result_loc_field->name);
14519 if (field == nullptr) {
14520 return ira->codegen->builtin_types.entry_invalid;
14521 }
14522 return field->type_entry;
14523 } else if (container_type->id == ZigTypeIdUnion) {
14524 zig_panic("TODO");
14525 } else {
14526 zig_unreachable();
14527 }
14528 }
1447914529 case ResultLocIdReturn:
1448014530 return ira->explicit_return_type;
1448114531 case ResultLocIdPeer:
......@@ -14491,7 +14541,10 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
1449114541 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value)
1449214542{
1449314543 if (result_loc->resolved_loc != nullptr) {
14494 return result_loc->resolved_loc;
14544 // allow to redo the result location if the value is known and comptime and the previous one isn't
14545 if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) {
14546 return result_loc->resolved_loc;
14547 }
1449514548 }
1449614549 result_loc->gen_instruction = value;
1449714550 result_loc->implicit_elem_type = value_type;
......@@ -14524,7 +14577,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
1452414577 return ira->codegen->invalid_instruction;
1452514578 bool is_comptime = force_comptime || (value != nullptr &&
1452614579 value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const);
14527 if (alloca_src->base.child == nullptr) {
14580 if (alloca_src->base.child == nullptr || is_comptime) {
1452814581 uint32_t align = 0;
1452914582 if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
1453014583 return ira->codegen->invalid_instruction;
......@@ -14539,12 +14592,40 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
1453914592 alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
1454014593 alloca_src->name_hint, force_comptime);
1454114594 }
14595 if (alloca_src->base.child != nullptr) {
14596 alloca_src->base.child->ref_count = 0;
14597 }
1454214598 alloca_src->base.child = alloca_gen;
1454314599 }
1454414600 result_loc->written = true;
1454514601 result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child;
1454614602 return result_loc->resolved_loc;
1454714603 }
14604 case ResultLocIdInstruction: {
14605 result_loc->written = true;
14606 result_loc->resolved_loc = result_loc->source_instruction->child;
14607 return result_loc->resolved_loc;
14608 }
14609 case ResultLocIdField: {
14610 ResultLocField *result_loc_field = reinterpret_cast<ResultLocField *>(result_loc);
14611
14612 ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child);
14613 if (type_is_invalid(container_type))
14614 return ira->codegen->invalid_instruction;
14615
14616 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr,
14617 result_loc_field->parent, container_type, nullptr);
14618 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
14619 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
14620 {
14621 return parent_result_loc;
14622 }
14623
14624 result_loc->written = true;
14625 result_loc->resolved_loc = ir_analyze_container_field_ptr(ira, result_loc_field->name,
14626 suspend_source_instr, parent_result_loc, container_type);
14627 return result_loc->resolved_loc;
14628 }
1454814629 case ResultLocIdReturn: {
1454914630 bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
1455014631 if (is_comptime) return nullptr;
......@@ -14593,7 +14674,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
1459314674 ira->resume_stack.append(opposite_peer->suspend_pos);
1459414675 }
1459514676 }
14596 ZigType *expected_type = ir_result_loc_expected_type(ira, peer_parent->parent);
14677 ZigType *expected_type = ir_result_loc_expected_type(ira, suspend_source_instr, peer_parent->parent);
1459714678 peer_parent->resolved_type = ir_resolve_peer_types(ira,
1459814679 peer_parent->base.source_instruction->source_node, expected_type, instructions,
1459914680 peer_parent->peer_count);
......@@ -14626,6 +14707,12 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
1462614707 return ir_implicit_cast(ira, target, dest_type);
1462714708}
1462814709
14710static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
14711 ZigType *ty = ir_resolve_type(ira, instruction->ty->child);
14712 if (type_is_invalid(ty))
14713 return ira->codegen->invalid_instruction;
14714 return ir_resolve_result(ira, &instruction->base, instruction->result_loc, ty, nullptr);
14715}
1462914716
1463014717static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
1463114718 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
......@@ -18330,8 +18417,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1833018417
1833118418 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);
1833218419
18333 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
18334
1833518420 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
1833618421 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1833718422
......@@ -18371,9 +18456,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1837118456 }
1837218457 field_assign_nodes[field_index] = field->source_node;
1837318458
18374 new_fields[field_index].value = casted_field_value;
18375 new_fields[field_index].type_struct_field = type_field;
18376
1837718459 if (const_val.special == ConstValSpecialStatic) {
1837818460 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {
1837918461 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
......@@ -18416,9 +18498,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1841618498 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
1841718499 copy_const_val(&runtime_inst->value, field->init_val, true);
1841818500
18419 new_fields[i].value = runtime_inst;
18420 new_fields[i].type_struct_field = field;
18421
1842218501 if (const_val.special == ConstValSpecialStatic) {
1842318502 copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
1842418503 }
......@@ -18451,12 +18530,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1845118530 return ira->codegen->invalid_instruction;
1845218531 }
1845318532
18454 IrInstruction *new_instruction = ir_build_struct_init(&ira->new_irb,
18455 instruction->scope, instruction->source_node,
18456 container_type, actual_field_count, new_fields);
18457 new_instruction->value.type = container_type;
18458 ir_add_alloca(ira, new_instruction, container_type);
18459 return new_instruction;
18533 // this instruction should not get to codegen
18534 IrInstruction *result = ir_const(ira, instruction, container_type);
18535 // this is how we signal to EndExpr the value is not comptime known
18536 result->value.special = ConstValSpecialRuntime;
18537 return result;
1846018538}
1846118539
1846218540static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
......@@ -23794,7 +23872,18 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
2379423872 if (type_is_invalid(value->value.type))
2379523873 return ira->codegen->invalid_instruction;
2379623874
23797 if (!instruction->result_loc->written) {
23875 bool want_resolve_result = instruction->result_loc->written;
23876 if (instruction->result_loc->written) {
23877 if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) {
23878 want_resolve_result = true;
23879 instruction->result_loc->scope_elide->activated = true;
23880 } else {
23881 want_resolve_result = false;
23882 }
23883 } else {
23884 want_resolve_result = true;
23885 }
23886 if (want_resolve_result) {
2379823887 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
2379923888 value->value.type, value);
2380023889 if (result_loc != nullptr) {
......@@ -23815,7 +23904,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2381523904 switch (instruction->id) {
2381623905 case IrInstructionIdInvalid:
2381723906 case IrInstructionIdWidenOrShorten:
23818 case IrInstructionIdStructInit:
2381923907 case IrInstructionIdUnionInit:
2382023908 case IrInstructionIdStructFieldPtr:
2382123909 case IrInstructionIdUnionFieldPtr:
......@@ -24036,6 +24124,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2403624124 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
2403724125 case IrInstructionIdImplicitCast:
2403824126 return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
24127 case IrInstructionIdResolveResult:
24128 return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
2403924129 case IrInstructionIdOpaqueType:
2404024130 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
2404124131 case IrInstructionIdSetAlignStack:
......@@ -24260,7 +24350,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2426024350 case IrInstructionIdCast:
2426124351 case IrInstructionIdContainerInitList:
2426224352 case IrInstructionIdContainerInitFields:
24263 case IrInstructionIdStructInit:
2426424353 case IrInstructionIdUnionInit:
2426524354 case IrInstructionIdFieldPtr:
2426624355 case IrInstructionIdElemPtr:
......@@ -24326,6 +24415,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2432624415 case IrInstructionIdTypeId:
2432724416 case IrInstructionIdAlignCast:
2432824417 case IrInstructionIdImplicitCast:
24418 case IrInstructionIdResolveResult:
2432924419 case IrInstructionIdOpaqueType:
2433024420 case IrInstructionIdArgType:
2433124421 case IrInstructionIdTagType:
src/ir_print.cpp+25-15
......@@ -207,6 +207,18 @@ static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var)
207207 fprintf(irp->f, ")");
208208}
209209
210static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) {
211 fprintf(irp->f, "inst(");
212 ir_print_other_instruction(irp, result_loc_inst->base.source_instruction);
213 fprintf(irp->f, ")");
214}
215
216static void ir_print_result_loc_field(IrPrint *irp, ResultLocField *result_loc_field) {
217 fprintf(irp->f, "field(name=%s,type=", buf_ptr(result_loc_field->name));
218 ir_print_other_instruction(irp, result_loc_field->container_type);
219 fprintf(irp->f, ")");
220}
221
210222static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) {
211223 fprintf(irp->f, "peer(next=");
212224 ir_print_other_block(irp, result_loc_peer->next_bb);
......@@ -225,6 +237,10 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
225237 return;
226238 case ResultLocIdVar:
227239 return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
240 case ResultLocIdInstruction:
241 return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
242 case ResultLocIdField:
243 return ir_print_result_loc_field(irp, (ResultLocField *)result_loc);
228244 case ResultLocIdPeer:
229245 return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
230246 case ResultLocIdPeerParent:
......@@ -352,18 +368,6 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
352368 fprintf(irp->f, "} // container init");
353369}
354370
355static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) {
356 fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name));
357 for (size_t i = 0; i < instruction->field_count; i += 1) {
358 IrInstructionStructInitField *field = &instruction->fields[i];
359 Buf *field_name = field->type_struct_field->name;
360 const char *comma = (i == 0) ? "" : ", ";
361 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name));
362 ir_print_other_instruction(irp, field->value);
363 }
364 fprintf(irp->f, "} // struct init");
365}
366
367371static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
368372 Buf *field_name = instruction->field->enum_field->name;
369373
......@@ -1265,6 +1269,12 @@ static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *inst
12651269 fprintf(irp->f, ")");
12661270}
12671271
1272static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) {
1273 fprintf(irp->f, "ResolveResult(");
1274 ir_print_result_loc(irp, instruction->result_loc);
1275 fprintf(irp->f, ")");
1276}
1277
12681278static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
12691279 fprintf(irp->f, "@OpaqueType()");
12701280}
......@@ -1588,9 +1598,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15881598 case IrInstructionIdContainerInitFields:
15891599 ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
15901600 break;
1591 case IrInstructionIdStructInit:
1592 ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
1593 break;
15941601 case IrInstructionIdUnionInit:
15951602 ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
15961603 break;
......@@ -1900,6 +1907,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
19001907 case IrInstructionIdImplicitCast:
19011908 ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction);
19021909 break;
1910 case IrInstructionIdResolveResult:
1911 ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
1912 break;
19031913 case IrInstructionIdOpaqueType:
19041914 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
19051915 break;