| ... | @@ -6765,8 +6765,71 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -6765,8 +6765,71 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 6765 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 6765 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 6766 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 6766 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 6767 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 6767 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| | 6768 | const target = sema.mod.getTarget(); |
| 6768 | | 6769 | |
| 6769 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); | 6770 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| | 6771 | switch (dest_ty.zigTypeTag()) { |
| | 6772 | .Type, |
| | 6773 | .Void, |
| | 6774 | .NoReturn, |
| | 6775 | .ComptimeFloat, |
| | 6776 | .ComptimeInt, |
| | 6777 | .Undefined, |
| | 6778 | .Null, |
| | 6779 | .Optional, |
| | 6780 | .ErrorUnion, |
| | 6781 | .ErrorSet, |
| | 6782 | .Opaque, |
| | 6783 | .Frame, |
| | 6784 | .AnyFrame, |
| | 6785 | .EnumLiteral, |
| | 6786 | .Union, |
| | 6787 | .Fn, |
| | 6788 | => return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(target)}), |
| | 6789 | |
| | 6790 | .Pointer => { |
| | 6791 | const msg = msg: { |
| | 6792 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to pointer type '{}'", .{dest_ty.fmt(target)}); |
| | 6793 | errdefer msg.destroy(sema.gpa); |
| | 6794 | |
| | 6795 | const pointee_ty = dest_ty.ptrInfo().data.pointee_type; |
| | 6796 | try sema.errNote(block, dest_ty_src, msg, "to cast to a pointer type, use @ptrCast({}, ...)", .{dest_ty.fmt(target)}); |
| | 6797 | try sema.errNote(block, dest_ty_src, msg, "to cast to a non-pointer type, use @bitCast({}, ...)", .{pointee_ty.fmt(target)}); |
| | 6798 | break :msg msg; |
| | 6799 | }; |
| | 6800 | return sema.failWithOwnedErrorMsg(block, msg); |
| | 6801 | }, |
| | 6802 | .Struct => { |
| | 6803 | if (dest_ty.containerLayout() == .Auto) { |
| | 6804 | const msg = msg: { |
| | 6805 | const msg = try sema.errMsg( |
| | 6806 | block, |
| | 6807 | dest_ty_src, |
| | 6808 | "cannot @bitCast to '{}', struct does not have a specified layout", |
| | 6809 | .{dest_ty.fmt(target)}, |
| | 6810 | ); |
| | 6811 | errdefer msg.destroy(sema.gpa); |
| | 6812 | |
| | 6813 | const ty_decl_src = dest_ty.declSrcLoc(); |
| | 6814 | try sema.mod.errNoteNonLazy( |
| | 6815 | ty_decl_src, |
| | 6816 | msg, |
| | 6817 | "consider using 'packed struct' or 'extern struct' for a specified layout.", |
| | 6818 | .{}, |
| | 6819 | ); |
| | 6820 | break :msg msg; |
| | 6821 | }; |
| | 6822 | return sema.failWithOwnedErrorMsg(block, msg); |
| | 6823 | } |
| | 6824 | }, |
| | 6825 | .BoundFn => @panic("TODO remove this type from the language and compiler"), |
| | 6826 | else => {}, |
| | 6827 | } |
| | 6828 | |
| | 6829 | // When bitcasting we compare the bit size of the types, so we need to |
| | 6830 | // fully resolve all composite types to finalize the layout. |
| | 6831 | try sema.resolveTypeFully(block, dest_ty_src, dest_ty); |
| | 6832 | |
| 6770 | const operand = sema.resolveInst(extra.rhs); | 6833 | const operand = sema.resolveInst(extra.rhs); |
| 6771 | return sema.bitCast(block, dest_ty, operand, operand_src); | 6834 | return sema.bitCast(block, dest_ty, operand, operand_src); |
| 6772 | } | 6835 | } |
| ... | @@ -18995,7 +19058,19 @@ fn bitCast( | ... | @@ -18995,7 +19058,19 @@ fn bitCast( |
| 18995 | const old_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst)); | 19058 | const old_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst)); |
| 18996 | try sema.resolveTypeLayout(block, inst_src, old_ty); | 19059 | try sema.resolveTypeLayout(block, inst_src, old_ty); |
| 18997 | | 19060 | |
| 18998 | // TODO validate the type size and other compile errors | 19061 | const target = sema.mod.getTarget(); |
| | 19062 | var dest_bits = dest_ty.bitSize(target); |
| | 19063 | var old_bits = old_ty.bitSize(target); |
| | 19064 | |
| | 19065 | if (old_bits != dest_bits) { |
| | 19066 | return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{ |
| | 19067 | dest_ty.fmt(target), |
| | 19068 | dest_bits, |
| | 19069 | old_ty.fmt(target), |
| | 19070 | old_bits, |
| | 19071 | }); |
| | 19072 | } |
| | 19073 | |
| 18999 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 19074 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 19000 | const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0); | 19075 | const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0); |
| 19001 | return sema.addConstant(dest_ty, result_val); | 19076 | return sema.addConstant(dest_ty, result_val); |