| ... | ... | @@ -1438,8 +1438,7 @@ pub const Object = struct { |
| 1438 | 1438 | const param = wip.arg(llvm_arg_i); |
| 1439 | 1439 | llvm_arg_i += 1; |
| 1440 | 1440 | const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, ""); |
| 1441 | | const alignment = |
| 1442 | | Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 1441 | const alignment = Builder.Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 1443 | 1442 | _ = try wip.store(.normal, param, field_ptr, alignment); |
| 1444 | 1443 | } |
| 1445 | 1444 | |
| ... | ... | @@ -6151,7 +6150,7 @@ pub const FuncGen = struct { |
| 6151 | 6150 | const body = unwrapped_try.else_body; |
| 6152 | 6151 | const err_union_ty = self.typeOf(unwrapped_try.error_union); |
| 6153 | 6152 | const is_unused = self.liveness.isUnused(inst); |
| 6154 | | return lowerTry(self, err_union, body, err_union_ty, false, false, is_unused, err_cold); |
| 6153 | return lowerTry(self, err_union, body, err_union_ty, false, .none, false, is_unused, err_cold); |
| 6155 | 6154 | } |
| 6156 | 6155 | |
| 6157 | 6156 | fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value { |
| ... | ... | @@ -6159,12 +6158,13 @@ pub const FuncGen = struct { |
| 6159 | 6158 | const unwrapped_try = self.air.unwrapTryPtr(inst); |
| 6160 | 6159 | const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr); |
| 6161 | 6160 | const body = unwrapped_try.else_body; |
| 6162 | | const err_union_ty = self.typeOf(unwrapped_try.error_union_ptr).childType(zcu); |
| 6161 | const err_union_ptr_ty = self.typeOf(unwrapped_try.error_union_ptr); |
| 6162 | const err_union_ty = err_union_ptr_ty.childType(zcu); |
| 6163 | 6163 | const is_unused = self.liveness.isUnused(inst); |
| 6164 | 6164 | |
| 6165 | 6165 | self.maybeMarkAllowZeroAccess(self.typeOf(unwrapped_try.error_union_ptr).ptrInfo(zcu)); |
| 6166 | 6166 | |
| 6167 | | return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused, err_cold); |
| 6167 | return lowerTry(self, err_union_ptr, body, err_union_ty, true, err_union_ptr_ty.ptrAlignment(zcu), true, is_unused, err_cold); |
| 6168 | 6168 | } |
| 6169 | 6169 | |
| 6170 | 6170 | fn lowerTry( |
| ... | ... | @@ -6173,6 +6173,7 @@ pub const FuncGen = struct { |
| 6173 | 6173 | body: []const Air.Inst.Index, |
| 6174 | 6174 | err_union_ty: Type, |
| 6175 | 6175 | operand_is_ptr: bool, |
| 6176 | operand_ptr_align: InternPool.Alignment, |
| 6176 | 6177 | can_elide_load: bool, |
| 6177 | 6178 | is_unused: bool, |
| 6178 | 6179 | err_cold: bool, |
| ... | ... | @@ -6185,15 +6186,19 @@ pub const FuncGen = struct { |
| 6185 | 6186 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| 6186 | 6187 | const error_type = try o.errorIntType(pt); |
| 6187 | 6188 | |
| 6189 | const err_set_align: InternPool.Alignment, const payload_align: InternPool.Alignment = if (operand_is_ptr) .{ |
| 6190 | operand_ptr_align.minStrict(Type.anyerror.abiAlignment(zcu)), |
| 6191 | operand_ptr_align.minStrict(payload_ty.abiAlignment(zcu)), |
| 6192 | } else .{ .none, .none }; |
| 6193 | |
| 6188 | 6194 | if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 6189 | 6195 | const loaded = loaded: { |
| 6190 | 6196 | const access_kind: Builder.MemoryAccessKind = |
| 6191 | 6197 | if (err_union_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 6192 | 6198 | |
| 6193 | 6199 | if (!payload_has_bits) { |
| 6194 | | // TODO add alignment to this load |
| 6195 | 6200 | break :loaded if (operand_is_ptr) |
| 6196 | | try fg.wip.load(access_kind, error_type, err_union, .default, "") |
| 6201 | try fg.wip.load(access_kind, error_type, err_union, err_set_align.toLlvm(), "") |
| 6197 | 6202 | else |
| 6198 | 6203 | err_union; |
| 6199 | 6204 | } |
| ... | ... | @@ -6201,12 +6206,11 @@ pub const FuncGen = struct { |
| 6201 | 6206 | if (operand_is_ptr or isByRef(err_union_ty, zcu)) { |
| 6202 | 6207 | const err_field_ptr = |
| 6203 | 6208 | try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, ""); |
| 6204 | | // TODO add alignment to this load |
| 6205 | 6209 | break :loaded try fg.wip.load( |
| 6206 | 6210 | if (operand_is_ptr) access_kind else .normal, |
| 6207 | 6211 | error_type, |
| 6208 | 6212 | err_field_ptr, |
| 6209 | | .default, |
| 6213 | err_set_align.toLlvm(), |
| 6210 | 6214 | "", |
| 6211 | 6215 | ); |
| 6212 | 6216 | } |
| ... | ... | @@ -6232,15 +6236,14 @@ pub const FuncGen = struct { |
| 6232 | 6236 | return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, ""); |
| 6233 | 6237 | } else if (isByRef(err_union_ty, zcu)) { |
| 6234 | 6238 | const payload_ptr = try fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, ""); |
| 6235 | | const payload_alignment = payload_ty.abiAlignment(zcu).toLlvm(); |
| 6236 | 6239 | if (isByRef(payload_ty, zcu)) { |
| 6237 | 6240 | if (can_elide_load) |
| 6238 | 6241 | return payload_ptr; |
| 6239 | 6242 | |
| 6240 | | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); |
| 6243 | return fg.loadByRef(payload_ptr, payload_ty, payload_align.toLlvm(), .normal); |
| 6241 | 6244 | } |
| 6242 | 6245 | const load_ty = err_union_llvm_ty.structFields(&o.builder)[offset]; |
| 6243 | | return fg.wip.load(.normal, load_ty, payload_ptr, payload_alignment, ""); |
| 6246 | return fg.wip.load(.normal, load_ty, payload_ptr, payload_align.toLlvm(), ""); |
| 6244 | 6247 | } |
| 6245 | 6248 | return fg.wip.extractValue(err_union, &.{offset}, ""); |
| 6246 | 6249 | } |
| ... | ... | @@ -6713,20 +6716,20 @@ pub const FuncGen = struct { |
| 6713 | 6716 | const slice_ty = self.typeOf(bin_op.lhs); |
| 6714 | 6717 | const slice = try self.resolveInst(bin_op.lhs); |
| 6715 | 6718 | const index = try self.resolveInst(bin_op.rhs); |
| 6716 | | const elem_ty = slice_ty.childType(zcu); |
| 6719 | const slice_info = slice_ty.ptrInfo(zcu); |
| 6720 | assert(slice_info.flags.size == .slice); |
| 6721 | const elem_ty: Type = .fromInterned(slice_info.child); |
| 6717 | 6722 | const llvm_elem_ty = try o.lowerType(pt, elem_ty); |
| 6718 | 6723 | const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); |
| 6719 | 6724 | const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, ""); |
| 6725 | const elem_align = slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)); |
| 6726 | const access_kind: Builder.MemoryAccessKind = if (slice_info.flags.is_volatile) .@"volatile" else .normal; |
| 6727 | self.maybeMarkAllowZeroAccess(slice_info); |
| 6720 | 6728 | if (isByRef(elem_ty, zcu)) { |
| 6721 | | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| 6722 | | |
| 6723 | | const slice_align = (slice_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm(); |
| 6724 | | return self.loadByRef(ptr, elem_ty, slice_align, if (slice_ty.isVolatilePtr(zcu)) .@"volatile" else .normal); |
| 6729 | return self.loadByRef(ptr, elem_ty, elem_align.toLlvm(), access_kind); |
| 6730 | } else { |
| 6731 | return self.loadTruncate(access_kind, elem_ty, ptr, elem_align.toLlvm()); |
| 6725 | 6732 | } |
| 6726 | | |
| 6727 | | self.maybeMarkAllowZeroAccess(slice_ty.ptrInfo(zcu)); |
| 6728 | | |
| 6729 | | return self.load(ptr, slice_ty); |
| 6730 | 6733 | } |
| 6731 | 6734 | |
| 6732 | 6735 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -7507,7 +7510,7 @@ pub const FuncGen = struct { |
| 7507 | 7510 | |
| 7508 | 7511 | if (optional_ty.optionalReprIsPayload(zcu)) { |
| 7509 | 7512 | const loaded = if (operand_is_ptr) |
| 7510 | | try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") |
| 7513 | try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") |
| 7511 | 7514 | else |
| 7512 | 7515 | operand; |
| 7513 | 7516 | if (payload_ty.isSlice(zcu)) { |
| ... | ... | @@ -7525,7 +7528,7 @@ pub const FuncGen = struct { |
| 7525 | 7528 | |
| 7526 | 7529 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7527 | 7530 | const loaded = if (operand_is_ptr) |
| 7528 | | try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") |
| 7531 | try self.wip.load(access_kind, optional_llvm_ty, operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") |
| 7529 | 7532 | else |
| 7530 | 7533 | operand; |
| 7531 | 7534 | return self.wip.icmp(cond, loaded, try o.builder.intValue(.i8, 0), ""); |
| ... | ... | @@ -7568,7 +7571,7 @@ pub const FuncGen = struct { |
| 7568 | 7571 | |
| 7569 | 7572 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7570 | 7573 | const loaded = if (operand_is_ptr) |
| 7571 | | try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "") |
| 7574 | try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") |
| 7572 | 7575 | else |
| 7573 | 7576 | operand; |
| 7574 | 7577 | return self.wip.icmp(cond, loaded, zero, ""); |
| ... | ... | @@ -7578,9 +7581,13 @@ pub const FuncGen = struct { |
| 7578 | 7581 | |
| 7579 | 7582 | const loaded = if (operand_is_ptr or isByRef(err_union_ty, zcu)) loaded: { |
| 7580 | 7583 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| 7584 | const err_alignment = if (operand_is_ptr) |
| 7585 | operand_ty.ptrAlignment(zcu).minStrict(Type.anyerror.abiAlignment(zcu)) |
| 7586 | else |
| 7587 | .none; |
| 7581 | 7588 | const err_field_ptr = |
| 7582 | 7589 | try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, ""); |
| 7583 | | break :loaded try self.wip.load(access_kind, error_type, err_field_ptr, .default, ""); |
| 7590 | break :loaded try self.wip.load(access_kind, error_type, err_field_ptr, err_alignment.toLlvm(), ""); |
| 7584 | 7591 | } else try self.wip.extractValue(operand, &.{err_field_index}, ""); |
| 7585 | 7592 | return self.wip.icmp(cond, loaded, zero, ""); |
| 7586 | 7593 | } |
| ... | ... | @@ -7625,6 +7632,7 @@ pub const FuncGen = struct { |
| 7625 | 7632 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7626 | 7633 | |
| 7627 | 7634 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 7635 | // Default alignment store because align of the non null bit is 1 anyway. |
| 7628 | 7636 | _ = try self.wip.store(access_kind, non_null_bit, operand, .default); |
| 7629 | 7637 | return operand; |
| 7630 | 7638 | } |
| ... | ... | @@ -7640,7 +7648,7 @@ pub const FuncGen = struct { |
| 7640 | 7648 | |
| 7641 | 7649 | self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); |
| 7642 | 7650 | |
| 7643 | | // TODO set alignment on this store |
| 7651 | // Default alignment store because align of the non null bit is 1 anyway. |
| 7644 | 7652 | _ = try self.wip.store(access_kind, non_null_bit, non_null_ptr, .default); |
| 7645 | 7653 | |
| 7646 | 7654 | // Then return the payload pointer (only if it's used). |
| ... | ... | @@ -7728,7 +7736,7 @@ pub const FuncGen = struct { |
| 7728 | 7736 | |
| 7729 | 7737 | self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); |
| 7730 | 7738 | |
| 7731 | | return self.wip.load(access_kind, error_type, operand, .default, ""); |
| 7739 | return self.wip.load(access_kind, error_type, operand, operand_ty.ptrAlignment(zcu).toLlvm(), ""); |
| 7732 | 7740 | } |
| 7733 | 7741 | |
| 7734 | 7742 | const offset = try errUnionErrorOffset(payload_ty, pt); |
| ... | ... | @@ -7752,6 +7760,7 @@ pub const FuncGen = struct { |
| 7752 | 7760 | const operand = try self.resolveInst(ty_op.operand); |
| 7753 | 7761 | const err_union_ptr_ty = self.typeOf(ty_op.operand); |
| 7754 | 7762 | const err_union_ty = err_union_ptr_ty.childType(zcu); |
| 7763 | const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); |
| 7755 | 7764 | |
| 7756 | 7765 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 7757 | 7766 | const non_error_val = try o.builder.intValue(try o.errorIntType(pt), 0); |
| ... | ... | @@ -7761,8 +7770,7 @@ pub const FuncGen = struct { |
| 7761 | 7770 | |
| 7762 | 7771 | if (!payload_ty.hasRuntimeBits(zcu)) { |
| 7763 | 7772 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7764 | | |
| 7765 | | _ = try self.wip.store(access_kind, non_error_val, operand, .default); |
| 7773 | _ = try self.wip.store(access_kind, non_error_val, operand, err_union_ptr_align.toLlvm()); |
| 7766 | 7774 | return operand; |
| 7767 | 7775 | } |
| 7768 | 7776 | const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); |
| ... | ... | @@ -7770,7 +7778,7 @@ pub const FuncGen = struct { |
| 7770 | 7778 | self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); |
| 7771 | 7779 | |
| 7772 | 7780 | const err_int_ty = try pt.errorIntType(); |
| 7773 | | const error_alignment = err_int_ty.abiAlignment(zcu).toLlvm(); |
| 7781 | const error_alignment = err_int_ty.abiAlignment(zcu).minStrict(err_union_ptr_align).toLlvm(); |
| 7774 | 7782 | const error_offset = try errUnionErrorOffset(payload_ty, pt); |
| 7775 | 7783 | // First set the non-error value. |
| 7776 | 7784 | const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, ""); |
| ... | ... | @@ -8451,9 +8459,8 @@ pub const FuncGen = struct { |
| 8451 | 8459 | _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment); |
| 8452 | 8460 | } |
| 8453 | 8461 | { |
| 8454 | | const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1); |
| 8455 | 8462 | const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, ""); |
| 8456 | | _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment); |
| 8463 | _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1)); |
| 8457 | 8464 | } |
| 8458 | 8465 | |
| 8459 | 8466 | return alloca_inst; |
| ... | ... | @@ -8813,9 +8820,8 @@ pub const FuncGen = struct { |
| 8813 | 8820 | _ = try self.wip.store(.normal, result, field_ptr, result_alignment); |
| 8814 | 8821 | } |
| 8815 | 8822 | { |
| 8816 | | const field_alignment = comptime Builder.Alignment.fromByteUnits(1); |
| 8817 | 8823 | const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, ""); |
| 8818 | | _ = try self.wip.store(.normal, overflow_bit, field_ptr, field_alignment); |
| 8824 | _ = try self.wip.store(.normal, overflow_bit, field_ptr, comptime .fromByteUnits(1)); |
| 8819 | 8825 | } |
| 8820 | 8826 | return alloca_inst; |
| 8821 | 8827 | } |
| ... | ... | @@ -9971,15 +9977,18 @@ pub const FuncGen = struct { |
| 9971 | 9977 | |
| 9972 | 9978 | const union_ptr = try self.resolveInst(bin_op.lhs); |
| 9973 | 9979 | const new_tag = try self.resolveInst(bin_op.rhs); |
| 9980 | const union_ptr_align = un_ptr_ty.ptrAlignment(zcu); |
| 9974 | 9981 | if (layout.payload_size == 0) { |
| 9975 | | // TODO alignment on this store |
| 9976 | | _ = try self.wip.store(access_kind, new_tag, union_ptr, .default); |
| 9982 | _ = try self.wip.store(access_kind, new_tag, union_ptr, union_ptr_align.toLlvm()); |
| 9977 | 9983 | return .none; |
| 9978 | 9984 | } |
| 9979 | 9985 | const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); |
| 9980 | 9986 | const tag_field_ptr = try self.wip.gepStruct(try o.lowerType(pt, un_ty), union_ptr, tag_index, ""); |
| 9981 | | // TODO alignment on this store |
| 9982 | | _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, .default); |
| 9987 | const tag_ptr_align: InternPool.Alignment = switch (layout.tagOffset()) { |
| 9988 | 0 => union_ptr_align, |
| 9989 | else => |off| .minStrict(union_ptr_align, .fromLog2Units(@ctz(off))), |
| 9990 | }; |
| 9991 | _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, tag_ptr_align.toLlvm()); |
| 9983 | 9992 | return .none; |
| 9984 | 9993 | } |
| 9985 | 9994 | |