Commit 077f9df15b

Andrew Kelley <andrew@ziglang.org>
2019-06-18 20:30:17
more miscellaneous fixes
when will it end
1 parent fdc6e0a
Changed files (1)
src
src/ir.cpp
@@ -14874,6 +14874,16 @@ static bool type_can_bit_cast(ZigType *t) {
     }
 }
 
+static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) {
+    ConstExprValue *undef_child = create_const_vals(1);
+    undef_child->type = ptr->value.type->data.pointer.child_type;
+    undef_child->special = ConstValSpecialUndef;
+    ptr->value.special = ConstValSpecialStatic;
+    ptr->value.data.x_ptr.mut = ConstPtrMutInfer;
+    ptr->value.data.x_ptr.special = ConstPtrSpecialRef;
+    ptr->value.data.x_ptr.data.ref.pointee = undef_child;
+}
+
 // 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)
@@ -14901,6 +14911,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
                 return ira->codegen->invalid_instruction;
             alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
                     PtrLenSingle, 0, 0, 0, false);
+            set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
             ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
             if (fn_entry != nullptr) {
                 fn_entry->alloca_gen_list.append(alloca_gen);
@@ -14958,6 +14969,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
             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);
+            set_up_result_loc_for_inferred_comptime(result_loc->resolved_loc);
             return result_loc->resolved_loc;
         }
         case ResultLocIdPeer: {
@@ -15132,7 +15144,6 @@ static void ir_reset_result(ResultLoc *result_loc) {
     result_loc->resolved_loc = nullptr;
     result_loc->gen_instruction = nullptr;
     result_loc->implicit_elem_type = nullptr;
-    // TODO handle result_loc->scope_elide = 
     switch (result_loc->id) {
         case ResultLocIdInvalid:
             zig_unreachable();
@@ -18289,27 +18300,77 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
     ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
             ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
 
+    bool same_comptime_repr = types_have_same_zig_comptime_repr(type_entry, child_type);
+
     if (instr_is_comptime(base_ptr)) {
-        ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
-        if (!val)
+        ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
+        if (!ptr_val)
             return ira->codegen->invalid_instruction;
-        if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
-            ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
-            if (maybe_val == nullptr)
+        if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+            ConstExprValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
+            if (optional_val == nullptr)
                 return ira->codegen->invalid_instruction;
 
-            if (optional_value_is_null(maybe_val)) {
+            if (initializing && optional_val->special == ConstValSpecialUndef) {
+                switch (type_has_one_possible_value(ira->codegen, child_type)) {
+                    case OnePossibleValueInvalid:
+                        return ira->codegen->invalid_instruction;
+                    case OnePossibleValueNo:
+                        if (!same_comptime_repr) {
+                            ConstExprValue *payload_val = create_const_vals(1);
+                            payload_val->type = child_type;
+                            payload_val->special = ConstValSpecialUndef;
+                            payload_val->parent.id = ConstParentIdOptionalPayload;
+                            payload_val->parent.data.p_optional_payload.optional_val = optional_val;
+
+                            optional_val->data.x_optional = payload_val;
+                            optional_val->special = ConstValSpecialStatic;
+                        }
+                        break;
+                    case OnePossibleValueYes: {
+                        ConstExprValue *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;
+                        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;
             }
-            IrInstruction *result = ir_const(ira, source_instr, result_type);
-            ConstExprValue *out_val = &result->value;
-            out_val->data.x_ptr.special = ConstPtrSpecialRef;
-            out_val->data.x_ptr.mut = val->data.x_ptr.mut;
-            if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
-                out_val->data.x_ptr.data.ref.pointee = maybe_val;
+
+            IrInstruction *result;
+            if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+                result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
+                        source_instr->source_node, base_ptr, false, initializing);
+                result->value.type = result_type;
+                result->value.special = ConstValSpecialStatic;
             } else {
-                out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
+                result = ir_const(ira, source_instr, result_type);
+            }
+            ConstExprValue *result_val = &result->value;
+            result_val->data.x_ptr.special = ConstPtrSpecialRef;
+            result_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
+            switch (type_has_one_possible_value(ira->codegen, child_type)) {
+                case OnePossibleValueInvalid:
+                    return ira->codegen->invalid_instruction;
+                case OnePossibleValueNo:
+                    if (same_comptime_repr) {
+                        result_val->data.x_ptr.data.ref.pointee = optional_val;
+                    } else {
+                        assert(optional_val->data.x_optional != nullptr);
+                        result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
+                    }
+                    break;
+                case OnePossibleValueYes:
+                    assert(optional_val->data.x_optional != nullptr);
+                    result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
+                    break;
             }
             return result;
         }
@@ -22409,10 +22470,16 @@ static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstru
             !instr_is_comptime(result))
     {
         IrInstruction *result_ptr = instruction->result_loc->resolved_loc;
-        // Convert the pointer to the result type. They should be the same, except this will resolve
-        // inferred error sets.
-        ZigType *new_ptr_type = get_pointer_to_type(ira->codegen, result->value.type, true);
-        return ir_analyze_ptr_cast(ira, &instruction->base, result_ptr, new_ptr_type, &instruction->base, false);
+        if (result->value.type->id == ZigTypeIdErrorUnion &&
+                result_ptr->value.type->data.pointer.child_type->id == ZigTypeIdErrorUnion)
+        {
+            // Convert the pointer to the result type. They should be the same, except this will resolve
+            // inferred error sets.
+            ZigType *new_ptr_type = get_pointer_to_type(ira->codegen, result->value.type, true);
+            return ir_analyze_ptr_cast(ira, &instruction->base, result_ptr, new_ptr_type, &instruction->base, false);
+        } else {
+            return result_ptr;
+        }
     }
     return ir_get_ref(ira, &instruction->base, result, true, false);
 }
@@ -22465,7 +22532,6 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *
 
     // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
     assert(ptr_type->id == ZigTypeIdPointer);
-    bool is_ptr_const = ptr_type->data.pointer.is_const;
 
     ZigType *type_entry = ptr_type->data.pointer.child_type;
     if (type_is_invalid(type_entry))
@@ -22477,31 +22543,63 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *
         return ira->codegen->invalid_instruction;
     }
 
+    ZigType *err_set_type = type_entry->data.error_union.err_set_type;
+    ZigType *result_type = get_pointer_to_type_extra(ira->codegen, err_set_type,
+            ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle,
+            ptr_type->data.pointer.explicit_alignment, 0, 0, false);
+
     if (instr_is_comptime(base_ptr)) {
         ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
         if (!ptr_val)
             return ira->codegen->invalid_instruction;
-        if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
+        if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
+            ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
+        {
             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, 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;
+            if (initializing && err_union_val->special == ConstValSpecialUndef) {
+                ConstExprValue *vals = create_const_vals(2);
+                ConstExprValue *err_set_val = &vals[0];
+                ConstExprValue *payload_val = &vals[1];
 
-                return ir_get_ref(ira, source_instr, err_set_val, is_ptr_const, false);
+                err_set_val->special = ConstValSpecialUndef;
+                err_set_val->type = err_set_type;
+                err_set_val->parent.id = ConstParentIdErrUnionCode;
+                err_set_val->parent.data.p_err_union_code.err_union_val = err_union_val;
+
+                payload_val->special = ConstValSpecialUndef;
+                payload_val->type = type_entry->data.error_union.payload_type;
+                payload_val->parent.id = ConstParentIdErrUnionPayload;
+                payload_val->parent.data.p_err_union_payload.err_union_val = err_union_val;
+
+                err_union_val->special = ConstValSpecialStatic;
+                err_union_val->data.x_err_union.error_set = err_set_val;
+                err_union_val->data.x_err_union.payload = payload_val;
+            }
+            ir_assert(err_union_val->special != ConstValSpecialRuntime, source_instr);
+
+            IrInstruction *result;
+            if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+                result = ir_build_unwrap_err_code(&ira->new_irb, source_instr->scope,
+                        source_instr->source_node, base_ptr);
+                result->value.type = result_type;
+                result->value.special = ConstValSpecialStatic;
+            } else {
+                result = ir_const(ira, source_instr, result_type);
             }
+            ConstExprValue *const_val = &result->value;
+            const_val->data.x_ptr.special = ConstPtrSpecialBaseErrorUnionCode;
+            const_val->data.x_ptr.data.base_err_union_code.err_union_val = err_union_val;
+            const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
+            return result;
         }
     }
 
     IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
         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);
+    result->value.type = result_type;
     return result;
 }
 
@@ -22547,6 +22645,23 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
             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 == ConstValSpecialUndef && initializing) {
+                ConstExprValue *vals = create_const_vals(2);
+                ConstExprValue *err_set_val = &vals[0];
+                ConstExprValue *payload_val = &vals[1];
+
+                err_set_val->special = ConstValSpecialStatic;
+                err_set_val->type = type_entry->data.error_union.err_set_type;
+                err_set_val->data.x_err_set = nullptr;
+
+                payload_val->special = ConstValSpecialUndef;
+                payload_val->type = payload_type;
+
+                err_union_val->special = ConstValSpecialStatic;
+                err_union_val->data.x_err_union.error_set = err_set_val;
+                err_union_val->data.x_err_union.payload = payload_val;
+            }
+
             if (err_union_val->special != ConstValSpecialRuntime) {
                 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
                 if (err != nullptr) {
@@ -22555,9 +22670,18 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
                     return ira->codegen->invalid_instruction;
                 }
 
-                IrInstruction *result = ir_const(ira, source_instr, result_type);
+                IrInstruction *result;
+                if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
+                    result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
+                        source_instr->source_node, base_ptr, safety_check_on, initializing);
+                    result->value.type = result_type;
+                    result->value.special = ConstValSpecialStatic;
+                } else {
+                    result = ir_const(ira, source_instr, result_type);
+                }
                 result->value.data.x_ptr.special = ConstPtrSpecialRef;
                 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
+                result->value.data.x_ptr.mut = ptr_val->data.x_ptr.mut;
                 return result;
             }
         }
@@ -23162,6 +23286,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
         case ZigTypeIdUndefined:
         case ZigTypeIdNull:
         case ZigTypeIdPromise:
+        case ZigTypeIdErrorUnion:
+        case ZigTypeIdErrorSet:
             zig_unreachable();
         case ZigTypeIdVoid:
             return;
@@ -23265,10 +23391,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
             }
         case ZigTypeIdOptional:
             zig_panic("TODO buf_write_value_bytes maybe type");
-        case ZigTypeIdErrorUnion:
-            zig_panic("TODO buf_write_value_bytes error union");
-        case ZigTypeIdErrorSet:
-            zig_panic("TODO buf_write_value_bytes pure error type");
         case ZigTypeIdFn:
             zig_panic("TODO buf_write_value_bytes fn type");
         case ZigTypeIdUnion:
@@ -24502,24 +24624,24 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
     if (type_is_invalid(value->value.type))
         return ira->codegen->invalid_instruction;
 
-    bool want_resolve_result = !instruction->result_loc->written;
-    if (want_resolve_result) {
-        IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
-                value->value.type, value, false);
-        if (result_loc != nullptr) {
-            if (type_is_invalid(result_loc->value.type))
-                return ira->codegen->invalid_instruction;
-            if (result_loc->value.type->id == ZigTypeIdUnreachable)
-                return result_loc;
+    bool was_written = instruction->result_loc->written;
+    IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
+            value->value.type, value, false);
+    if (result_loc != nullptr) {
+        if (type_is_invalid(result_loc->value.type))
+            return ira->codegen->invalid_instruction;
+        if (result_loc->value.type->id == ZigTypeIdUnreachable)
+            return result_loc;
 
-            instruction->result_loc->written = true;
+        if (!was_written) {
             ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
-            if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
-                if (instr_is_comptime(value)) {
-                    result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
-                } else {
-                    result_loc->value.special = ConstValSpecialRuntime;
-                }
+        }
+
+        if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
+            if (instr_is_comptime(value)) {
+                result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
+            } else {
+                result_loc->value.special = ConstValSpecialRuntime;
             }
         }
     }