Sema: correct types in @memset and @memcpy

Closes #12750
This commit is contained in:
Veikka Tuominen 2022-09-07 19:11:26 +03:00
parent 924679abc4
commit 0fa80e66b7
2 changed files with 40 additions and 29 deletions

View File

@ -18076,8 +18076,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
const target = sema.mod.getTarget();
try sema.resolveTypeLayout(block, lhs_src, ty);
switch (ty.tag()) {
.@"struct", .tuple, .anon_struct => {},
switch (ty.zigTypeTag()) {
.Struct => {},
else => {
const msg = msg: {
const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
@ -19617,28 +19617,19 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
const dest_ptr = try sema.resolveInst(extra.dest);
const dest_ptr_ty = sema.typeOf(dest_ptr);
const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
if (dest_ptr_ty.isConstPtr()) {
return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
}
// TODO AstGen's coerced_ty cannot handle volatile here
var dest_ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
dest_ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, dest_ptr_info);
const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
const uncasted_src_ptr = try sema.resolveInst(extra.source);
const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr);
try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty);
const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
const wanted_src_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
.pointee_type = dest_ptr_ty.elemType2(),
.@"align" = src_ptr_info.@"align",
.@"addrspace" = src_ptr_info.@"addrspace",
.mutable = false,
.@"allowzero" = src_ptr_info.@"allowzero",
.@"volatile" = src_ptr_info.@"volatile",
.size = .Many,
});
const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);
var src_ptr_info = Type.initTag(.manyptr_const_u8).ptrInfo().data;
src_ptr_info.@"volatile" = sema.typeOf(uncasted_src_ptr).isVolatilePtr();
const src_ptr_ty = try Type.ptr(sema.arena, sema.mod, src_ptr_info);
const src_ptr = try sema.coerce(block, src_ptr_ty, uncasted_src_ptr, src_src);
const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
@ -19674,14 +19665,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const value_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
const dest_ptr = try sema.resolveInst(extra.dest);
const dest_ptr_ty = sema.typeOf(dest_ptr);
try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
if (dest_ptr_ty.isConstPtr()) {
return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
}
const elem_ty = dest_ptr_ty.elemType2();
const value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.byte), value_src);
const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
// TODO AstGen's coerced_ty cannot handle volatile here
var ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
const value = try sema.coerce(block, Type.u8, try sema.resolveInst(extra.byte), value_src);
const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {

View File

@ -0,0 +1,19 @@
pub export fn entry() void {
var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
var slice: []u8 = &buf;
const a: u32 = 1234;
@memcpy(slice, @ptrCast([*]const u8, &a), 4);
}
pub export fn entry1() void {
var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
var ptr: *u8 = &buf[0];
@memcpy(ptr, 0, 4);
}
// error
// backend=stage2
// target=native
//
// :5:13: error: expected type '[*]u8', found '[]u8'
// :10:13: error: expected type '[*]u8', found '*u8'
// :10:13: note: a single pointer cannot cast into a many pointer