diff --git a/BRANCH_TODO b/BRANCH_TODO index fc8a654772..843703e20b 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,8 +1,8 @@ Scratch pad for stuff to do before merging master ================================================= - * struct initializations - * function call parameters + * array initializations + * union initializations * bitCast look 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 return ir_build_ref(irb, scope, value->source_node, value, false, false); handle if with no else - - - - diff --git a/src/all_types.hpp b/src/all_types.hpp index 0061b5999f..fbd788c9d9 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1957,6 +1957,7 @@ enum ScopeId { ScopeIdCompTime, ScopeIdCoroPrelude, ScopeIdRuntime, + ScopeIdElide, }; struct Scope { @@ -1970,6 +1971,14 @@ struct Scope { ScopeId id; }; +// This scope, when activated, causes all the instructions in the scope to be omitted +// from the generated code. +struct ScopeElide { + Scope base; + + bool activated; +}; + // This scope comes from global declarations or from // declarations in a container declaration // NodeTypeContainerDecl @@ -2189,7 +2198,6 @@ enum IrInstructionId { IrInstructionIdResizeSlice, IrInstructionIdContainerInitList, IrInstructionIdContainerInitFields, - IrInstructionIdStructInit, IrInstructionIdUnionInit, IrInstructionIdUnreachable, IrInstructionIdTypeOf, @@ -2279,6 +2287,7 @@ enum IrInstructionId { IrInstructionIdPtrType, IrInstructionIdAlignCast, IrInstructionIdImplicitCast, + IrInstructionIdResolveResult, IrInstructionIdOpaqueType, IrInstructionIdSetAlignStack, IrInstructionIdArgType, @@ -2366,6 +2375,7 @@ struct IrInstructionCondBr { IrBasicBlock *then_block; IrBasicBlock *else_block; IrInstruction *is_comptime; + ResultLoc *result_loc; }; struct IrInstructionBr { @@ -2646,20 +2656,6 @@ struct IrInstructionContainerInitFields { IrInstructionContainerInitFieldsField *fields; }; -struct IrInstructionStructInitField { - IrInstruction *value; - TypeStructField *type_struct_field; -}; - -struct IrInstructionStructInit { - IrInstruction base; - - ZigType *struct_type; - size_t field_count; - IrInstructionStructInitField *fields; - LLVMValueRef tmp_ptr; -}; - struct IrInstructionUnionInit { IrInstruction base; @@ -3581,13 +3577,22 @@ struct IrInstructionImplicitCast { IrInstruction *target; }; +struct IrInstructionResolveResult { + IrInstruction base; + + ResultLoc *result_loc; + IrInstruction *ty; +}; + enum ResultLocId { ResultLocIdInvalid, ResultLocIdNone, ResultLocIdVar, + ResultLocIdField, ResultLocIdReturn, ResultLocIdPeer, ResultLocIdPeerParent, + ResultLocIdInstruction, }; struct ResultLoc { @@ -3597,6 +3602,7 @@ struct ResultLoc { IrInstruction *source_instruction; IrInstruction *gen_instruction; // value to store to the result loc ZigType *implicit_elem_type; + ScopeElide *scope_elide; }; struct ResultLocNone { @@ -3609,6 +3615,14 @@ struct ResultLocVar { ZigVar *var; }; +struct ResultLocField { + ResultLoc base; + + ResultLoc *parent; + Buf *name; + IrInstruction *container_type; +}; + struct ResultLocReturn { ResultLoc base; }; @@ -3636,6 +3650,11 @@ struct ResultLocPeer { IrSuspendPosition suspend_pos; }; +// The result location is the source instruction +struct ResultLocInstruction { + ResultLoc base; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp index 771e11e93f..6299ac6699 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -166,6 +166,12 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruct return &scope->base; } +ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent) { + ScopeElide *scope = allocate(1); + init_scope(g, &scope->base, ScopeIdElide, node, parent); + return scope; +} + ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeSuspend); ScopeSuspend *scope = allocate(1); diff --git a/src/analyze.hpp b/src/analyze.hpp index 57f1072355..2f3ec663da 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -121,6 +121,7 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn * Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime); +ScopeElide *create_elide_scope(CodeGen *g, AstNode *node, Scope *parent); void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str); ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); diff --git a/src/codegen.cpp b/src/codegen.cpp index eecc2239db..4fa13c39a2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -715,6 +715,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { case ScopeIdCompTime: case ScopeIdCoroPrelude: case ScopeIdRuntime: + case ScopeIdElide: return get_di_scope(g, scope->parent); } zig_unreachable(); @@ -2383,7 +2384,6 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut } static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) { - LLVMValueRef value = ir_llvm_value(g, return_instruction->value); ZigType *return_type = return_instruction->value->value.type; 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 if (return_instruction->value->value.special != ConstValSpecialRuntime) { // if it's comptime we have to do this but if it's runtime trust that // result location mechanism took care of it. + LLVMValueRef value = ir_llvm_value(g, return_instruction->value); gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value); } LLVMBuildRetVoid(g->builder); } else if (handle_is_ptr(return_type)) { + LLVMValueRef value = ir_llvm_value(g, return_instruction->value); LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } else { + LLVMValueRef value = ir_llvm_value(g, return_instruction->value); LLVMBuildRet(g->builder, value); } return nullptr; @@ -5032,29 +5035,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); } -static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) { - for (size_t i = 0; i < instruction->field_count; i += 1) { - IrInstructionStructInitField *field = &instruction->fields[i]; - TypeStructField *type_struct_field = field->type_struct_field; - if (!type_has_bits(type_struct_field->type_entry)) - continue; - - LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, - (unsigned)type_struct_field->gen_index, ""); - LLVMValueRef value = ir_llvm_value(g, field->value); - - uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry); - uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field); - - ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, - false, false, PtrLenSingle, field_align_bytes, - (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false); - - gen_assign_raw(g, field_ptr, ptr_type, value); - } - return instruction->tmp_ptr; -} - static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) { TypeUnionField *type_union_field = instruction->field; @@ -5531,10 +5511,6 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) { } static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { - if (!g->strip_debug_symbols) { - set_debug_location(g, instruction); - } - switch (instruction->id) { case IrInstructionIdInvalid: case IrInstructionIdConst: @@ -5609,6 +5585,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdEndExpr: case IrInstructionIdAllocaGen: case IrInstructionIdImplicitCast: + case IrInstructionIdResolveResult: zig_unreachable(); case IrInstructionIdDeclVarGen: @@ -5705,8 +5682,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); case IrInstructionIdUnionTag: return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction); - case IrInstructionIdStructInit: - return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); case IrInstructionIdUnionInit: return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); case IrInstructionIdPtrCastGen: @@ -5791,6 +5766,34 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, zig_unreachable(); } +static bool scope_is_elided(Scope *scope) { + for (;;) { + switch (scope->id) { + case ScopeIdDecls: + case ScopeIdCompTime: + case ScopeIdCImport: + zig_unreachable(); + case ScopeIdElide: + if (reinterpret_cast(scope)->activated) + return true; + // fallthrough + case ScopeIdBlock: + case ScopeIdDefer: + case ScopeIdDeferExpr: + case ScopeIdVarDecl: + case ScopeIdLoop: + case ScopeIdSuspend: + case ScopeIdCoroPrelude: + case ScopeIdRuntime: + scope = scope->parent; + continue; + case ScopeIdFnDef: + return false; + } + zig_unreachable(); + } +} + static void ir_render(CodeGen *g, ZigFn *fn_entry) { assert(fn_entry); @@ -5806,7 +5809,12 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { if (instruction->ref_count == 0 && !ir_has_side_effects(instruction)) continue; - instruction->llvm_value = ir_render_instruction(g, executable, instruction); + if (!scope_is_elided(instruction->scope)) { + if (!g->strip_debug_symbols) { + set_debug_location(g, instruction); + } + instruction->llvm_value = ir_render_instruction(g, executable, instruction); + } } current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder); } @@ -6891,9 +6899,6 @@ static void do_code_gen(CodeGen *g) { } else if (instruction->id == IrInstructionIdContainerInitList) { IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction; slot = &container_init_list_instruction->tmp_ptr; - } else if (instruction->id == IrInstructionIdStructInit) { - IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction; - slot = &struct_init_instruction->tmp_ptr; } else if (instruction->id == IrInstructionIdUnionInit) { IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction; slot = &union_init_instruction->tmp_ptr; diff --git a/src/ir.cpp b/src/ir.cpp index 7f5b7da6e1..d34630554c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -616,10 +616,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { return IrInstructionIdRef; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) { - return IrInstructionIdStructInit; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) { return IrInstructionIdUnionInit; } @@ -888,6 +884,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *) return IrInstructionIdImplicitCast; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) { + return IrInstructionIdResolveResult; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) { return IrInstructionIdOpaqueType; } @@ -1517,20 +1517,6 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop return &container_init_fields_instruction->base; } -static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode *source_node, - ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields) -{ - IrInstructionStructInit *struct_init_instruction = ir_build_instruction(irb, scope, source_node); - struct_init_instruction->struct_type = struct_type; - struct_init_instruction->field_count = field_count; - struct_init_instruction->fields = fields; - - for (size_t i = 0; i < field_count; i += 1) - ir_ref_instruction(fields[i].value, irb->current_basic_block); - - return &struct_init_instruction->base; -} - static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigType *union_type, TypeUnionField *field, IrInstruction *init_value) { @@ -2764,6 +2750,18 @@ static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } +static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node, + ResultLoc *result_loc, IrInstruction *ty) +{ + IrInstructionResolveResult *instruction = ir_build_instruction(irb, scope, source_node); + instruction->result_loc = result_loc; + instruction->ty = ty; + + ir_ref_instruction(ty, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) { IrInstructionOpaqueType *instruction = ir_build_instruction(irb, scope, source_node); @@ -3220,6 +3218,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco case ScopeIdSuspend: case ScopeIdCompTime: case ScopeIdRuntime: + case ScopeIdElide: scope = scope->parent; continue; case ScopeIdDeferExpr: @@ -3276,6 +3275,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o case ScopeIdSuspend: case ScopeIdCompTime: case ScopeIdRuntime: + case ScopeIdElide: scope = scope->parent; continue; case ScopeIdDeferExpr: @@ -5549,7 +5549,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod zig_unreachable(); } -static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, + ResultLoc *result_loc) +{ assert(node->type == NodeTypeContainerInitExpr); 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 if (container_type == irb->codegen->invalid_instruction) return container_type; - if (kind == ContainerInitKindStruct) { - size_t field_count = container_init_expr->entries.length; - IrInstructionContainerInitFieldsField *fields = allocate(field_count); - for (size_t i = 0; i < field_count; i += 1) { - AstNode *entry_node = container_init_expr->entries.at(i); - assert(entry_node->type == NodeTypeStructValueField); + switch (kind) { + case ContainerInitKindStruct: { + src_assert(result_loc->scope_elide == nullptr, node); + result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope); + size_t field_count = container_init_expr->entries.length; + IrInstructionContainerInitFieldsField *fields = allocate(field_count); + for (size_t i = 0; i < field_count; i += 1) { + AstNode *entry_node = container_init_expr->entries.at(i); + assert(entry_node->type == NodeTypeStructValueField); - Buf *name = entry_node->data.struct_val_field.name; - AstNode *expr_node = entry_node->data.struct_val_field.expr; - IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope); - if (expr_value == irb->codegen->invalid_instruction) - return expr_value; + Buf *name = entry_node->data.struct_val_field.name; + AstNode *expr_node = entry_node->data.struct_val_field.expr; - fields[i].name = name; - fields[i].value = expr_value; - fields[i].source_node = entry_node; + ResultLoc *child_result_loc = nullptr; + if (result_loc != nullptr) { + IrInstruction *container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base, + expr_node, result_loc, container_type); + IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node, + container_ptr, name); + ResultLocInstruction *result_loc_inst = allocate(1); + result_loc_inst->base.id = ResultLocIdInstruction; + result_loc_inst->base.source_instruction = field_ptr; + ir_ref_instruction(field_ptr, irb->current_basic_block); + child_result_loc = &result_loc_inst->base; + } + + IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, &result_loc->scope_elide->base, + LValNone, child_result_loc); + if (expr_value == irb->codegen->invalid_instruction) + return expr_value; + + fields[i].name = name; + fields[i].value = expr_value; + fields[i].source_node = entry_node; + } + IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields); + + return ir_lval_wrap(irb, scope, init_fields, lval, result_loc); } - return ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields); - } else if (kind == ContainerInitKindArray) { - size_t item_count = container_init_expr->entries.length; - IrInstruction **values = allocate(item_count); - for (size_t i = 0; i < item_count; i += 1) { - AstNode *expr_node = container_init_expr->entries.at(i); - IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope); - if (expr_value == irb->codegen->invalid_instruction) - return expr_value; + case ContainerInitKindArray: { + size_t item_count = container_init_expr->entries.length; + IrInstruction **values = allocate(item_count); + for (size_t i = 0; i < item_count; i += 1) { + AstNode *expr_node = container_init_expr->entries.at(i); + IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope); + if (expr_value == irb->codegen->invalid_instruction) + return expr_value; - values[i] = expr_value; + values[i] = expr_value; + } + IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, item_count, values); + return ir_lval_wrap(irb, scope, init_list, lval, result_loc); } - return ir_build_container_init_list(irb, scope, node, container_type, item_count, values); - } else { - zig_unreachable(); } + zig_unreachable(); } static 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 case NodeTypePrefixOpExpr: return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc); case NodeTypeContainerInitExpr: - return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval, result_loc); + return ir_gen_container_init_expr(irb, scope, node, lval, result_loc); case NodeTypeVariableDeclaration: return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc); case NodeTypeWhileExpr: @@ -14468,7 +14492,9 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in return &result->base; } -static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_loc) { +static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr, + ResultLoc *result_loc) +{ switch (result_loc->id) { case ResultLocIdInvalid: case ResultLocIdPeerParent: @@ -14476,6 +14502,30 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, ResultLoc *result_lo case ResultLocIdNone: case ResultLocIdVar: return nullptr; + case ResultLocIdInstruction: + return result_loc->source_instruction->child->value.type; + case ResultLocIdField: { + if (result_loc->resolved_loc != nullptr) { + ZigType *ptr_type = result_loc->resolved_loc->value.type; + assert(ptr_type->id == ZigTypeIdPointer); + return ptr_type->data.pointer.child_type; + } + ResultLocField *result_loc_field = reinterpret_cast(result_loc); + ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child); + if (type_is_invalid(container_type)) + return ira->codegen->builtin_types.entry_invalid; + if (container_type->id == ZigTypeIdStruct) { + TypeStructField *field = find_struct_type_field(container_type, result_loc_field->name); + if (field == nullptr) { + return ira->codegen->builtin_types.entry_invalid; + } + return field->type_entry; + } else if (container_type->id == ZigTypeIdUnion) { + zig_panic("TODO"); + } else { + zig_unreachable(); + } + } case ResultLocIdReturn: return ira->explicit_return_type; case ResultLocIdPeer: @@ -14491,7 +14541,10 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s ResultLoc *result_loc, ZigType *value_type, IrInstruction *value) { if (result_loc->resolved_loc != nullptr) { - return result_loc->resolved_loc; + // allow to redo the result location if the value is known and comptime and the previous one isn't + if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) { + return result_loc->resolved_loc; + } } result_loc->gen_instruction = value; result_loc->implicit_elem_type = value_type; @@ -14524,7 +14577,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s return ira->codegen->invalid_instruction; bool is_comptime = force_comptime || (value != nullptr && value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const); - if (alloca_src->base.child == nullptr) { + if (alloca_src->base.child == nullptr || is_comptime) { uint32_t align = 0; if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) { return ira->codegen->invalid_instruction; @@ -14539,12 +14592,40 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align, alloca_src->name_hint, force_comptime); } + if (alloca_src->base.child != nullptr) { + alloca_src->base.child->ref_count = 0; + } alloca_src->base.child = alloca_gen; } result_loc->written = true; result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child; return result_loc->resolved_loc; } + case ResultLocIdInstruction: { + result_loc->written = true; + result_loc->resolved_loc = result_loc->source_instruction->child; + return result_loc->resolved_loc; + } + case ResultLocIdField: { + ResultLocField *result_loc_field = reinterpret_cast(result_loc); + + ZigType *container_type = ir_resolve_type(ira, result_loc_field->container_type->child); + if (type_is_invalid(container_type)) + return ira->codegen->invalid_instruction; + + IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, + result_loc_field->parent, container_type, nullptr); + if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || + parent_result_loc->value.type->id == ZigTypeIdUnreachable) + { + return parent_result_loc; + } + + result_loc->written = true; + result_loc->resolved_loc = ir_analyze_container_field_ptr(ira, result_loc_field->name, + suspend_source_instr, parent_result_loc, container_type); + return result_loc->resolved_loc; + } case ResultLocIdReturn: { bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime; if (is_comptime) return nullptr; @@ -14593,7 +14674,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s ira->resume_stack.append(opposite_peer->suspend_pos); } } - ZigType *expected_type = ir_result_loc_expected_type(ira, peer_parent->parent); + ZigType *expected_type = ir_result_loc_expected_type(ira, suspend_source_instr, peer_parent->parent); peer_parent->resolved_type = ir_resolve_peer_types(ira, peer_parent->base.source_instruction->source_node, expected_type, instructions, peer_parent->peer_count); @@ -14626,6 +14707,12 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns return ir_implicit_cast(ira, target, dest_type); } +static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) { + ZigType *ty = ir_resolve_type(ira, instruction->ty->child); + if (type_is_invalid(ty)) + return ira->codegen->invalid_instruction; + return ir_resolve_result(ira, &instruction->base, instruction->result_loc, ty, nullptr); +} static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry, 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 AstNode **field_assign_nodes = allocate(actual_field_count); - IrInstructionStructInitField *new_fields = allocate(actual_field_count); - bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; @@ -18371,9 +18456,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc } field_assign_nodes[field_index] = field->source_node; - new_fields[field_index].value = casted_field_value; - new_fields[field_index].type_struct_field = type_field; - if (const_val.special == ConstValSpecialStatic) { if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) { 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 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type); copy_const_val(&runtime_inst->value, field->init_val, true); - new_fields[i].value = runtime_inst; - new_fields[i].type_struct_field = field; - if (const_val.special == ConstValSpecialStatic) { copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true); } @@ -18451,12 +18530,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc return ira->codegen->invalid_instruction; } - IrInstruction *new_instruction = ir_build_struct_init(&ira->new_irb, - instruction->scope, instruction->source_node, - container_type, actual_field_count, new_fields); - new_instruction->value.type = container_type; - ir_add_alloca(ira, new_instruction, container_type); - return new_instruction; + // this instruction should not get to codegen + IrInstruction *result = ir_const(ira, instruction, container_type); + // this is how we signal to EndExpr the value is not comptime known + result->value.special = ConstValSpecialRuntime; + return result; } static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, @@ -23794,7 +23872,18 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; - if (!instruction->result_loc->written) { + bool want_resolve_result = instruction->result_loc->written; + if (instruction->result_loc->written) { + if (instruction->result_loc->scope_elide != nullptr && instr_is_comptime(value)) { + want_resolve_result = true; + instruction->result_loc->scope_elide->activated = true; + } else { + want_resolve_result = false; + } + } else { + want_resolve_result = true; + } + if (want_resolve_result) { IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, value->value.type, value); if (result_loc != nullptr) { @@ -23815,7 +23904,6 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction switch (instruction->id) { case IrInstructionIdInvalid: case IrInstructionIdWidenOrShorten: - case IrInstructionIdStructInit: case IrInstructionIdUnionInit: case IrInstructionIdStructFieldPtr: case IrInstructionIdUnionFieldPtr: @@ -24036,6 +24124,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction); case IrInstructionIdImplicitCast: return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction); + case IrInstructionIdResolveResult: + return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction); case IrInstructionIdOpaqueType: return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction); case IrInstructionIdSetAlignStack: @@ -24260,7 +24350,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCast: case IrInstructionIdContainerInitList: case IrInstructionIdContainerInitFields: - case IrInstructionIdStructInit: case IrInstructionIdUnionInit: case IrInstructionIdFieldPtr: case IrInstructionIdElemPtr: @@ -24326,6 +24415,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdTypeId: case IrInstructionIdAlignCast: case IrInstructionIdImplicitCast: + case IrInstructionIdResolveResult: case IrInstructionIdOpaqueType: case IrInstructionIdArgType: case IrInstructionIdTagType: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 7d56b157d5..0f80a9b9e3 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -207,6 +207,18 @@ static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var) fprintf(irp->f, ")"); } +static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) { + fprintf(irp->f, "inst("); + ir_print_other_instruction(irp, result_loc_inst->base.source_instruction); + fprintf(irp->f, ")"); +} + +static void ir_print_result_loc_field(IrPrint *irp, ResultLocField *result_loc_field) { + fprintf(irp->f, "field(name=%s,type=", buf_ptr(result_loc_field->name)); + ir_print_other_instruction(irp, result_loc_field->container_type); + fprintf(irp->f, ")"); +} + static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) { fprintf(irp->f, "peer(next="); 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) { return; case ResultLocIdVar: return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc); + case ResultLocIdInstruction: + return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc); + case ResultLocIdField: + return ir_print_result_loc_field(irp, (ResultLocField *)result_loc); case ResultLocIdPeer: return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc); case ResultLocIdPeerParent: @@ -352,18 +368,6 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI fprintf(irp->f, "} // container init"); } -static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) { - fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name)); - for (size_t i = 0; i < instruction->field_count; i += 1) { - IrInstructionStructInitField *field = &instruction->fields[i]; - Buf *field_name = field->type_struct_field->name; - const char *comma = (i == 0) ? "" : ", "; - fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name)); - ir_print_other_instruction(irp, field->value); - } - fprintf(irp->f, "} // struct init"); -} - static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) { Buf *field_name = instruction->field->enum_field->name; @@ -1265,6 +1269,12 @@ static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *inst fprintf(irp->f, ")"); } +static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) { + fprintf(irp->f, "ResolveResult("); + ir_print_result_loc(irp, instruction->result_loc); + fprintf(irp->f, ")"); +} + static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) { fprintf(irp->f, "@OpaqueType()"); } @@ -1588,9 +1598,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdContainerInitFields: ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction); break; - case IrInstructionIdStructInit: - ir_print_struct_init(irp, (IrInstructionStructInit *)instruction); - break; case IrInstructionIdUnionInit: ir_print_union_init(irp, (IrInstructionUnionInit *)instruction); break; @@ -1900,6 +1907,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdImplicitCast: ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction); break; + case IrInstructionIdResolveResult: + ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction); + break; case IrInstructionIdOpaqueType: ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction); break;