| ... | ... | @@ -4539,7 +4539,7 @@ pub const FuncGen = struct { |
| 4539 | 4539 | } |
| 4540 | 4540 | // We need to emit instructions to check for equality/inequality |
| 4541 | 4541 | // of optionals that are not pointers. |
| 4542 | | const is_by_ref = isByRef(operand_ty); |
| 4542 | const is_by_ref = isByRef(scalar_ty); |
| 4543 | 4543 | const lhs_non_null = self.optIsNonNull(lhs, is_by_ref); |
| 4544 | 4544 | const rhs_non_null = self.optIsNonNull(rhs, is_by_ref); |
| 4545 | 4545 | const llvm_i2 = self.context.intType(2); |
| ... | ... | @@ -4564,8 +4564,8 @@ pub const FuncGen = struct { |
| 4564 | 4564 | _ = self.builder.buildBr(end_block); |
| 4565 | 4565 | |
| 4566 | 4566 | self.builder.positionBuilderAtEnd(both_pl_block); |
| 4567 | | const lhs_payload = self.optPayloadHandle(lhs, is_by_ref); |
| 4568 | | const rhs_payload = self.optPayloadHandle(rhs, is_by_ref); |
| 4567 | const lhs_payload = self.optPayloadHandle(lhs, scalar_ty); |
| 4568 | const rhs_payload = self.optPayloadHandle(rhs, scalar_ty); |
| 4569 | 4569 | const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); |
| 4570 | 4570 | _ = self.builder.buildBr(end_block); |
| 4571 | 4571 | const both_pl_block_end = self.builder.getInsertBlock(); |
| ... | ... | @@ -4740,12 +4740,14 @@ pub const FuncGen = struct { |
| 4740 | 4740 | const err_set_ty = try fg.dg.lowerType(Type.anyerror); |
| 4741 | 4741 | const zero = err_set_ty.constNull(); |
| 4742 | 4742 | if (!payload_has_bits) { |
| 4743 | // TODO add alignment to this load |
| 4743 | 4744 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; |
| 4744 | 4745 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4745 | 4746 | } |
| 4746 | 4747 | const err_field_index = errUnionErrorOffset(payload_ty, target); |
| 4747 | 4748 | if (operand_is_ptr or isByRef(err_union_ty)) { |
| 4748 | 4749 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); |
| 4750 | // TODO add alignment to this load |
| 4749 | 4751 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); |
| 4750 | 4752 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4751 | 4753 | } |
| ... | ... | @@ -4765,13 +4767,22 @@ pub const FuncGen = struct { |
| 4765 | 4767 | if (!payload_has_bits) { |
| 4766 | 4768 | if (!operand_is_ptr) return null; |
| 4767 | 4769 | |
| 4768 | | // TODO once we update to LLVM 14 this bitcast won't be necessary. |
| 4770 | // TODO once we update to an LLVM version with opaque pointers |
| 4771 | // this bitcast won't be necessary. |
| 4769 | 4772 | const res_ptr_ty = try fg.dg.lowerType(result_ty); |
| 4770 | 4773 | return fg.builder.buildBitCast(err_union, res_ptr_ty, ""); |
| 4771 | 4774 | } |
| 4772 | 4775 | const offset = errUnionPayloadOffset(payload_ty, target); |
| 4773 | 4776 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 4774 | 4777 | return fg.builder.buildStructGEP(err_union, offset, ""); |
| 4778 | } else if (isByRef(err_union_ty)) { |
| 4779 | const payload_ptr = fg.builder.buildStructGEP(err_union, offset, ""); |
| 4780 | if (isByRef(payload_ty)) { |
| 4781 | return payload_ptr; |
| 4782 | } |
| 4783 | const load_inst = fg.builder.buildLoad(payload_ptr, ""); |
| 4784 | load_inst.setAlignment(payload_ty.abiAlignment(target)); |
| 4785 | return load_inst; |
| 4775 | 4786 | } |
| 4776 | 4787 | return fg.builder.buildExtractValue(err_union, offset, ""); |
| 4777 | 4788 | } |
| ... | ... | @@ -5730,12 +5741,7 @@ pub const FuncGen = struct { |
| 5730 | 5741 | // The payload and the optional are the same value. |
| 5731 | 5742 | return operand; |
| 5732 | 5743 | } |
| 5733 | | const index_type = self.context.intType(32); |
| 5734 | | const indices: [2]*const llvm.Value = .{ |
| 5735 | | index_type.constNull(), // dereference the pointer |
| 5736 | | index_type.constNull(), // first field is the payload |
| 5737 | | }; |
| 5738 | | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| 5744 | return self.builder.buildStructGEP(operand, 0, ""); |
| 5739 | 5745 | } |
| 5740 | 5746 | |
| 5741 | 5747 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | ... | @@ -5761,24 +5767,17 @@ pub const FuncGen = struct { |
| 5761 | 5767 | // Setting to non-null will be done when the payload is set. |
| 5762 | 5768 | return operand; |
| 5763 | 5769 | } |
| 5764 | | const index_type = self.context.intType(32); |
| 5765 | | { |
| 5766 | | // First set the non-null bit. |
| 5767 | | const indices: [2]*const llvm.Value = .{ |
| 5768 | | index_type.constNull(), // dereference the pointer |
| 5769 | | index_type.constInt(1, .False), // second field is the non-null bit |
| 5770 | | }; |
| 5771 | | const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| 5772 | | _ = self.builder.buildStore(non_null_bit, non_null_ptr); |
| 5773 | | } |
| 5770 | |
| 5771 | // First set the non-null bit. |
| 5772 | const non_null_ptr = self.builder.buildStructGEP(operand, 1, ""); |
| 5773 | // TODO set alignment on this store |
| 5774 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); |
| 5775 | |
| 5774 | 5776 | // Then return the payload pointer (only if it's used). |
| 5775 | 5777 | if (self.liveness.isUnused(inst)) |
| 5776 | 5778 | return null; |
| 5777 | | const indices: [2]*const llvm.Value = .{ |
| 5778 | | index_type.constNull(), // dereference the pointer |
| 5779 | | index_type.constNull(), // first field is the payload |
| 5780 | | }; |
| 5781 | | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| 5779 | |
| 5780 | return self.builder.buildStructGEP(operand, 0, ""); |
| 5782 | 5781 | } |
| 5783 | 5782 | |
| 5784 | 5783 | fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | ... | @@ -5795,7 +5794,7 @@ pub const FuncGen = struct { |
| 5795 | 5794 | return operand; |
| 5796 | 5795 | } |
| 5797 | 5796 | |
| 5798 | | return self.optPayloadHandle(operand, isByRef(payload_ty)); |
| 5797 | return self.optPayloadHandle(operand, optional_ty); |
| 5799 | 5798 | } |
| 5800 | 5799 | |
| 5801 | 5800 | fn airErrUnionPayload( |
| ... | ... | @@ -5807,6 +5806,8 @@ pub const FuncGen = struct { |
| 5807 | 5806 | |
| 5808 | 5807 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5809 | 5808 | const operand = try self.resolveInst(ty_op.operand); |
| 5809 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 5810 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 5810 | 5811 | const result_ty = self.air.typeOfIndex(inst); |
| 5811 | 5812 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; |
| 5812 | 5813 | const target = self.dg.module.getTarget(); |
| ... | ... | @@ -5821,6 +5822,14 @@ pub const FuncGen = struct { |
| 5821 | 5822 | const offset = errUnionPayloadOffset(payload_ty, target); |
| 5822 | 5823 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 5823 | 5824 | return self.builder.buildStructGEP(operand, offset, ""); |
| 5825 | } else if (isByRef(err_union_ty)) { |
| 5826 | const payload_ptr = self.builder.buildStructGEP(operand, offset, ""); |
| 5827 | if (isByRef(payload_ty)) { |
| 5828 | return payload_ptr; |
| 5829 | } |
| 5830 | const load_inst = self.builder.buildLoad(payload_ptr, ""); |
| 5831 | load_inst.setAlignment(payload_ty.abiAlignment(target)); |
| 5832 | return load_inst; |
| 5824 | 5833 | } |
| 5825 | 5834 | return self.builder.buildExtractValue(operand, offset, ""); |
| 5826 | 5835 | } |
| ... | ... | @@ -5874,16 +5883,11 @@ pub const FuncGen = struct { |
| 5874 | 5883 | _ = self.builder.buildStore(non_error_val, operand); |
| 5875 | 5884 | return operand; |
| 5876 | 5885 | } |
| 5877 | | const index_type = self.context.intType(32); |
| 5878 | 5886 | const target = self.dg.module.getTarget(); |
| 5879 | 5887 | { |
| 5880 | 5888 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 5881 | 5889 | // First set the non-error value. |
| 5882 | | const indices: [2]*const llvm.Value = .{ |
| 5883 | | index_type.constNull(), // dereference the pointer |
| 5884 | | index_type.constInt(error_offset, .False), |
| 5885 | | }; |
| 5886 | | const non_null_ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| 5890 | const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, ""); |
| 5887 | 5891 | const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); |
| 5888 | 5892 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| 5889 | 5893 | } |
| ... | ... | @@ -5892,11 +5896,7 @@ pub const FuncGen = struct { |
| 5892 | 5896 | return null; |
| 5893 | 5897 | |
| 5894 | 5898 | const payload_offset = errUnionPayloadOffset(payload_ty, target); |
| 5895 | | const indices: [2]*const llvm.Value = .{ |
| 5896 | | index_type.constNull(), // dereference the pointer |
| 5897 | | index_type.constInt(payload_offset, .False), |
| 5898 | | }; |
| 5899 | | return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); |
| 5899 | return self.builder.buildStructGEP(operand, payload_offset, ""); |
| 5900 | 5900 | } |
| 5901 | 5901 | |
| 5902 | 5902 | fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { |
| ... | ... | @@ -6391,8 +6391,30 @@ pub const FuncGen = struct { |
| 6391 | 6391 | const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); |
| 6392 | 6392 | |
| 6393 | 6393 | var ty_buf: Type.Payload.Pointer = undefined; |
| 6394 | | const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?, ""); |
| 6395 | | return self.builder.buildInsertValue(partial, overflow_bit, llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?, ""); |
| 6394 | const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?; |
| 6395 | const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?; |
| 6396 | |
| 6397 | if (isByRef(dest_ty)) { |
| 6398 | const target = self.dg.module.getTarget(); |
| 6399 | const alloca_inst = self.buildAlloca(llvm_dest_ty); |
| 6400 | const result_alignment = dest_ty.abiAlignment(target); |
| 6401 | alloca_inst.setAlignment(result_alignment); |
| 6402 | { |
| 6403 | const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); |
| 6404 | const store_inst = self.builder.buildStore(result, field_ptr); |
| 6405 | store_inst.setAlignment(result_alignment); |
| 6406 | } |
| 6407 | { |
| 6408 | const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); |
| 6409 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); |
| 6410 | store_inst.setAlignment(1); |
| 6411 | } |
| 6412 | |
| 6413 | return alloca_inst; |
| 6414 | } |
| 6415 | |
| 6416 | const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, ""); |
| 6417 | return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, ""); |
| 6396 | 6418 | } |
| 6397 | 6419 | |
| 6398 | 6420 | fn buildElementwiseCall( |
| ... | ... | @@ -6721,8 +6743,30 @@ pub const FuncGen = struct { |
| 6721 | 6743 | const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, ""); |
| 6722 | 6744 | |
| 6723 | 6745 | var ty_buf: Type.Payload.Pointer = undefined; |
| 6724 | | const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?, ""); |
| 6725 | | return self.builder.buildInsertValue(partial, overflow_bit, llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?, ""); |
| 6746 | const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?; |
| 6747 | const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?; |
| 6748 | |
| 6749 | if (isByRef(dest_ty)) { |
| 6750 | const target = self.dg.module.getTarget(); |
| 6751 | const alloca_inst = self.buildAlloca(llvm_dest_ty); |
| 6752 | const result_alignment = dest_ty.abiAlignment(target); |
| 6753 | alloca_inst.setAlignment(result_alignment); |
| 6754 | { |
| 6755 | const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); |
| 6756 | const store_inst = self.builder.buildStore(result, field_ptr); |
| 6757 | store_inst.setAlignment(result_alignment); |
| 6758 | } |
| 6759 | { |
| 6760 | const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); |
| 6761 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); |
| 6762 | store_inst.setAlignment(1); |
| 6763 | } |
| 6764 | |
| 6765 | return alloca_inst; |
| 6766 | } |
| 6767 | |
| 6768 | const partial = self.builder.buildInsertValue(llvm_dest_ty.getUndef(), result, result_index, ""); |
| 6769 | return self.builder.buildInsertValue(partial, overflow_bit, overflow_index, ""); |
| 6726 | 6770 | } |
| 6727 | 6771 | |
| 6728 | 6772 | fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | ... | @@ -7347,11 +7391,9 @@ pub const FuncGen = struct { |
| 7347 | 7391 | } |
| 7348 | 7392 | |
| 7349 | 7393 | comptime assert(optional_layout_version == 3); |
| 7350 | | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| 7394 | |
| 7351 | 7395 | const non_null_bit = self.builder.buildNot(success_bit, ""); |
| 7352 | | const non_null_field = self.builder.buildZExt(non_null_bit, self.dg.context.intType(8), ""); |
| 7353 | | const partial = self.builder.buildInsertValue(optional_llvm_ty.getUndef(), payload, 0, ""); |
| 7354 | | return self.builder.buildInsertValue(partial, non_null_field, 1, ""); |
| 7396 | return buildOptional(self, optional_ty, payload, non_null_bit); |
| 7355 | 7397 | } |
| 7356 | 7398 | |
| 7357 | 7399 | fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | ... | @@ -7515,11 +7557,13 @@ pub const FuncGen = struct { |
| 7515 | 7557 | const union_ptr = try self.resolveInst(bin_op.lhs); |
| 7516 | 7558 | const new_tag = try self.resolveInst(bin_op.rhs); |
| 7517 | 7559 | if (layout.payload_size == 0) { |
| 7560 | // TODO alignment on this store |
| 7518 | 7561 | _ = self.builder.buildStore(new_tag, union_ptr); |
| 7519 | 7562 | return null; |
| 7520 | 7563 | } |
| 7521 | 7564 | const tag_index = @boolToInt(layout.tag_align < layout.payload_align); |
| 7522 | 7565 | const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, ""); |
| 7566 | // TODO alignment on this store |
| 7523 | 7567 | _ = self.builder.buildStore(new_tag, tag_field_ptr); |
| 7524 | 7568 | return null; |
| 7525 | 7569 | } |
| ... | ... | @@ -8336,17 +8380,9 @@ pub const FuncGen = struct { |
| 8336 | 8380 | fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { |
| 8337 | 8381 | const field = b: { |
| 8338 | 8382 | if (is_by_ref) { |
| 8339 | | const index_type = self.context.intType(32); |
| 8340 | | |
| 8341 | | const indices: [2]*const llvm.Value = .{ |
| 8342 | | index_type.constNull(), |
| 8343 | | index_type.constInt(1, .False), |
| 8344 | | }; |
| 8345 | | |
| 8346 | | const field_ptr = self.builder.buildInBoundsGEP(opt_handle, &indices, indices.len, ""); |
| 8383 | const field_ptr = self.builder.buildStructGEP(opt_handle, 1, ""); |
| 8347 | 8384 | break :b self.builder.buildLoad(field_ptr, ""); |
| 8348 | 8385 | } |
| 8349 | | |
| 8350 | 8386 | break :b self.builder.buildExtractValue(opt_handle, 1, ""); |
| 8351 | 8387 | }; |
| 8352 | 8388 | comptime assert(optional_layout_version == 3); |
| ... | ... | @@ -8355,18 +8391,63 @@ pub const FuncGen = struct { |
| 8355 | 8391 | } |
| 8356 | 8392 | |
| 8357 | 8393 | /// Assumes the optional is not pointer-like and payload has bits. |
| 8358 | | fn optPayloadHandle(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { |
| 8359 | | if (is_by_ref) { |
| 8394 | fn optPayloadHandle( |
| 8395 | fg: *FuncGen, |
| 8396 | opt_handle: *const llvm.Value, |
| 8397 | opt_ty: Type, |
| 8398 | ) *const llvm.Value { |
| 8399 | var buf: Type.Payload.ElemType = undefined; |
| 8400 | const payload_ty = opt_ty.optionalChild(&buf); |
| 8401 | |
| 8402 | if (isByRef(opt_ty)) { |
| 8360 | 8403 | // We have a pointer and we need to return a pointer to the first field. |
| 8361 | | const index_type = self.context.intType(32); |
| 8362 | | const indices: [2]*const llvm.Value = .{ |
| 8363 | | index_type.constNull(), // dereference the pointer |
| 8364 | | index_type.constNull(), // first field is the payload |
| 8365 | | }; |
| 8366 | | return self.builder.buildInBoundsGEP(opt_handle, &indices, indices.len, ""); |
| 8404 | const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, ""); |
| 8405 | |
| 8406 | if (isByRef(payload_ty)) { |
| 8407 | return payload_ptr; |
| 8408 | } |
| 8409 | const target = fg.dg.module.getTarget(); |
| 8410 | const payload_alignment = payload_ty.abiAlignment(target); |
| 8411 | const load_inst = fg.builder.buildLoad(payload_ptr, ""); |
| 8412 | load_inst.setAlignment(payload_alignment); |
| 8413 | return load_inst; |
| 8414 | } |
| 8415 | |
| 8416 | assert(!isByRef(payload_ty)); |
| 8417 | return fg.builder.buildExtractValue(opt_handle, 0, ""); |
| 8418 | } |
| 8419 | |
| 8420 | fn buildOptional( |
| 8421 | self: *FuncGen, |
| 8422 | optional_ty: Type, |
| 8423 | payload: *const llvm.Value, |
| 8424 | non_null_bit: *const llvm.Value, |
| 8425 | ) !?*const llvm.Value { |
| 8426 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| 8427 | const non_null_field = self.builder.buildZExt(non_null_bit, self.dg.context.intType(8), ""); |
| 8428 | |
| 8429 | if (isByRef(optional_ty)) { |
| 8430 | const target = self.dg.module.getTarget(); |
| 8431 | const alloca_inst = self.buildAlloca(optional_llvm_ty); |
| 8432 | const payload_alignment = optional_ty.abiAlignment(target); |
| 8433 | alloca_inst.setAlignment(payload_alignment); |
| 8434 | |
| 8435 | { |
| 8436 | const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, ""); |
| 8437 | const store_inst = self.builder.buildStore(payload, field_ptr); |
| 8438 | store_inst.setAlignment(payload_alignment); |
| 8439 | } |
| 8440 | { |
| 8441 | const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, ""); |
| 8442 | const store_inst = self.builder.buildStore(non_null_field, field_ptr); |
| 8443 | store_inst.setAlignment(1); |
| 8444 | } |
| 8445 | |
| 8446 | return alloca_inst; |
| 8367 | 8447 | } |
| 8368 | 8448 | |
| 8369 | | return self.builder.buildExtractValue(opt_handle, 0, ""); |
| 8449 | const partial = self.builder.buildInsertValue(optional_llvm_ty.getUndef(), payload, 0, ""); |
| 8450 | return self.builder.buildInsertValue(partial, non_null_field, 1, ""); |
| 8370 | 8451 | } |
| 8371 | 8452 | |
| 8372 | 8453 | fn fieldPtr( |
| ... | ... | @@ -9275,10 +9356,12 @@ fn ccAbiPromoteInt( |
| 9275 | 9356 | return null; |
| 9276 | 9357 | } |
| 9277 | 9358 | |
| 9359 | /// This is the one source of truth for whether a type is passed around as an LLVM pointer, |
| 9360 | /// or as an LLVM value. |
| 9278 | 9361 | fn isByRef(ty: Type) bool { |
| 9279 | 9362 | // For tuples and structs, if there are more than this many non-void |
| 9280 | 9363 | // fields, then we make it byref, otherwise byval. |
| 9281 | | const max_fields_byval = 2; |
| 9364 | const max_fields_byval = 0; |
| 9282 | 9365 | |
| 9283 | 9366 | switch (ty.zigTypeTag()) { |
| 9284 | 9367 | .Type, |
| ... | ... | @@ -9332,10 +9415,23 @@ fn isByRef(ty: Type) bool { |
| 9332 | 9415 | return false; |
| 9333 | 9416 | }, |
| 9334 | 9417 | .Union => return ty.hasRuntimeBits(), |
| 9335 | | .ErrorUnion => return isByRef(ty.errorUnionPayload()), |
| 9418 | .ErrorUnion => { |
| 9419 | const payload_ty = ty.errorUnionPayload(); |
| 9420 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 9421 | return false; |
| 9422 | } |
| 9423 | return true; |
| 9424 | }, |
| 9336 | 9425 | .Optional => { |
| 9337 | 9426 | var buf: Type.Payload.ElemType = undefined; |
| 9338 | | return isByRef(ty.optionalChild(&buf)); |
| 9427 | const payload_ty = ty.optionalChild(&buf); |
| 9428 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 9429 | return false; |
| 9430 | } |
| 9431 | if (ty.optionalReprIsPayload()) { |
| 9432 | return false; |
| 9433 | } |
| 9434 | return true; |
| 9339 | 9435 | }, |
| 9340 | 9436 | } |
| 9341 | 9437 | } |