authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-02 05:44:19+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-05-12 17:07:50+02:00
log44bf64a7099a825394e686a78abd3d465c7ec3f7
treea1ce13d3e45e8541e460b7901cdf79cb67a80b56
parent427810f3edea1beba77e3f84dd695dd0a8c35f00
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

llvm: Fix a bunch of volatile semantics violations.

Also fix some cases where we were being overzealous in applying volatile.

1 files changed, 73 insertions(+), 33 deletions(-)

src/codegen/llvm.zig+73-33
...@@ -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 {
62596259
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 load6266 // 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 else6269 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 load6276 // 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));
67856788
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 }
67896792
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));
68636866
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 }
68676870
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);
76017615
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));
76037620
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 else7624 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 {
76217638
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 else7642 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 }
76297646
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 }
76337650
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);
76507667
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 == 07673 .eq => .true, // 0 == 0
...@@ -7661,7 +7681,7 @@ pub const FuncGen = struct {...@@ -7661,7 +7681,7 @@ pub const FuncGen = struct {
76617681
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 else7685 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));
77147739
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, "");
77287753
7729 self.maybeMarkAllowZeroAccess(self.typeOf(ty_op.operand).ptrInfo(zcu));7754 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
77307755
7731 // TODO set alignment on this store7756 // 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);
77337758
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 }
78177842
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;
78217849
7822 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));7850 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
78237851
7824 return self.wip.load(.normal, error_type, operand, .default, "");7852 return self.wip.load(access_kind, error_type, operand, .default, "");
7825 }7853 }
78267854
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 {
78317859
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 }
78367864
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);
78477876
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));
78527885
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));
78597892
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 {
80798112
8080 self.maybeMarkAllowZeroAccess(vector_ptr_ty.ptrInfo(zcu));8113 self.maybeMarkAllowZeroAccess(vector_ptr_ty.ptrInfo(zcu));
80818114
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;
1004810084
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));
1005010089
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 store10093 // 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 store10099 // 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 }
1006410103
...@@ -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);
1127111311
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, "");
1127311313
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, "");
1127511315
...@@ -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 bit11328 // Convert to equally-sized integer type in order to perform the bit