| ... | @@ -4740,12 +4740,14 @@ pub const FuncGen = struct { | ... | @@ -4740,12 +4740,14 @@ pub const FuncGen = struct { |
| 4740 | const err_set_ty = try fg.dg.lowerType(Type.anyerror); | 4740 | const err_set_ty = try fg.dg.lowerType(Type.anyerror); |
| 4741 | const zero = err_set_ty.constNull(); | 4741 | const zero = err_set_ty.constNull(); |
| 4742 | if (!payload_has_bits) { | 4742 | if (!payload_has_bits) { |
| | 4743 | // TODO add alignment to this load |
| 4743 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; | 4744 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; |
| 4744 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | 4745 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4745 | } | 4746 | } |
| 4746 | const err_field_index = errUnionErrorOffset(payload_ty, target); | 4747 | const err_field_index = errUnionErrorOffset(payload_ty, target); |
| 4747 | if (operand_is_ptr or isByRef(err_union_ty)) { | 4748 | if (operand_is_ptr or isByRef(err_union_ty)) { |
| 4748 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); | 4749 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); |
| | 4750 | // TODO add alignment to this load |
| 4749 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); | 4751 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); |
| 4750 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | 4752 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4751 | } | 4753 | } |
| ... | @@ -4765,13 +4767,22 @@ pub const FuncGen = struct { | ... | @@ -4765,13 +4767,22 @@ pub const FuncGen = struct { |
| 4765 | if (!payload_has_bits) { | 4767 | if (!payload_has_bits) { |
| 4766 | if (!operand_is_ptr) return null; | 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 | const res_ptr_ty = try fg.dg.lowerType(result_ty); | 4772 | const res_ptr_ty = try fg.dg.lowerType(result_ty); |
| 4770 | return fg.builder.buildBitCast(err_union, res_ptr_ty, ""); | 4773 | return fg.builder.buildBitCast(err_union, res_ptr_ty, ""); |
| 4771 | } | 4774 | } |
| 4772 | const offset = errUnionPayloadOffset(payload_ty, target); | 4775 | const offset = errUnionPayloadOffset(payload_ty, target); |
| 4773 | if (operand_is_ptr or isByRef(payload_ty)) { | 4776 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 4774 | return fg.builder.buildStructGEP(err_union, offset, ""); | 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 | return fg.builder.buildExtractValue(err_union, offset, ""); | 4787 | return fg.builder.buildExtractValue(err_union, offset, ""); |
| 4777 | } | 4788 | } |
| ... | @@ -5795,6 +5806,8 @@ pub const FuncGen = struct { | ... | @@ -5795,6 +5806,8 @@ pub const FuncGen = struct { |
| 5795 | | 5806 | |
| 5796 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5807 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5797 | const operand = try self.resolveInst(ty_op.operand); | 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; |
| 5798 | const result_ty = self.air.typeOfIndex(inst); | 5811 | const result_ty = self.air.typeOfIndex(inst); |
| 5799 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; | 5812 | const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; |
| 5800 | const target = self.dg.module.getTarget(); | 5813 | const target = self.dg.module.getTarget(); |
| ... | @@ -5809,6 +5822,14 @@ pub const FuncGen = struct { | ... | @@ -5809,6 +5822,14 @@ pub const FuncGen = struct { |
| 5809 | const offset = errUnionPayloadOffset(payload_ty, target); | 5822 | const offset = errUnionPayloadOffset(payload_ty, target); |
| 5810 | if (operand_is_ptr or isByRef(payload_ty)) { | 5823 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 5811 | return self.builder.buildStructGEP(operand, offset, ""); | 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; |
| 5812 | } | 5833 | } |
| 5813 | return self.builder.buildExtractValue(operand, offset, ""); | 5834 | return self.builder.buildExtractValue(operand, offset, ""); |
| 5814 | } | 5835 | } |
| ... | @@ -9338,6 +9359,8 @@ fn ccAbiPromoteInt( | ... | @@ -9338,6 +9359,8 @@ fn ccAbiPromoteInt( |
| 9338 | fn isByRef(ty: Type) bool { | 9359 | fn isByRef(ty: Type) bool { |
| 9339 | // For tuples and structs, if there are more than this many non-void | 9360 | // For tuples and structs, if there are more than this many non-void |
| 9340 | // fields, then we make it byref, otherwise byval. | 9361 | // fields, then we make it byref, otherwise byval. |
| | 9362 | // TODO we actually want to set this to 2, however it is tripping an LLVM 14 regression: |
| | 9363 | // https://github.com/llvm/llvm-project/issues/56585 |
| 9341 | const max_fields_byval = 0; | 9364 | const max_fields_byval = 0; |
| 9342 | | 9365 | |
| 9343 | switch (ty.zigTypeTag()) { | 9366 | switch (ty.zigTypeTag()) { |
| ... | @@ -9392,7 +9415,17 @@ fn isByRef(ty: Type) bool { | ... | @@ -9392,7 +9415,17 @@ fn isByRef(ty: Type) bool { |
| 9392 | return false; | 9415 | return false; |
| 9393 | }, | 9416 | }, |
| 9394 | .Union => return ty.hasRuntimeBits(), | 9417 | .Union => return ty.hasRuntimeBits(), |
| 9395 | .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 | // TODO we actually want this logic: |
| | 9425 | // however it is tripping an LLVM 14 regression: |
| | 9426 | // https://github.com/llvm/llvm-project/issues/56585 |
| | 9427 | //return isByRef(payload_ty); |
| | 9428 | }, |
| 9396 | .Optional => { | 9429 | .Optional => { |
| 9397 | var buf: Type.Payload.ElemType = undefined; | 9430 | var buf: Type.Payload.ElemType = undefined; |
| 9398 | const payload_ty = ty.optionalChild(&buf); | 9431 | const payload_ty = ty.optionalChild(&buf); |