Commit 2ba29a1907

Andrew Kelley <andrew@ziglang.org>
2019-06-14 17:01:38
fix peer result location with error code and payload
1 parent fdaca1b
Changed files (4)
src/all_types.hpp
@@ -3099,6 +3099,7 @@ struct IrInstructionTestErr {
 struct IrInstructionUnwrapErrCode {
     IrInstruction base;
 
+    bool initializing;
     IrInstruction *err_union_ptr;
 };
 
src/codegen.cpp
@@ -4901,6 +4901,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
     if (!type_has_bits(payload_type)) {
         return err_union_ptr;
     } else {
+        // TODO assign undef to the payload
         LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
         return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
     }
src/ir.cpp
@@ -193,6 +193,8 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
         IrInstruction *base_ptr, bool safety_check_on, bool initializing);
 static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
         IrInstruction *base_ptr, bool safety_check_on, bool initializing);
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+        IrInstruction *base_ptr, bool initializing);
 
 static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
     assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -15016,13 +15018,17 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
     if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
         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) {
-        IrInstruction *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) {
-            return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
+        if (value_type->id == ZigTypeIdErrorSet) {
+            return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
         } else {
-            return unwrapped_err_ptr;
+            IrInstruction *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) {
+                return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
+            } else {
+                return unwrapped_err_ptr;
+            }
         }
     }
     return result_loc;
@@ -16437,6 +16443,9 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
                     peer_parent->base.source_instruction->source_node, expected_type, instructions,
                     peer_parent->peer_count);
 
+            // the logic below assumes there are no instructions in the new current basic block yet
+            ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);
+
             // 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);
@@ -16445,6 +16454,21 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
             {
                 return parent_result_loc;
             }
+            // If the above code generated any instructions in the current basic block, we need
+            // to move them to the peer parent predecessor.
+            ZigList<IrInstruction *> instrs_to_move = {};
+            while (ira->new_irb.current_basic_block->instruction_list.length != 0) {
+                instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop());
+            }
+            if (instrs_to_move.length != 0) {
+                IrBasicBlock *predecessor = peer_parent->base.source_instruction->child->owner_bb;
+                IrInstruction *branch_instruction = predecessor->instruction_list.pop();
+                ir_assert(branch_instruction->value.type->id == ZigTypeIdUnreachable, &phi_instruction->base);
+                while (instrs_to_move.length != 0) {
+                    predecessor->instruction_list.append(instrs_to_move.pop());
+                }
+                predecessor->instruction_list.append(branch_instruction);
+            }
         }
 
         IrSuspendPosition suspend_pos;
@@ -22213,10 +22237,9 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
     }
 }
 
-static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
-    IrInstruction *base_ptr = instruction->err_union_ptr->child;
-    if (type_is_invalid(base_ptr->value.type))
-        return ira->codegen->invalid_instruction;
+static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
+        IrInstruction *base_ptr, bool initializing)
+{
     ZigType *ptr_type = base_ptr->value.type;
 
     // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
@@ -22238,30 +22261,38 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
         if (!ptr_val)
             return ira->codegen->invalid_instruction;
         if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
-            ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+            ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
             if (err_union_val == nullptr)
                 return ira->codegen->invalid_instruction;
             if (err_union_val->special != ConstValSpecialRuntime) {
                 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
                 assert(err != nullptr);
 
-                IrInstruction *err_set_val = ir_const(ira, &instruction->base,
-                                                 type_entry->data.error_union.err_set_type);
+                IrInstruction *err_set_val = ir_const(ira, source_instr, type_entry->data.error_union.err_set_type);
                 err_set_val->value.data.x_err_set = err;
                 err_set_val->value.parent.id = ConstParentIdErrUnionCode;
                 err_set_val->value.parent.data.p_err_union_code.err_union_val = err_union_val;
 
-                return ir_get_ref(ira, &instruction->base, err_set_val, is_ptr_const, false);
+                return ir_get_ref(ira, source_instr, err_set_val, is_ptr_const, false);
             }
         }
     }
 
     IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
-        instruction->base.scope, instruction->base.source_node, base_ptr);
+        source_instr->scope, source_instr->source_node, base_ptr);
     result->value.type = get_pointer_to_type(ira->codegen, type_entry->data.error_union.err_set_type, is_ptr_const);
     return result;
 }
 
+static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
+        IrInstructionUnwrapErrCode *instruction)
+{
+    IrInstruction *base_ptr = instruction->err_union_ptr->child;
+    if (type_is_invalid(base_ptr->value.type))
+        return ira->codegen->invalid_instruction;
+    return ir_analyze_unwrap_err_code(ira, &instruction->base, base_ptr, false);
+}
+
 static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
         IrInstruction *base_ptr, bool safety_check_on, bool initializing)
 {
@@ -24783,7 +24814,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdFrameAddress:
         case IrInstructionIdHandle:
         case IrInstructionIdTestErr:
-        case IrInstructionIdUnwrapErrCode:
         case IrInstructionIdFnProto:
         case IrInstructionIdTestComptime:
         case IrInstructionIdPtrCastSrc:
@@ -24846,8 +24876,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
             {
                 IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction =
                     (IrInstructionUnwrapErrPayload *)instruction;
-                return unwrap_err_payload_instruction->safety_check_on;
+                return unwrap_err_payload_instruction->safety_check_on ||
+                    unwrap_err_payload_instruction->initializing;
             }
+        case IrInstructionIdUnwrapErrCode:
+            return reinterpret_cast<IrInstructionUnwrapErrCode *>(instruction)->initializing;
         case IrInstructionIdErrWrapPayload:
             return reinterpret_cast<IrInstructionErrWrapPayload *>(instruction)->result_loc != nullptr;
         case IrInstructionIdErrWrapCode:
test/stage1/behavior.zig
@@ -21,7 +21,7 @@ comptime {
     _ = @import("behavior/bugs/1486.zig");
     _ = @import("behavior/bugs/1500.zig");
     _ = @import("behavior/bugs/1607.zig");
-    //_ = @import("behavior/bugs/1851.zig");
+    _ = @import("behavior/bugs/1851.zig");
     _ = @import("behavior/bugs/1914.zig");
     _ = @import("behavior/bugs/2006.zig");
     _ = @import("behavior/bugs/2114.zig");
@@ -41,16 +41,16 @@ comptime {
     _ = @import("behavior/byval_arg_var.zig");
     //_ = @import("behavior/cancel.zig");
     //_ = @import("behavior/cast.zig");
-    //_ = @import("behavior/const_slice_child.zig");
+    _ = @import("behavior/const_slice_child.zig");
     //_ = @import("behavior/coroutine_await_struct.zig");
     //_ = @import("behavior/coroutines.zig");
-    //_ = @import("behavior/defer.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/field_parent_ptr.zig");
-    //_ = @import("behavior/fn.zig");
+    _ = @import("behavior/fn.zig");
     _ = @import("behavior/fn_in_struct_in_comptime.zig");
     _ = @import("behavior/for.zig");
     //_ = @import("behavior/generics.zig");
@@ -59,13 +59,13 @@ comptime {
     //_ = @import("behavior/import.zig");
     _ = @import("behavior/incomplete_struct_param_tld.zig");
     _ = @import("behavior/inttoptr.zig");
-    //_ = @import("behavior/ir_block_deps.zig");
+    _ = @import("behavior/ir_block_deps.zig");
     //_ = @import("behavior/math.zig");
     //_ = @import("behavior/merge_error_sets.zig");
     //_ = @import("behavior/misc.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/popcount.zig");
@@ -93,7 +93,7 @@ comptime {
     //_ = @import("behavior/union.zig");
     _ = @import("behavior/var_args.zig");
     _ = @import("behavior/vector.zig");
-    //_ = @import("behavior/void.zig");
+    _ = @import("behavior/void.zig");
     //_ = @import("behavior/while.zig");
     _ = @import("behavior/widening.zig");
 }