| ... | @@ -17772,6 +17772,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -17772,6 +17772,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17772 | | 17772 | |
| 17773 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17773 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17774 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 17774 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| | 17775 | const src = inst_data.src(); |
| 17775 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 17776 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 17776 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 17777 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 17777 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 17778 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| ... | @@ -17783,6 +17784,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17783,6 +17784,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17783 | try sema.checkPtrType(block, dest_ty_src, dest_ty); | 17784 | try sema.checkPtrType(block, dest_ty_src, dest_ty); |
| 17784 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 17785 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| 17785 | | 17786 | |
| | 17787 | const operand_info = operand_ty.ptrInfo().data; |
| | 17788 | const dest_info = dest_ty.ptrInfo().data; |
| | 17789 | if (!operand_info.mutable and dest_info.mutable) { |
| | 17790 | return sema.fail(block, src, "cast discards const qualifier", .{}); |
| | 17791 | } |
| | 17792 | if (operand_info.@"volatile" and !dest_info.@"volatile") { |
| | 17793 | return sema.fail(block, src, "cast discards volatile qualifier", .{}); |
| | 17794 | } |
| | 17795 | |
| 17786 | const dest_is_slice = dest_ty.isSlice(); | 17796 | const dest_is_slice = dest_ty.isSlice(); |
| 17787 | const operand_is_slice = operand_ty.isSlice(); | 17797 | const operand_is_slice = operand_ty.isSlice(); |
| 17788 | if (dest_is_slice and !operand_is_slice) { | 17798 | if (dest_is_slice and !operand_is_slice) { |
| ... | @@ -17793,15 +17803,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17793,15 +17803,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17793 | else | 17803 | else |
| 17794 | operand; | 17804 | operand; |
| 17795 | | 17805 | |
| 17796 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { | | |
| 17797 | if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { | | |
| 17798 | return sema.failWithUseOfUndef(block, operand_src); | | |
| 17799 | } | | |
| 17800 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { | | |
| 17801 | return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); | | |
| 17802 | } | | |
| 17803 | } | | |
| 17804 | | | |
| 17805 | const dest_elem_ty = dest_ty.elemType2(); | 17806 | const dest_elem_ty = dest_ty.elemType2(); |
| 17806 | try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty); | 17807 | try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty); |
| 17807 | const dest_align = dest_ty.ptrAlignment(target); | 17808 | const dest_align = dest_ty.ptrAlignment(target); |
| ... | @@ -17835,7 +17836,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17835,7 +17836,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17835 | } | 17836 | } |
| 17836 | } | 17837 | } |
| 17837 | | 17838 | |
| 17838 | return sema.coerceCompatiblePtrs(block, aligned_dest_ty, ptr, operand_src); | 17839 | if (dest_align > operand_align) { |
| | 17840 | const msg = msg: { |
| | 17841 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); |
| | 17842 | errdefer msg.destroy(sema.gpa); |
| | 17843 | |
| | 17844 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ |
| | 17845 | operand_ty.fmt(sema.mod), operand_align, |
| | 17846 | }); |
| | 17847 | try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{ |
| | 17848 | dest_ty.fmt(sema.mod), dest_align, |
| | 17849 | }); |
| | 17850 | break :msg msg; |
| | 17851 | }; |
| | 17852 | return sema.failWithOwnedErrorMsg(msg); |
| | 17853 | } |
| | 17854 | |
| | 17855 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { |
| | 17856 | if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { |
| | 17857 | return sema.failWithUseOfUndef(block, operand_src); |
| | 17858 | } |
| | 17859 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { |
| | 17860 | return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); |
| | 17861 | } |
| | 17862 | return sema.addConstant(aligned_dest_ty, operand_val); |
| | 17863 | } |
| | 17864 | |
| | 17865 | try sema.requireRuntimeBlock(block, src, null); |
| | 17866 | if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and |
| | 17867 | try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) |
| | 17868 | { |
| | 17869 | const ptr_int = try block.addUnOp(.ptrtoint, ptr); |
| | 17870 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); |
| | 17871 | const ok = if (operand_is_slice) ok: { |
| | 17872 | const len = try sema.analyzeSliceLen(block, operand_src, operand); |
| | 17873 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); |
| | 17874 | break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); |
| | 17875 | } else is_non_zero; |
| | 17876 | try sema.addSafetyCheck(block, ok, .cast_to_null); |
| | 17877 | } |
| | 17878 | |
| | 17879 | return block.addBitCast(aligned_dest_ty, ptr); |
| 17839 | } | 17880 | } |
| 17840 | | 17881 | |
| 17841 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17882 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |