mirror of
https://github.com/ziglang/zig.git
synced 2026-01-30 11:13:38 +00:00
Merge pull request #10871 from schmee/stage2-bitcast-safety
stage2: add type checking for @bitCast
This commit is contained in:
commit
f9a2c0fc6c
57
src/Sema.zig
57
src/Sema.zig
@ -6800,8 +6800,51 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
|
||||
switch (dest_ty.zigTypeTag()) {
|
||||
.AnyFrame,
|
||||
.ComptimeFloat,
|
||||
.ComptimeInt,
|
||||
.Enum,
|
||||
.EnumLiteral,
|
||||
.ErrorSet,
|
||||
.ErrorUnion,
|
||||
.Fn,
|
||||
.Frame,
|
||||
.NoReturn,
|
||||
.Null,
|
||||
.Opaque,
|
||||
.Optional,
|
||||
.Type,
|
||||
.Undefined,
|
||||
.Void,
|
||||
=> return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(target)}),
|
||||
|
||||
.Pointer => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', use @ptrCast to cast to a pointer", .{
|
||||
dest_ty.fmt(target),
|
||||
}),
|
||||
.Struct, .Union => if (dest_ty.containerLayout() == .Auto) {
|
||||
const container = switch (dest_ty.zigTypeTag()) {
|
||||
.Struct => "struct",
|
||||
.Union => "union",
|
||||
else => unreachable,
|
||||
};
|
||||
return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', {s} does not have a guaranteed in-memory layout", .{
|
||||
dest_ty.fmt(target), container,
|
||||
});
|
||||
},
|
||||
.BoundFn => @panic("TODO remove this type from the language and compiler"),
|
||||
|
||||
.Array,
|
||||
.Bool,
|
||||
.Float,
|
||||
.Int,
|
||||
.Vector,
|
||||
=> {},
|
||||
}
|
||||
|
||||
const operand = sema.resolveInst(extra.rhs);
|
||||
return sema.bitCast(block, dest_ty, operand, operand_src);
|
||||
}
|
||||
@ -19137,7 +19180,19 @@ fn bitCast(
|
||||
const old_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst));
|
||||
try sema.resolveTypeLayout(block, inst_src, old_ty);
|
||||
|
||||
// TODO validate the type size and other compile errors
|
||||
const target = sema.mod.getTarget();
|
||||
var dest_bits = dest_ty.bitSize(target);
|
||||
var old_bits = old_ty.bitSize(target);
|
||||
|
||||
if (old_bits != dest_bits) {
|
||||
return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{
|
||||
dest_ty.fmt(target),
|
||||
dest_bits,
|
||||
old_ty.fmt(target),
|
||||
old_bits,
|
||||
});
|
||||
}
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
|
||||
const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0);
|
||||
return sema.addConstant(dest_ty, result_val);
|
||||
|
||||
14
src/type.zig
14
src/type.zig
@ -3274,8 +3274,20 @@ pub const Type = extern union {
|
||||
const int_tag_ty = ty.intTagType(&buffer);
|
||||
return int_tag_ty.bitSize(target);
|
||||
},
|
||||
|
||||
.@"union", .union_tagged => {
|
||||
@panic("TODO bitSize unions");
|
||||
const union_obj = ty.cast(Payload.Union).?.data;
|
||||
|
||||
const fields = union_obj.fields;
|
||||
if (fields.count() == 0) return 0;
|
||||
|
||||
assert(union_obj.haveFieldTypes());
|
||||
|
||||
var size: u64 = 0;
|
||||
for (fields.values()) |field| {
|
||||
size = @maximum(size, field.ty.bitSize(target));
|
||||
}
|
||||
return size;
|
||||
},
|
||||
|
||||
.vector => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user