| ... | @@ -5546,7 +5546,7 @@ pub const FuncGen = struct { | ... | @@ -5546,7 +5546,7 @@ pub const FuncGen = struct { |
| 5546 | ptr_ty.ptrAlignment(zcu).toLlvm(), | 5546 | ptr_ty.ptrAlignment(zcu).toLlvm(), |
| 5547 | try o.builder.intValue(.i8, 0xaa), | 5547 | try o.builder.intValue(.i8, 0xaa), |
| 5548 | len, | 5548 | len, |
| 5549 | if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, | 5549 | .normal, |
| 5550 | self.disable_intrinsics, | 5550 | self.disable_intrinsics, |
| 5551 | ); | 5551 | ); |
| 5552 | const owner_mod = self.ng.ownerModule(); | 5552 | const owner_mod = self.ng.ownerModule(); |
| ... | @@ -5781,8 +5781,8 @@ pub const FuncGen = struct { | ... | @@ -5781,8 +5781,8 @@ pub const FuncGen = struct { |
| 5781 | // of optionals that are not pointers. | 5781 | // of optionals that are not pointers. |
| 5782 | const is_by_ref = isByRef(scalar_ty, zcu); | 5782 | const is_by_ref = isByRef(scalar_ty, zcu); |
| 5783 | const opt_llvm_ty = try o.lowerType(scalar_ty); | 5783 | const opt_llvm_ty = try o.lowerType(scalar_ty); |
| 5784 | const lhs_non_null = try self.optCmpNull(.ne, opt_llvm_ty, lhs, is_by_ref); | 5784 | const lhs_non_null = try self.optCmpNull(.ne, opt_llvm_ty, lhs, is_by_ref, .normal); |
| 5785 | const rhs_non_null = try self.optCmpNull(.ne, opt_llvm_ty, rhs, is_by_ref); | 5785 | const rhs_non_null = try self.optCmpNull(.ne, opt_llvm_ty, rhs, is_by_ref, .normal); |
| 5786 | const llvm_i2 = try o.builder.intType(2); | 5786 | const llvm_i2 = try o.builder.intType(2); |
| 5787 | const lhs_non_null_i2 = try self.wip.cast(.zext, lhs_non_null, llvm_i2, ""); | 5787 | const lhs_non_null_i2 = try self.wip.cast(.zext, lhs_non_null, llvm_i2, ""); |
| 5788 | const rhs_non_null_i2 = try self.wip.cast(.zext, rhs_non_null, llvm_i2, ""); | 5788 | const rhs_non_null_i2 = try self.wip.cast(.zext, rhs_non_null, llvm_i2, ""); |
| ... | @@ -6259,10 +6259,13 @@ pub const FuncGen = struct { | ... | @@ -6259,10 +6259,13 @@ pub const FuncGen = struct { |
| 6259 | | 6259 | |
| 6260 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { | 6260 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 6261 | const loaded = loaded: { | 6261 | const loaded = loaded: { |
| | 6262 | const access_kind: Builder.MemoryAccessKind = |
| | 6263 | if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 6264 | |
| 6262 | if (!payload_has_bits) { | 6265 | if (!payload_has_bits) { |
| 6263 | // TODO add alignment to this load | 6266 | // TODO add alignment to this load |
| 6264 | break :loaded if (operand_is_ptr) | 6267 | break :loaded if (operand_is_ptr) |
| 6265 | try fg.wip.load(.normal, error_type, err_union, .default, "") | 6268 | try fg.wip.load(access_kind, error_type, err_union, .default, "") |
| 6266 | else | 6269 | else |
| 6267 | err_union; | 6270 | err_union; |
| 6268 | } | 6271 | } |
| ... | @@ -6272,7 +6275,7 @@ pub const FuncGen = struct { | ... | @@ -6272,7 +6275,7 @@ pub const FuncGen = struct { |
| 6272 | try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, ""); | 6275 | try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, ""); |
| 6273 | // TODO add alignment to this load | 6276 | // TODO add alignment to this load |
| 6274 | break :loaded try fg.wip.load( | 6277 | break :loaded try fg.wip.load( |
| 6275 | .normal, | 6278 | if (operand_is_ptr) access_kind else .normal, |
| 6276 | error_type, | 6279 | error_type, |
| 6277 | err_field_ptr, | 6280 | err_field_ptr, |
| 6278 | .default, | 6281 | .default, |
| ... | @@ -6784,7 +6787,7 @@ pub const FuncGen = struct { | ... | @@ -6784,7 +6787,7 @@ pub const FuncGen = struct { |
| 6784 | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); | 6787 | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| 6785 | | 6788 | |
| 6786 | const elem_alignment = elem_ty.abiAlignment(zcu).toLlvm(); | 6789 | const elem_alignment = elem_ty.abiAlignment(zcu).toLlvm(); |
| 6787 | return self.loadByRef(ptr, elem_ty, elem_alignment, .normal); | 6790 | return self.loadByRef(ptr, elem_ty, elem_alignment, if (slice_ty.isVolatilePtr(zcu)) .@"volatile" else .normal); |
| 6788 | } | 6791 | } |
| 6789 | | 6792 | |
| 6790 | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); | 6793 | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| ... | @@ -6862,7 +6865,7 @@ pub const FuncGen = struct { | ... | @@ -6862,7 +6865,7 @@ pub const FuncGen = struct { |
| 6862 | self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); | 6865 | self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); |
| 6863 | | 6866 | |
| 6864 | const elem_alignment = elem_ty.abiAlignment(zcu).toLlvm(); | 6867 | const elem_alignment = elem_ty.abiAlignment(zcu).toLlvm(); |
| 6865 | return self.loadByRef(ptr, elem_ty, elem_alignment, .normal); | 6868 | return self.loadByRef(ptr, elem_ty, elem_alignment, if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal); |
| 6866 | } | 6869 | } |
| 6867 | | 6870 | |
| 6868 | self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); | 6871 | self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); |
| ... | @@ -7409,7 +7412,13 @@ pub const FuncGen = struct { | ... | @@ -7409,7 +7412,13 @@ pub const FuncGen = struct { |
| 7409 | llvm_param_types[llvm_param_i] = llvm_rw_val.typeOfWip(&self.wip); | 7412 | llvm_param_types[llvm_param_i] = llvm_rw_val.typeOfWip(&self.wip); |
| 7410 | } else { | 7413 | } else { |
| 7411 | const alignment = rw_ty.abiAlignment(zcu).toLlvm(); | 7414 | const alignment = rw_ty.abiAlignment(zcu).toLlvm(); |
| 7412 | const loaded = try self.wip.load(.normal, llvm_elem_ty, llvm_rw_val, alignment, ""); | 7415 | const loaded = try self.wip.load( |
| | 7416 | if (rw_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, |
| | 7417 | llvm_elem_ty, |
| | 7418 | llvm_rw_val, |
| | 7419 | alignment, |
| | 7420 | "", |
| | 7421 | ); |
| 7413 | llvm_param_values[llvm_param_i] = loaded; | 7422 | llvm_param_values[llvm_param_i] = loaded; |
| 7414 | llvm_param_types[llvm_param_i] = llvm_elem_ty; | 7423 | llvm_param_types[llvm_param_i] = llvm_elem_ty; |
| 7415 | } | 7424 | } |
| ... | @@ -7573,7 +7582,12 @@ pub const FuncGen = struct { | ... | @@ -7573,7 +7582,12 @@ pub const FuncGen = struct { |
| 7573 | const output_ptr = try self.resolveInst(output); | 7582 | const output_ptr = try self.resolveInst(output); |
| 7574 | const output_ptr_ty = self.typeOf(output); | 7583 | const output_ptr_ty = self.typeOf(output); |
| 7575 | const alignment = output_ptr_ty.ptrAlignment(zcu).toLlvm(); | 7584 | const alignment = output_ptr_ty.ptrAlignment(zcu).toLlvm(); |
| 7576 | _ = try self.wip.store(.normal, output_value, output_ptr, alignment); | 7585 | _ = try self.wip.store( |
| | 7586 | if (output_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, |
| | 7587 | output_value, |
| | 7588 | output_ptr, |
| | 7589 | alignment, |
| | 7590 | ); |
| 7577 | } else { | 7591 | } else { |
| 7578 | ret_val = output_value; | 7592 | ret_val = output_value; |
| 7579 | } | 7593 | } |
| ... | @@ -7599,11 +7613,14 @@ pub const FuncGen = struct { | ... | @@ -7599,11 +7613,14 @@ pub const FuncGen = struct { |
| 7599 | const optional_llvm_ty = try o.lowerType(optional_ty); | 7613 | const optional_llvm_ty = try o.lowerType(optional_ty); |
| 7600 | const payload_ty = optional_ty.optionalChild(zcu); | 7614 | const payload_ty = optional_ty.optionalChild(zcu); |
| 7601 | | 7615 | |
| | 7616 | const access_kind: Builder.MemoryAccessKind = |
| | 7617 | if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 7618 | |
| 7602 | if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); | 7619 | if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| 7603 | | 7620 | |
| 7604 | if (optional_ty.optionalReprIsPayload(zcu)) { | 7621 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| 7605 | const loaded = if (operand_is_ptr) | 7622 | const loaded = if (operand_is_ptr) |
| 7606 | try self.wip.load(.normal, optional_llvm_ty, operand, .default, "") | 7623 | try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") |
| 7607 | else | 7624 | else |
| 7608 | operand; | 7625 | operand; |
| 7609 | if (payload_ty.isSlice(zcu)) { | 7626 | if (payload_ty.isSlice(zcu)) { |
| ... | @@ -7621,14 +7638,14 @@ pub const FuncGen = struct { | ... | @@ -7621,14 +7638,14 @@ pub const FuncGen = struct { |
| 7621 | | 7638 | |
| 7622 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 7639 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7623 | const loaded = if (operand_is_ptr) | 7640 | const loaded = if (operand_is_ptr) |
| 7624 | try self.wip.load(.normal, optional_llvm_ty, operand, .default, "") | 7641 | try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") |
| 7625 | else | 7642 | else |
| 7626 | operand; | 7643 | operand; |
| 7627 | return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), ""); | 7644 | return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), ""); |
| 7628 | } | 7645 | } |
| 7629 | | 7646 | |
| 7630 | const is_by_ref = operand_is_ptr or isByRef(optional_ty, zcu); | 7647 | const is_by_ref = operand_is_ptr or isByRef(optional_ty, zcu); |
| 7631 | return self.optCmpNull(cond, optional_llvm_ty, operand, is_by_ref); | 7648 | return self.optCmpNull(cond, optional_llvm_ty, operand, is_by_ref, access_kind); |
| 7632 | } | 7649 | } |
| 7633 | | 7650 | |
| 7634 | fn airIsErr( | 7651 | fn airIsErr( |
| ... | @@ -7648,6 +7665,9 @@ pub const FuncGen = struct { | ... | @@ -7648,6 +7665,9 @@ pub const FuncGen = struct { |
| 7648 | const error_type = try o.errorIntType(); | 7665 | const error_type = try o.errorIntType(); |
| 7649 | const zero = try o.builder.intValue(error_type, 0); | 7666 | const zero = try o.builder.intValue(error_type, 0); |
| 7650 | | 7667 | |
| | 7668 | const access_kind: Builder.MemoryAccessKind = |
| | 7669 | if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 7670 | |
| 7651 | if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { | 7671 | if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 7652 | const val: Builder.Constant = switch (cond) { | 7672 | const val: Builder.Constant = switch (cond) { |
| 7653 | .eq => .true, // 0 == 0 | 7673 | .eq => .true, // 0 == 0 |
| ... | @@ -7661,7 +7681,7 @@ pub const FuncGen = struct { | ... | @@ -7661,7 +7681,7 @@ pub const FuncGen = struct { |
| 7661 | | 7681 | |
| 7662 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 7682 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7663 | const loaded = if (operand_is_ptr) | 7683 | const loaded = if (operand_is_ptr) |
| 7664 | try self.wip.load(.normal, try o.lowerType(err_union_ty), operand, .default, "") | 7684 | try self.wip.load(access_kind, try o.lowerType(err_union_ty), operand, .default, "") |
| 7665 | else | 7685 | else |
| 7666 | operand; | 7686 | operand; |
| 7667 | return self.wip.icmp(cond, loaded, zero, ""); | 7687 | return self.wip.icmp(cond, loaded, zero, ""); |
| ... | @@ -7673,7 +7693,7 @@ pub const FuncGen = struct { | ... | @@ -7673,7 +7693,7 @@ pub const FuncGen = struct { |
| 7673 | const err_union_llvm_ty = try o.lowerType(err_union_ty); | 7693 | const err_union_llvm_ty = try o.lowerType(err_union_ty); |
| 7674 | const err_field_ptr = | 7694 | const err_field_ptr = |
| 7675 | try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, ""); | 7695 | try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, ""); |
| 7676 | break :loaded try self.wip.load(.normal, error_type, err_field_ptr, .default, ""); | 7696 | break :loaded try self.wip.load(access_kind, error_type, err_field_ptr, .default, ""); |
| 7677 | } else try self.wip.extractValue(operand, &.{err_field_index}, ""); | 7697 | } else try self.wip.extractValue(operand, &.{err_field_index}, ""); |
| 7678 | return self.wip.icmp(cond, loaded, zero, ""); | 7698 | return self.wip.icmp(cond, loaded, zero, ""); |
| 7679 | } | 7699 | } |
| ... | @@ -7706,14 +7726,19 @@ pub const FuncGen = struct { | ... | @@ -7706,14 +7726,19 @@ pub const FuncGen = struct { |
| 7706 | const zcu = pt.zcu; | 7726 | const zcu = pt.zcu; |
| 7707 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 7727 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 7708 | const operand = try self.resolveInst(ty_op.operand); | 7728 | const operand = try self.resolveInst(ty_op.operand); |
| 7709 | const optional_ty = self.typeOf(ty_op.operand).childType(zcu); | 7729 | const optional_ptr_ty = self.typeOf(ty_op.operand); |
| | 7730 | const optional_ty = optional_ptr_ty.childType(zcu); |
| 7710 | const payload_ty = optional_ty.optionalChild(zcu); | 7731 | const payload_ty = optional_ty.optionalChild(zcu); |
| 7711 | const non_null_bit = try o.builder.intValue(.i8, 1); | 7732 | const non_null_bit = try o.builder.intValue(.i8, 1); |
| | 7733 | |
| | 7734 | const access_kind: Builder.MemoryAccessKind = |
| | 7735 | if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 7736 | |
| 7712 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 7737 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7713 | self.maybeMarkAllowZeroAccess(self.typeOf(ty_op.operand).ptrInfo(zcu)); | 7738 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7714 | | 7739 | |
| 7715 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. | 7740 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 7716 | _ = try self.wip.store(.normal, non_null_bit, operand, .default); | 7741 | _ = try self.wip.store(access_kind, non_null_bit, operand, .default); |
| 7717 | return operand; | 7742 | return operand; |
| 7718 | } | 7743 | } |
| 7719 | if (optional_ty.optionalReprIsPayload(zcu)) { | 7744 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| ... | @@ -7726,10 +7751,10 @@ pub const FuncGen = struct { | ... | @@ -7726,10 +7751,10 @@ pub const FuncGen = struct { |
| 7726 | const optional_llvm_ty = try o.lowerType(optional_ty); | 7751 | const optional_llvm_ty = try o.lowerType(optional_ty); |
| 7727 | const non_null_ptr = try self.wip.gepStruct(optional_llvm_ty, operand, 1, ""); | 7752 | const non_null_ptr = try self.wip.gepStruct(optional_llvm_ty, operand, 1, ""); |
| 7728 | | 7753 | |
| 7729 | self.maybeMarkAllowZeroAccess(self.typeOf(ty_op.operand).ptrInfo(zcu)); | 7754 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7730 | | 7755 | |
| 7731 | // TODO set alignment on this store | 7756 | // TODO set alignment on this store |
| 7732 | _ = try self.wip.store(.normal, non_null_bit, non_null_ptr, .default); | 7757 | _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default); |
| 7733 | | 7758 | |
| 7734 | // Then return the payload pointer (only if it's used). | 7759 | // Then return the payload pointer (only if it's used). |
| 7735 | if (self.liveness.isUnused(inst)) return .none; | 7760 | if (self.liveness.isUnused(inst)) return .none; |
| ... | @@ -7815,13 +7840,16 @@ pub const FuncGen = struct { | ... | @@ -7815,13 +7840,16 @@ pub const FuncGen = struct { |
| 7815 | } | 7840 | } |
| 7816 | } | 7841 | } |
| 7817 | | 7842 | |
| | 7843 | const access_kind: Builder.MemoryAccessKind = |
| | 7844 | if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 7845 | |
| 7818 | const payload_ty = err_union_ty.errorUnionPayload(zcu); | 7846 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 7819 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 7847 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7820 | if (!operand_is_ptr) return operand; | 7848 | if (!operand_is_ptr) return operand; |
| 7821 | | 7849 | |
| 7822 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); | 7850 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| 7823 | | 7851 | |
| 7824 | return self.wip.load(.normal, error_type, operand, .default, ""); | 7852 | return self.wip.load(access_kind, error_type, operand, .default, ""); |
| 7825 | } | 7853 | } |
| 7826 | | 7854 | |
| 7827 | const offset = try errUnionErrorOffset(payload_ty, pt); | 7855 | const offset = try errUnionErrorOffset(payload_ty, pt); |
| ... | @@ -7831,7 +7859,7 @@ pub const FuncGen = struct { | ... | @@ -7831,7 +7859,7 @@ pub const FuncGen = struct { |
| 7831 | | 7859 | |
| 7832 | const err_union_llvm_ty = try o.lowerType(err_union_ty); | 7860 | const err_union_llvm_ty = try o.lowerType(err_union_ty); |
| 7833 | const err_field_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, ""); | 7861 | const err_field_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, ""); |
| 7834 | return self.wip.load(.normal, error_type, err_field_ptr, .default, ""); | 7862 | return self.wip.load(access_kind, error_type, err_field_ptr, .default, ""); |
| 7835 | } | 7863 | } |
| 7836 | | 7864 | |
| 7837 | return self.wip.extractValue(operand, &.{offset}, ""); | 7865 | return self.wip.extractValue(operand, &.{offset}, ""); |
| ... | @@ -7843,26 +7871,31 @@ pub const FuncGen = struct { | ... | @@ -7843,26 +7871,31 @@ pub const FuncGen = struct { |
| 7843 | const zcu = pt.zcu; | 7871 | const zcu = pt.zcu; |
| 7844 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 7872 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 7845 | const operand = try self.resolveInst(ty_op.operand); | 7873 | const operand = try self.resolveInst(ty_op.operand); |
| 7846 | const err_union_ty = self.typeOf(ty_op.operand).childType(zcu); | 7874 | const err_union_ptr_ty = self.typeOf(ty_op.operand); |
| | 7875 | const err_union_ty = err_union_ptr_ty.childType(zcu); |
| 7847 | | 7876 | |
| 7848 | const payload_ty = err_union_ty.errorUnionPayload(zcu); | 7877 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 7849 | const non_error_val = try o.builder.intValue(try o.errorIntType(), 0); | 7878 | const non_error_val = try o.builder.intValue(try o.errorIntType(), 0); |
| | 7879 | |
| | 7880 | const access_kind: Builder.MemoryAccessKind = |
| | 7881 | if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 7882 | |
| 7850 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 7883 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 7851 | self.maybeMarkAllowZeroAccess(self.typeOf(ty_op.operand).ptrInfo(zcu)); | 7884 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7852 | | 7885 | |
| 7853 | _ = try self.wip.store(.normal, non_error_val, operand, .default); | 7886 | _ = try self.wip.store(access_kind, non_error_val, operand, .default); |
| 7854 | return operand; | 7887 | return operand; |
| 7855 | } | 7888 | } |
| 7856 | const err_union_llvm_ty = try o.lowerType(err_union_ty); | 7889 | const err_union_llvm_ty = try o.lowerType(err_union_ty); |
| 7857 | { | 7890 | { |
| 7858 | self.maybeMarkAllowZeroAccess(self.typeOf(ty_op.operand).ptrInfo(zcu)); | 7891 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7859 | | 7892 | |
| 7860 | const err_int_ty = try pt.errorIntType(); | 7893 | const err_int_ty = try pt.errorIntType(); |
| 7861 | const error_alignment = err_int_ty.abiAlignment(zcu).toLlvm(); | 7894 | const error_alignment = err_int_ty.abiAlignment(zcu).toLlvm(); |
| 7862 | const error_offset = try errUnionErrorOffset(payload_ty, pt); | 7895 | const error_offset = try errUnionErrorOffset(payload_ty, pt); |
| 7863 | // First set the non-error value. | 7896 | // First set the non-error value. |
| 7864 | const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, ""); | 7897 | const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, ""); |
| 7865 | _ = try self.wip.store(.normal, non_error_val, non_null_ptr, error_alignment); | 7898 | _ = try self.wip.store(access_kind, non_error_val, non_null_ptr, error_alignment); |
| 7866 | } | 7899 | } |
| 7867 | // Then return the payload pointer (only if it is used). | 7900 | // Then return the payload pointer (only if it is used). |
| 7868 | if (self.liveness.isUnused(inst)) return .none; | 7901 | if (self.liveness.isUnused(inst)) return .none; |
| ... | @@ -8079,6 +8112,8 @@ pub const FuncGen = struct { | ... | @@ -8079,6 +8112,8 @@ pub const FuncGen = struct { |
| 8079 | | 8112 | |
| 8080 | self.maybeMarkAllowZeroAccess(vector_ptr_ty.ptrInfo(zcu)); | 8113 | self.maybeMarkAllowZeroAccess(vector_ptr_ty.ptrInfo(zcu)); |
| 8081 | | 8114 | |
| | 8115 | // TODO: Emitting a load here is a violation of volatile semantics. Not fixable in general. |
| | 8116 | // https://github.com/ziglang/zig/issues/18652#issuecomment-2452844908 |
| 8082 | const access_kind: Builder.MemoryAccessKind = | 8117 | const access_kind: Builder.MemoryAccessKind = |
| 8083 | if (vector_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; | 8118 | if (vector_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 8084 | const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(zcu)); | 8119 | const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(zcu)); |
| ... | @@ -10042,23 +10077,27 @@ pub const FuncGen = struct { | ... | @@ -10042,23 +10077,27 @@ pub const FuncGen = struct { |
| 10042 | const pt = o.pt; | 10077 | const pt = o.pt; |
| 10043 | const zcu = pt.zcu; | 10078 | const zcu = pt.zcu; |
| 10044 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 10079 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 10045 | const un_ty = self.typeOf(bin_op.lhs).childType(zcu); | 10080 | const un_ptr_ty = self.typeOf(bin_op.lhs); |
| | 10081 | const un_ty = un_ptr_ty.childType(zcu); |
| 10046 | const layout = un_ty.unionGetLayout(zcu); | 10082 | const layout = un_ty.unionGetLayout(zcu); |
| 10047 | if (layout.tag_size == 0) return .none; | 10083 | if (layout.tag_size == 0) return .none; |
| 10048 | | 10084 | |
| 10049 | self.maybeMarkAllowZeroAccess(self.typeOf(bin_op.lhs).ptrInfo(zcu)); | 10085 | const access_kind: Builder.MemoryAccessKind = |
| | 10086 | if (un_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| | 10087 | |
| | 10088 | self.maybeMarkAllowZeroAccess(un_ptr_ty.ptrInfo(zcu)); |
| 10050 | | 10089 | |
| 10051 | const union_ptr = try self.resolveInst(bin_op.lhs); | 10090 | const union_ptr = try self.resolveInst(bin_op.lhs); |
| 10052 | const new_tag = try self.resolveInst(bin_op.rhs); | 10091 | const new_tag = try self.resolveInst(bin_op.rhs); |
| 10053 | if (layout.payload_size == 0) { | 10092 | if (layout.payload_size == 0) { |
| 10054 | // TODO alignment on this store | 10093 | // TODO alignment on this store |
| 10055 | _ = try self.wip.store(.normal, new_tag, union_ptr, .default); | 10094 | _ = try self.wip.store(access_kind, new_tag, union_ptr, .default); |
| 10056 | return .none; | 10095 | return .none; |
| 10057 | } | 10096 | } |
| 10058 | const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); | 10097 | const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); |
| 10059 | const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(un_ty), union_ptr, tag_index, ""); | 10098 | const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(un_ty), union_ptr, tag_index, ""); |
| 10060 | // TODO alignment on this store | 10099 | // TODO alignment on this store |
| 10061 | _ = try self.wip.store(.normal, new_tag, tag_field_ptr, .default); | 10100 | _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, .default); |
| 10062 | return .none; | 10101 | return .none; |
| 10063 | } | 10102 | } |
| 10064 | | 10103 | |
| ... | @@ -10955,12 +10994,13 @@ pub const FuncGen = struct { | ... | @@ -10955,12 +10994,13 @@ pub const FuncGen = struct { |
| 10955 | opt_llvm_ty: Builder.Type, | 10994 | opt_llvm_ty: Builder.Type, |
| 10956 | opt_handle: Builder.Value, | 10995 | opt_handle: Builder.Value, |
| 10957 | is_by_ref: bool, | 10996 | is_by_ref: bool, |
| | 10997 | access_kind: Builder.MemoryAccessKind, |
| 10958 | ) Allocator.Error!Builder.Value { | 10998 | ) Allocator.Error!Builder.Value { |
| 10959 | const o = self.ng.object; | 10999 | const o = self.ng.object; |
| 10960 | const field = b: { | 11000 | const field = b: { |
| 10961 | if (is_by_ref) { | 11001 | if (is_by_ref) { |
| 10962 | const field_ptr = try self.wip.gepStruct(opt_llvm_ty, opt_handle, 1, ""); | 11002 | const field_ptr = try self.wip.gepStruct(opt_llvm_ty, opt_handle, 1, ""); |
| 10963 | break :b try self.wip.load(.normal, .i8, field_ptr, .default, ""); | 11003 | break :b try self.wip.load(access_kind, .i8, field_ptr, .default, ""); |
| 10964 | } | 11004 | } |
| 10965 | break :b try self.wip.extractValue(opt_handle, &.{1}, ""); | 11005 | break :b try self.wip.extractValue(opt_handle, &.{1}, ""); |
| 10966 | }; | 11006 | }; |
| ... | @@ -11269,7 +11309,7 @@ pub const FuncGen = struct { | ... | @@ -11269,7 +11309,7 @@ pub const FuncGen = struct { |
| 11269 | const vec_elem_ty = try o.lowerType(elem_ty); | 11309 | const vec_elem_ty = try o.lowerType(elem_ty); |
| 11270 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); | 11310 | const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); |
| 11271 | | 11311 | |
| 11272 | const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, ""); | 11312 | const loaded_vector = try self.wip.load(.normal, vec_ty, ptr, ptr_alignment, ""); |
| 11273 | | 11313 | |
| 11274 | const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, ""); | 11314 | const modified_vector = try self.wip.insertElement(loaded_vector, elem, index_u32, ""); |
| 11275 | | 11315 | |
| ... | @@ -11282,7 +11322,7 @@ pub const FuncGen = struct { | ... | @@ -11282,7 +11322,7 @@ pub const FuncGen = struct { |
| 11282 | const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); | 11322 | const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); |
| 11283 | assert(ordering == .none); | 11323 | assert(ordering == .none); |
| 11284 | const containing_int = | 11324 | const containing_int = |
| 11285 | try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, ""); | 11325 | try self.wip.load(.normal, containing_int_ty, ptr, ptr_alignment, ""); |
| 11286 | const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); | 11326 | const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); |
| 11287 | const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset); | 11327 | const shift_amt = try o.builder.intConst(containing_int_ty, info.packed_offset.bit_offset); |
| 11288 | // Convert to equally-sized integer type in order to perform the bit | 11328 | // Convert to equally-sized integer type in order to perform the bit |