authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-02-12 16:57:58+01:00
committergravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2022-03-25 23:33:05+01:00
logdc5dc3ac59bb0f013a867b278b994b76df655480
tree70b623144f9c795168712b2e437a42d130b04afe
parenta7b3082ba0d07c66d2ec19304ffe993d77f714b7

stage2: add type checking for @bitCast


1 files changed, 76 insertions(+), 1 deletions(-)

src/Sema.zig+76-1
...@@ -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();
67686769
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);
1899719060
18998 // TODO validate the type size and other compile errors19061 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);