| ... | @@ -960,6 +960,7 @@ fn analyzeBodyInner( | ... | @@ -960,6 +960,7 @@ fn analyzeBodyInner( |
| 960 | .elem_val => try sema.zirElemVal(block, inst), | 960 | .elem_val => try sema.zirElemVal(block, inst), |
| 961 | .elem_val_node => try sema.zirElemValNode(block, inst), | 961 | .elem_val_node => try sema.zirElemValNode(block, inst), |
| 962 | .elem_type_index => try sema.zirElemTypeIndex(block, inst), | 962 | .elem_type_index => try sema.zirElemTypeIndex(block, inst), |
| | 963 | .elem_type => try sema.zirElemType(block, inst), |
| 963 | .enum_literal => try sema.zirEnumLiteral(block, inst), | 964 | .enum_literal => try sema.zirEnumLiteral(block, inst), |
| 964 | .int_from_enum => try sema.zirIntFromEnum(block, inst), | 965 | .int_from_enum => try sema.zirIntFromEnum(block, inst), |
| 965 | .enum_from_int => try sema.zirEnumFromInt(block, inst), | 966 | .enum_from_int => try sema.zirEnumFromInt(block, inst), |
| ... | @@ -1044,7 +1045,6 @@ fn analyzeBodyInner( | ... | @@ -1044,7 +1045,6 @@ fn analyzeBodyInner( |
| 1044 | .int_cast => try sema.zirIntCast(block, inst), | 1045 | .int_cast => try sema.zirIntCast(block, inst), |
| 1045 | .ptr_cast => try sema.zirPtrCast(block, inst), | 1046 | .ptr_cast => try sema.zirPtrCast(block, inst), |
| 1046 | .truncate => try sema.zirTruncate(block, inst), | 1047 | .truncate => try sema.zirTruncate(block, inst), |
| 1047 | .align_cast => try sema.zirAlignCast(block, inst), | | |
| 1048 | .has_decl => try sema.zirHasDecl(block, inst), | 1048 | .has_decl => try sema.zirHasDecl(block, inst), |
| 1049 | .has_field => try sema.zirHasField(block, inst), | 1049 | .has_field => try sema.zirHasField(block, inst), |
| 1050 | .byte_swap => try sema.zirByteSwap(block, inst), | 1050 | .byte_swap => try sema.zirByteSwap(block, inst), |
| ... | @@ -1172,13 +1172,12 @@ fn analyzeBodyInner( | ... | @@ -1172,13 +1172,12 @@ fn analyzeBodyInner( |
| 1172 | .reify => try sema.zirReify( block, extended, inst), | 1172 | .reify => try sema.zirReify( block, extended, inst), |
| 1173 | .builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended), | 1173 | .builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended), |
| 1174 | .cmpxchg => try sema.zirCmpxchg( block, extended), | 1174 | .cmpxchg => try sema.zirCmpxchg( block, extended), |
| 1175 | .addrspace_cast => try sema.zirAddrSpaceCast( block, extended), | | |
| 1176 | .c_va_arg => try sema.zirCVaArg( block, extended), | 1175 | .c_va_arg => try sema.zirCVaArg( block, extended), |
| 1177 | .c_va_copy => try sema.zirCVaCopy( block, extended), | 1176 | .c_va_copy => try sema.zirCVaCopy( block, extended), |
| 1178 | .c_va_end => try sema.zirCVaEnd( block, extended), | 1177 | .c_va_end => try sema.zirCVaEnd( block, extended), |
| 1179 | .c_va_start => try sema.zirCVaStart( block, extended), | 1178 | .c_va_start => try sema.zirCVaStart( block, extended), |
| 1180 | .const_cast, => try sema.zirConstCast( block, extended), | 1179 | .ptr_cast_full => try sema.zirPtrCastFull( block, extended), |
| 1181 | .volatile_cast, => try sema.zirVolatileCast( block, extended), | 1180 | .ptr_cast_no_dest => try sema.zirPtrCastNoDest( block, extended), |
| 1182 | .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode), | 1181 | .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1183 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), | 1182 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1184 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), | 1183 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), |
| ... | @@ -1821,6 +1820,24 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins | ... | @@ -1821,6 +1820,24 @@ pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Ins |
| 1821 | return ty; | 1820 | return ty; |
| 1822 | } | 1821 | } |
| 1823 | | 1822 | |
| | 1823 | fn resolveCastDestType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, builtin_name: []const u8) !Type { |
| | 1824 | return sema.resolveType(block, src, zir_ref) catch |err| switch (err) { |
| | 1825 | error.GenericPoison => { |
| | 1826 | // Cast builtins use their result type as the destination type, but |
| | 1827 | // it could be an anytype argument, which we can't catch in AstGen. |
| | 1828 | const msg = msg: { |
| | 1829 | const msg = try sema.errMsg(block, src, "{s} must have a known result type", .{builtin_name}); |
| | 1830 | errdefer msg.destroy(sema.gpa); |
| | 1831 | try sema.errNote(block, src, msg, "result type is unknown due to anytype parameter", .{}); |
| | 1832 | try sema.errNote(block, src, msg, "use @as to provide explicit result type", .{}); |
| | 1833 | break :msg msg; |
| | 1834 | }; |
| | 1835 | return sema.failWithOwnedErrorMsg(msg); |
| | 1836 | }, |
| | 1837 | else => |e| return e, |
| | 1838 | }; |
| | 1839 | } |
| | 1840 | |
| 1824 | fn analyzeAsType( | 1841 | fn analyzeAsType( |
| 1825 | sema: *Sema, | 1842 | sema: *Sema, |
| 1826 | block: *Block, | 1843 | block: *Block, |
| ... | @@ -7953,6 +7970,14 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -7953,6 +7970,14 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 7953 | } | 7970 | } |
| 7954 | } | 7971 | } |
| 7955 | | 7972 | |
| | 7973 | fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| | 7974 | const mod = sema.mod; |
| | 7975 | const un_node = sema.code.instructions.items(.data)[inst].un_node; |
| | 7976 | const ptr_ty = try sema.resolveType(block, .unneeded, un_node.operand); |
| | 7977 | assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction |
| | 7978 | return sema.addType(ptr_ty.childType(mod)); |
| | 7979 | } |
| | 7980 | |
| 7956 | fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 7981 | fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 7957 | const mod = sema.mod; | 7982 | const mod = sema.mod; |
| 7958 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 7983 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| ... | @@ -8278,13 +8303,12 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8278,13 +8303,12 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8278 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 8303 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 8279 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 8304 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8280 | const src = inst_data.src(); | 8305 | const src = inst_data.src(); |
| 8281 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 8306 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 8282 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 8307 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@enumFromInt"); |
| 8283 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | | |
| 8284 | const operand = try sema.resolveInst(extra.rhs); | 8308 | const operand = try sema.resolveInst(extra.rhs); |
| 8285 | | 8309 | |
| 8286 | if (dest_ty.zigTypeTag(mod) != .Enum) { | 8310 | if (dest_ty.zigTypeTag(mod) != .Enum) { |
| 8287 | return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(mod)}); | 8311 | return sema.fail(block, src, "expected enum, found '{}'", .{dest_ty.fmt(mod)}); |
| 8288 | } | 8312 | } |
| 8289 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); | 8313 | _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); |
| 8290 | | 8314 | |
| ... | @@ -9572,14 +9596,14 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9572,14 +9596,14 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9572 | defer tracy.end(); | 9596 | defer tracy.end(); |
| 9573 | | 9597 | |
| 9574 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9598 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9575 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9599 | const src = inst_data.src(); |
| 9576 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 9600 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9577 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 9601 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9578 | | 9602 | |
| 9579 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 9603 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@intCast"); |
| 9580 | const operand = try sema.resolveInst(extra.rhs); | 9604 | const operand = try sema.resolveInst(extra.rhs); |
| 9581 | | 9605 | |
| 9582 | return sema.intCast(block, inst_data.src(), dest_ty, dest_ty_src, operand, operand_src, true); | 9606 | return sema.intCast(block, inst_data.src(), dest_ty, src, operand, operand_src, true); |
| 9583 | } | 9607 | } |
| 9584 | | 9608 | |
| 9585 | fn intCast( | 9609 | fn intCast( |
| ... | @@ -9733,11 +9757,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9733,11 +9757,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9733 | | 9757 | |
| 9734 | const mod = sema.mod; | 9758 | const mod = sema.mod; |
| 9735 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9759 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9736 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9760 | const src = inst_data.src(); |
| 9737 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 9761 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9738 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 9762 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9739 | | 9763 | |
| 9740 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 9764 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@bitCast"); |
| 9741 | const operand = try sema.resolveInst(extra.rhs); | 9765 | const operand = try sema.resolveInst(extra.rhs); |
| 9742 | const operand_ty = sema.typeOf(operand); | 9766 | const operand_ty = sema.typeOf(operand); |
| 9743 | switch (dest_ty.zigTypeTag(mod)) { | 9767 | switch (dest_ty.zigTypeTag(mod)) { |
| ... | @@ -9756,14 +9780,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9756,14 +9780,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9756 | .Type, | 9780 | .Type, |
| 9757 | .Undefined, | 9781 | .Undefined, |
| 9758 | .Void, | 9782 | .Void, |
| 9759 | => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}), | 9783 | => return sema.fail(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}), |
| 9760 | | 9784 | |
| 9761 | .Enum => { | 9785 | .Enum => { |
| 9762 | const msg = msg: { | 9786 | const msg = msg: { |
| 9763 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); | 9787 | const msg = try sema.errMsg(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); |
| 9764 | errdefer msg.destroy(sema.gpa); | 9788 | errdefer msg.destroy(sema.gpa); |
| 9765 | switch (operand_ty.zigTypeTag(mod)) { | 9789 | switch (operand_ty.zigTypeTag(mod)) { |
| 9766 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), | 9790 | .Int, .ComptimeInt => try sema.errNote(block, src, msg, "use @enumFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), |
| 9767 | else => {}, | 9791 | else => {}, |
| 9768 | } | 9792 | } |
| 9769 | | 9793 | |
| ... | @@ -9774,11 +9798,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9774,11 +9798,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9774 | | 9798 | |
| 9775 | .Pointer => { | 9799 | .Pointer => { |
| 9776 | const msg = msg: { | 9800 | const msg = msg: { |
| 9777 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); | 9801 | const msg = try sema.errMsg(block, src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}); |
| 9778 | errdefer msg.destroy(sema.gpa); | 9802 | errdefer msg.destroy(sema.gpa); |
| 9779 | switch (operand_ty.zigTypeTag(mod)) { | 9803 | switch (operand_ty.zigTypeTag(mod)) { |
| 9780 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), | 9804 | .Int, .ComptimeInt => try sema.errNote(block, src, msg, "use @ptrFromInt to cast from '{}'", .{operand_ty.fmt(mod)}), |
| 9781 | .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}), | 9805 | .Pointer => try sema.errNote(block, src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}), |
| 9782 | else => {}, | 9806 | else => {}, |
| 9783 | } | 9807 | } |
| 9784 | | 9808 | |
| ... | @@ -9792,7 +9816,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -9792,7 +9816,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 9792 | .Union => "union", | 9816 | .Union => "union", |
| 9793 | else => unreachable, | 9817 | else => unreachable, |
| 9794 | }; | 9818 | }; |
| 9795 | return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{ | 9819 | return sema.fail(block, src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{ |
| 9796 | dest_ty.fmt(mod), container, | 9820 | dest_ty.fmt(mod), container, |
| 9797 | }); | 9821 | }); |
| 9798 | }, | 9822 | }, |
| ... | @@ -9876,11 +9900,11 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -9876,11 +9900,11 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9876 | | 9900 | |
| 9877 | const mod = sema.mod; | 9901 | const mod = sema.mod; |
| 9878 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 9902 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 9879 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 9903 | const src = inst_data.src(); |
| 9880 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 9904 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 9881 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 9905 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 9882 | | 9906 | |
| 9883 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 9907 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@floatCast"); |
| 9884 | const operand = try sema.resolveInst(extra.rhs); | 9908 | const operand = try sema.resolveInst(extra.rhs); |
| 9885 | | 9909 | |
| 9886 | const target = mod.getTarget(); | 9910 | const target = mod.getTarget(); |
| ... | @@ -9889,7 +9913,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -9889,7 +9913,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 9889 | .Float => false, | 9913 | .Float => false, |
| 9890 | else => return sema.fail( | 9914 | else => return sema.fail( |
| 9891 | block, | 9915 | block, |
| 9892 | dest_ty_src, | 9916 | src, |
| 9893 | "expected float type, found '{}'", | 9917 | "expected float type, found '{}'", |
| 9894 | .{dest_ty.fmt(mod)}, | 9918 | .{dest_ty.fmt(mod)}, |
| 9895 | ), | 9919 | ), |
| ... | @@ -20552,50 +20576,6 @@ fn reifyStruct( | ... | @@ -20552,50 +20576,6 @@ fn reifyStruct( |
| 20552 | return decl_val; | 20576 | return decl_val; |
| 20553 | } | 20577 | } |
| 20554 | | 20578 | |
| 20555 | fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | | |
| 20556 | const mod = sema.mod; | | |
| 20557 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | | |
| 20558 | const src = LazySrcLoc.nodeOffset(extra.node); | | |
| 20559 | const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | | |
| 20560 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; | | |
| 20561 | | | |
| 20562 | const dest_addrspace = try sema.analyzeAddressSpace(block, addrspace_src, extra.lhs, .pointer); | | |
| 20563 | const ptr = try sema.resolveInst(extra.rhs); | | |
| 20564 | const ptr_ty = sema.typeOf(ptr); | | |
| 20565 | | | |
| 20566 | try sema.checkPtrOperand(block, ptr_src, ptr_ty); | | |
| 20567 | | | |
| 20568 | var ptr_info = ptr_ty.ptrInfo(mod); | | |
| 20569 | const src_addrspace = ptr_info.flags.address_space; | | |
| 20570 | if (!target_util.addrSpaceCastIsValid(sema.mod.getTarget(), src_addrspace, dest_addrspace)) { | | |
| 20571 | const msg = msg: { | | |
| 20572 | const msg = try sema.errMsg(block, src, "invalid address space cast", .{}); | | |
| 20573 | errdefer msg.destroy(sema.gpa); | | |
| 20574 | try sema.errNote(block, src, msg, "address space '{s}' is not compatible with address space '{s}'", .{ @tagName(src_addrspace), @tagName(dest_addrspace) }); | | |
| 20575 | break :msg msg; | | |
| 20576 | }; | | |
| 20577 | return sema.failWithOwnedErrorMsg(msg); | | |
| 20578 | } | | |
| 20579 | | | |
| 20580 | ptr_info.flags.address_space = dest_addrspace; | | |
| 20581 | const dest_ptr_ty = try mod.ptrType(ptr_info); | | |
| 20582 | const dest_ty = if (ptr_ty.zigTypeTag(mod) == .Optional) | | |
| 20583 | try mod.optionalType(dest_ptr_ty.toIntern()) | | |
| 20584 | else | | |
| 20585 | dest_ptr_ty; | | |
| 20586 | | | |
| 20587 | try sema.requireRuntimeBlock(block, src, ptr_src); | | |
| 20588 | // TODO: Address space cast safety? | | |
| 20589 | | | |
| 20590 | return block.addInst(.{ | | |
| 20591 | .tag = .addrspace_cast, | | |
| 20592 | .data = .{ .ty_op = .{ | | |
| 20593 | .ty = try sema.addType(dest_ty), | | |
| 20594 | .operand = ptr, | | |
| 20595 | } }, | | |
| 20596 | }); | | |
| 20597 | } | | |
| 20598 | | | |
| 20599 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { | 20579 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { |
| 20600 | const va_list_ty = try sema.getBuiltinType("VaList"); | 20580 | const va_list_ty = try sema.getBuiltinType("VaList"); |
| 20601 | const va_list_ptr = try sema.mod.singleMutPtrType(va_list_ty); | 20581 | const va_list_ptr = try sema.mod.singleMutPtrType(va_list_ty); |
| ... | @@ -20711,14 +20691,14 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -20711,14 +20691,14 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20711 | fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20691 | fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20712 | const mod = sema.mod; | 20692 | const mod = sema.mod; |
| 20713 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 20693 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| | 20694 | const src = inst_data.src(); |
| 20714 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 20695 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20715 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20696 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20716 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 20697 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@intFromFloat"); |
| 20717 | const dest_ty = try sema.resolveType(block, ty_src, extra.lhs); | | |
| 20718 | const operand = try sema.resolveInst(extra.rhs); | 20698 | const operand = try sema.resolveInst(extra.rhs); |
| 20719 | const operand_ty = sema.typeOf(operand); | 20699 | const operand_ty = sema.typeOf(operand); |
| 20720 | | 20700 | |
| 20721 | _ = try sema.checkIntType(block, ty_src, dest_ty); | 20701 | _ = try sema.checkIntType(block, src, dest_ty); |
| 20722 | try sema.checkFloatType(block, operand_src, operand_ty); | 20702 | try sema.checkFloatType(block, operand_src, operand_ty); |
| 20723 | | 20703 | |
| 20724 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 20704 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| ... | @@ -20751,14 +20731,14 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -20751,14 +20731,14 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 20751 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20731 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20752 | const mod = sema.mod; | 20732 | const mod = sema.mod; |
| 20753 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 20733 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| | 20734 | const src = inst_data.src(); |
| 20754 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 20735 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20755 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20736 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20756 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 20737 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@floatFromInt"); |
| 20757 | const dest_ty = try sema.resolveType(block, ty_src, extra.lhs); | | |
| 20758 | const operand = try sema.resolveInst(extra.rhs); | 20738 | const operand = try sema.resolveInst(extra.rhs); |
| 20759 | const operand_ty = sema.typeOf(operand); | 20739 | const operand_ty = sema.typeOf(operand); |
| 20760 | | 20740 | |
| 20761 | try sema.checkFloatType(block, ty_src, dest_ty); | 20741 | try sema.checkFloatType(block, src, dest_ty); |
| 20762 | _ = try sema.checkIntType(block, operand_src, operand_ty); | 20742 | _ = try sema.checkIntType(block, operand_src, operand_ty); |
| 20763 | | 20743 | |
| 20764 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | 20744 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| ... | @@ -20779,21 +20759,20 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -20779,21 +20759,20 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 20779 | | 20759 | |
| 20780 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 20760 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20781 | | 20761 | |
| 20782 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 20762 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20783 | const operand_res = try sema.resolveInst(extra.rhs); | 20763 | const operand_res = try sema.resolveInst(extra.rhs); |
| 20784 | const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src); | 20764 | const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src); |
| 20785 | | 20765 | |
| 20786 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20766 | const ptr_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrFromInt"); |
| 20787 | const ptr_ty = try sema.resolveType(block, src, extra.lhs); | 20767 | try sema.checkPtrType(block, src, ptr_ty); |
| 20788 | try sema.checkPtrType(block, type_src, ptr_ty); | | |
| 20789 | const elem_ty = ptr_ty.elemType2(mod); | 20768 | const elem_ty = ptr_ty.elemType2(mod); |
| 20790 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); | 20769 | const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema); |
| 20791 | | 20770 | |
| 20792 | if (ptr_ty.isSlice(mod)) { | 20771 | if (ptr_ty.isSlice(mod)) { |
| 20793 | const msg = msg: { | 20772 | const msg = msg: { |
| 20794 | const msg = try sema.errMsg(block, type_src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)}); | 20773 | const msg = try sema.errMsg(block, src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)}); |
| 20795 | errdefer msg.destroy(sema.gpa); | 20774 | errdefer msg.destroy(sema.gpa); |
| 20796 | try sema.errNote(block, type_src, msg, "slice length cannot be inferred from address", .{}); | 20775 | try sema.errNote(block, src, msg, "slice length cannot be inferred from address", .{}); |
| 20797 | break :msg msg; | 20776 | break :msg msg; |
| 20798 | }; | 20777 | }; |
| 20799 | return sema.failWithOwnedErrorMsg(msg); | 20778 | return sema.failWithOwnedErrorMsg(msg); |
| ... | @@ -20841,12 +20820,11 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -20841,12 +20820,11 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20841 | const ip = &mod.intern_pool; | 20820 | const ip = &mod.intern_pool; |
| 20842 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 20821 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 20843 | const src = LazySrcLoc.nodeOffset(extra.node); | 20822 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 20844 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 20823 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| 20845 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; | 20824 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@errSetCast"); |
| 20846 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | | |
| 20847 | const operand = try sema.resolveInst(extra.rhs); | 20825 | const operand = try sema.resolveInst(extra.rhs); |
| 20848 | const operand_ty = sema.typeOf(operand); | 20826 | const operand_ty = sema.typeOf(operand); |
| 20849 | try sema.checkErrorSetType(block, dest_ty_src, dest_ty); | 20827 | try sema.checkErrorSetType(block, src, dest_ty); |
| 20850 | try sema.checkErrorSetType(block, operand_src, operand_ty); | 20828 | try sema.checkErrorSetType(block, operand_src, operand_ty); |
| 20851 | | 20829 | |
| 20852 | // operand must be defined since it can be an invalid error value | 20830 | // operand must be defined since it can be an invalid error value |
| ... | @@ -20869,7 +20847,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -20869,7 +20847,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20869 | break :disjoint true; | 20847 | break :disjoint true; |
| 20870 | } | 20848 | } |
| 20871 | | 20849 | |
| 20872 | try sema.resolveInferredErrorSetTy(block, dest_ty_src, dest_ty); | 20850 | try sema.resolveInferredErrorSetTy(block, src, dest_ty); |
| 20873 | try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty); | 20851 | try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty); |
| 20874 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { | 20852 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { |
| 20875 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) | 20853 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) |
| ... | @@ -20924,159 +20902,415 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -20924,159 +20902,415 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20924 | return block.addBitCast(dest_ty, operand); | 20902 | return block.addBitCast(dest_ty, operand); |
| 20925 | } | 20903 | } |
| 20926 | | 20904 | |
| | 20905 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| | 20906 | const flags = @bitCast(Zir.Inst.FullPtrCastFlags, @truncate(u5, extended.small)); |
| | 20907 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| | 20908 | const src = LazySrcLoc.nodeOffset(extra.node); |
| | 20909 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| | 20910 | const operand = try sema.resolveInst(extra.rhs); |
| | 20911 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrCast"); // TODO: better error message (builtin name) |
| | 20912 | return sema.ptrCastFull( |
| | 20913 | block, |
| | 20914 | flags, |
| | 20915 | src, |
| | 20916 | operand, |
| | 20917 | operand_src, |
| | 20918 | dest_ty, |
| | 20919 | ); |
| | 20920 | } |
| | 20921 | |
| 20927 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20922 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20928 | const mod = sema.mod; | | |
| 20929 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 20923 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 20930 | const src = inst_data.src(); | 20924 | const src = inst_data.src(); |
| 20931 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20925 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20932 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | | |
| 20933 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 20926 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 20934 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 20927 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@ptrCast"); |
| 20935 | const operand = try sema.resolveInst(extra.rhs); | 20928 | const operand = try sema.resolveInst(extra.rhs); |
| | 20929 | |
| | 20930 | return sema.ptrCastFull( |
| | 20931 | block, |
| | 20932 | .{ .ptr_cast = true }, |
| | 20933 | src, |
| | 20934 | operand, |
| | 20935 | operand_src, |
| | 20936 | dest_ty, |
| | 20937 | ); |
| | 20938 | } |
| | 20939 | |
| | 20940 | fn ptrCastFull( |
| | 20941 | sema: *Sema, |
| | 20942 | block: *Block, |
| | 20943 | flags: Zir.Inst.FullPtrCastFlags, |
| | 20944 | src: LazySrcLoc, |
| | 20945 | operand: Air.Inst.Ref, |
| | 20946 | operand_src: LazySrcLoc, |
| | 20947 | dest_ty: Type, |
| | 20948 | ) CompileError!Air.Inst.Ref { |
| | 20949 | const mod = sema.mod; |
| 20936 | const operand_ty = sema.typeOf(operand); | 20950 | const operand_ty = sema.typeOf(operand); |
| 20937 | | 20951 | |
| 20938 | try sema.checkPtrType(block, dest_ty_src, dest_ty); | 20952 | try sema.checkPtrType(block, src, dest_ty); |
| 20939 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 20953 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| 20940 | | 20954 | |
| 20941 | const operand_info = operand_ty.ptrInfo(mod); | 20955 | const src_info = operand_ty.ptrInfo(mod); |
| 20942 | const dest_info = dest_ty.ptrInfo(mod); | 20956 | const dest_info = dest_ty.ptrInfo(mod); |
| 20943 | if (operand_info.flags.is_const and !dest_info.flags.is_const) { | | |
| 20944 | const msg = msg: { | | |
| 20945 | const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{}); | | |
| 20946 | errdefer msg.destroy(sema.gpa); | | |
| 20947 | | 20957 | |
| 20948 | try sema.errNote(block, src, msg, "consider using '@constCast'", .{}); | 20958 | try sema.resolveTypeLayout(src_info.child.toType()); |
| 20949 | break :msg msg; | 20959 | try sema.resolveTypeLayout(dest_info.child.toType()); |
| 20950 | }; | | |
| 20951 | return sema.failWithOwnedErrorMsg(msg); | | |
| 20952 | } | | |
| 20953 | if (operand_info.flags.is_volatile and !dest_info.flags.is_volatile) { | | |
| 20954 | const msg = msg: { | | |
| 20955 | const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{}); | | |
| 20956 | errdefer msg.destroy(sema.gpa); | | |
| 20957 | | 20960 | |
| 20958 | try sema.errNote(block, src, msg, "consider using '@volatileCast'", .{}); | 20961 | const src_slice_like = src_info.flags.size == .Slice or |
| 20959 | break :msg msg; | 20962 | (src_info.flags.size == .One and src_info.child.toType().zigTypeTag(mod) == .Array); |
| 20960 | }; | 20963 | |
| 20961 | return sema.failWithOwnedErrorMsg(msg); | 20964 | const dest_slice_like = dest_info.flags.size == .Slice or |
| | 20965 | (dest_info.flags.size == .One and dest_info.child.toType().zigTypeTag(mod) == .Array); |
| | 20966 | |
| | 20967 | if (dest_info.flags.size == .Slice and !src_slice_like) { |
| | 20968 | return sema.fail(block, src, "illegal pointer cast to slice", .{}); |
| 20962 | } | 20969 | } |
| 20963 | if (operand_info.flags.address_space != dest_info.flags.address_space) { | | |
| 20964 | const msg = msg: { | | |
| 20965 | const msg = try sema.errMsg(block, src, "cast changes pointer address space", .{}); | | |
| 20966 | errdefer msg.destroy(sema.gpa); | | |
| 20967 | | 20970 | |
| 20968 | try sema.errNote(block, src, msg, "consider using '@addrSpaceCast'", .{}); | 20971 | if (dest_info.flags.size == .Slice) { |
| 20969 | break :msg msg; | 20972 | const src_elem_size = switch (src_info.flags.size) { |
| | 20973 | .Slice => src_info.child.toType().abiSize(mod), |
| | 20974 | // pointer to array |
| | 20975 | .One => src_info.child.toType().childType(mod).abiSize(mod), |
| | 20976 | else => unreachable, |
| 20970 | }; | 20977 | }; |
| 20971 | return sema.failWithOwnedErrorMsg(msg); | 20978 | const dest_elem_size = dest_info.child.toType().abiSize(mod); |
| | 20979 | if (src_elem_size != dest_elem_size) { |
| | 20980 | return sema.fail(block, src, "TODO: implement @ptrCast between slices changing the length", .{}); |
| | 20981 | } |
| 20972 | } | 20982 | } |
| 20973 | | 20983 | |
| 20974 | const dest_is_slice = dest_ty.isSlice(mod); | 20984 | // The checking logic in this function must stay in sync with Sema.coerceInMemoryAllowedPtrs |
| 20975 | const operand_is_slice = operand_ty.isSlice(mod); | | |
| 20976 | if (dest_is_slice and !operand_is_slice) { | | |
| 20977 | return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{}); | | |
| 20978 | } | | |
| 20979 | const ptr = if (operand_is_slice and !dest_is_slice) | | |
| 20980 | try sema.analyzeSlicePtr(block, operand_src, operand, operand_ty) | | |
| 20981 | else | | |
| 20982 | operand; | | |
| 20983 | | 20985 | |
| 20984 | const dest_elem_ty = dest_ty.elemType2(mod); | 20986 | if (!flags.ptr_cast) { |
| 20985 | try sema.resolveTypeLayout(dest_elem_ty); | 20987 | check_size: { |
| 20986 | const dest_align = dest_ty.ptrAlignment(mod); | 20988 | if (src_info.flags.size == dest_info.flags.size) break :check_size; |
| 20987 | | 20989 | if (src_slice_like and dest_slice_like) break :check_size; |
| 20988 | const operand_elem_ty = operand_ty.elemType2(mod); | 20990 | if (src_info.flags.size == .C) break :check_size; |
| 20989 | try sema.resolveTypeLayout(operand_elem_ty); | 20991 | if (dest_info.flags.size == .C) break :check_size; |
| 20990 | const operand_align = operand_ty.ptrAlignment(mod); | 20992 | return sema.failWithOwnedErrorMsg(msg: { |
| 20991 | | 20993 | const msg = try sema.errMsg(block, src, "cannot implicitly convert {s} pointer to {s} pointer", .{ |
| 20992 | // If the destination is less aligned than the source, preserve the source alignment | 20994 | pointerSizeString(src_info.flags.size), |
| 20993 | const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: { | 20995 | pointerSizeString(dest_info.flags.size), |
| 20994 | // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result | 20996 | }); |
| 20995 | var dest_ptr_info = dest_ty.ptrInfo(mod); | 20997 | errdefer msg.destroy(sema.gpa); |
| 20996 | dest_ptr_info.flags.alignment = Alignment.fromNonzeroByteUnits(operand_align); | 20998 | if (dest_info.flags.size == .Many and |
| 20997 | if (dest_ty.zigTypeTag(mod) == .Optional) { | 20999 | (src_info.flags.size == .Slice or |
| 20998 | break :blk try mod.optionalType((try mod.ptrType(dest_ptr_info)).toIntern()); | 21000 | (src_info.flags.size == .One and src_info.child.toType().zigTypeTag(mod) == .Array))) |
| 20999 | } else { | 21001 | { |
| 21000 | break :blk try mod.ptrType(dest_ptr_info); | 21002 | try sema.errNote(block, src, msg, "use 'ptr' field to convert slice to many pointer", .{}); |
| | 21003 | } else { |
| | 21004 | try sema.errNote(block, src, msg, "use @ptrCast to change pointer size", .{}); |
| | 21005 | } |
| | 21006 | break :msg msg; |
| | 21007 | }); |
| | 21008 | } |
| | 21009 | |
| | 21010 | check_child: { |
| | 21011 | const src_child = if (dest_info.flags.size == .Slice and src_info.flags.size == .One) blk: { |
| | 21012 | // *[n]T -> []T |
| | 21013 | break :blk src_info.child.toType().childType(mod); |
| | 21014 | } else src_info.child.toType(); |
| | 21015 | |
| | 21016 | const dest_child = dest_info.child.toType(); |
| | 21017 | |
| | 21018 | const imc_res = try sema.coerceInMemoryAllowed( |
| | 21019 | block, |
| | 21020 | dest_child, |
| | 21021 | src_child, |
| | 21022 | !dest_info.flags.is_const, |
| | 21023 | mod.getTarget(), |
| | 21024 | src, |
| | 21025 | operand_src, |
| | 21026 | ); |
| | 21027 | if (imc_res == .ok) break :check_child; |
| | 21028 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21029 | const msg = try sema.errMsg(block, src, "pointer element type '{}' cannot coerce into element type '{}'", .{ |
| | 21030 | src_child.fmt(mod), |
| | 21031 | dest_child.fmt(mod), |
| | 21032 | }); |
| | 21033 | errdefer msg.destroy(sema.gpa); |
| | 21034 | try imc_res.report(sema, block, src, msg); |
| | 21035 | try sema.errNote(block, src, msg, "use @ptrCast to cast pointer element type", .{}); |
| | 21036 | break :msg msg; |
| | 21037 | }); |
| | 21038 | } |
| | 21039 | |
| | 21040 | check_sent: { |
| | 21041 | if (dest_info.sentinel == .none) break :check_sent; |
| | 21042 | if (src_info.flags.size == .C) break :check_sent; |
| | 21043 | if (src_info.sentinel != .none) { |
| | 21044 | const coerced_sent = try mod.intern_pool.getCoerced(sema.gpa, src_info.sentinel, dest_info.child); |
| | 21045 | if (dest_info.sentinel == coerced_sent) break :check_sent; |
| | 21046 | } |
| | 21047 | if (src_slice_like and src_info.flags.size == .One and dest_info.flags.size == .Slice) { |
| | 21048 | // [*]nT -> []T |
| | 21049 | const arr_ty = src_info.child.toType(); |
| | 21050 | if (arr_ty.sentinel(mod)) |src_sentinel| { |
| | 21051 | const coerced_sent = try mod.intern_pool.getCoerced(sema.gpa, src_sentinel.toIntern(), dest_info.child); |
| | 21052 | if (dest_info.sentinel == coerced_sent) break :check_sent; |
| | 21053 | } |
| | 21054 | } |
| | 21055 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21056 | const msg = if (src_info.sentinel == .none) blk: { |
| | 21057 | break :blk try sema.errMsg(block, src, "destination pointer requires '{}' sentinel", .{ |
| | 21058 | dest_info.sentinel.toValue().fmtValue(dest_info.child.toType(), mod), |
| | 21059 | }); |
| | 21060 | } else blk: { |
| | 21061 | break :blk try sema.errMsg(block, src, "pointer sentinel '{}' cannot coerce into pointer sentinel '{}'", .{ |
| | 21062 | src_info.sentinel.toValue().fmtValue(src_info.child.toType(), mod), |
| | 21063 | dest_info.sentinel.toValue().fmtValue(dest_info.child.toType(), mod), |
| | 21064 | }); |
| | 21065 | }; |
| | 21066 | errdefer msg.destroy(sema.gpa); |
| | 21067 | try sema.errNote(block, src, msg, "use @ptrCast to cast pointer sentinel", .{}); |
| | 21068 | break :msg msg; |
| | 21069 | }); |
| 21001 | } | 21070 | } |
| 21002 | }; | | |
| 21003 | | 21071 | |
| 21004 | if (dest_is_slice) { | 21072 | if (src_info.packed_offset.host_size != dest_info.packed_offset.host_size) { |
| 21005 | const operand_elem_size = operand_elem_ty.abiSize(mod); | 21073 | return sema.failWithOwnedErrorMsg(msg: { |
| 21006 | const dest_elem_size = dest_elem_ty.abiSize(mod); | 21074 | const msg = try sema.errMsg(block, src, "pointer host size '{}' cannot coerce into pointer host size '{}'", .{ |
| 21007 | if (operand_elem_size != dest_elem_size) { | 21075 | src_info.packed_offset.host_size, |
| 21008 | return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{}); | 21076 | dest_info.packed_offset.host_size, |
| | 21077 | }); |
| | 21078 | errdefer msg.destroy(sema.gpa); |
| | 21079 | try sema.errNote(block, src, msg, "use @ptrCast to cast pointer host size", .{}); |
| | 21080 | break :msg msg; |
| | 21081 | }); |
| | 21082 | } |
| | 21083 | |
| | 21084 | if (src_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset) { |
| | 21085 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21086 | const msg = try sema.errMsg(block, src, "pointer bit offset '{}' cannot coerce into pointer bit offset '{}'", .{ |
| | 21087 | src_info.packed_offset.bit_offset, |
| | 21088 | dest_info.packed_offset.bit_offset, |
| | 21089 | }); |
| | 21090 | errdefer msg.destroy(sema.gpa); |
| | 21091 | try sema.errNote(block, src, msg, "use @ptrCast to cast pointer bit offset", .{}); |
| | 21092 | break :msg msg; |
| | 21093 | }); |
| | 21094 | } |
| | 21095 | |
| | 21096 | check_allowzero: { |
| | 21097 | const src_allows_zero = operand_ty.ptrAllowsZero(mod); |
| | 21098 | const dest_allows_zero = dest_ty.ptrAllowsZero(mod); |
| | 21099 | if (!src_allows_zero) break :check_allowzero; |
| | 21100 | if (dest_allows_zero) break :check_allowzero; |
| | 21101 | |
| | 21102 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21103 | const msg = try sema.errMsg(block, src, "'{}' could have null values which are illegal in type '{}'", .{ |
| | 21104 | operand_ty.fmt(mod), |
| | 21105 | dest_ty.fmt(mod), |
| | 21106 | }); |
| | 21107 | errdefer msg.destroy(sema.gpa); |
| | 21108 | try sema.errNote(block, src, msg, "use @ptrCast to assert the pointer is not null", .{}); |
| | 21109 | break :msg msg; |
| | 21110 | }); |
| 21009 | } | 21111 | } |
| | 21112 | |
| | 21113 | // TODO: vector index? |
| 21010 | } | 21114 | } |
| 21011 | | 21115 | |
| 21012 | if (dest_align > operand_align) { | 21116 | const src_align = src_info.flags.alignment.toByteUnitsOptional() orelse src_info.child.toType().abiAlignment(mod); |
| 21013 | const msg = msg: { | 21117 | const dest_align = dest_info.flags.alignment.toByteUnitsOptional() orelse dest_info.child.toType().abiAlignment(mod); |
| 21014 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); | 21118 | if (!flags.align_cast) { |
| 21015 | errdefer msg.destroy(sema.gpa); | 21119 | if (dest_align > src_align) { |
| | 21120 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21121 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); |
| | 21122 | errdefer msg.destroy(sema.gpa); |
| | 21123 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ |
| | 21124 | operand_ty.fmt(mod), src_align, |
| | 21125 | }); |
| | 21126 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ |
| | 21127 | dest_ty.fmt(mod), dest_align, |
| | 21128 | }); |
| | 21129 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); |
| | 21130 | break :msg msg; |
| | 21131 | }); |
| | 21132 | } |
| | 21133 | } |
| 21016 | | 21134 | |
| 21017 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ | 21135 | if (!flags.addrspace_cast) { |
| 21018 | operand_ty.fmt(mod), operand_align, | 21136 | if (src_info.flags.address_space != dest_info.flags.address_space) { |
| | 21137 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21138 | const msg = try sema.errMsg(block, src, "cast changes pointer address space", .{}); |
| | 21139 | errdefer msg.destroy(sema.gpa); |
| | 21140 | try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{ |
| | 21141 | operand_ty.fmt(mod), @tagName(src_info.flags.address_space), |
| | 21142 | }); |
| | 21143 | try sema.errNote(block, src, msg, "'{}' has address space '{s}'", .{ |
| | 21144 | dest_ty.fmt(mod), @tagName(dest_info.flags.address_space), |
| | 21145 | }); |
| | 21146 | try sema.errNote(block, src, msg, "use @addrSpaceCast to cast pointer address space", .{}); |
| | 21147 | break :msg msg; |
| | 21148 | }); |
| | 21149 | } |
| | 21150 | } else { |
| | 21151 | // Some address space casts are always disallowed |
| | 21152 | if (!target_util.addrSpaceCastIsValid(mod.getTarget(), src_info.flags.address_space, dest_info.flags.address_space)) { |
| | 21153 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21154 | const msg = try sema.errMsg(block, src, "invalid address space cast", .{}); |
| | 21155 | errdefer msg.destroy(sema.gpa); |
| | 21156 | try sema.errNote(block, operand_src, msg, "address space '{s}' is not compatible with address space '{s}'", .{ |
| | 21157 | @tagName(src_info.flags.address_space), |
| | 21158 | @tagName(dest_info.flags.address_space), |
| | 21159 | }); |
| | 21160 | break :msg msg; |
| 21019 | }); | 21161 | }); |
| 21020 | try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{ | 21162 | } |
| 21021 | dest_ty.fmt(mod), dest_align, | 21163 | } |
| | 21164 | |
| | 21165 | if (!flags.const_cast) { |
| | 21166 | if (src_info.flags.is_const and !dest_info.flags.is_const) { |
| | 21167 | return sema.failWithOwnedErrorMsg(msg: { |
| | 21168 | const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{}); |
| | 21169 | errdefer msg.destroy(sema.gpa); |
| | 21170 | try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{}); |
| | 21171 | break :msg msg; |
| 21022 | }); | 21172 | }); |
| | 21173 | } |
| | 21174 | } |
| 21023 | | 21175 | |
| 21024 | try sema.errNote(block, src, msg, "consider using '@alignCast'", .{}); | 21176 | if (!flags.volatile_cast) { |
| 21025 | break :msg msg; | 21177 | if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) { |
| 21026 | }; | 21178 | return sema.failWithOwnedErrorMsg(msg: { |
| 21027 | return sema.failWithOwnedErrorMsg(msg); | 21179 | const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{}); |
| | 21180 | errdefer msg.destroy(sema.gpa); |
| | 21181 | try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{}); |
| | 21182 | break :msg msg; |
| | 21183 | }); |
| | 21184 | } |
| 21028 | } | 21185 | } |
| 21029 | | 21186 | |
| 21030 | if (try sema.resolveMaybeUndefVal(ptr)) |operand_val| { | 21187 | const ptr = if (src_info.flags.size == .Slice and dest_info.flags.size != .Slice) ptr: { |
| 21031 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isUndef(mod)) { | 21188 | break :ptr try sema.analyzeSlicePtr(block, operand_src, operand, operand_ty); |
| 21032 | return sema.failWithUseOfUndef(block, operand_src); | 21189 | } else operand; |
| | 21190 | |
| | 21191 | const dest_ptr_ty = if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) blk: { |
| | 21192 | // Only convert to a many-pointer at first |
| | 21193 | var info = dest_info; |
| | 21194 | info.flags.size = .Many; |
| | 21195 | const ty = try mod.ptrType(info); |
| | 21196 | if (dest_ty.zigTypeTag(mod) == .Optional) { |
| | 21197 | break :blk try mod.optionalType(ty.toIntern()); |
| | 21198 | } else { |
| | 21199 | break :blk ty; |
| 21033 | } | 21200 | } |
| 21034 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) { | 21201 | } else dest_ty; |
| 21035 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}); | 21202 | |
| | 21203 | // Cannot do @addrSpaceCast at comptime |
| | 21204 | if (!flags.addrspace_cast) { |
| | 21205 | if (try sema.resolveMaybeUndefVal(ptr)) |ptr_val| { |
| | 21206 | if (!dest_ty.ptrAllowsZero(mod) and ptr_val.isUndef(mod)) { |
| | 21207 | return sema.failWithUseOfUndef(block, operand_src); |
| | 21208 | } |
| | 21209 | if (!dest_ty.ptrAllowsZero(mod) and ptr_val.isNull(mod)) { |
| | 21210 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}); |
| | 21211 | } |
| | 21212 | if (dest_align > src_align) { |
| | 21213 | if (try ptr_val.getUnsignedIntAdvanced(mod, null)) |addr| { |
| | 21214 | if (addr % dest_align != 0) { |
| | 21215 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align }); |
| | 21216 | } |
| | 21217 | } |
| | 21218 | } |
| | 21219 | if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) { |
| | 21220 | if (ptr_val.isUndef(mod)) return sema.addConstUndef(dest_ty); |
| | 21221 | const arr_len = try mod.intValue(Type.usize, src_info.child.toType().arrayLen(mod)); |
| | 21222 | return sema.addConstant((try mod.intern(.{ .ptr = .{ |
| | 21223 | .ty = dest_ty.toIntern(), |
| | 21224 | .addr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr, |
| | 21225 | .len = arr_len.toIntern(), |
| | 21226 | } })).toValue()); |
| | 21227 | } else { |
| | 21228 | assert(dest_ptr_ty.eql(dest_ty, mod)); |
| | 21229 | return sema.addConstant(try mod.getCoerced(ptr_val, dest_ty)); |
| | 21230 | } |
| 21036 | } | 21231 | } |
| 21037 | return sema.addConstant(try mod.getCoerced(operand_val, aligned_dest_ty)); | | |
| 21038 | } | 21232 | } |
| 21039 | | 21233 | |
| 21040 | try sema.requireRuntimeBlock(block, src, null); | 21234 | try sema.requireRuntimeBlock(block, src, null); |
| | 21235 | |
| 21041 | if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and | 21236 | if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and |
| 21042 | (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn)) | 21237 | (try sema.typeHasRuntimeBits(dest_info.child.toType()) or dest_info.child.toType().zigTypeTag(mod) == .Fn)) |
| 21043 | { | 21238 | { |
| 21044 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); | 21239 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); |
| 21045 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); | 21240 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); |
| 21046 | const ok = if (operand_is_slice) ok: { | 21241 | const ok = if (src_info.flags.size == .Slice and dest_info.flags.size == .Slice) ok: { |
| 21047 | const len = try sema.analyzeSliceLen(block, operand_src, operand); | 21242 | const len = try sema.analyzeSliceLen(block, operand_src, ptr); |
| 21048 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); | 21243 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); |
| 21049 | break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); | 21244 | break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); |
| 21050 | } else is_non_zero; | 21245 | } else is_non_zero; |
| 21051 | try sema.addSafetyCheck(block, ok, .cast_to_null); | 21246 | try sema.addSafetyCheck(block, ok, .cast_to_null); |
| 21052 | } | 21247 | } |
| 21053 | | 21248 | |
| 21054 | return block.addBitCast(aligned_dest_ty, ptr); | 21249 | if (block.wantSafety() and dest_align > src_align and try sema.typeHasRuntimeBits(dest_info.child.toType())) { |
| 21055 | } | 21250 | const align_minus_1 = try sema.addConstant( |
| 21056 | | 21251 | try mod.intValue(Type.usize, dest_align - 1), |
| 21057 | fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 21252 | ); |
| 21058 | const mod = sema.mod; | 21253 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); |
| 21059 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 21254 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); |
| 21060 | const src = LazySrcLoc.nodeOffset(extra.node); | 21255 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| 21061 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 21256 | const ok = if (src_info.flags.size == .Slice and dest_info.flags.size == .Slice) ok: { |
| 21062 | const operand = try sema.resolveInst(extra.operand); | 21257 | const len = try sema.analyzeSliceLen(block, operand_src, ptr); |
| 21063 | const operand_ty = sema.typeOf(operand); | 21258 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); |
| 21064 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 21259 | break :ok try block.addBinOp(.bit_or, len_zero, is_aligned); |
| | 21260 | } else is_aligned; |
| | 21261 | try sema.addSafetyCheck(block, ok, .incorrect_alignment); |
| | 21262 | } |
| 21065 | | 21263 | |
| 21066 | var ptr_info = operand_ty.ptrInfo(mod); | 21264 | // If we're going from an array pointer to a slice, this will only be the pointer part! |
| 21067 | ptr_info.flags.is_const = false; | 21265 | const result_ptr = if (flags.addrspace_cast) ptr: { |
| 21068 | const dest_ty = try mod.ptrType(ptr_info); | 21266 | // We can't change address spaces with a bitcast, so this requires two instructions |
| | 21267 | var intermediate_info = src_info; |
| | 21268 | intermediate_info.flags.address_space = dest_info.flags.address_space; |
| | 21269 | const intermediate_ptr_ty = try mod.ptrType(intermediate_info); |
| | 21270 | const intermediate_ty = if (dest_ptr_ty.zigTypeTag(mod) == .Optional) blk: { |
| | 21271 | break :blk try mod.optionalType(intermediate_ptr_ty.toIntern()); |
| | 21272 | } else intermediate_ptr_ty; |
| | 21273 | const intermediate = try block.addInst(.{ |
| | 21274 | .tag = .addrspace_cast, |
| | 21275 | .data = .{ .ty_op = .{ |
| | 21276 | .ty = try sema.addType(intermediate_ty), |
| | 21277 | .operand = ptr, |
| | 21278 | } }, |
| | 21279 | }); |
| | 21280 | if (intermediate_ty.eql(dest_ptr_ty, mod)) { |
| | 21281 | // We only changed the address space, so no need for a bitcast |
| | 21282 | break :ptr intermediate; |
| | 21283 | } |
| | 21284 | break :ptr try block.addBitCast(dest_ptr_ty, intermediate); |
| | 21285 | } else ptr: { |
| | 21286 | break :ptr try block.addBitCast(dest_ptr_ty, ptr); |
| | 21287 | }; |
| 21069 | | 21288 | |
| 21070 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | 21289 | if (dest_info.flags.size == .Slice and src_info.flags.size != .Slice) { |
| 21071 | return sema.addConstant(try mod.getCoerced(operand_val, dest_ty)); | 21290 | // We have to construct a slice using the operand's child's array length |
| | 21291 | // Note that we know from the check at the start of the function that operand_ty is slice-like |
| | 21292 | const arr_len = try sema.addConstant( |
| | 21293 | try mod.intValue(Type.usize, src_info.child.toType().arrayLen(mod)), |
| | 21294 | ); |
| | 21295 | return block.addInst(.{ |
| | 21296 | .tag = .slice, |
| | 21297 | .data = .{ .ty_pl = .{ |
| | 21298 | .ty = try sema.addType(dest_ty), |
| | 21299 | .payload = try sema.addExtra(Air.Bin{ |
| | 21300 | .lhs = result_ptr, |
| | 21301 | .rhs = arr_len, |
| | 21302 | }), |
| | 21303 | } }, |
| | 21304 | }); |
| | 21305 | } else { |
| | 21306 | assert(dest_ptr_ty.eql(dest_ty, mod)); |
| | 21307 | return result_ptr; |
| 21072 | } | 21308 | } |
| 21073 | | | |
| 21074 | try sema.requireRuntimeBlock(block, src, null); | | |
| 21075 | return block.addBitCast(dest_ty, operand); | | |
| 21076 | } | 21309 | } |
| 21077 | | 21310 | |
| 21078 | fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 21311 | fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 21079 | const mod = sema.mod; | 21312 | const mod = sema.mod; |
| | 21313 | const flags = @bitCast(Zir.Inst.FullPtrCastFlags, @truncate(u5, extended.small)); |
| 21080 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 21314 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 21081 | const src = LazySrcLoc.nodeOffset(extra.node); | 21315 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 21082 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 21316 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| ... | @@ -21085,11 +21319,12 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -21085,11 +21319,12 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 21085 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 21319 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| 21086 | | 21320 | |
| 21087 | var ptr_info = operand_ty.ptrInfo(mod); | 21321 | var ptr_info = operand_ty.ptrInfo(mod); |
| 21088 | ptr_info.flags.is_volatile = false; | 21322 | if (flags.const_cast) ptr_info.flags.is_const = false; |
| | 21323 | if (flags.volatile_cast) ptr_info.flags.is_volatile = false; |
| 21089 | const dest_ty = try mod.ptrType(ptr_info); | 21324 | const dest_ty = try mod.ptrType(ptr_info); |
| 21090 | | 21325 | |
| 21091 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | 21326 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 21092 | return sema.addConstant(operand_val); | 21327 | return sema.addConstant(try mod.getCoerced(operand_val, dest_ty)); |
| 21093 | } | 21328 | } |
| 21094 | | 21329 | |
| 21095 | try sema.requireRuntimeBlock(block, src, null); | 21330 | try sema.requireRuntimeBlock(block, src, null); |
| ... | @@ -21100,24 +21335,21 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -21100,24 +21335,21 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 21100 | const mod = sema.mod; | 21335 | const mod = sema.mod; |
| 21101 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 21336 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 21102 | const src = inst_data.src(); | 21337 | const src = inst_data.src(); |
| 21103 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 21338 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 21104 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | | |
| 21105 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 21339 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 21106 | const dest_scalar_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 21340 | const dest_ty = try sema.resolveCastDestType(block, src, extra.lhs, "@truncate"); |
| | 21341 | const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src); |
| 21107 | const operand = try sema.resolveInst(extra.rhs); | 21342 | const operand = try sema.resolveInst(extra.rhs); |
| 21108 | const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty); | | |
| 21109 | const operand_ty = sema.typeOf(operand); | 21343 | const operand_ty = sema.typeOf(operand); |
| 21110 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); | 21344 | const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); |
| 21111 | const is_vector = operand_ty.zigTypeTag(mod) == .Vector; | | |
| 21112 | const dest_ty = if (is_vector) | | |
| 21113 | try mod.vectorType(.{ | | |
| 21114 | .len = operand_ty.vectorLen(mod), | | |
| 21115 | .child = dest_scalar_ty.toIntern(), | | |
| 21116 | }) | | |
| 21117 | else | | |
| 21118 | dest_scalar_ty; | | |
| 21119 | | 21345 | |
| 21120 | if (dest_is_comptime_int) { | 21346 | const operand_is_vector = operand_ty.zigTypeTag(mod) == .Vector; |
| | 21347 | const dest_is_vector = dest_ty.zigTypeTag(mod) == .Vector; |
| | 21348 | if (operand_is_vector != dest_is_vector) { |
| | 21349 | return sema.fail(block, operand_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(mod), operand_ty.fmt(mod) }); |
| | 21350 | } |
| | 21351 | |
| | 21352 | if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 21121 | return sema.coerce(block, dest_ty, operand, operand_src); | 21353 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 21122 | } | 21354 | } |
| 21123 | | 21355 | |
| ... | @@ -21147,7 +21379,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -21147,7 +21379,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 21147 | .{ dest_ty.fmt(mod), operand_ty.fmt(mod) }, | 21379 | .{ dest_ty.fmt(mod), operand_ty.fmt(mod) }, |
| 21148 | ); | 21380 | ); |
| 21149 | errdefer msg.destroy(sema.gpa); | 21381 | errdefer msg.destroy(sema.gpa); |
| 21150 | try sema.errNote(block, dest_ty_src, msg, "destination type has {d} bits", .{ | 21382 | try sema.errNote(block, src, msg, "destination type has {d} bits", .{ |
| 21151 | dest_info.bits, | 21383 | dest_info.bits, |
| 21152 | }); | 21384 | }); |
| 21153 | try sema.errNote(block, operand_src, msg, "operand type has {d} bits", .{ | 21385 | try sema.errNote(block, operand_src, msg, "operand type has {d} bits", .{ |
| ... | @@ -21161,7 +21393,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -21161,7 +21393,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 21161 | | 21393 | |
| 21162 | if (try sema.resolveMaybeUndefValIntable(operand)) |val| { | 21394 | if (try sema.resolveMaybeUndefValIntable(operand)) |val| { |
| 21163 | if (val.isUndef(mod)) return sema.addConstUndef(dest_ty); | 21395 | if (val.isUndef(mod)) return sema.addConstUndef(dest_ty); |
| 21164 | if (!is_vector) { | 21396 | if (!dest_is_vector) { |
| 21165 | return sema.addConstant(try mod.getCoerced( | 21397 | return sema.addConstant(try mod.getCoerced( |
| 21166 | try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod), | 21398 | try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod), |
| 21167 | dest_ty, | 21399 | dest_ty, |
| ... | @@ -21182,59 +21414,6 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -21182,59 +21414,6 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 21182 | return block.addTyOp(.trunc, dest_ty, operand); | 21414 | return block.addTyOp(.trunc, dest_ty, operand); |
| 21183 | } | 21415 | } |
| 21184 | | 21416 | |
| 21185 | fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | | |
| 21186 | const mod = sema.mod; | | |
| 21187 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | | |
| 21188 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | | |
| 21189 | const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | | |
| 21190 | const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | | |
| 21191 | const dest_align = try sema.resolveAlign(block, align_src, extra.lhs); | | |
| 21192 | const ptr = try sema.resolveInst(extra.rhs); | | |
| 21193 | const ptr_ty = sema.typeOf(ptr); | | |
| 21194 | | | |
| 21195 | try sema.checkPtrOperand(block, ptr_src, ptr_ty); | | |
| 21196 | | | |
| 21197 | var ptr_info = ptr_ty.ptrInfo(mod); | | |
| 21198 | ptr_info.flags.alignment = dest_align; | | |
| 21199 | var dest_ty = try mod.ptrType(ptr_info); | | |
| 21200 | if (ptr_ty.zigTypeTag(mod) == .Optional) { | | |
| 21201 | dest_ty = try mod.optionalType(dest_ty.toIntern()); | | |
| 21202 | } | | |
| 21203 | | | |
| 21204 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| { | | |
| 21205 | if (try val.getUnsignedIntAdvanced(mod, null)) |addr| { | | |
| 21206 | const dest_align_bytes = dest_align.toByteUnitsOptional().?; | | |
| 21207 | if (addr % dest_align_bytes != 0) { | | |
| 21208 | return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align_bytes }); | | |
| 21209 | } | | |
| 21210 | } | | |
| 21211 | return sema.addConstant(try mod.getCoerced(val, dest_ty)); | | |
| 21212 | } | | |
| 21213 | | | |
| 21214 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | | |
| 21215 | if (block.wantSafety() and dest_align.order(Alignment.fromNonzeroByteUnits(1)).compare(.gt) and | | |
| 21216 | try sema.typeHasRuntimeBits(ptr_info.child.toType())) | | |
| 21217 | { | | |
| 21218 | const align_minus_1 = try sema.addConstant( | | |
| 21219 | try mod.intValue(Type.usize, dest_align.toByteUnitsOptional().? - 1), | | |
| 21220 | ); | | |
| 21221 | const actual_ptr = if (ptr_ty.isSlice(mod)) | | |
| 21222 | try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty) | | |
| 21223 | else | | |
| 21224 | ptr; | | |
| 21225 | const ptr_int = try block.addUnOp(.int_from_ptr, actual_ptr); | | |
| 21226 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); | | |
| 21227 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | | |
| 21228 | const ok = if (ptr_ty.isSlice(mod)) ok: { | | |
| 21229 | const len = try sema.analyzeSliceLen(block, ptr_src, ptr); | | |
| 21230 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); | | |
| 21231 | break :ok try block.addBinOp(.bit_or, len_zero, is_aligned); | | |
| 21232 | } else is_aligned; | | |
| 21233 | try sema.addSafetyCheck(block, ok, .incorrect_alignment); | | |
| 21234 | } | | |
| 21235 | return sema.bitCast(block, dest_ty, ptr, ptr_src, null); | | |
| 21236 | } | | |
| 21237 | | | |
| 21238 | fn zirBitCount( | 21417 | fn zirBitCount( |
| 21239 | sema: *Sema, | 21418 | sema: *Sema, |
| 21240 | block: *Block, | 21419 | block: *Block, |
| ... | @@ -21546,7 +21725,7 @@ fn checkPtrOperand( | ... | @@ -21546,7 +21725,7 @@ fn checkPtrOperand( |
| 21546 | }; | 21725 | }; |
| 21547 | return sema.failWithOwnedErrorMsg(msg); | 21726 | return sema.failWithOwnedErrorMsg(msg); |
| 21548 | }, | 21727 | }, |
| 21549 | .Optional => if (ty.isPtrLikeOptional(mod)) return, | 21728 | .Optional => if (ty.childType(mod).zigTypeTag(mod) == .Pointer) return, |
| 21550 | else => {}, | 21729 | else => {}, |
| 21551 | } | 21730 | } |
| 21552 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)}); | 21731 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)}); |
| ... | @@ -21577,7 +21756,7 @@ fn checkPtrType( | ... | @@ -21577,7 +21756,7 @@ fn checkPtrType( |
| 21577 | }; | 21756 | }; |
| 21578 | return sema.failWithOwnedErrorMsg(msg); | 21757 | return sema.failWithOwnedErrorMsg(msg); |
| 21579 | }, | 21758 | }, |
| 21580 | .Optional => if (ty.isPtrLikeOptional(mod)) return, | 21759 | .Optional => if (ty.childType(mod).zigTypeTag(mod) == .Pointer) return, |
| 21581 | else => {}, | 21760 | else => {}, |
| 21582 | } | 21761 | } |
| 21583 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)}); | 21762 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)}); |