Commit 771e88951a
Changed files (7)
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;
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<ScopeElide>(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<ScopeSuspend>(1);
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);
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<ScopeElide *>(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;
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<IrInstructionStructInit>(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<IrInstructionResolveResult>(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<IrInstructionOpaqueType>(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<IrInstructionContainerInitFieldsField>(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;
-
- fields[i].name = name;
- fields[i].value = expr_value;
- fields[i].source_node = entry_node;
- }
- 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<IrInstruction *>(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;
- }
- return ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
- } else {
- zig_unreachable();
+ 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<IrInstructionContainerInitFieldsField>(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;
+
+ 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<ResultLocInstruction>(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);
+ }
+ case ContainerInitKindArray: {
+ size_t item_count = container_init_expr->entries.length;
+ IrInstruction **values = allocate<IrInstruction *>(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;
+ }
+ 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);
+ }
}
+ 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<ResultLocField *>(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<ResultLocField *>(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<AstNode *>(actual_field_count);
- IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(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:
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;
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
-
-
-
-