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 | 438 ++++++++++++++++++++------------------- src/ir.hpp | 6 +- test/stage1/behavior.zig | 28 +-- 6 files changed, 278 insertions(+), 234 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 4d6f68daff879cfe3ae3a1cee690fa1cd305bd11..216fddcb102a107b48497326852b397f1def644a 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 b7838003c816fdb5ccc8435364df433eb024ee09..435020014d35eac44f8d393a4231338b7e287708 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 cd009b3beaf9db8da74b75dbce82e6a116194fa3..c4add2ce71575d1ec5d93a0f0455994d1fb692b8 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 818644f5012784788c5d46032e4511c09136204f..67bd46364498bb7267e9cbe3c7d8d146cdb43a03 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; } +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) { - 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); + 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 003bf4897dcf86ce277eb9144d677c53812a1258..4f9ed6bcdb31583a590e6b40aa53c7c94305c841 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 ea8720d98ca62d78e12acdfc3ff45353b5e24c15..d70947be5f32fa3b82821b95b8d1ef7c3f3a34d5 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"); -- 2.54.0 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 435020014d35eac44f8d393a4231338b7e287708..fe0b396d283d75ea54de56c7998fabfc8c5c7f80 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 67bd46364498bb7267e9cbe3c7d8d146cdb43a03..a1e8f9c43b0e543c21f356e27a836f42e9a4554d 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 d70947be5f32fa3b82821b95b8d1ef7c3f3a34d5..870ccf1aaa8177134b217a67bbfab1adb81beb92 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"); -- 2.54.0 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 a1e8f9c43b0e543c21f356e27a836f42e9a4554d..8580e419fac7fd550df581602b749e0a1548394f 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 870ccf1aaa8177134b217a67bbfab1adb81beb92..45d699f6b5dc5f5f6e09caa87ce916a32117b324 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"); -- 2.54.0 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 216fddcb102a107b48497326852b397f1def644a..6f9db1c2741de86c7ddd42feaa66f53663be7cb9 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 fe0b396d283d75ea54de56c7998fabfc8c5c7f80..14419d274c9f1ec1d98ad0365131ab2f9eed0288 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 8580e419fac7fd550df581602b749e0a1548394f..8d3b98435a70fe2372421396056b50b045df8448 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 45d699f6b5dc5f5f6e09caa87ce916a32117b324..a468030f6b1cc746c7bfd7f375a325bd37c985e1 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"); -- 2.54.0 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 8d3b98435a70fe2372421396056b50b045df8448..e82061670241bca1040ad55f7d000a134228bfb2 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 a468030f6b1cc746c7bfd7f375a325bd37c985e1..bd091c0c6004b2fcadf4e84e9258ef0a3996ca54 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 3506e7e24046e8430751cb9f0a808866cef299ee..114b0262b1a88d7232dc1d809f7d7984e2d22ce6 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; -- 2.54.0 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 6f9db1c2741de86c7ddd42feaa66f53663be7cb9..49cbf38d03e84c9ec64c8a608642dba6ecb22031 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 e82061670241bca1040ad55f7d000a134228bfb2..b926b3ae3b83dde10b0ff195f629b815b64cfed5 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 bd091c0c6004b2fcadf4e84e9258ef0a3996ca54..a5f13c204ca919fa75812ab73e546e67772ef70f 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"); -- 2.54.0 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 14419d274c9f1ec1d98ad0365131ab2f9eed0288..94d0c66e196dbc28c2d416c178713ed0265ddc94 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 c4add2ce71575d1ec5d93a0f0455994d1fb692b8..6b2b95d246b94d6dcd7d406207412dc26c551d0b 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 b926b3ae3b83dde10b0ff195f629b815b64cfed5..5b1494553a6b9058a413bd472832ce35aeddbbb6 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 4b227e9d7c3ebf6f6df15bece446ee79534962af..a1173690b549623b974397f00856483907e4f2a1 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 8dcd41438e45c30a7d4552867c06f6808c7dcebd..e1722921f5a8611e485ff0a7c76b959aed1c2e20 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 a5f13c204ca919fa75812ab73e546e67772ef70f..62a6dedccd684753393573743f1ea9a5ba770dcb 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"); -- 2.54.0 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 62a6dedccd684753393573743f1ea9a5ba770dcb..e362a9405ed92f5a102be6c726cbf7a34fef0c04 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 63c31fb03ee8dbc4c3b1583c0eac8a82a784eeaa..c309bc061fa06d14975b8c70dfc1e576ffd54941 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" { -- 2.54.0 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 5b1494553a6b9058a413bd472832ce35aeddbbb6..42bc8758e2766414aafe3d1bce12b4ccf6225a2e 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 e362a9405ed92f5a102be6c726cbf7a34fef0c04..066551bf1c05800b87d849d2b136024dcf4c0a23 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"); -- 2.54.0 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 42bc8758e2766414aafe3d1bce12b4ccf6225a2e..cb47806f1bf586760143610be365188c34c9d06d 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 066551bf1c05800b87d849d2b136024dcf4c0a23..f9bd9deef4f8ef592d6a357727f7f514af5dc0db 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"); -- 2.54.0 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 94d0c66e196dbc28c2d416c178713ed0265ddc94..4b3b024b538351d98ff50cb730317796dd7a945c 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 f9bd9deef4f8ef592d6a357727f7f514af5dc0db..ea8720d98ca62d78e12acdfc3ff45353b5e24c15 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"); -- 2.54.0 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 fe3dd6902de559539df6eae0044af763f8c10ea6..9c315c169c311632a0849d2034fbc4e669391cfc 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))}); +} -- 2.54.0 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 fe274195ef829237d3b421862587d828d32b322b..a5ab984228819b6ecf989e85f150115dcc000ef6 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 9a58a8c980d538721b593b21ca3e213d7172e818..ef43ebd575e72cd1955c248d6d04b9217a0ce52b 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 4e06ab5f65f6059333846e157d27b85fa2c46194..d4a0cb39c9193fea13e75d46ad725acbca88ee84 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 bb45fe00bc8544afcccdb20242e401393c911732..9eefdb01cf9fe69647c7e3f9cf8fb410dc2400c2 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))}); +} -- 2.54.0 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 d4a0cb39c9193fea13e75d46ad725acbca88ee84..94d39b8cb60ef110c7b5aa46c6c9146245b7456b 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); -- 2.54.0 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 94d39b8cb60ef110c7b5aa46c6c9146245b7456b..7f995a43438a0f946b91d5a1199d63bf85b7b177 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 9eefdb01cf9fe69647c7e3f9cf8fb410dc2400c2..2cc1026354a93ac687f2c4d598ecef53d77feaa9 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)))}); +} -- 2.54.0 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 7f995a43438a0f946b91d5a1199d63bf85b7b177..47978bb648c1034b2e492e16a519aef967a0ace7 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 e33def59c46e3af6f16476e079dbb873738b43b5..ed81fae791a80458eb1282e4e3af70f927a874c8 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"); + } + } +} -- 2.54.0 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 f6c0ccafb3e9faee0c8b78ebb3457ec19ef681d6..23b11ef28475b9d0fea5e1e6d1387d20c3c6f0b6 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); -- 2.54.0 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 47978bb648c1034b2e492e16a519aef967a0ace7..89e92585b3dd9d46391f56c6818c499b06790d01 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 bd11de5dbf97b7d549a22e4b9fc4acd56e027442..c77b49f03a28ef12ae2b318396b7ab072ea6917f 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); +} -- 2.54.0 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 993a693d8821894f8fa6d6be4fb6383c82cf51b8..e9515a69cc1e0b5da8e91a8e79ee91037d4498a8 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 ef43ebd575e72cd1955c248d6d04b9217a0ce52b..2eb5e450835e5f6352698828cbc1c00cb362f7bc 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 -- 2.54.0 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 89e92585b3dd9d46391f56c6818c499b06790d01..b87deb88fe537d0e35de5c961a830de2d457c6f3 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); -- 2.54.0 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 b87deb88fe537d0e35de5c961a830de2d457c6f3..3a17842d836b7daea23538955593beba4c6a4af9 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; -- 2.54.0 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 a5ab984228819b6ecf989e85f150115dcc000ef6..db4200b734df2ab6da04e89e9cfa7e43d016f5de 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 4d9d8e1e82bcb61f59e63236a59709c2d36d2a74..fa002b707e854b2da8b7491444c0c156ec9112df 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(); +} -- 2.54.0 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 db4200b734df2ab6da04e89e9cfa7e43d016f5de..2210a17da37ebb27f6a81659451755caed4a1fc4 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: -- 2.54.0 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 2eb5e450835e5f6352698828cbc1c00cb362f7bc..f749b21008ac74eaa3ef1e4241463eb4fb4eadce 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 d832c71b787d7877ef91f77740ad3e4d6c844472..5a522961bdc0b6c62d761ec208e25994f1495b7d 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: -- 2.54.0 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 5a522961bdc0b6c62d761ec208e25994f1495b7d..dcbf80bd78c6e2a275121d8fd966346ef1289d3e 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) { -- 2.54.0 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 dcbf80bd78c6e2a275121d8fd966346ef1289d3e..fcf8f06e0e377ae3a84a31a1d31c03f5ba6770ee 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 { -- 2.54.0 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 e9515a69cc1e0b5da8e91a8e79ee91037d4498a8..c2405127dcdc7a878e2acf60847f36f97dfeacf9 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 fcf8f06e0e377ae3a84a31a1d31c03f5ba6770ee..631e268f5582a2ad84b115be94bf8d83de256e9e 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 4a8dde2cdc52f819aa8a98720ad16a7b7b7d58bc..89e187aed2f37b284c2088b68b616eb18c3ff5d0 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", -- 2.54.0 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 560f82961c98691bf781d0a01897902ca07ce03e..d310f53c06149503abd879a737245f98173daddb 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)) { -- 2.54.0