From fbcee58cfcabddd3e0842e22141a983a8169502f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 9 Jan 2020 19:15:46 -0500 Subject: [PATCH 01/28] zig ir.cpp details: remove the mem_slot mechanism Previously, there was hacky code to deal with result locations and how they work with regards to comptime values and runtime values. In addition, there was a hacky "mem_slot" mechanism that managed the memory for local variables, and acted differently depending on comptime vs runtime situations. All that is deleted in this commit, and as a result, result locations code has one less complication. Importantly, this means that a comptime result location is now passed to a function when it is evaluated at comptime. This test causes many regressions, and some of the behavior tests are disabled (commented out) in this commit. Future commits will re-enable the tests before merging the branch. --- src/all_types.hpp | 1 - src/analyze.cpp | 37 +++- src/codegen.cpp | 2 +- src/ir.cpp | 440 ++++++++++++++++++++------------------- src/ir.hpp | 6 +- test/stage1/behavior.zig | 28 +-- 6 files changed, 279 insertions(+), 235 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 4d6f68daf..216fddcb1 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2230,7 +2230,6 @@ struct ZigVar { Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; - size_t mem_slot_index; IrExecutable *owner_exec; Buf *section_name; diff --git a/src/analyze.cpp b/src/analyze.cpp index b7838003c..435020014 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1102,11 +1102,28 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name, UndefAllowed undef) { + Error err; + + ZigValue *result = create_const_vals(1); + ZigValue *result_ptr = create_const_vals(1); + result->special = ConstValSpecialUndef; + result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry; + result_ptr->special = ConstValSpecialStatic; + result_ptr->type = get_pointer_to_type(g, result->type, false); + result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar; + result_ptr->data.x_ptr.special = ConstPtrSpecialRef; + result_ptr->data.x_ptr.data.ref.pointee = result; + size_t backward_branch_count = 0; size_t backward_branch_quota = default_backward_branch_quota; - return ir_eval_const_value(g, scope, node, type_entry, + if ((err = ir_eval_const_value(g, scope, node, result_ptr, &backward_branch_count, &backward_branch_quota, - nullptr, nullptr, node, type_name, nullptr, nullptr, undef); + nullptr, nullptr, node, type_name, nullptr, nullptr, undef))) + { + return g->invalid_instruction->value; + } + destroy(result_ptr, "ZigValue"); + return result; } Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type, @@ -3805,7 +3822,6 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf variable_entry->var_type = var_type; variable_entry->parent_scope = parent_scope; variable_entry->shadowable = false; - variable_entry->mem_slot_index = SIZE_MAX; variable_entry->src_arg_index = SIZE_MAX; assert(name); @@ -3906,7 +3922,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { // TODO more validation for types that can't be used for export/extern variables ZigType *implicit_type = nullptr; - if (explicit_type && explicit_type->id == ZigTypeIdInvalid) { + if (explicit_type != nullptr && explicit_type->id == ZigTypeIdInvalid) { implicit_type = explicit_type; } else if (var_decl->expr) { init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, @@ -4694,8 +4710,14 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { assert(!fn_type->data.fn.is_generic); FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; + if (fn->analyzed_executable.begin_scope == nullptr) { + fn->analyzed_executable.begin_scope = &fn->def_scope->base; + } + if (fn->analyzed_executable.source_node == nullptr) { + fn->analyzed_executable.source_node = fn->body_node; + } ZigType *block_return_type = ir_analyze(g, fn->ir_executable, - &fn->analyzed_executable, fn_type_id->return_type, return_type_node); + &fn->analyzed_executable, fn_type_id->return_type, return_type_node, nullptr); fn->src_implicit_return_type = block_return_type; if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) { @@ -6850,6 +6872,7 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu } case ConstArraySpecialNone: { ZigValue *base = &array->data.s_none.elements[start]; + assert(base != nullptr); assert(start + len <= const_val->type->data.array.len); buf_appendf(buf, "%s{", buf_ptr(type_name)); @@ -6865,6 +6888,10 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu } void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) { + if (const_val == nullptr) { + buf_appendf(buf, "(invalid nullptr value)"); + return; + } switch (const_val->special) { case ConstValSpecialRuntime: buf_appendf(buf, "(runtime value)"); diff --git a/src/codegen.cpp b/src/codegen.cpp index cd009b3be..c4add2ce7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7604,7 +7604,7 @@ static void do_code_gen(CodeGen *g) { } else { if (want_sret) { g->cur_ret_ptr = LLVMGetParam(fn, 0); - } else if (handle_is_ptr(fn_type_id->return_type)) { + } else if (type_has_bits(fn_type_id->return_type)) { g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); // TODO add debug info variable for this } else { diff --git a/src/ir.cpp b/src/ir.cpp index 818644f50..67bd46364 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17,10 +17,6 @@ #include -struct IrExecContext { - ZigList mem_slot_list; -}; - struct IrBuilder { CodeGen *codegen; IrExecutable *exec; @@ -32,7 +28,6 @@ struct IrAnalyze { CodeGen *codegen; IrBuilder old_irb; IrBuilder new_irb; - IrExecContext exec_context; size_t old_bb_index; size_t instruction_index; ZigType *explicit_return_type; @@ -42,6 +37,7 @@ struct IrAnalyze { IrBasicBlock *const_predecessor_bb; size_t ref_count; size_t break_debug_id; // for debugging purposes + IrInstruction *return_ptr; // For the purpose of using in a debugger void dump(); @@ -238,10 +234,10 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ ZigType *dest_type); static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool non_null_comptime, bool allow_discard); + bool allow_discard); static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool non_null_comptime, bool allow_discard); + bool allow_discard); static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *base_ptr, bool safety_check_on, bool initializing); static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr, @@ -640,7 +636,6 @@ static void ira_deref(IrAnalyze *ira) { //destroy(ira->old_irb.exec, "IrExecutablePass1"); ira->src_implicit_return_type_list.deinit(); ira->resume_stack.deinit(); - ira->exec_context.mem_slot_list.deinit(); destroy(ira, "IrAnalyze"); } @@ -813,12 +808,6 @@ static size_t exec_next_debug_id(IrExecutable *exec) { return result; } -static size_t exec_next_mem_slot(IrExecutable *exec) { - size_t result = exec->mem_slot_count; - exec->mem_slot_count += 1; - return result; -} - static ZigFn *exec_fn_entry(IrExecutable *exec) { return exec->fn_entry; } @@ -859,16 +848,46 @@ static void ir_ref_var(ZigVar *var) { var->ref_count += 1; } -ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { - ZigValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr, - node, nullptr, ira->new_irb.exec, nullptr, UndefBad); +static void create_result_ptr(CodeGen *codegen, ZigType *expected_type, + ZigValue **out_result, ZigValue **out_result_ptr) +{ + ZigValue *result = create_const_vals(1); + ZigValue *result_ptr = create_const_vals(1); + result->special = ConstValSpecialUndef; + result->type = expected_type; + result_ptr->special = ConstValSpecialStatic; + result_ptr->type = get_pointer_to_type(codegen, result->type, false); + result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar; + result_ptr->data.x_ptr.special = ConstPtrSpecialRef; + result_ptr->data.x_ptr.data.ref.pointee = result; + *out_result = result; + *out_result_ptr = result_ptr; +} + +ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { + Error err; + + ZigValue *result; + ZigValue *result_ptr; + create_result_ptr(ira->codegen, ira->codegen->builtin_types.entry_type, &result, &result_ptr); + + if ((err = ir_eval_const_value(ira->codegen, scope, node, result_ptr, + ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + nullptr, nullptr, node, nullptr, ira->new_irb.exec, nullptr, UndefBad))) + { + return ira->codegen->builtin_types.entry_invalid; + } if (type_is_invalid(result->type)) return ira->codegen->builtin_types.entry_invalid; assert(result->special != ConstValSpecialRuntime); - return result->data.x_type; + ZigType *res_type = result->data.x_type; + + destroy(result_ptr, "ZigValue"); + destroy(result, "ZigValue"); + + return res_type; } static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { @@ -1839,9 +1858,11 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); } -static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { +static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, + ZigType *ty) +{ IrInstructionReturnPtr *instruction = ir_build_instruction(&ira->new_irb, - source_instruction->scope, source_instruction->source_node); + scope, source_node); instruction->base.value->type = ty; return &instruction->base; } @@ -3649,6 +3670,7 @@ static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNod { IrInstructionResetResult *instruction = ir_build_instruction(irb, scope, source_node); instruction->result_loc = result_loc; + instruction->base.is_gen = true; return &instruction->base; } @@ -4315,7 +4337,6 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s ZigVar *variable_entry = allocate(1, "ZigVar"); variable_entry->parent_scope = parent_scope; variable_entry->shadowable = is_shadowable; - variable_entry->mem_slot_index = SIZE_MAX; variable_entry->is_comptime = is_comptime; variable_entry->src_arg_index = SIZE_MAX; variable_entry->const_value = create_const_vals(1); @@ -4379,7 +4400,6 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n (is_underscored ? nullptr : name), src_is_const, gen_is_const, (is_underscored ? true : is_shadowable), is_comptime, false); if (is_comptime != nullptr || gen_is_const) { - var->mem_slot_index = exec_next_mem_slot(irb->exec); var->owner_exec = irb->exec; } assert(var->child_scope); @@ -4516,6 +4536,10 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode // only generate unconditional defers ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); + ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result)); } @@ -9182,6 +9206,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec if (!instr_is_unreachable(result)) { ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result, nullptr)); // no need for save_err_ret_addr because this cannot return error + ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + result_loc_ret->base.id = ResultLocIdReturn; + ir_build_reset_result(irb, scope, node, &result_loc_ret->base); + ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); ir_mark_gen(ir_build_return(irb, scope, result->source_node, result)); } @@ -9280,19 +9308,12 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va return val; } -static ZigValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { +static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutable *exec) { IrBasicBlock *bb = exec->basic_block_list.at(0); for (size_t i = 0; i < bb->instruction_list.length; i += 1) { IrInstruction *instruction = bb->instruction_list.at(i); if (instruction->id == IrInstructionIdReturn) { - IrInstructionReturn *ret_inst = (IrInstructionReturn *)instruction; - IrInstruction *operand = ret_inst->operand; - if (operand->value->special == ConstValSpecialRuntime) { - exec_add_error_node(codegen, exec, operand->source_node, - buf_sprintf("unable to evaluate constant expression")); - return codegen->invalid_instruction->value; - } - return operand->value; + return ErrorNone; } else if (ir_has_side_effects(instruction)) { if (instr_is_comptime(instruction)) { switch (instruction->id) { @@ -9308,8 +9329,8 @@ static ZigValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { continue; } exec_add_error_node(codegen, exec, instruction->source_node, - buf_sprintf("unable to evaluate constant expression")); - return codegen->invalid_instruction->value; + buf_sprintf("unable to evaluate constant expression")); + return ErrorSemanticAnalyzeFail; } } zig_unreachable(); @@ -11696,26 +11717,29 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, array_ptr->value->type)); if (instr_is_comptime(array_ptr)) { - ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr->value, source_instr->source_node); + ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); + if (array_ptr_val == nullptr) + return ira->codegen->invalid_instruction; + ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node); if (pointee == nullptr) return ira->codegen->invalid_instruction; if (pointee->special != ConstValSpecialRuntime) { - assert(array_ptr->value->type->id == ZigTypeIdPointer); - ZigType *array_type = array_ptr->value->type->data.pointer.child_type; + assert(array_ptr_val->type->id == ZigTypeIdPointer); + ZigType *array_type = array_ptr_val->type->data.pointer.child_type; assert(is_slice(wanted_type)); bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const); - result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr->value->data.x_ptr.mut; + result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; result->value->type = wanted_type; return result; } } if (result_loc == nullptr) result_loc = no_result_loc(); - IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, - false, true); + IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, + nullptr, true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -12020,15 +12044,17 @@ static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAll return value->value; } -ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, - ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota, +Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, + ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) { Error err; - if (expected_type != nullptr && type_is_invalid(expected_type)) - return codegen->invalid_instruction->value; + src_assert(return_ptr->type->id == ZigTypeIdPointer, source_node); + + if (type_is_invalid(return_ptr->type)) + return ErrorSemanticAnalyzeFail; IrExecutable *ir_executable = allocate(1, "IrExecutablePass1"); ir_executable->source_node = source_node; @@ -12040,11 +12066,11 @@ ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_executable->begin_scope = scope; if (!ir_gen(codegen, node, scope, ir_executable)) - return codegen->invalid_instruction->value; + return ErrorSemanticAnalyzeFail; if (ir_executable->first_err_trace_msg != nullptr) { codegen->trace_err = ir_executable->first_err_trace_msg; - return codegen->invalid_instruction->value; + return ErrorSemanticAnalyzeFail; } if (codegen->verbose_ir) { @@ -12065,9 +12091,10 @@ ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, analyzed_executable->backward_branch_count = backward_branch_count; analyzed_executable->backward_branch_quota = backward_branch_quota; analyzed_executable->begin_scope = scope; - ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node); + ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, + return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr); if (type_is_invalid(result_type)) { - return codegen->invalid_instruction->value; + return ErrorSemanticAnalyzeFail; } if (codegen->verbose_ir) { @@ -12076,14 +12103,16 @@ ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, fprintf(stderr, "}\n"); } - ZigValue *result = ir_exec_const_result(codegen, analyzed_executable); - if (type_is_invalid(result->type)) - return codegen->invalid_instruction->value; + if ((err = ir_exec_scan_for_side_effects(codegen, analyzed_executable))) + return err; + ZigValue *result = const_ptr_pointee(nullptr, codegen, return_ptr, source_node); + if (result == nullptr) + return ErrorSemanticAnalyzeFail; if ((err = ir_resolve_const_val(codegen, analyzed_executable, node, result, undef_allowed))) - return codegen->invalid_instruction->value; + return err; - return result; + return ErrorNone; } static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) { @@ -12268,7 +12297,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so } IrInstruction *result_loc_inst = nullptr; if (result_loc != nullptr) { - result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); + result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -12311,7 +12340,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction IrInstruction *result_loc_inst; if (handle_is_ptr(wanted_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); - result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); + result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -12430,7 +12459,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so IrInstruction *result_loc_inst; if (handle_is_ptr(wanted_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); - result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); + result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -12503,8 +12532,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi IrInstruction *result_loc; if (type_has_bits(ptr_type) && !handle_is_ptr(value->value->type)) { - result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value->type, nullptr, true, - false, true); + result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value->type, + nullptr, true, true); } else { result_loc = nullptr; } @@ -13232,7 +13261,7 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * result_loc = no_result_loc(); } IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, - true, false, true); + true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -14117,7 +14146,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, - true, false, true); + true, true); if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { return result_loc_inst; } @@ -16043,7 +16072,7 @@ static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instr->scope); IrInstruction *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), - new_type, nullptr, false, false, true); + new_type, nullptr, false, true); uint32_t new_field_count = op1_field_count + op2_field_count; new_type->data.structure.src_field_count = new_field_count; @@ -16631,29 +16660,14 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, break; } - if (var->var_type != nullptr && !is_comptime_var) { - // This is at least the second time we've seen this variable declaration during analysis. - // This means that this is actually a different variable due to, e.g. an inline while loop. - // We make a new variable so that it can hold a different type, and so the debug info can - // be distinct. - ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, - buf_create_from_str(var->name), var->src_is_const, var->gen_is_const, - var->shadowable, var->is_comptime, true); - new_var->owner_exec = var->owner_exec; - new_var->align_bytes = var->align_bytes; - if (var->mem_slot_index != SIZE_MAX) { - ZigValue *vals = create_const_vals(1); - new_var->mem_slot_index = ira->exec_context.mem_slot_list.length; - ira->exec_context.mem_slot_list.append(vals); - } - - var->next_var = new_var; - var = new_var; + while (var->next_var != nullptr) { + var = var->next_var; } // This must be done after possibly creating a new variable above var->ref_count = 0; + var->ptr_instruction = var_ptr; var->var_type = result_type; assert(var->var_type); @@ -16695,16 +16709,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, var_ptr->value->special = ConstValSpecialRuntime; ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false); } - - if (instr_is_comptime(var_ptr) && var->mem_slot_index != SIZE_MAX) { - assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length); - ZigValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index); - copy_const_val(mem_slot, init_val); - ira_ref(var->owner_exec->analysis); - - if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) { - return ir_const_void(ira, &decl_var_instruction->base); - } + if (instr_is_comptime(var_ptr) && + (is_comptime_var || (var_class_requires_const && var->gen_is_const))) + { + return ir_const_void(ira, &decl_var_instruction->base); } } else if (is_comptime_var) { ir_add_error(ira, &decl_var_instruction->base, @@ -17161,7 +17169,7 @@ static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out } static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime) + ResultLoc *result_loc, ZigType *value_type) { if (type_is_invalid(value_type)) return ira->codegen->invalid_instruction; @@ -17181,7 +17189,7 @@ static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *su // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool non_null_comptime, bool allow_discard) + bool allow_discard) { Error err; if (result_loc->resolved_loc != nullptr) { @@ -17201,54 +17209,58 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return nullptr; } // need to return a result location and don't have one. use a stack allocation - return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, - force_runtime, non_null_comptime); + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type); } case ResultLocIdVar: { ResultLocVar *result_loc_var = reinterpret_cast(result_loc); assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc); + IrInstructionAllocaSrc *alloca_src = + reinterpret_cast(result_loc->source_instruction); + + ZigVar *var = result_loc_var->var; + if (var->var_type != nullptr && !ir_get_var_is_comptime(var)) { + // This is at least the second time we've seen this variable declaration during analysis. + // This means that this is actually a different variable due to, e.g. an inline while loop. + // We make a new variable so that it can hold a different type, and so the debug info can + // be distinct. + ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, + buf_create_from_str(var->name), var->src_is_const, var->gen_is_const, + var->shadowable, var->is_comptime, true); + new_var->owner_exec = var->owner_exec; + new_var->align_bytes = var->align_bytes; + + var->next_var = new_var; + var = new_var; + } if (value_type->id == ZigTypeIdUnreachable || value_type->id == ZigTypeIdOpaque) { ir_add_error(ira, result_loc->source_instruction, buf_sprintf("variable of type '%s' not allowed", buf_ptr(&value_type->name))); return ira->codegen->invalid_instruction; } - - IrInstructionAllocaSrc *alloca_src = - reinterpret_cast(result_loc->source_instruction); - bool force_comptime; - if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime)) - return ira->codegen->invalid_instruction; - bool is_comptime = force_comptime || (!force_runtime && value != nullptr && - value->value->special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const); - - if (alloca_src->base.child == nullptr || is_comptime) { + if (alloca_src->base.child == nullptr || var->ptr_instruction == nullptr) { + bool force_comptime; + if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime)) + return ira->codegen->invalid_instruction; uint32_t align = 0; if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, nullptr, &align)) { return ira->codegen->invalid_instruction; } - IrInstruction *alloca_gen; - if (is_comptime && value != nullptr) { - if (align > value->value->llvm_align) { - value->value->llvm_align = align; - } - alloca_gen = ir_get_ref(ira, result_loc->source_instruction, value, true, false); - } else { - alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align, - alloca_src->name_hint, force_comptime); - if (force_runtime) { - alloca_gen->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; - alloca_gen->value->special = ConstValSpecialRuntime; - } + IrInstruction *alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, + value_type, align, alloca_src->name_hint, force_comptime); + if (force_runtime) { + alloca_gen->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; + alloca_gen->value->special = ConstValSpecialRuntime; } if (alloca_src->base.child != nullptr && !result_loc->written) { alloca_src->base.child->ref_count = 0; } alloca_src->base.child = alloca_gen; + var->ptr_instruction = alloca_gen; } result_loc->written = true; - result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child; - return result_loc->resolved_loc; + result_loc->resolved_loc = alloca_src->base.child; + return alloca_src->base.child; } case ResultLocIdInstruction: { result_loc->written = true; @@ -17260,27 +17272,8 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe reinterpret_cast(result_loc)->implicit_return_type_done = true; ira->src_implicit_return_type_list.append(value); } - if (!non_null_comptime) { - bool is_comptime = value != nullptr && value->value->special != ConstValSpecialRuntime; - if (is_comptime) - return nullptr; - } - bool has_bits; - if ((err = type_has_bits2(ira->codegen, ira->explicit_return_type, &has_bits))) - return ira->codegen->invalid_instruction; - if (!has_bits || !handle_is_ptr(ira->explicit_return_type)) { - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - if (fn_entry == nullptr || fn_entry->inferred_async_node == nullptr) { - return nullptr; - } - } - - ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false); result_loc->written = true; - result_loc->resolved_loc = ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type); - if (ir_should_inline(ira->old_irb.exec, result_loc->source_instruction->scope)) { - set_up_result_loc_for_inferred_comptime(result_loc->resolved_loc); - } + result_loc->resolved_loc = ira->return_ptr; return result_loc->resolved_loc; } case ResultLocIdPeer: { @@ -17289,7 +17282,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (peer_parent->peers.length == 1) { IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - value_type, value, force_runtime, non_null_comptime, true); + value_type, value, force_runtime, true); result_peer->suspend_pos.basic_block_index = SIZE_MAX; result_peer->suspend_pos.instruction_index = SIZE_MAX; if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || @@ -17307,11 +17300,8 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return ira->codegen->invalid_instruction; if (is_condition_comptime) { peer_parent->skipped = true; - if (non_null_comptime) { - return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - value_type, value, force_runtime, non_null_comptime, true); - } - return nullptr; + return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, + value_type, value, force_runtime, true); } bool peer_parent_has_type; if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) @@ -17319,7 +17309,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (peer_parent_has_type) { peer_parent->skipped = true; IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - value_type, value, force_runtime || !is_condition_comptime, true, true); + value_type, value, force_runtime || !is_condition_comptime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) { @@ -17344,7 +17334,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime, true); + peer_parent->resolved_type, nullptr, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) { @@ -17357,16 +17347,13 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return result_loc->resolved_loc; } case ResultLocIdCast: { - if (value != nullptr && value->value->special != ConstValSpecialRuntime && !non_null_comptime) - return nullptr; ResultLocCast *result_cast = reinterpret_cast(result_loc); ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) return ira->codegen->invalid_instruction; if (dest_type == ira->codegen->builtin_types.entry_var) { - return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, - force_runtime, non_null_comptime); + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type); } IrInstruction *casted_value; @@ -17380,7 +17367,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent, - dest_type, casted_value, force_runtime, non_null_comptime, true); + dest_type, casted_value, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) { @@ -17430,8 +17417,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe // We will not be able to provide a result location for this value. Create // a new result location. result_cast->parent->written = false; - return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, - force_runtime, non_null_comptime); + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type); } result_loc->written = true; @@ -17477,12 +17463,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe bitcasted_value = nullptr; } - if (bitcasted_value == nullptr || type_is_invalid(bitcasted_value->value->type)) { + if (bitcasted_value != nullptr && type_is_invalid(bitcasted_value->value->type)) { return bitcasted_value; } IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, - dest_type, bitcasted_value, force_runtime, non_null_comptime, true); + dest_type, bitcasted_value, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) { @@ -17526,7 +17512,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool non_null_comptime, bool allow_discard) + bool allow_discard) { Error err; if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction && @@ -17538,7 +17524,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s } bool was_already_resolved = result_loc_pass1->resolved_loc != nullptr; IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, - value, force_runtime, non_null_comptime, allow_discard); + value, force_runtime, allow_discard); if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value->type))) return result_loc; @@ -17685,7 +17671,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, return ira->codegen->invalid_instruction; } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - implicit_elem_type, nullptr, false, true, true); + implicit_elem_type, nullptr, false, true); if (result_loc != nullptr) return result_loc; @@ -17694,7 +17680,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, instruction->result_loc->id == ResultLocIdReturn) { result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(), - implicit_elem_type, nullptr, false, true, true); + implicit_elem_type, nullptr, false, true); if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) { @@ -17798,7 +17784,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstruction *sourc } else { ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry); IrInstruction *result_loc = ir_resolve_result(ira, source_instr, call_result_loc, - frame_type, nullptr, true, true, false); + frame_type, nullptr, true, false); if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; } @@ -17934,10 +17920,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, var = var->next_var; } - if (var->mem_slot_index != SIZE_MAX && var->owner_exec->analysis == nullptr) { - assert(ira->codegen->errors.length != 0); - return ira->codegen->invalid_instruction; + if (var->ptr_instruction != nullptr) { + return var->ptr_instruction; } + if (var->var_type == nullptr || type_is_invalid(var->var_type)) return ira->codegen->invalid_instruction; @@ -17957,13 +17943,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, if (value_is_comptime(var->const_value)) { mem_slot = var->const_value; - } else if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { - // find the relevant exec_context - assert(var->owner_exec != nullptr); - assert(var->owner_exec->analysis != nullptr); - IrExecContext *exec_context = &var->owner_exec->analysis->exec_context; - assert(var->mem_slot_index < exec_context->mem_slot_list.length); - mem_slot = exec_context->mem_slot_list.at(var->mem_slot_index); } if (mem_slot != nullptr) { @@ -18297,10 +18276,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i if (result == nullptr) { // Analyze the fn body block like any other constant expression. AstNode *body_node = fn_entry->body_node; - result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, - nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, - UndefOk); + ZigValue *result_ptr; + create_result_ptr(ira->codegen, return_type, &result, &result_ptr); + if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, + ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, + UndefOk))) + { + return ira->codegen->invalid_instruction; + } + destroy(result_ptr, "ZigValue"); + result_ptr = nullptr; if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.incomplete = false; @@ -18407,14 +18393,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i } if (fn_proto_node->data.fn_proto.align_expr != nullptr) { - ZigValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, - fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), - ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, - nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, - nullptr, UndefBad); - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + ZigValue *align_result; + ZigValue *result_ptr; + create_result_ptr(ira->codegen, get_align_amt_type(ira->codegen), &align_result, &result_ptr); + if ((err = ir_eval_const_value(ira->codegen, impl_fn->child_scope, + fn_proto_node->data.fn_proto.align_expr, result_ptr, + ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, + nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, + nullptr, UndefBad))) + { + return ira->codegen->invalid_instruction; + } + IrInstructionConst *const_instruction = ir_create_instruction_noval(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); - copy_const_val(const_instruction->base.value, align_result); + const_instruction->base.value = align_result; + destroy(result_ptr, "ZigValue"); uint32_t align_bytes = 0; ir_resolve_align(ira, &const_instruction->base, nullptr, &align_bytes); @@ -18491,7 +18484,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i IrInstruction *result_loc; if (handle_is_ptr(impl_fn_type_id->return_type)) { result_loc = ir_resolve_result(ira, source_instr, call_result_loc, - impl_fn_type_id->return_type, nullptr, true, true, false); + impl_fn_type_id->return_type, nullptr, true, false); if (result_loc != nullptr) { if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; @@ -18623,7 +18616,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i IrInstruction *result_loc; if (handle_is_ptr(return_type)) { result_loc = ir_resolve_result(ira, source_instr, call_result_loc, - return_type, nullptr, true, true, false); + return_type, nullptr, true, false); if (result_loc != nullptr) { if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; @@ -19307,7 +19300,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh // In case resolving the parent activates a suspend, do it now IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent, - peer_parent->resolved_type, nullptr, false, false, true); + peer_parent->resolved_type, nullptr, false, true); if (parent_result_loc != nullptr && (type_is_invalid(parent_result_loc->value->type) || instr_is_unreachable(parent_result_loc))) { @@ -19702,8 +19695,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct if (orig_array_ptr_val->special != ConstValSpecialRuntime && orig_array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr && - (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || - array_type->id == ZigTypeIdArray)) + (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar)) { ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, elem_ptr_instruction->base.source_node); @@ -19768,6 +19760,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct (array_type->id != ZigTypeIdPointer || array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) { + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + elem_ptr_instruction->base.source_node, array_ptr_val, UndefBad))) + { + return ira->codegen->invalid_instruction; + } if (array_type->id == ZigTypeIdPointer) { IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); ZigValue *out_val = result->value; @@ -21129,6 +21126,8 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *base_ptr, bool safety_check_on, bool initializing) { + Error err; + ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr); if (type_is_invalid(type_entry)) return ira->codegen->invalid_instruction; @@ -21209,9 +21208,14 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr break; } } - } else if (optional_value_is_null(optional_val)) { - ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); - return ira->codegen->invalid_instruction; + } else { + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + source_instr->source_node, optional_val, UndefBad))) + return ira->codegen->invalid_instruction; + if (optional_value_is_null(optional_val)) { + ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); + return ira->codegen->invalid_instruction; + } } IrInstruction *result; @@ -23812,11 +23816,18 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct // Execute the C import block like an inline function ZigType *void_type = ira->codegen->builtin_types.entry_void; - ZigValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, + ZigValue *cimport_result; + ZigValue *result_ptr; + create_result_ptr(ira->codegen, void_type, &cimport_result, &result_ptr); + if ((err = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, result_ptr, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, - &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad); + &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad))) + { + return ira->codegen->invalid_instruction; + } if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; + destroy(result_ptr, "ZigValue"); ZigPackage *cur_scope_pkg = scope_package(instruction->base.scope); Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, @@ -24169,7 +24180,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi IrInstruction *result_loc; if (handle_is_ptr(result_type)) { result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - result_type, nullptr, true, false, true); + result_type, nullptr, true, true); if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; } @@ -24434,7 +24445,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - dest_slice_type, nullptr, true, false, true); + dest_slice_type, nullptr, true, true); if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) { return result_loc; } @@ -24519,7 +24530,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - dest_slice_type, nullptr, true, false, true); + dest_slice_type, nullptr, true, true); if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; } @@ -25560,7 +25571,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - return_type, nullptr, true, false, true); + return_type, nullptr, true, true); if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { return result_loc; } @@ -28318,7 +28329,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct bool was_written = instruction->result_loc->written; IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - value->value->type, value, false, false, true); + value->value->type, value, false, true); if (result_loc != nullptr) { if (type_is_invalid(result_loc->value->type)) return ira->codegen->invalid_instruction; @@ -28353,7 +28364,7 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns return operand; IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, - &instruction->result_loc_cast->base, operand->value->type, operand, false, false, true); + &instruction->result_loc_cast->base, operand->value->type, operand, false, true); if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) return result_loc; @@ -28369,15 +28380,15 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst return operand; IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, - &instruction->result_loc_bit_cast->base, operand->value->type, operand, false, false, true); + &instruction->result_loc_bit_cast->base, operand->value->type, operand, false, true); if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) return result_loc; - if (instruction->result_loc_bit_cast->parent->gen_instruction != nullptr) { - return instruction->result_loc_bit_cast->parent->gen_instruction; - } - - return result_loc; + ZigType *dest_type = ir_resolve_type(ira, + instruction->result_loc_bit_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ira->codegen->invalid_instruction; + return ir_analyze_bit_cast(ira, &instruction->base, operand, dest_type); } static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira, @@ -28508,7 +28519,7 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction IrInstruction *result_loc; if (type_has_bits(result_type)) { result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, - result_type, nullptr, true, true, true); + result_type, nullptr, true, true); if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) return result_loc; } else { @@ -28900,7 +28911,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction // This function attempts to evaluate IR code while doing type checking and other analysis. // It emits a new IrExecutable which is partially evaluated IR code. ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, - ZigType *expected_type, AstNode *expected_type_source_node) + ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) { assert(old_exec->first_err_trace_msg == nullptr); assert(expected_type == nullptr || !type_is_invalid(expected_type)); @@ -28919,12 +28930,6 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ ira->new_irb.codegen = codegen; ira->new_irb.exec = new_exec; - ZigValue *vals = create_const_vals(ira->old_irb.exec->mem_slot_count); - ira->exec_context.mem_slot_list.resize(ira->old_irb.exec->mem_slot_count); - for (size_t i = 0; i < ira->exec_context.mem_slot_list.length; i += 1) { - ira->exec_context.mem_slot_list.items[i] = &vals[i]; - } - IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); ir_ref_bb(new_entry_bb); @@ -28933,6 +28938,19 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ ir_start_bb(ira, old_entry_bb, nullptr); + if (result_ptr != nullptr) { + assert(result_ptr->type->id == ZigTypeIdPointer); + IrInstructionConst *const_inst = ir_create_instruction( + &ira->new_irb, new_exec->begin_scope, new_exec->source_node); + const_inst->base.value = result_ptr; + ira->return_ptr = &const_inst->base; + } else { + assert(new_exec->begin_scope != nullptr); + assert(new_exec->source_node != nullptr); + ira->return_ptr = ir_build_return_ptr(ira, new_exec->begin_scope, new_exec->source_node, + get_pointer_to_type(codegen, expected_type, false)); + } + while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); diff --git a/src/ir.hpp b/src/ir.hpp index 003bf4897..4f9ed6bcd 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -18,15 +18,15 @@ enum IrPass { bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); -ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, - ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota, +Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, + ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, - ZigType *expected_type, AstNode *expected_type_source_node); + ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr); bool ir_has_side_effects(IrInstruction *instruction); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index ea8720d98..d70947be5 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -24,7 +24,7 @@ comptime { _ = @import("behavior/bugs/1500.zig"); _ = @import("behavior/bugs/1607.zig"); _ = @import("behavior/bugs/1735.zig"); - _ = @import("behavior/bugs/1741.zig"); + //_ = @import("behavior/bugs/1741.zig"); _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/1914.zig"); _ = @import("behavior/bugs/2006.zig"); @@ -43,7 +43,7 @@ comptime { _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); _ = @import("behavior/bugs/624.zig"); - _ = @import("behavior/bugs/655.zig"); + //_ = @import("behavior/bugs/655.zig"); _ = @import("behavior/bugs/656.zig"); _ = @import("behavior/bugs/679.zig"); _ = @import("behavior/bugs/704.zig"); @@ -54,36 +54,36 @@ comptime { _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); - _ = @import("behavior/cast.zig"); + //_ = @import("behavior/cast.zig"); _ = @import("behavior/const_slice_child.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/enum_with_members.zig"); - _ = @import("behavior/error.zig"); - _ = @import("behavior/eval.zig"); + //_ = @import("behavior/error.zig"); + //_ = @import("behavior/eval.zig"); _ = @import("behavior/field_parent_ptr.zig"); _ = @import("behavior/floatop.zig"); _ = @import("behavior/fn.zig"); _ = @import("behavior/fn_in_struct_in_comptime.zig"); _ = @import("behavior/fn_delegation.zig"); - _ = @import("behavior/for.zig"); + //_ = @import("behavior/for.zig"); _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); _ = @import("behavior/hasfield.zig"); - _ = @import("behavior/if.zig"); + //_ = @import("behavior/if.zig"); _ = @import("behavior/import.zig"); _ = @import("behavior/incomplete_struct_param_tld.zig"); _ = @import("behavior/inttoptr.zig"); _ = @import("behavior/ir_block_deps.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/merge_error_sets.zig"); - _ = @import("behavior/misc.zig"); + //_ = @import("behavior/misc.zig"); _ = @import("behavior/muladd.zig"); _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/new_stack_call.zig"); - _ = @import("behavior/null.zig"); - _ = @import("behavior/optional.zig"); - _ = @import("behavior/pointers.zig"); + //_ = @import("behavior/null.zig"); + //_ = @import("behavior/optional.zig"); + //_ = @import("behavior/pointers.zig"); _ = @import("behavior/popcount.zig"); _ = @import("behavior/ptrcast.zig"); _ = @import("behavior/pub_enum.zig"); @@ -93,7 +93,7 @@ comptime { _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice.zig"); _ = @import("behavior/slicetobytes.zig"); - _ = @import("behavior/struct.zig"); + //_ = @import("behavior/struct.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); _ = @import("behavior/switch.zig"); @@ -107,11 +107,11 @@ comptime { _ = @import("behavior/type.zig"); _ = @import("behavior/type_info.zig"); _ = @import("behavior/typename.zig"); - _ = @import("behavior/undefined.zig"); + //_ = @import("behavior/undefined.zig"); _ = @import("behavior/underscore.zig"); _ = @import("behavior/union.zig"); _ = @import("behavior/usingnamespace.zig"); - _ = @import("behavior/var_args.zig"); + //_ = @import("behavior/var_args.zig"); _ = @import("behavior/vector.zig"); _ = @import("behavior/void.zig"); _ = @import("behavior/while.zig"); From b6c8fead00aa5d7b39697aedb0cb1eef53010b83 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 9 Jan 2020 19:29:51 -0500 Subject: [PATCH 02/28] fix regression in global const alignment --- src/analyze.cpp | 2 ++ src/ir.cpp | 1 + test/stage1/behavior.zig | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 435020014..fe0b396d2 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -9303,7 +9303,9 @@ bool type_has_optional_repr(ZigType *ty) { } void copy_const_val(ZigValue *dest, ZigValue *src) { + uint32_t prev_align = dest->llvm_align; memcpy(dest, src, sizeof(ZigValue)); + dest->llvm_align = prev_align; if (src->special != ConstValSpecialStatic) return; dest->parent.id = ConstParentIdNone; diff --git a/src/ir.cpp b/src/ir.cpp index 67bd46364..a1e8f9c43 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17052,6 +17052,7 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in ZigValue *pointee = create_const_vals(1); pointee->special = ConstValSpecialUndef; + pointee->llvm_align = align; IrInstructionAllocaGen *result = ir_build_alloca_gen(ira, source_inst, align, name_hint); result->base.value->special = ConstValSpecialStatic; diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index d70947be5..870ccf1aa 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -24,7 +24,7 @@ comptime { _ = @import("behavior/bugs/1500.zig"); _ = @import("behavior/bugs/1607.zig"); _ = @import("behavior/bugs/1735.zig"); - //_ = @import("behavior/bugs/1741.zig"); + _ = @import("behavior/bugs/1741.zig"); _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/1914.zig"); _ = @import("behavior/bugs/2006.zig"); From 96d64a40a6cd31b8483c9f2899561c23fa266060 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 9 Jan 2020 20:17:45 -0500 Subject: [PATCH 03/28] fix regression with var ptrs not being const --- src/ir.cpp | 10 ++++++---- test/stage1/behavior.zig | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index a1e8f9c43..8580e419f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17921,8 +17921,12 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, var = var->next_var; } + bool is_volatile = false; + ZigType *var_ptr_type = get_pointer_to_type_extra(ira->codegen, var->var_type, + var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false); + if (var->ptr_instruction != nullptr) { - return var->ptr_instruction; + return ir_implicit_cast(ira, var->ptr_instruction, var_ptr_type); } if (var->var_type == nullptr || type_is_invalid(var->var_type)) @@ -17932,12 +17936,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, bool comptime_var_mem = ir_get_var_is_comptime(var); bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern; - bool is_volatile = false; IrInstruction *result = ir_build_var_ptr(&ira->new_irb, instruction->scope, instruction->source_node, var); - result->value->type = get_pointer_to_type_extra(ira->codegen, var->var_type, - var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false); + result->value->type = var_ptr_type; if (linkage_makes_it_runtime || var->is_thread_local) goto no_mem_slot; diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 870ccf1aa..45d699f6b 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -43,7 +43,7 @@ comptime { _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); _ = @import("behavior/bugs/624.zig"); - //_ = @import("behavior/bugs/655.zig"); + _ = @import("behavior/bugs/655.zig"); _ = @import("behavior/bugs/656.zig"); _ = @import("behavior/bugs/679.zig"); _ = @import("behavior/bugs/704.zig"); From d0b055d69e44848cf602a1ce8709ed568728a822 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 11 Jan 2020 16:41:45 -0500 Subject: [PATCH 04/28] fix implicit cast regression --- src/all_types.hpp | 3 + src/analyze.cpp | 128 ++++++++++++++++++++++++++++++++++++++- src/ir.cpp | 24 +++----- test/stage1/behavior.zig | 6 +- 4 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 216fddcb1..6f9db1c27 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -473,6 +473,9 @@ struct ZigValue { // uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning //ZigValue(const ZigValue &other) = delete; // plz zero initialize with {} //ZigValue& operator= (const ZigValue &other) = delete; // use copy_const_val + + // for use in debuggers + void dump(); }; enum ReturnKnowledge { diff --git a/src/analyze.cpp b/src/analyze.cpp index fe0b396d2..14419d274 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -9304,11 +9304,12 @@ bool type_has_optional_repr(ZigType *ty) { void copy_const_val(ZigValue *dest, ZigValue *src) { uint32_t prev_align = dest->llvm_align; + ConstParent prev_parent = dest->parent; memcpy(dest, src, sizeof(ZigValue)); dest->llvm_align = prev_align; if (src->special != ConstValSpecialStatic) return; - dest->parent.id = ConstParentIdNone; + dest->parent = prev_parent; if (dest->type->id == ZigTypeIdStruct) { dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { @@ -9362,3 +9363,128 @@ bool type_is_numeric(ZigType *ty) { } zig_unreachable(); } + +static void dump_value_indent(ZigValue *val, int indent) { + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, "Value@%p(", val); + if (val->type != nullptr) { + fprintf(stderr, "%s)", buf_ptr(&val->type->name)); + } else { + fprintf(stderr, "type=nullptr)"); + } + switch (val->special) { + case ConstValSpecialUndef: + fprintf(stderr, "[undefined]\n"); + return; + case ConstValSpecialLazy: + fprintf(stderr, "[lazy]\n"); + return; + case ConstValSpecialRuntime: + fprintf(stderr, "[runtime]\n"); + return; + case ConstValSpecialStatic: + break; + } + if (val->type == nullptr) + return; + switch (val->type->id) { + case ZigTypeIdInvalid: + fprintf(stderr, "\n"); + return; + case ZigTypeIdUnreachable: + fprintf(stderr, "\n"); + return; + case ZigTypeIdVoid: + fprintf(stderr, "<{}>\n"); + return; + case ZigTypeIdMetaType: + fprintf(stderr, "<%s>\n", buf_ptr(&val->data.x_type->name)); + return; + case ZigTypeIdBool: + fprintf(stderr, "<%s>\n", val->data.x_bool ? "true" : "false"); + return; + case ZigTypeIdComptimeFloat: + case ZigTypeIdComptimeInt: + case ZigTypeIdInt: + case ZigTypeIdFloat: + case ZigTypeIdUndefined: + fprintf(stderr, "\n"); + return; + + case ZigTypeIdStruct: + fprintf(stderr, "type->data.structure.src_field_count; i += 1) { + for (int j = 0; j < indent; j += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name)); + dump_value_indent(val->data.x_struct.fields[i], 1); + } + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, ">\n"); + return; + + case ZigTypeIdOptional: + fprintf(stderr, "<\n"); + dump_value_indent(val->data.x_optional, indent + 1); + + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, ">\n"); + return; + + case ZigTypeIdErrorUnion: + if (val->data.x_err_union.payload != nullptr) { + fprintf(stderr, "<\n"); + dump_value_indent(val->data.x_err_union.payload, indent + 1); + } else { + fprintf(stderr, "<\n"); + dump_value_indent(val->data.x_err_union.error_set, 0); + } + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, ">\n"); + return; + + case ZigTypeIdPointer: + switch (val->data.x_ptr.special) { + case ConstPtrSpecialRef: + fprintf(stderr, "data.x_ptr.data.ref.pointee, indent + 1); + break; + default: + fprintf(stderr, "TODO dump more pointer things\n"); + } + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, ">\n"); + return; + + case ZigTypeIdVector: + case ZigTypeIdArray: + case ZigTypeIdNull: + case ZigTypeIdErrorSet: + case ZigTypeIdEnum: + case ZigTypeIdUnion: + case ZigTypeIdFn: + case ZigTypeIdBoundFn: + case ZigTypeIdOpaque: + case ZigTypeIdFnFrame: + case ZigTypeIdAnyFrame: + case ZigTypeIdEnumLiteral: + fprintf(stderr, "\n"); + return; + } + zig_unreachable(); +} + +void ZigValue::dump() { + dump_value_indent(this, 0); +} diff --git a/src/ir.cpp b/src/ir.cpp index 8580e419f..8d3b98435 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4190,12 +4190,6 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeReturnExpr); - ZigFn *fn_entry = exec_fn_entry(irb->exec); - if (!fn_entry) { - add_node_error(irb->codegen, node, buf_sprintf("return expression outside function definition")); - return irb->codegen->invalid_instruction; - } - ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); if (scope_defer_expr) { if (!scope_defer_expr->reported_err) { @@ -17079,9 +17073,11 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in result->base.value->type = get_pointer_to_type_extra(ira->codegen, var_type, false, false, PtrLenSingle, align, 0, 0, false); - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - if (fn_entry != nullptr) { - fn_entry->alloca_gen_list.append(result); + if (!force_comptime) { + ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + if (fn_entry != nullptr) { + fn_entry->alloca_gen_list.append(result); + } } result->base.is_gen = true; return &result->base; @@ -17619,7 +17615,8 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s result_loc, false, true); ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type; if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && - value_type->id != ZigTypeIdNull) { + value_type->id != ZigTypeIdNull) + { return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true); } else { return unwrapped_err_ptr; @@ -21176,7 +21173,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr if (instr_is_comptime(base_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); - if (!ptr_val) + if (ptr_val == nullptr) return ira->codegen->invalid_instruction; if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { ZigValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); @@ -28366,11 +28363,6 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns if (type_is_invalid(operand->value->type)) return operand; - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, - &instruction->result_loc_cast->base, operand->value->type, operand, false, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) - return result_loc; - ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) return ira->codegen->invalid_instruction; diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 45d699f6b..a468030f6 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -54,7 +54,7 @@ comptime { _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); - //_ = @import("behavior/cast.zig"); + _ = @import("behavior/cast.zig"); _ = @import("behavior/const_slice_child.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); @@ -81,9 +81,9 @@ comptime { _ = @import("behavior/muladd.zig"); _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/new_stack_call.zig"); - //_ = @import("behavior/null.zig"); + _ = @import("behavior/null.zig"); //_ = @import("behavior/optional.zig"); - //_ = @import("behavior/pointers.zig"); + _ = @import("behavior/pointers.zig"); _ = @import("behavior/popcount.zig"); _ = @import("behavior/ptrcast.zig"); _ = @import("behavior/pub_enum.zig"); From fb8da16a60e13b09c5c6bb4989c204da536597b7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 12:16:35 -0500 Subject: [PATCH 05/28] fix regressions in get_elem_ptr related to undefined --- src/ir.cpp | 8 ++++---- test/stage1/behavior.zig | 4 ++-- test/stage1/behavior/undefined.zig | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 8d3b98435..e82061670 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17918,6 +17918,9 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, var = var->next_var; } + if (var->var_type == nullptr || type_is_invalid(var->var_type)) + return ira->codegen->invalid_instruction; + bool is_volatile = false; ZigType *var_ptr_type = get_pointer_to_type_extra(ira->codegen, var->var_type, var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false); @@ -17926,9 +17929,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, return ir_implicit_cast(ira, var->ptr_instruction, var_ptr_type); } - if (var->var_type == nullptr || type_is_invalid(var->var_type)) - return ira->codegen->invalid_instruction; - ZigValue *mem_slot = nullptr; bool comptime_var_mem = ir_get_var_is_comptime(var); @@ -19761,7 +19761,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) { if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, - elem_ptr_instruction->base.source_node, array_ptr_val, UndefBad))) + elem_ptr_instruction->base.source_node, array_ptr_val, UndefOk))) { return ira->codegen->invalid_instruction; } diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index a468030f6..bd091c0c6 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -66,7 +66,7 @@ comptime { _ = @import("behavior/fn.zig"); _ = @import("behavior/fn_in_struct_in_comptime.zig"); _ = @import("behavior/fn_delegation.zig"); - //_ = @import("behavior/for.zig"); + _ = @import("behavior/for.zig"); _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); _ = @import("behavior/hasfield.zig"); @@ -107,7 +107,7 @@ comptime { _ = @import("behavior/type.zig"); _ = @import("behavior/type_info.zig"); _ = @import("behavior/typename.zig"); - //_ = @import("behavior/undefined.zig"); + _ = @import("behavior/undefined.zig"); _ = @import("behavior/underscore.zig"); _ = @import("behavior/union.zig"); _ = @import("behavior/usingnamespace.zig"); diff --git a/test/stage1/behavior/undefined.zig b/test/stage1/behavior/undefined.zig index 3506e7e24..114b0262b 100644 --- a/test/stage1/behavior/undefined.zig +++ b/test/stage1/behavior/undefined.zig @@ -1,5 +1,6 @@ -const expect = @import("std").testing.expect; -const mem = @import("std").mem; +const std = @import("std"); +const expect = std.testing.expect; +const mem = std.mem; fn initStaticArray() [10]i32 { var array: [10]i32 = undefined; From e48157c3cb817ff1551f74fc1da9f420e38ccbd5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 13:12:53 -0500 Subject: [PATCH 06/28] fix regression with inferred struct fields --- src/all_types.hpp | 1 + src/ir.cpp | 102 +++++++++++++++++++++------------------ test/stage1/behavior.zig | 6 +-- 3 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 6f9db1c27..49cbf38d0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1230,6 +1230,7 @@ static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; struct InferredStructField { ZigType *inferred_struct_type; Buf *field_name; + bool already_resolved; }; struct ZigTypePointer { diff --git a/src/ir.cpp b/src/ir.cpp index e82061670..b926b3ae3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17519,7 +17519,6 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s { result_loc_pass1 = no_result_loc(); } - bool was_already_resolved = result_loc_pass1->resolved_loc != nullptr; IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, value, force_runtime, allow_discard); if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value->type))) @@ -17532,56 +17531,63 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s } InferredStructField *isf = result_loc->value->type->data.pointer.inferred_struct_field; - if (!was_already_resolved && isf != nullptr) { - // Now it's time to add the field to the struct type. - uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count; - uint32_t new_field_count = old_field_count + 1; - isf->inferred_struct_type->data.structure.src_field_count = new_field_count; - isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields( - isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count); - - TypeStructField *field = isf->inferred_struct_type->data.structure.fields[old_field_count]; - field->name = isf->field_name; - field->type_entry = value_type; - field->type_val = create_const_type(ira->codegen, field->type_entry); - field->src_index = old_field_count; - field->decl_node = value ? value->source_node : suspend_source_instr->source_node; - if (value && instr_is_comptime(value)) { - ZigValue *val = ir_resolve_const(ira, value, UndefOk); - if (!val) - return ira->codegen->invalid_instruction; - field->is_comptime = true; - field->init_val = create_const_vals(1); - copy_const_val(field->init_val, val); - return result_loc; - } - - ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); + if (isf != nullptr) { + TypeStructField *field; IrInstruction *casted_ptr; - if (instr_is_comptime(result_loc)) { - casted_ptr = ir_const(ira, suspend_source_instr, struct_ptr_type); - copy_const_val(casted_ptr->value, result_loc->value); - casted_ptr->value->type = struct_ptr_type; - } else { + if (isf->already_resolved) { + field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); casted_ptr = result_loc; - } - if (instr_is_comptime(casted_ptr)) { - ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); - if (!ptr_val) - return ira->codegen->invalid_instruction; - if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { - ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, - suspend_source_instr->source_node); - struct_val->special = ConstValSpecialStatic; - struct_val->data.x_struct.fields = realloc_const_vals_ptrs(struct_val->data.x_struct.fields, - old_field_count, new_field_count); + } else { + isf->already_resolved = true; + // Now it's time to add the field to the struct type. + uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count; + uint32_t new_field_count = old_field_count + 1; + isf->inferred_struct_type->data.structure.src_field_count = new_field_count; + isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields( + isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count); - ZigValue *field_val = struct_val->data.x_struct.fields[old_field_count]; - field_val->special = ConstValSpecialUndef; - field_val->type = field->type_entry; - field_val->parent.id = ConstParentIdStruct; - field_val->parent.data.p_struct.struct_val = struct_val; - field_val->parent.data.p_struct.field_index = old_field_count; + field = isf->inferred_struct_type->data.structure.fields[old_field_count]; + field->name = isf->field_name; + field->type_entry = value_type; + field->type_val = create_const_type(ira->codegen, field->type_entry); + field->src_index = old_field_count; + field->decl_node = value ? value->source_node : suspend_source_instr->source_node; + if (value && instr_is_comptime(value)) { + ZigValue *val = ir_resolve_const(ira, value, UndefOk); + if (!val) + return ira->codegen->invalid_instruction; + field->is_comptime = true; + field->init_val = create_const_vals(1); + copy_const_val(field->init_val, val); + return result_loc; + } + + ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); + if (instr_is_comptime(result_loc)) { + casted_ptr = ir_const(ira, suspend_source_instr, struct_ptr_type); + copy_const_val(casted_ptr->value, result_loc->value); + casted_ptr->value->type = struct_ptr_type; + } else { + casted_ptr = result_loc; + } + if (instr_is_comptime(casted_ptr)) { + ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, + suspend_source_instr->source_node); + struct_val->special = ConstValSpecialStatic; + struct_val->data.x_struct.fields = realloc_const_vals_ptrs(struct_val->data.x_struct.fields, + old_field_count, new_field_count); + + ZigValue *field_val = struct_val->data.x_struct.fields[old_field_count]; + field_val->special = ConstValSpecialUndef; + field_val->type = field->type_entry; + field_val->parent.id = ConstParentIdStruct; + field_val->parent.data.p_struct.struct_val = struct_val; + field_val->parent.data.p_struct.field_index = old_field_count; + } } } diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index bd091c0c6..a5f13c204 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -60,7 +60,7 @@ comptime { _ = @import("behavior/enum.zig"); _ = @import("behavior/enum_with_members.zig"); //_ = @import("behavior/error.zig"); - //_ = @import("behavior/eval.zig"); + _ = @import("behavior/eval.zig"); _ = @import("behavior/field_parent_ptr.zig"); _ = @import("behavior/floatop.zig"); _ = @import("behavior/fn.zig"); @@ -93,7 +93,7 @@ comptime { _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice.zig"); _ = @import("behavior/slicetobytes.zig"); - //_ = @import("behavior/struct.zig"); + _ = @import("behavior/struct.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); _ = @import("behavior/switch.zig"); @@ -111,7 +111,7 @@ comptime { _ = @import("behavior/underscore.zig"); _ = @import("behavior/union.zig"); _ = @import("behavior/usingnamespace.zig"); - //_ = @import("behavior/var_args.zig"); + _ = @import("behavior/var_args.zig"); _ = @import("behavior/vector.zig"); _ = @import("behavior/void.zig"); _ = @import("behavior/while.zig"); From 8bf425957b253d0ab2e4902d57340b19b7436698 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 16:51:58 -0500 Subject: [PATCH 07/28] fix regressions double implicit casting return ptr --- src/analyze.cpp | 31 ++++++++++++++++++++++++++++--- src/codegen.cpp | 1 + src/ir.cpp | 15 ++++++--------- src/softfloat.hpp | 17 +++++++++++++++++ src/util.hpp | 21 ++------------------- test/stage1/behavior.zig | 2 +- 6 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 14419d274..94d0c66e1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -9396,6 +9396,9 @@ static void dump_value_indent(ZigValue *val, int indent) { case ZigTypeIdUnreachable: fprintf(stderr, "\n"); return; + case ZigTypeIdUndefined: + fprintf(stderr, "\n"); + return; case ZigTypeIdVoid: fprintf(stderr, "<{}>\n"); return; @@ -9405,11 +9408,16 @@ static void dump_value_indent(ZigValue *val, int indent) { case ZigTypeIdBool: fprintf(stderr, "<%s>\n", val->data.x_bool ? "true" : "false"); return; - case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: - case ZigTypeIdInt: + case ZigTypeIdInt: { + Buf *tmp_buf = buf_alloc(); + bigint_append_buf(tmp_buf, &val->data.x_bigint, 10); + fprintf(stderr, "<%s>\n", buf_ptr(tmp_buf)); + buf_destroy(tmp_buf); + return; + } + case ZigTypeIdComptimeFloat: case ZigTypeIdFloat: - case ZigTypeIdUndefined: fprintf(stderr, "\n"); return; @@ -9458,6 +9466,23 @@ static void dump_value_indent(ZigValue *val, int indent) { fprintf(stderr, "data.x_ptr.data.ref.pointee, indent + 1); break; + case ConstPtrSpecialBaseStruct: { + ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val; + size_t field_index = val->data.x_ptr.data.base_struct.field_index; + fprintf(stderr, "data.x_struct.fields[field_index]; + if (field_val != nullptr) { + dump_value_indent(field_val, indent + 1); + } else { + for (int i = 0; i < indent; i += 1) { + fprintf(stderr, " "); + } + fprintf(stderr, "(invalid null field)\n"); + } + } + break; + } default: fprintf(stderr, "TODO dump more pointer things\n"); } diff --git a/src/codegen.cpp b/src/codegen.cpp index c4add2ce7..6b2b95d24 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -20,6 +20,7 @@ #include "zig_llvm.h" #include "userland.h" #include "dump_analysis.hpp" +#include "softfloat.hpp" #include #include diff --git a/src/ir.cpp b/src/ir.cpp index b926b3ae3..5b1494553 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12313,8 +12313,8 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction if (type_is_invalid(casted_payload->value->type)) return ira->codegen->invalid_instruction; - ZigValue *val = ir_resolve_const(ira, casted_payload, UndefBad); - if (!val) + ZigValue *val = ir_resolve_const(ira, casted_payload, UndefOk); + if (val == nullptr) return ira->codegen->invalid_instruction; ZigValue *err_set_val = create_const_vals(1); @@ -17519,6 +17519,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s { result_loc_pass1 = no_result_loc(); } + bool was_written = result_loc_pass1->written; IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, value, force_runtime, allow_discard); if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value->type))) @@ -17596,6 +17597,9 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s result_loc_pass1->resolved_loc = result_loc; } + if (was_written) { + return result_loc; + } ir_assert(result_loc->value->type->id == ZigTypeIdPointer, suspend_source_instr); ZigType *actual_elem_type = result_loc->value->type->data.pointer.child_type; @@ -18242,13 +18246,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i return ira->codegen->invalid_instruction; } - if (fn_proto_node->data.fn_proto.is_var_args) { - ir_add_error(ira, source_instr, - buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313")); - return ira->codegen->invalid_instruction; - } - - for (size_t call_i = 0; call_i < args_len; call_i += 1) { IrInstruction *old_arg = args_ptr[call_i]; diff --git a/src/softfloat.hpp b/src/softfloat.hpp index 4b227e9d7..a1173690b 100644 --- a/src/softfloat.hpp +++ b/src/softfloat.hpp @@ -12,4 +12,21 @@ extern "C" { #include "softfloat.h" } +static inline float16_t zig_double_to_f16(double x) { + float64_t y; + static_assert(sizeof(x) == sizeof(y), ""); + memcpy(&y, &x, sizeof(x)); + return f64_to_f16(y); +} + + +// Return value is safe to coerce to float even when |x| is NaN or Infinity. +static inline double zig_f16_to_double(float16_t x) { + float64_t y = f16_to_f64(x); + double z; + static_assert(sizeof(y) == sizeof(z), ""); + memcpy(&z, &y, sizeof(y)); + return z; +} + #endif diff --git a/src/util.hpp b/src/util.hpp index 8dcd41438..e1722921f 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -38,6 +38,8 @@ #if defined(__MINGW32__) || defined(__MINGW64__) #define BREAKPOINT __debugbreak() +#elif defined(__i386__) || defined(__x86_64__) +#define BREAKPOINT __asm__ volatile("int $0x03"); #elif defined(__clang__) #define BREAKPOINT __builtin_debugtrap() #elif defined(__GNUC__) @@ -49,8 +51,6 @@ #endif -#include "softfloat.hpp" - ATTRIBUTE_COLD ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF(1, 2) @@ -244,23 +244,6 @@ static inline uint8_t log2_u64(uint64_t x) { return (63 - clzll(x)); } -static inline float16_t zig_double_to_f16(double x) { - float64_t y; - static_assert(sizeof(x) == sizeof(y), ""); - memcpy(&y, &x, sizeof(x)); - return f64_to_f16(y); -} - - -// Return value is safe to coerce to float even when |x| is NaN or Infinity. -static inline double zig_f16_to_double(float16_t x) { - float64_t y = f16_to_f64(x); - double z; - static_assert(sizeof(y) == sizeof(z), ""); - memcpy(&z, &y, sizeof(y)); - return z; -} - void zig_pretty_print_bytes(FILE *f, double n); template diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index a5f13c204..62a6dedcc 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -59,7 +59,7 @@ comptime { _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/enum_with_members.zig"); - //_ = @import("behavior/error.zig"); + _ = @import("behavior/error.zig"); _ = @import("behavior/eval.zig"); _ = @import("behavior/field_parent_ptr.zig"); _ = @import("behavior/floatop.zig"); From b952b8448648102dbe62fb1b4137c6d57806b78b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 17:08:28 -0500 Subject: [PATCH 08/28] relax language requirements regarding else unreachable --- test/stage1/behavior.zig | 2 +- test/stage1/behavior/if.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 62a6dedcc..e362a9405 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -70,7 +70,7 @@ comptime { _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); _ = @import("behavior/hasfield.zig"); - //_ = @import("behavior/if.zig"); + _ = @import("behavior/if.zig"); _ = @import("behavior/import.zig"); _ = @import("behavior/incomplete_struct_param_tld.zig"); _ = @import("behavior/inttoptr.zig"); diff --git a/test/stage1/behavior/if.zig b/test/stage1/behavior/if.zig index 63c31fb03..c309bc061 100644 --- a/test/stage1/behavior/if.zig +++ b/test/stage1/behavior/if.zig @@ -72,7 +72,7 @@ test "const result loc, runtime if cond, else unreachable" { var t = true; const x = if (t) Num.Two else unreachable; - if (x != .Two) @compileError("bad"); + expect(x == .Two); } test "if prongs cast to expected type instead of peer type resolution" { From 6a8c9f730686dc572a7ba71f9a22b143da863793 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 17:42:01 -0500 Subject: [PATCH 09/28] fix regression with optionals and globals --- src/ir.cpp | 15 +++++++++------ test/stage1/behavior.zig | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 5b1494553..42bc8758e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17606,12 +17606,15 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && value_type->id != ZigTypeIdNull) { - bool has_bits; - if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) - return ira->codegen->invalid_instruction; - if (has_bits) { - result_loc_pass1->written = false; - return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); + bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type); + if (!same_comptime_repr) { + bool has_bits; + if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) + return ira->codegen->invalid_instruction; + if (has_bits) { + result_loc_pass1->written = false; + return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); + } } } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) { bool has_bits; diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index e362a9405..066551bf1 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -82,7 +82,7 @@ comptime { _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/new_stack_call.zig"); _ = @import("behavior/null.zig"); - //_ = @import("behavior/optional.zig"); + _ = @import("behavior/optional.zig"); _ = @import("behavior/pointers.zig"); _ = @import("behavior/popcount.zig"); _ = @import("behavior/ptrcast.zig"); From 8f336b397010206d282aec9ce45b47f3b0a5a720 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 20:38:24 -0500 Subject: [PATCH 10/28] revert one part of ir get_elem_ptr analysis this reverts one part of 4c3bfeca. it solves some behavior regressions but introduces new ones. This change was incorrect to make however, and this commit takes the code in a better direction. --- src/ir.cpp | 26 +++++++++----------------- test/stage1/behavior.zig | 4 ++-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 42bc8758e..cb47806f1 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17942,8 +17942,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, return ir_implicit_cast(ira, var->ptr_instruction, var_ptr_type); } - ZigValue *mem_slot = nullptr; - bool comptime_var_mem = ir_get_var_is_comptime(var); bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern; @@ -17951,17 +17949,11 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, instruction->scope, instruction->source_node, var); result->value->type = var_ptr_type; - if (linkage_makes_it_runtime || var->is_thread_local) - goto no_mem_slot; - - if (value_is_comptime(var->const_value)) { - mem_slot = var->const_value; - } - - if (mem_slot != nullptr) { - switch (mem_slot->special) { + if (!linkage_makes_it_runtime && !var->is_thread_local && value_is_comptime(var->const_value)) { + ZigValue *val = var->const_value; + switch (val->special) { case ConstValSpecialRuntime: - goto no_mem_slot; + break; case ConstValSpecialStatic: // fallthrough case ConstValSpecialLazy: // fallthrough case ConstValSpecialUndef: { @@ -17977,15 +17969,12 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, result->value->special = ConstValSpecialStatic; result->value->data.x_ptr.mut = ptr_mut; result->value->data.x_ptr.special = ConstPtrSpecialRef; - result->value->data.x_ptr.data.ref.pointee = mem_slot; + result->value->data.x_ptr.data.ref.pointee = val; return result; } } - zig_unreachable(); } -no_mem_slot: - bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); result->value->data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack; @@ -19699,9 +19688,12 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align); } + // TODO The `array_type->id == ZigTypeIdArray` exception here should not be an exception; + // the `orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar` clause should be omitted completely. + // However there are bugs to fix before this improvement can be made. if (orig_array_ptr_val->special != ConstValSpecialRuntime && orig_array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr && - (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar)) + (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == ZigTypeIdArray)) { ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, elem_ptr_instruction->base.source_node); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 066551bf1..f9bd9deef 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -1,7 +1,7 @@ comptime { _ = @import("behavior/align.zig"); _ = @import("behavior/alignof.zig"); - _ = @import("behavior/array.zig"); + //_ = @import("behavior/array.zig"); _ = @import("behavior/asm.zig"); _ = @import("behavior/async_fn.zig"); _ = @import("behavior/atomics.zig"); @@ -77,7 +77,7 @@ comptime { _ = @import("behavior/ir_block_deps.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/merge_error_sets.zig"); - //_ = @import("behavior/misc.zig"); + _ = @import("behavior/misc.zig"); _ = @import("behavior/muladd.zig"); _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/new_stack_call.zig"); From 396d57c498278a39d069842321fcdaac90babf02 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2020 20:49:19 -0500 Subject: [PATCH 11/28] fix failing array test by improving copy_const_val --- src/analyze.cpp | 10 ++++++++++ test/stage1/behavior.zig | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 94d0c66e1..4b3b024b5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -9318,6 +9318,16 @@ void copy_const_val(ZigValue *dest, ZigValue *src) { dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i; } + } else if (dest->type->id == ZigTypeIdArray) { + if (dest->data.x_array.special == ConstArraySpecialNone) { + dest->data.x_array.data.s_none.elements = create_const_vals(dest->type->data.array.len); + for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) { + copy_const_val(&dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]); + dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray; + dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest; + dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i; + } + } } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { dest->data.x_optional = create_const_vals(1); copy_const_val(dest->data.x_optional, src->data.x_optional); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index f9bd9deef..ea8720d98 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -1,7 +1,7 @@ comptime { _ = @import("behavior/align.zig"); _ = @import("behavior/alignof.zig"); - //_ = @import("behavior/array.zig"); + _ = @import("behavior/array.zig"); _ = @import("behavior/asm.zig"); _ = @import("behavior/async_fn.zig"); _ = @import("behavior/atomics.zig"); From 1a08c0d40b8c6e72532762281365a5105116dc00 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 23 Jan 2020 00:46:44 -0500 Subject: [PATCH 12/28] new test case --- test/stage1/behavior/bitcast.zig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/stage1/behavior/bitcast.zig b/test/stage1/behavior/bitcast.zig index fe3dd6902..9c315c169 100644 --- a/test/stage1/behavior/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -167,3 +167,12 @@ test "nested bitcast" { S.foo(42); comptime S.foo(42); } + +test "bitcast passed as tuple element" { + const S = struct { + fn foo(args: var) void { + expect(args[0] == 1.00000e-09); + } + }; + S.foo(.{@bitCast(f32, @as(u32, 814313563))}); +} From c0fee9dfc7be5ab2c232a4787223a8e56a56745b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 17:30:39 -0500 Subject: [PATCH 13/28] fix nested bitcast passed as tuple element --- src/analyze.cpp | 22 ++++++-- src/codegen.cpp | 6 +++ src/ir.cpp | 92 ++++++++++++++++++++------------ test/stage1/behavior/bitcast.zig | 17 +++--- 4 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index fe274195e..a5ab98422 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -593,9 +593,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con } if (inferred_struct_field != nullptr) { - entry->abi_size = g->builtin_types.entry_usize->abi_size; - entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; - entry->abi_align = g->builtin_types.entry_usize->abi_align; + entry->abi_size = SIZE_MAX; + entry->size_in_bits = SIZE_MAX; + entry->abi_align = UINT32_MAX; } else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) { if (type_has_bits(child_type)) { entry->abi_size = g->builtin_types.entry_usize->abi_size; @@ -6474,7 +6474,21 @@ static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) { } ty->data.pointer.resolve_loop_flag_zero_bits = true; - ZigType *elem_type = ty->data.pointer.child_type; + ZigType *elem_type; + InferredStructField *isf = ty->data.pointer.inferred_struct_field; + if (isf != nullptr) { + TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); + assert(field != nullptr); + if (field->is_comptime) { + ty->abi_size = 0; + ty->size_in_bits = 0; + ty->abi_align = 0; + return ErrorNone; + } + elem_type = field->type_entry; + } else { + elem_type = ty->data.pointer.child_type; + } bool has_bits; if ((err = type_has_bits2(g, elem_type, &has_bits))) diff --git a/src/codegen.cpp b/src/codegen.cpp index 9a58a8c98..ef43ebd57 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3120,8 +3120,14 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executab static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenCast *cast_instruction) { + Error err; ZigType *actual_type = cast_instruction->value->value->type; ZigType *wanted_type = cast_instruction->base.value->type; + bool wanted_type_has_bits; + if ((err = type_has_bits2(g, wanted_type, &wanted_type_has_bits))) + codegen_report_errors_and_exit(g); + if (!wanted_type_has_bits) + return nullptr; LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value); ir_assert(expr_val, &cast_instruction->base); diff --git a/src/ir.cpp b/src/ir.cpp index 4e06ab5f6..d4a0cb39c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -880,7 +880,6 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdEnumLiteral: - case ZigTypeIdPointer: case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdBoundFn: @@ -889,6 +888,8 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte case ZigTypeIdAnyFrame: case ZigTypeIdFn: return true; + case ZigTypeIdPointer: + return expected->data.pointer.inferred_struct_field == actual->data.pointer.inferred_struct_field; case ZigTypeIdFloat: return expected->data.floating.bit_count == actual->data.floating.bit_count; case ZigTypeIdInt: @@ -7014,6 +7015,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod ResultLocBitCast *result_loc_bit_cast = allocate(1); result_loc_bit_cast->base.id = ResultLocIdBitCast; result_loc_bit_cast->base.source_instruction = dest_type; + result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; ir_ref_instruction(dest_type, irb->current_basic_block); result_loc_bit_cast->parent = result_loc; @@ -13597,32 +13599,31 @@ static IrInstGen *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInst *source_in return result; } -static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value, - bool is_const, bool is_volatile) +static IrInstGen *ir_get_ref2(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value, + ZigType *elem_type, bool is_const, bool is_volatile) { Error err; - if (type_is_invalid(value->value->type)) + if (type_is_invalid(elem_type)) return ira->codegen->invalid_inst_gen; if (instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, LazyOk); if (!val) return ira->codegen->invalid_inst_gen; - return ir_get_const_ptr(ira, source_instruction, val, value->value->type, + return ir_get_const_ptr(ira, source_instruction, val, elem_type, ConstPtrMutComptimeConst, is_const, is_volatile, 0); } - ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value->type, + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type, is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); if ((err = type_resolve(ira->codegen, ptr_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_inst_gen; IrInstGen *result_loc; - if (type_has_bits(ptr_type) && !handle_is_ptr(value->value->type)) { - result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value->type, - nullptr, true, true); + if (type_has_bits(ptr_type) && !handle_is_ptr(elem_type)) { + result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), elem_type, nullptr, true, true); } else { result_loc = nullptr; } @@ -13632,6 +13633,12 @@ static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstG return new_instruction; } +static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value, + bool is_const, bool is_volatile) +{ + return ir_get_ref2(ira, source_instruction, value, value->value->type, is_const, is_volatile); +} + static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, ZigType *union_type) { assert(union_type->id == ZigTypeIdUnion); @@ -18204,6 +18211,21 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc return result_loc->resolved_loc; } +static bool result_loc_is_discard(ResultLoc *result_loc_pass1) { + if (result_loc_pass1->id == ResultLocIdInstruction && + result_loc_pass1->source_instruction->id == IrInstSrcIdConst) + { + IrInstSrcConst *const_inst = reinterpret_cast(result_loc_pass1->source_instruction); + if (value_is_comptime(const_inst->value) && + const_inst->value->type->id == ZigTypeIdPointer && + const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard) + { + return true; + } + } + return false; +} + // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstGen *value, bool force_runtime, @@ -18494,13 +18516,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i assert(parent_ptr_type->id == ZigTypeIdPointer); ZigType *child_type = parent_ptr_type->data.pointer.child_type; - bool has_bits; - if ((err = type_has_bits2(ira->codegen, child_type, &has_bits))) { - return ira->codegen->invalid_inst_gen; - } - - // This happens when the bitCast result is assigned to _ - if (!has_bits) { + if (result_loc_is_discard(result_bit_cast->parent)) { assert(allow_discard); return parent_result_loc; } @@ -18531,16 +18547,8 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr bool allow_discard) { Error err; - if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction && - result_loc_pass1->source_instruction->id == IrInstSrcIdConst) - { - IrInstSrcConst *const_inst = reinterpret_cast(result_loc_pass1->source_instruction); - if (value_is_comptime(const_inst->value) && - const_inst->value->type->id == ZigTypeIdPointer && - const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard) - { - result_loc_pass1 = no_result_loc(); - } + if (!allow_discard && result_loc_is_discard(result_loc_pass1)) { + result_loc_pass1 = no_result_loc(); } bool was_written = result_loc_pass1->written; IrInstGen *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, @@ -21062,7 +21070,7 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins IrInstGen *elem = ir_const(ira, source_instr, field_type); memoize_field_init_val(ira->codegen, struct_type, field); copy_const_val(elem->value, field->init_val); - return ir_get_ref(ira, source_instr, elem, true, false); + return ir_get_ref2(ira, source_instr, elem, field_type, true, false); } switch (type_has_one_possible_value(ira->codegen, field_type)) { case OnePossibleValueInvalid: @@ -27708,7 +27716,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_inst_gen; - if (type_has_bits(dest_type) && !type_has_bits(src_type)) { + if (type_has_bits(dest_type) && !type_has_bits(src_type) && safety_check_on) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("'%s' and '%s' do not have the same in-memory representation", buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); @@ -27723,7 +27731,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type); UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad; ZigValue *val = ir_resolve_const(ira, ptr, is_undef_allowed); - if (!val) + if (val == nullptr) return ira->codegen->invalid_inst_gen; if (value_is_comptime(val) && val->special != ConstValSpecialUndef) { @@ -27738,15 +27746,31 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn } IrInstGen *result; - if (ptr->value->data.x_ptr.mut == ConstPtrMutInfer) { + if (val->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); - - if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_inst_gen; } else { result = ir_const(ira, source_instr, dest_type); } - copy_const_val(result->value, val); + InferredStructField *isf = (val->type->id == ZigTypeIdPointer) ? + val->type->data.pointer.inferred_struct_field : nullptr; + if (isf == nullptr) { + copy_const_val(result->value, val); + } else { + // The destination value should have x_ptr struct pointing to underlying struct value + result->value->data.x_ptr.mut = val->data.x_ptr.mut; + TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); + assert(field != nullptr); + if (field->is_comptime) { + result->value->data.x_ptr.special = ConstPtrSpecialRef; + result->value->data.x_ptr.data.ref.pointee = field->init_val; + } else { + assert(val->data.x_ptr.special == ConstPtrSpecialRef); + result->value->data.x_ptr.special = ConstPtrSpecialBaseStruct; + result->value->data.x_ptr.data.base_struct.struct_val = val->data.x_ptr.data.ref.pointee; + result->value->data.x_ptr.data.base_struct.field_index = field->src_index; + } + result->value->special = ConstValSpecialStatic; + } result->value->type = dest_type; // Keep the bigger alignment, it can only help- diff --git a/test/stage1/behavior/bitcast.zig b/test/stage1/behavior/bitcast.zig index bb45fe00b..9eefdb01c 100644 --- a/test/stage1/behavior/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -168,11 +168,12 @@ test "nested bitcast" { comptime S.foo(42); } -//test "bitcast passed as tuple element" { -// const S = struct { -// fn foo(args: var) void { -// expect(args[0] == 1.00000e-09); -// } -// }; -// S.foo(.{@bitCast(f32, @as(u32, 814313563))}); -//} +test "bitcast passed as tuple element" { + const S = struct { + fn foo(args: var) void { + comptime expect(@TypeOf(args[0]) == f32); + expect(args[0] == 12.34); + } + }; + S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))}); +} From b96872ef2f619de476fb79c0bb142ebdace62382 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 17:45:29 -0500 Subject: [PATCH 14/28] `@bitCast` result location: fix passing invalid alignment when the value has 0 bits --- src/ir.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index d4a0cb39c..94d39b8cb 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18525,10 +18525,11 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i return ira->codegen->invalid_inst_gen; } - uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { return ira->codegen->invalid_inst_gen; } + uint64_t parent_ptr_align = 0; + if (type_has_bits(value_type)) parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle, parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero); From b38b96784406c1d9e5f4246442f9414dba6812d2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 18:26:39 -0500 Subject: [PATCH 15/28] fix triple level result location with bitcast sandwich ...passed as tuple element --- src/ir.cpp | 16 ++++++++++++++-- test/stage1/behavior/bitcast.zig | 10 ++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 94d39b8cb..7f995a434 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18505,6 +18505,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i return bitcasted_value; } + bool parent_was_written = result_bit_cast->parent->written; IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, dest_type, bitcasted_value, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || @@ -18521,13 +18522,24 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i return parent_result_loc; } - if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) { + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) { return ira->codegen->invalid_inst_gen; } - if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { + if ((err = type_resolve(ira->codegen, value_type, ResolveStatusSizeKnown))) { return ira->codegen->invalid_inst_gen; } + + if (child_type != ira->codegen->builtin_types.entry_var) { + if (type_size(ira->codegen, child_type) != type_size(ira->codegen, value_type)) { + // pointer cast won't work; we need a temporary location. + result_bit_cast->parent->written = parent_was_written; + result_loc->written = true; + result_loc->resolved_loc = ir_resolve_result(ira, suspend_source_instr, no_result_loc(), + value_type, bitcasted_value, force_runtime, true); + return result_loc->resolved_loc; + } + } uint64_t parent_ptr_align = 0; if (type_has_bits(value_type)) parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, diff --git a/test/stage1/behavior/bitcast.zig b/test/stage1/behavior/bitcast.zig index 9eefdb01c..2cc102635 100644 --- a/test/stage1/behavior/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -177,3 +177,13 @@ test "bitcast passed as tuple element" { }; S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))}); } + +test "triple level result location with bitcast sandwich passed as tuple element" { + const S = struct { + fn foo(args: var) void { + comptime expect(@TypeOf(args[0]) == f64); + expect(args[0] > 12.33 and args[0] < 12.35); + } + }; + S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))}); +} From 37ab960492885c24a6b135f7955188d5f81d9a5a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 18:59:46 -0500 Subject: [PATCH 16/28] fix not handling undefined u0 correctly --- src/ir.cpp | 28 +++++++++++++++++++++++----- test/stage1/behavior/eval.zig | 13 +++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 7f995a434..47978bb64 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15644,9 +15644,27 @@ static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, } // Returns ErrorNotLazy when the value cannot be determined -static Error lazy_cmp_zero(AstNode *source_node, ZigValue *val, Cmp *result) { +static Error lazy_cmp_zero(CodeGen *codegen, AstNode *source_node, ZigValue *val, Cmp *result) { Error err; + switch (type_has_one_possible_value(codegen, val->type)) { + case OnePossibleValueInvalid: + return ErrorSemanticAnalyzeFail; + case OnePossibleValueNo: + break; + case OnePossibleValueYes: + switch (val->type->id) { + case ZigTypeIdInt: + src_assert(val->type->data.integral.bit_count == 0, source_node); + *result = CmpEQ; + return ErrorNone; + case ZigTypeIdUndefined: + return ErrorNotLazy; + default: + zig_unreachable(); + } + } + switch (val->special) { case ConstValSpecialRuntime: case ConstValSpecialUndef: @@ -15700,12 +15718,12 @@ static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, IrInst* source_instr, // Before resolving the values, we special case comparisons against zero. These can often // be done without resolving lazy values, preventing potential dependency loops. Cmp op1_cmp_zero; - if ((err = lazy_cmp_zero(source_instr->source_node, op1_val, &op1_cmp_zero))) { + if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op1_val, &op1_cmp_zero))) { if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; return ira->codegen->trace_err; } Cmp op2_cmp_zero; - if ((err = lazy_cmp_zero(source_instr->source_node, op2_val, &op2_cmp_zero))) { + if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op2_val, &op2_cmp_zero))) { if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally; return ira->codegen->trace_err; } @@ -15869,14 +15887,14 @@ static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_i } Cmp op1_cmp_zero; bool have_op1_cmp_zero = false; - if ((err = lazy_cmp_zero(source_instr->source_node, op1->value, &op1_cmp_zero))) { + if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op1->value, &op1_cmp_zero))) { if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen; } else { have_op1_cmp_zero = true; } Cmp op2_cmp_zero; bool have_op2_cmp_zero = false; - if ((err = lazy_cmp_zero(source_instr->source_node, op2->value, &op2_cmp_zero))) { + if ((err = lazy_cmp_zero(ira->codegen, source_instr->source_node, op2->value, &op2_cmp_zero))) { if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen; } else { have_op2_cmp_zero = true; diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig index e33def59c..ed81fae79 100644 --- a/test/stage1/behavior/eval.zig +++ b/test/stage1/behavior/eval.zig @@ -804,3 +804,16 @@ test "comptime assign int to optional int" { expectEqual(20, x.?); } } + +test "return 0 from function that has u0 return type" { + const S = struct { + fn foo_zero() u0 { + return 0; + } + }; + comptime { + if (S.foo_zero() != 0) { + @compileError("test failed"); + } + } +} From d8e25499963849f756498196f919575cb646f3dd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 19:42:13 -0500 Subject: [PATCH 17/28] remove invalid use of `allowzero` in std.crypto.murmur --- lib/std/hash/murmur.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/hash/murmur.zig b/lib/std/hash/murmur.zig index f6c0ccafb..23b11ef28 100644 --- a/lib/std/hash/murmur.zig +++ b/lib/std/hash/murmur.zig @@ -15,7 +15,7 @@ pub const Murmur2_32 = struct { const m: u32 = 0x5bd1e995; const len = @truncate(u32, str.len); var h1: u32 = seed ^ len; - for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| { + for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| { var k1: u32 = v; if (builtin.endian == builtin.Endian.Big) k1 = @byteSwap(u32, k1); @@ -100,7 +100,7 @@ pub const Murmur2_64 = struct { const m: u64 = 0xc6a4a7935bd1e995; const len = @as(u64, str.len); var h1: u64 = seed ^ (len *% m); - for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| { + for (@ptrCast([*]align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| { var k1: u64 = v; if (builtin.endian == builtin.Endian.Big) k1 = @byteSwap(u64, k1); @@ -180,7 +180,7 @@ pub const Murmur3_32 = struct { const c2: u32 = 0x1b873593; const len = @truncate(u32, str.len); var h1: u32 = seed; - for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| { + for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| { var k1: u32 = v; if (builtin.endian == builtin.Endian.Big) k1 = @byteSwap(u32, k1); From 9d59cdb8c13db0cfbc01f499dc227b1964ca24cc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 19:42:32 -0500 Subject: [PATCH 18/28] fix auto created variables not having correct alignment --- src/ir.cpp | 2 +- test/stage1/behavior/misc.zig | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 47978bb64..89e92585b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17729,7 +17729,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV var->var_type = ira->codegen->builtin_types.entry_invalid; return ir_const_void(ira, &decl_var_instruction->base.base); } - var->align_bytes = get_abi_alignment(ira->codegen, result_type); + var->align_bytes = get_ptr_align(ira->codegen, var_ptr->value->type); } else { if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, nullptr, &var->align_bytes)) { var->var_type = ira->codegen->builtin_types.entry_invalid; diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index bd11de5db..c77b49f03 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -781,3 +781,16 @@ test "pointer to thread local array" { std.mem.copy(u8, buffer[0..], s); std.testing.expectEqualSlices(u8, buffer[0..], s); } + +test "auto created variables have correct alignment" { + const S = struct { + fn foo(str: [*]const u8) u32 { + for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| { + return v; + } + return 0; + } + }; + expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a); + comptime expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a); +} From c58633ef17beb908fdfed46d7ca13e08d0d93648 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 20:56:24 -0500 Subject: [PATCH 19/28] fix assertion with var debug loc not initialized --- src/all_types.hpp | 1 + src/codegen.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 993a693d8..e9515a69c 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2286,6 +2286,7 @@ struct ZigVar { bool is_thread_local; bool is_comptime_memoized; bool is_comptime_memoized_value; + bool did_the_decl_codegen; }; struct ErrorTableEntry { diff --git a/src/codegen.cpp b/src/codegen.cpp index ef43ebd57..2eb5e4508 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3505,6 +3505,7 @@ static void render_decl_var(CodeGen *g, ZigVar *var) { static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) { instruction->var->ptr_instruction = instruction->var_ptr; + instruction->var->did_the_decl_codegen = true; render_decl_var(g, instruction->var); return nullptr; } @@ -3973,7 +3974,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { return; case ScopeIdVarDecl: { ZigVar *var = reinterpret_cast(scope)->var; - if (var->ptr_instruction != nullptr) { + if (var->did_the_decl_codegen) { render_decl_var(g, var); } // fallthrough From ae20574d5efaa7c63d78299b761eee38515b5865 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 21:30:11 -0500 Subject: [PATCH 20/28] add missing spill for for loops with pointer elems --- src/ir.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 89e92585b..b87deb88f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8477,9 +8477,8 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); - Scope *elem_ptr_scope = node->data.for_expr.elem_is_ptr ? parent_scope : &spill_scope->base; - IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, elem_ptr_scope, node, array_val_ptr, index_val, false, - PtrLenSingle, nullptr); + IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, &spill_scope->base, node, array_val_ptr, index_val, + false, PtrLenSingle, nullptr); // TODO make it an error to write to element variable or i variable. Buf *elem_var_name = elem_node->data.symbol_expr.symbol; ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); From 8710fdbf39c793027f332bd00efe70edaa86d91c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jan 2020 22:05:27 -0500 Subject: [PATCH 21/28] fix line, column numbers of compile errors --- src/ir.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index b87deb88f..3a17842d8 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18413,7 +18413,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i IrInstGen *casted_value; if (value != nullptr) { - casted_value = ir_implicit_cast(ira, value, dest_type); + casted_value = ir_implicit_cast2(ira, suspend_source_instr, value, dest_type); if (type_is_invalid(casted_value->value->type)) return ira->codegen->invalid_inst_gen; dest_type = casted_value->value->type; @@ -18860,7 +18860,8 @@ static IrInstGen *ir_analyze_async_call(IrAnalyze *ira, IrInst* source_instr, Zi if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } - result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false)); + result_loc = ir_implicit_cast2(ira, &call_result_loc->source_instruction->base, result_loc, + get_pointer_to_type(ira->codegen, frame_type, false)); if (type_is_invalid(result_loc->value->type)) return ira->codegen->invalid_inst_gen; return &ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, arg_count, @@ -19177,7 +19178,7 @@ static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, } static IrInstGen *analyze_casted_new_stack(IrAnalyze *ira, IrInst* source_instr, - IrInstGen *new_stack, bool is_async_call_builtin, ZigFn *fn_entry) + IrInstGen *new_stack, IrInst *new_stack_src, bool is_async_call_builtin, ZigFn *fn_entry) { if (new_stack == nullptr) return nullptr; @@ -19202,14 +19203,14 @@ static IrInstGen *analyze_casted_new_stack(IrAnalyze *ira, IrInst* source_instr, false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false); ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); ira->codegen->need_frame_size_prefix_data = true; - return ir_implicit_cast(ira, new_stack, u8_slice); + return ir_implicit_cast2(ira, new_stack_src, new_stack, u8_slice); } } static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, ZigFn *fn_entry, ZigType *fn_type, IrInstGen *fn_ref, IrInstGen *first_arg_ptr, CallModifier modifier, - IrInstGen *new_stack, bool is_async_call_builtin, + IrInstGen *new_stack, IrInst *new_stack_src, bool is_async_call_builtin, IrInstGen **args_ptr, size_t args_len, IrInstGen *ret_ptr, ResultLoc *call_result_loc) { Error err; @@ -19486,8 +19487,8 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, case ReqCompTimeYes: // Throw out our work and call the function as if it were comptime. return ir_analyze_fn_call(ira, source_instr, fn_entry, fn_type, fn_ref, first_arg_ptr, - CallModifierCompileTime, new_stack, is_async_call_builtin, args_ptr, args_len, - ret_ptr, call_result_loc); + CallModifierCompileTime, new_stack, new_stack_src, is_async_call_builtin, + args_ptr, args_len, ret_ptr, call_result_loc); case ReqCompTimeInvalid: return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: @@ -19522,7 +19523,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, } IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, - is_async_call_builtin, impl_fn); + new_stack_src, is_async_call_builtin, impl_fn); if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type)) return ira->codegen->invalid_inst_gen; @@ -19647,7 +19648,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; } - IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, + IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, new_stack_src, is_async_call_builtin, fn_entry); if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type)) return ira->codegen->invalid_inst_gen; @@ -19706,10 +19707,12 @@ static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_ins IrInstGen *first_arg_ptr, CallModifier modifier) { IrInstGen *new_stack = nullptr; + IrInst *new_stack_src = nullptr; if (call_instruction->new_stack) { new_stack = call_instruction->new_stack->child; if (type_is_invalid(new_stack->value->type)) return ira->codegen->invalid_inst_gen; + new_stack_src = &call_instruction->new_stack->base; } IrInstGen **args_ptr = allocate(call_instruction->arg_count, "IrInstGen *"); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { @@ -19724,7 +19727,7 @@ static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_ins return ira->codegen->invalid_inst_gen; } IrInstGen *result = ir_analyze_fn_call(ira, &call_instruction->base.base, fn_entry, fn_type, fn_ref, - first_arg_ptr, modifier, new_stack, call_instruction->is_async_call_builtin, + first_arg_ptr, modifier, new_stack, new_stack_src, call_instruction->is_async_call_builtin, args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc); deallocate(args_ptr, call_instruction->arg_count, "IrInstGen *"); return result; @@ -19824,7 +19827,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, } return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, - modifier, stack, false, args_ptr, args_len, nullptr, result_loc); + modifier, stack, &stack->base, false, args_ptr, args_len, nullptr, result_loc); } static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) { @@ -29477,7 +29480,7 @@ static IrInstGen *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstSrcResume } ZigType *any_frame_type = get_any_frame_type(ira->codegen, nullptr); - IrInstGen *casted_frame = ir_implicit_cast(ira, frame, any_frame_type); + IrInstGen *casted_frame = ir_implicit_cast2(ira, &instruction->frame->base, frame, any_frame_type); if (type_is_invalid(casted_frame->value->type)) return ira->codegen->invalid_inst_gen; From 287d3c37e1f53b6f0a0b29753b68254001194e62 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 11:39:36 -0500 Subject: [PATCH 22/28] fix 0-bit child type coerced to optional return ptr result location by un-special-casing 0 bit types in result locations --- src/analyze.cpp | 20 +++++++++++++- src/ir.cpp | 45 ++++++++++--------------------- test/stage1/behavior/optional.zig | 22 +++++++++++++++ 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index a5ab98422..db4200b73 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5700,6 +5700,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) { assert(field_type != nullptr); result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type); } + } else if (result->type->id == ZigTypeIdPointer) { + result->data.x_ptr.special = ConstPtrSpecialRef; + result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type); } g->one_possible_values.put(type_entry, result); return result; @@ -9471,7 +9474,11 @@ static void dump_value_indent(ZigValue *val, int indent) { fprintf(stderr, " "); } fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name)); - dump_value_indent(val->data.x_struct.fields[i], 1); + if (val->data.x_struct.fields == nullptr) { + fprintf(stderr, "\n"); + } else { + dump_value_indent(val->data.x_struct.fields[i], 1); + } } for (int i = 0; i < indent; i += 1) { fprintf(stderr, " "); @@ -9505,6 +9512,9 @@ static void dump_value_indent(ZigValue *val, int indent) { case ZigTypeIdPointer: switch (val->data.x_ptr.special) { + case ConstPtrSpecialInvalid: + fprintf(stderr, "\n"); + return; case ConstPtrSpecialRef: fprintf(stderr, "data.x_ptr.data.ref.pointee, indent + 1); @@ -9526,6 +9536,14 @@ static void dump_value_indent(ZigValue *val, int indent) { } break; } + case ConstPtrSpecialBaseOptionalPayload: { + ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val; + fprintf(stderr, "codegen, actual_elem_type, value_type); if (!same_comptime_repr) { - bool has_bits; - if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) - return ira->codegen->invalid_inst_gen; - if (has_bits) { - result_loc_pass1->written = false; - return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); - } + result_loc_pass1->written = false; + return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); } } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) { - bool has_bits; - if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) - return ira->codegen->invalid_inst_gen; - if (has_bits) { - if (value_type->id == ZigTypeIdErrorSet) { - return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true); + if (value_type->id == ZigTypeIdErrorSet) { + return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true); + } else { + IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr, + result_loc, false, true); + ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type; + if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && + value_type->id != ZigTypeIdNull) + { + return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true); } else { - IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr, - result_loc, false, true); - ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type; - if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && - value_type->id != ZigTypeIdNull) - { - return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true); - } else { - return unwrapped_err_ptr; - } + return unwrapped_err_ptr; } } } @@ -22215,14 +22204,8 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou } break; case OnePossibleValueYes: { - ZigValue *pointee = create_const_vals(1); - pointee->special = ConstValSpecialStatic; - pointee->type = child_type; - pointee->parent.id = ConstParentIdOptionalPayload; - pointee->parent.data.p_optional_payload.optional_val = optional_val; - optional_val->special = ConstValSpecialStatic; - optional_val->data.x_optional = pointee; + optional_val->data.x_optional = get_the_one_possible_value(ira->codegen, child_type); break; } } diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig index 4d9d8e1e8..fa002b707 100644 --- a/test/stage1/behavior/optional.zig +++ b/test/stage1/behavior/optional.zig @@ -153,3 +153,25 @@ test "optional with void type" { var x = Foo{ .x = null }; expect(x.x == null); } + +test "0-bit child type coerced to optional return ptr result location" { + const S = struct { + fn doTheTest() void { + var y = Foo{}; + var z = y.thing(); + expect(z != null); + } + + const Foo = struct { + pub const Bar = struct { + field: *Foo, + }; + + pub fn thing(self: *Foo) ?Bar { + return Bar{ .field = self }; + } + }; + }; + S.doTheTest(); + comptime S.doTheTest(); +} From 5c55a9b4e8d6d1f5ee3548cf8033e7e69951b308 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 11:52:48 -0500 Subject: [PATCH 23/28] fix compile error regression with struct containing itself --- src/analyze.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/analyze.cpp b/src/analyze.cpp index db4200b73..2210a17da 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5641,6 +5641,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { return OnePossibleValueYes; return type_has_one_possible_value(g, type_entry->data.array.child_type); case ZigTypeIdStruct: + // If the recursive function call asks, then we are not one possible value. + type_entry->one_possible_value = OnePossibleValueNo; for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { TypeStructField *field = type_entry->data.structure.fields[i]; OnePossibleValue opv = (field->type_entry != nullptr) ? @@ -5648,6 +5650,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { type_val_resolve_has_one_possible_value(g, field->type_val); switch (opv) { case OnePossibleValueInvalid: + type_entry->one_possible_value = OnePossibleValueInvalid; return OnePossibleValueInvalid; case OnePossibleValueNo: return OnePossibleValueNo; @@ -5655,6 +5658,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { continue; } } + type_entry->one_possible_value = OnePossibleValueYes; return OnePossibleValueYes; case ZigTypeIdErrorSet: case ZigTypeIdEnum: From e0000c47bd22c7b351247b72a85ca26c1c2ada96 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 12:32:39 -0500 Subject: [PATCH 24/28] fix regression of storing optional with 0-bit payload --- src/codegen.cpp | 4 ++++ src/ir.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 2eb5e4508..f749b2100 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4731,6 +4731,10 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *e LLVMPositionBuilderAtEnd(g->builder, ok_block); } if (!type_has_bits(child_type)) { + if (instruction->initializing) { + LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false); + gen_store_untyped(g, non_null_bit, base_ptr, 0, false); + } return nullptr; } else { bool is_scalar = !handle_is_ptr(maybe_type); diff --git a/src/ir.cpp b/src/ir.cpp index d832c71b7..5a522961b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10402,6 +10402,7 @@ static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *ex if (instr_is_comptime(instruction)) { switch (instruction->id) { case IrInstGenIdUnwrapErrPayload: + case IrInstGenIdOptionalUnwrapPtr: case IrInstGenIdUnionFieldPtr: continue; default: @@ -18671,7 +18672,7 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr { bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type); if (!same_comptime_repr) { - result_loc_pass1->written = false; + result_loc_pass1->written = was_written; return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); } } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) { @@ -29971,7 +29972,6 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { case IrInstGenIdReturnPtr: case IrInstGenIdStructFieldPtr: case IrInstGenIdTestNonNull: - case IrInstGenIdOptionalUnwrapPtr: case IrInstGenIdClz: case IrInstGenIdCtz: case IrInstGenIdPopCount: @@ -30028,6 +30028,8 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { return reinterpret_cast(instruction)->initializing; case IrInstGenIdUnionFieldPtr: return reinterpret_cast(instruction)->initializing; + case IrInstGenIdOptionalUnwrapPtr: + return reinterpret_cast(instruction)->initializing; case IrInstGenIdErrWrapPayload: return reinterpret_cast(instruction)->result_loc != nullptr; case IrInstGenIdErrWrapCode: From 86da9346e4839007931f811fd34498d8209baed0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 13:25:49 -0500 Subject: [PATCH 25/28] fix error message column/line number regressions --- src/ir.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 5a522961b..dcbf80bd7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -232,7 +232,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, ZigValue *out_val, ZigValue *ptr_val); static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr, - ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on); + IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on); static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed); static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, @@ -14999,7 +14999,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, dest_ptr_type = wanted_type->data.maybe.child_type; } if (dest_ptr_type != nullptr) { - return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); + return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true); } } @@ -15041,7 +15041,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) { - return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true); + return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true); } // cast from integer to C pointer @@ -18478,7 +18478,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i result_loc->written = true; result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, - ptr_type, &result_cast->base.source_instruction->base, false); + &parent_result_loc->base, ptr_type, &result_cast->base.source_instruction->base, false); return result_loc->resolved_loc; } case ResultLocIdBitCast: { @@ -18566,7 +18566,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i result_loc->written = true; result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, - ptr_type, &result_bit_cast->base.source_instruction->base, false); + &parent_result_loc->base, ptr_type, &result_bit_cast->base.source_instruction->base, false); return result_loc->resolved_loc; } } @@ -22716,8 +22716,8 @@ static IrInstGen *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstSrcSwi ref_type->data.pointer.explicit_alignment, ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, ref_type->data.pointer.allow_zero); - return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, new_target_value_ptr_type, - &instruction->base.base, false); + return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, + &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false); } else { ir_add_error(ira, &instruction->base.base, buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name))); @@ -22797,8 +22797,8 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, ref_type->data.pointer.explicit_alignment, ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, ref_type->data.pointer.allow_zero); - return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, new_target_value_ptr_type, - &instruction->base.base, false); + return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, + &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false); } return target_value_ptr; @@ -27688,7 +27688,7 @@ static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t alig } static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr, - ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on) + IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on) { Error err; @@ -27704,7 +27704,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn ZigType *src_ptr_type = get_src_ptr_type(src_type); if (src_ptr_type == nullptr) { - ir_add_error(ira, &ptr->base, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); + ir_add_error(ira, ptr_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); return ira->codegen->invalid_inst_gen; } @@ -27737,7 +27737,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("'%s' and '%s' do not have the same in-memory representation", buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); - add_error_note(ira->codegen, msg, ptr->base.source_node, + add_error_note(ira->codegen, msg, ptr_src->source_node, buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name))); add_error_note(ira->codegen, msg, dest_type_src->source_node, buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name))); @@ -27801,7 +27801,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn if (dest_align_bytes > src_align_bytes) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); - add_error_note(ira->codegen, msg, ptr->base.source_node, + add_error_note(ira->codegen, msg, ptr_src->source_node, buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes)); add_error_note(ira->codegen, msg, dest_type_src->source_node, buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes)); @@ -27834,8 +27834,8 @@ static IrInstGen *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstSrcPtrCa if (type_is_invalid(src_type)) return ira->codegen->invalid_inst_gen; - return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, dest_type, &dest_type_value->base, - instruction->safety_check_on); + return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, &instruction->ptr->base, + dest_type, &dest_type_value->base, instruction->safety_check_on); } static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue *val, size_t len) { From 793d81c4e8b75a8a3d8f51917af6634213b7cabc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 13:33:51 -0500 Subject: [PATCH 26/28] fix result locations not handling undefined correctly --- src/ir.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index dcbf80bd7..fcf8f06e0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18668,14 +18668,16 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr ir_assert(result_loc->value->type->id == ZigTypeIdPointer, suspend_source_instr); ZigType *actual_elem_type = result_loc->value->type->data.pointer.child_type; if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && - value_type->id != ZigTypeIdNull) + value_type->id != ZigTypeIdNull && value_type->id != ZigTypeIdUndefined) { bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type); if (!same_comptime_repr) { result_loc_pass1->written = was_written; return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); } - } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) { + } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion && + value_type->id != ZigTypeIdUndefined) + { if (value_type->id == ZigTypeIdErrorSet) { return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true); } else { @@ -18683,7 +18685,7 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr result_loc, false, true); ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type; if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && - value_type->id != ZigTypeIdNull) + value_type->id != ZigTypeIdNull && value_type->id != ZigTypeIdUndefined) { return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true); } else { From 504ce86ac991938fcd0544d771c7743833060dda Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 14:17:25 -0500 Subject: [PATCH 27/28] fix more compile error test regressions --- src/all_types.hpp | 1 + src/ir.cpp | 81 ++++++++++++++++++++++++----------------- test/compile_errors.zig | 13 +++---- 3 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index e9515a69c..c2405127d 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -317,6 +317,7 @@ struct ConstErrValue { struct ConstBoundFnValue { ZigFn *fn; IrInstGen *first_arg; + IrInst *first_arg_src; }; struct ConstArgTuple { diff --git a/src/ir.cpp b/src/ir.cpp index fcf8f06e0..631e268f5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -218,7 +218,8 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst *source_instr, IrInstGen * ResultLoc *result_loc); static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg); static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type, bool initializing); + IrInst* source_instr, IrInstGen *container_ptr, IrInst *container_ptr_src, + ZigType *container_type, bool initializing); static void ir_assert(bool ok, IrInst* source_instruction); static void ir_assert_gen(bool ok, IrInstGen *source_instruction); static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var); @@ -13040,10 +13041,13 @@ static IrInstGen *ir_const_fn(IrAnalyze *ira, IrInst *source_instr, ZigFn *fn_en return result; } -static IrInstGen *ir_const_bound_fn(IrAnalyze *ira, IrInst *src_inst, ZigFn *fn_entry, IrInstGen *first_arg) { +static IrInstGen *ir_const_bound_fn(IrAnalyze *ira, IrInst *src_inst, ZigFn *fn_entry, IrInstGen *first_arg, + IrInst *first_arg_src) +{ IrInstGen *result = ir_const(ira, src_inst, get_bound_fn_type(ira->codegen, fn_entry)); result->value->data.x_bound_fn.fn = fn_entry; result->value->data.x_bound_fn.first_arg = first_arg; + result->value->data.x_bound_fn.first_arg_src = first_arg_src; return result; } @@ -15481,7 +15485,7 @@ static IrInstGen *ir_analyze_instruction_return(IrAnalyze *ira, IrInstSrcReturn casted_operand->value->type->id == ZigTypeIdPointer && casted_operand->value->data.rh_ptr == RuntimeHintPtrStack) { - ir_add_error(ira, &casted_operand->base, buf_sprintf("function returns address of local variable")); + ir_add_error(ira, &instruction->operand->base, buf_sprintf("function returns address of local variable")); return ir_unreach_error(ira); } @@ -18895,7 +18899,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node } static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_node, - IrInstGen *arg, Scope **child_scope, size_t *next_proto_i, + IrInstGen *arg, IrInst *arg_src, Scope **child_scope, size_t *next_proto_i, GenericFnTypeId *generic_id, FnTypeId *fn_type_id, IrInstGen **casted_args, ZigFn *impl_fn) { @@ -18914,7 +18918,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod if (type_is_invalid(param_type)) return false; - casted_arg = ir_implicit_cast(ira, arg, param_type); + casted_arg = ir_implicit_cast2(ira, arg_src, arg, param_type); if (type_is_invalid(casted_arg->value->type)) return false; } else { @@ -19201,7 +19205,7 @@ static IrInstGen *analyze_casted_new_stack(IrAnalyze *ira, IrInst* source_instr, static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, ZigFn *fn_entry, ZigType *fn_type, IrInstGen *fn_ref, - IrInstGen *first_arg_ptr, CallModifier modifier, + IrInstGen *first_arg_ptr, IrInst *first_arg_ptr_src, CallModifier modifier, IrInstGen *new_stack, IrInst *new_stack_src, bool is_async_call_builtin, IrInstGen **args_ptr, size_t args_len, IrInstGen *ret_ptr, ResultLoc *call_result_loc) { @@ -19416,8 +19420,8 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; } - if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope, - &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) + if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, first_arg_ptr_src, + &impl_fn->child_scope, &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) { return ira->codegen->invalid_inst_gen; } @@ -19431,7 +19435,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(next_proto_i); assert(param_decl_node->type == NodeTypeParamDecl); - if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, + if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &arg->base, &impl_fn->child_scope, &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) { return ira->codegen->invalid_inst_gen; @@ -19479,7 +19483,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, case ReqCompTimeYes: // Throw out our work and call the function as if it were comptime. return ir_analyze_fn_call(ira, source_instr, fn_entry, fn_type, fn_ref, first_arg_ptr, - CallModifierCompileTime, new_stack, new_stack_src, is_async_call_builtin, + first_arg_ptr_src, CallModifierCompileTime, new_stack, new_stack_src, is_async_call_builtin, args_ptr, args_len, ret_ptr, call_result_loc); case ReqCompTimeInvalid: return ira->codegen->invalid_inst_gen; @@ -19600,7 +19604,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; } - IrInstGen *casted_arg = ir_implicit_cast(ira, first_arg, param_type); + IrInstGen *casted_arg = ir_implicit_cast2(ira, first_arg_ptr_src, first_arg, param_type); if (type_is_invalid(casted_arg->value->type)) return ira->codegen->invalid_inst_gen; @@ -19696,7 +19700,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type, IrInstGen *fn_ref, - IrInstGen *first_arg_ptr, CallModifier modifier) + IrInstGen *first_arg_ptr, IrInst *first_arg_ptr_src, CallModifier modifier) { IrInstGen *new_stack = nullptr; IrInst *new_stack_src = nullptr; @@ -19719,8 +19723,9 @@ static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_ins return ira->codegen->invalid_inst_gen; } IrInstGen *result = ir_analyze_fn_call(ira, &call_instruction->base.base, fn_entry, fn_type, fn_ref, - first_arg_ptr, modifier, new_stack, new_stack_src, call_instruction->is_async_call_builtin, - args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc); + first_arg_ptr, first_arg_ptr_src, modifier, new_stack, new_stack_src, + call_instruction->is_async_call_builtin, args_ptr, call_instruction->arg_count, ret_ptr, + call_instruction->result_loc); deallocate(args_ptr, call_instruction->arg_count, "IrInstGen *"); return result; } @@ -19771,12 +19776,14 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, } IrInstGen *first_arg_ptr = nullptr; + IrInst *first_arg_ptr_src = nullptr; ZigFn *fn = nullptr; if (instr_is_comptime(fn_ref)) { if (fn_ref->value->type->id == ZigTypeIdBoundFn) { assert(fn_ref->value->special == ConstValSpecialStatic); fn = fn_ref->value->data.x_bound_fn.fn; first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; + first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src; if (type_is_invalid(first_arg_ptr->value->type)) return ira->codegen->invalid_inst_gen; } else { @@ -19818,7 +19825,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; } - return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, + return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, first_arg_ptr_src, modifier, stack, &stack->base, false, args_ptr, args_len, nullptr, result_loc); } @@ -19894,14 +19901,15 @@ static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *cal ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type; CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_type, - fn_ref, nullptr, modifier); + fn_ref, nullptr, nullptr, modifier); } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) { assert(fn_ref->value->special == ConstValSpecialStatic); ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn; IrInstGen *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; + IrInst *first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src; CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, - fn_ref, first_arg_ptr, modifier); + fn_ref, first_arg_ptr, first_arg_ptr_src, modifier); } else { ir_add_error(ira, &fn_ref->base, buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name))); @@ -19911,7 +19919,7 @@ static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *cal if (fn_ref->value->type->id == ZigTypeIdFn) { return ir_analyze_fn_call_src(ira, call_instruction, nullptr, fn_ref->value->type, - fn_ref, nullptr, modifier); + fn_ref, nullptr, nullptr, modifier); } else { ir_add_error(ira, &fn_ref->base, buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name))); @@ -21009,7 +21017,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, ZigType *bare_struct_type, Buf *field_name, IrInst* source_instr, - IrInstGen *container_ptr, ZigType *container_type) + IrInstGen *container_ptr, IrInst *container_ptr_src, ZigType *container_type) { if (!is_slice(bare_struct_type)) { ScopeDecls *container_scope = get_container_scope(bare_struct_type); @@ -21030,7 +21038,8 @@ static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, if (type_is_invalid(fn_entry->type_entry)) return ira->codegen->invalid_inst_gen; - IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn_entry, container_ptr); + IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn_entry, container_ptr, + container_ptr_src); return ir_get_ref(ira, source_instr, bound_fn_value, true, false); } else if (tld->id == TldIdVar) { resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); @@ -21049,7 +21058,8 @@ static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, if (var->const_value->type->id == ZigTypeIdFn) { ir_assert(var->const_value->data.x_ptr.special == ConstPtrSpecialFunction, source_instr); ZigFn *fn = var->const_value->data.x_ptr.data.fn.fn_entry; - IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn, container_ptr); + IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn, container_ptr, + container_ptr_src); return ir_get_ref(ira, source_instr, bound_fn_value, true, false); } } @@ -21213,7 +21223,8 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, } static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type, bool initializing) + IrInst* source_instr, IrInstGen *container_ptr, IrInst *container_ptr_src, + ZigType *container_type, bool initializing) { Error err; @@ -21235,13 +21246,13 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing); } else { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, - source_instr, container_ptr, container_type); + source_instr, container_ptr, container_ptr_src, container_type); } } if (bare_type->id == ZigTypeIdEnum) { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, - source_instr, container_ptr, container_type); + source_instr, container_ptr, container_ptr_src, container_type); } if (bare_type->id == ZigTypeIdUnion) { @@ -21251,7 +21262,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name TypeUnionField *field = find_union_type_field(bare_type, field_name); if (field == nullptr) { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, - source_instr, container_ptr, container_type); + source_instr, container_ptr, container_ptr_src, container_type); } ZigType *field_type = resolve_union_field_type(ira->codegen, field); @@ -21445,10 +21456,14 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel if (container_type->id == ZigTypeIdPointer) { ZigType *bare_type = container_ref_type(container_type); IrInstGen *container_child = ir_get_deref(ira, &field_ptr_instruction->base.base, container_ptr, nullptr); - IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, container_child, bare_type, field_ptr_instruction->initializing); + IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, + container_child, &field_ptr_instruction->container_ptr->base, bare_type, + field_ptr_instruction->initializing); return result; } else { - IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, container_ptr, container_type, field_ptr_instruction->initializing); + IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, + container_ptr, &field_ptr_instruction->container_ptr->base, container_type, + field_ptr_instruction->initializing); return result; } } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) { @@ -25096,7 +25111,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch // TODO let this be volatile ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); - IrInstGen *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type); + IrInstGen *casted_ptr = ir_implicit_cast2(ira, &instruction->ptr->base, ptr, ptr_type); if (type_is_invalid(casted_ptr->value->type)) return ira->codegen->invalid_inst_gen; @@ -25124,11 +25139,11 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch if (!ir_resolve_atomic_order(ira, failure_order_value, &failure_order)) return ira->codegen->invalid_inst_gen; - IrInstGen *casted_cmp_value = ir_implicit_cast(ira, cmp_value, operand_type); + IrInstGen *casted_cmp_value = ir_implicit_cast2(ira, &instruction->cmp_value->base, cmp_value, operand_type); if (type_is_invalid(casted_cmp_value->value->type)) return ira->codegen->invalid_inst_gen; - IrInstGen *casted_new_value = ir_implicit_cast(ira, new_value, operand_type); + IrInstGen *casted_new_value = ir_implicit_cast2(ira, &instruction->new_value->base, new_value, operand_type); if (type_is_invalid(casted_new_value->value->type)) return ira->codegen->invalid_inst_gen; @@ -25219,7 +25234,7 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc } if (dest_type->id == ZigTypeIdComptimeInt) { - return ir_implicit_cast(ira, target, dest_type); + return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); } if (instr_is_comptime(target)) { @@ -25273,7 +25288,7 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa } if (instr_is_comptime(target)) { - return ir_implicit_cast(ira, target, dest_type); + return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); } if (dest_type->id == ZigTypeIdComptimeInt) { @@ -25401,7 +25416,7 @@ static IrInstGen *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstSrcFro src_ptr_align, 0, 0, false); ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); - IrInstGen *casted_value = ir_implicit_cast(ira, target, u8_slice); + IrInstGen *casted_value = ir_implicit_cast2(ira, &instruction->target->base, target, u8_slice); if (type_is_invalid(casted_value->value->type)) return ira->codegen->invalid_inst_gen; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 4a8dde2cd..89e187aed 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1658,7 +1658,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.addTest("return invalid type from test", \\test "example" { return 1; } , &[_][]const u8{ - "tmp.zig:1:25: error: integer value 1 cannot be coerced to type 'void'", + "tmp.zig:1:25: error: expected type 'void', found 'comptime_int'", }); cases.add("threadlocal qualifier on const", @@ -2487,7 +2487,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var rule_set = try Foo.init(); \\} , &[_][]const u8{ - "tmp.zig:2:10: error: expected type 'i32', found 'type'", + "tmp.zig:2:19: error: expected type 'i32', found 'type'", }); cases.add("slicing single-item pointer", @@ -3393,7 +3393,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\fn b() void {} , &[_][]const u8{ - "tmp.zig:3:6: error: unreachable code", + "tmp.zig:3:5: error: unreachable code", }); cases.add("bad import", @@ -4011,8 +4011,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@TypeOf(Foo)); } , &[_][]const u8{ - "tmp.zig:5:25: error: unable to evaluate constant expression", - "tmp.zig:2:12: note: referenced here", + "tmp.zig:5:25: error: cannot store runtime value in compile time variable", + "tmp.zig:2:12: note: called from here", }); cases.add("addition with non numbers", @@ -4652,7 +4652,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\fn something() anyerror!void { } , &[_][]const u8{ "tmp.zig:2:5: error: expected type 'void', found 'anyerror'", - "tmp.zig:1:15: note: return type declared here", }); cases.add("invalid pointer for var type", @@ -5743,7 +5742,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ @export(entry, .{.name = "entry", .linkage = @as(u32, 1234) }); \\} , &[_][]const u8{ - "tmp.zig:3:50: error: expected type 'std.builtin.GlobalLinkage', found 'u32'", + "tmp.zig:3:59: error: expected type 'std.builtin.GlobalLinkage', found 'comptime_int'", }); cases.add("struct with invalid field", From 3ed52e5453a6971c6a3db0846f503478922d4ea5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Jan 2020 14:54:34 -0500 Subject: [PATCH 28/28] fix build.zig logic for -target-cpu and -target-feature fix a false negative for detecting the ability to emit these flags. it matters for stage0/stage1 on aarch64 --- lib/std/build.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/build.zig b/lib/std/build.zig index 560f82961..d310f53c0 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1978,6 +1978,9 @@ pub const LibExeObjStep = struct { const all_features = self.target.getArch().allFeaturesList(); var populated_cpu_features = cross.cpu_features.cpu.features; + if (self.target.getArch().subArchFeature()) |sub_arch_index| { + populated_cpu_features.addFeature(sub_arch_index); + } populated_cpu_features.populateDependencies(all_features); if (populated_cpu_features.eql(cross.cpu_features.features)) {