| author | |
| committer | |
| log | 83a7303bbf92fcada2e61f2906f84ccf53e50ff0 |
| tree | e3930f9b1a3ee2c4f835055ab221197696ecb5c3 |
| parent | 0f65cc9275cde61fe20f28e4f059c8af4c63b051 |
6 files changed, 38 insertions(+), 27 deletions(-)
src/Sema.zig+32-5| ... | @@ -21959,17 +21959,44 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -21959,17 +21959,44 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 21959 | const dest_ptr_ty = sema.typeOf(dest_ptr); | 21959 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 21960 | try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty); | 21960 | try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty); |
| 21961 | 21961 | ||
| 21962 | const elem_ty = dest_ptr_ty.elemType2(); | 21962 | const dest_elem_ty = dest_ptr_ty.elemType2(); |
| 21963 | const elem = try sema.coerce(block, elem_ty, uncoerced_elem, value_src); | 21963 | const target = sema.mod.getTarget(); |
| 21964 | 21964 | ||
| 21965 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { | 21965 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { |
| 21966 | if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src; | 21966 | if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src; |
| 21967 | if (try sema.resolveMaybeUndefVal(elem)) |elem_val| { | 21967 | if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| { |
| 21968 | _ = elem_val; | 21968 | const len_air_ref = try sema.fieldVal(block, src, dest_ptr, "len", dest_src); |
| 21969 | return sema.fail(block, src, "TODO: @memset at comptime", .{}); | 21969 | const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse |
| 21970 | break :rs dest_src; | ||
| 21971 | const len_u64 = (try len_val.getUnsignedIntAdvanced(target, sema)).?; | ||
| 21972 | const len = try sema.usizeCast(block, dest_src, len_u64); | ||
| 21973 | for (0..len) |i| { | ||
| 21974 | const elem_index = try sema.addIntUnsigned(Type.usize, i); | ||
| 21975 | const elem_ptr = try sema.elemPtr( | ||
| 21976 | block, | ||
| 21977 | src, | ||
| 21978 | dest_ptr, | ||
| 21979 | elem_index, | ||
| 21980 | src, | ||
| 21981 | true, // init | ||
| 21982 | false, // oob_safety | ||
| 21983 | ); | ||
| 21984 | try sema.storePtr2( | ||
| 21985 | block, | ||
| 21986 | src, | ||
| 21987 | elem_ptr, | ||
| 21988 | dest_src, | ||
| 21989 | uncoerced_elem, | ||
| 21990 | value_src, | ||
| 21991 | .store, | ||
| 21992 | ); | ||
| 21993 | } | ||
| 21994 | return; | ||
| 21970 | } else break :rs value_src; | 21995 | } else break :rs value_src; |
| 21971 | } else dest_src; | 21996 | } else dest_src; |
| 21972 | 21997 | ||
| 21998 | const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); | ||
| 21999 | |||
| 21973 | try sema.requireRuntimeBlock(block, src, runtime_src); | 22000 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 21974 | _ = try block.addInst(.{ | 22001 | _ = try block.addInst(.{ |
| 21975 | .tag = if (block.wantSafety()) .memset_safe else .memset, | 22002 | .tag = if (block.wantSafety()) .memset_safe else .memset, |
test/behavior/basic.zig+1-17| ... | @@ -359,8 +359,7 @@ test "@memset on array pointers" { | ... | @@ -359,8 +359,7 @@ test "@memset on array pointers" { |
| 359 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 359 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 360 | 360 | ||
| 361 | try testMemsetArray(); | 361 | try testMemsetArray(); |
| 362 | // TODO this doesn't pass yet | 362 | try comptime testMemsetArray(); |
| 363 | // try comptime testMemsetArray(); | ||
| 364 | } | 363 | } |
| 365 | 364 | ||
| 366 | fn testMemsetArray() !void { | 365 | fn testMemsetArray() !void { |
| ... | @@ -371,15 +370,7 @@ fn testMemsetArray() !void { | ... | @@ -371,15 +370,7 @@ fn testMemsetArray() !void { |
| 371 | try expect(foo[0] == 'A'); | 370 | try expect(foo[0] == 'A'); |
| 372 | try expect(foo[11] == 'A'); | 371 | try expect(foo[11] == 'A'); |
| 373 | try expect(foo[19] == 'A'); | 372 | try expect(foo[19] == 'A'); |
| 374 | |||
| 375 | // memset array to undefined, ABI size == 1 | ||
| 376 | @setRuntimeSafety(true); | ||
| 377 | @memset(&foo, undefined); | ||
| 378 | try expect(foo[0] == 0xaa); | ||
| 379 | try expect(foo[11] == 0xaa); | ||
| 380 | try expect(foo[19] == 0xaa); | ||
| 381 | } | 373 | } |
| 382 | |||
| 383 | { | 374 | { |
| 384 | // memset array to non-undefined, ABI size > 1 | 375 | // memset array to non-undefined, ABI size > 1 |
| 385 | var foo: [20]u32 = undefined; | 376 | var foo: [20]u32 = undefined; |
| ... | @@ -387,13 +378,6 @@ fn testMemsetArray() !void { | ... | @@ -387,13 +378,6 @@ fn testMemsetArray() !void { |
| 387 | try expect(foo[0] == 1234); | 378 | try expect(foo[0] == 1234); |
| 388 | try expect(foo[11] == 1234); | 379 | try expect(foo[11] == 1234); |
| 389 | try expect(foo[19] == 1234); | 380 | try expect(foo[19] == 1234); |
| 390 | |||
| 391 | // memset array to undefined, ABI size > 1 | ||
| 392 | @setRuntimeSafety(true); | ||
| 393 | @memset(&foo, undefined); | ||
| 394 | try expect(foo[0] == 0xaaaaaaaa); | ||
| 395 | try expect(foo[11] == 0xaaaaaaaa); | ||
| 396 | try expect(foo[19] == 0xaaaaaaaa); | ||
| 397 | } | 381 | } |
| 398 | } | 382 | } |
| 399 | 383 |
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+2-2| ... | @@ -2,12 +2,12 @@ pub export fn entry() void { | ... | @@ -2,12 +2,12 @@ pub export fn entry() void { |
| 2 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; | 2 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; |
| 3 | var slice: []u8 = &buf; | 3 | var slice: []u8 = &buf; |
| 4 | const a: u32 = 1234; | 4 | const a: u32 = 1234; |
| 5 | @memcpy(slice, @ptrCast([*]const u8, &a), 4); | 5 | @memcpy(slice, @ptrCast([*]const u8, &a)); |
| 6 | } | 6 | } |
| 7 | pub export fn entry1() void { | 7 | pub export fn entry1() void { |
| 8 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; | 8 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; |
| 9 | var ptr: *u8 = &buf[0]; | 9 | var ptr: *u8 = &buf[0]; |
| 10 | @memcpy(ptr, 0, 4); | 10 | @memcpy(ptr, 0); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | // error | 13 | // error |
test/cases/safety/@tagName on corrupted enum value.zig	+1-1| ... | @@ -15,7 +15,7 @@ const E = enum(u32) { | ... | @@ -15,7 +15,7 @@ const E = enum(u32) { |
| 15 | 15 | ||
| 16 | pub fn main() !void { | 16 | pub fn main() !void { |
| 17 | var e: E = undefined; | 17 | var e: E = undefined; |
| 18 | @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | 18 | @memset(@ptrCast([*]u8, &e)[0..@sizeOf(E)], 0x55); |
| 19 | var n = @tagName(e); | 19 | var n = @tagName(e); |
| 20 | _ = n; | 20 | _ = n; |
| 21 | return error.TestFailed; | 21 | return error.TestFailed; |
test/cases/safety/@tagName on corrupted union value.zig	+1-1| ... | @@ -15,7 +15,7 @@ const U = union(enum(u32)) { | ... | @@ -15,7 +15,7 @@ const U = union(enum(u32)) { |
| 15 | 15 | ||
| 16 | pub fn main() !void { | 16 | pub fn main() !void { |
| 17 | var u: U = undefined; | 17 | var u: U = undefined; |
| 18 | @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | 18 | @memset(@ptrCast([*]u8, &u)[0..@sizeOf(U)], 0x55); |
| 19 | var t: @typeInfo(U).Union.tag_type.? = u; | 19 | var t: @typeInfo(U).Union.tag_type.? = u; |
| 20 | var n = @tagName(t); | 20 | var n = @tagName(t); |
| 21 | _ = n; | 21 | _ = n; |
test/cases/safety/switch on corrupted enum value.zig	+1-1| ... | @@ -15,7 +15,7 @@ const E = enum(u32) { | ... | @@ -15,7 +15,7 @@ const E = enum(u32) { |
| 15 | 15 | ||
| 16 | pub fn main() !void { | 16 | pub fn main() !void { |
| 17 | var e: E = undefined; | 17 | var e: E = undefined; |
| 18 | @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E)); | 18 | @memset(@ptrCast([*]u8, &e)[0..@sizeOf(E)], 0x55); |
| 19 | switch (e) { | 19 | switch (e) { |
| 20 | .X, .Y => @breakpoint(), | 20 | .X, .Y => @breakpoint(), |
| 21 | } | 21 | } |