authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-27 14:01:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-28 13:24:43-07:00
log73d3fb9883c1d89fd1460a18f186a1737613bfbc
tree82a217e658c77730704bbaa85bf2857d26e339e5
parent6261c1373168b265047db5704d9d0fd5f2e458f2

C backend: fix ptr comparison of array ptrs when one is null-terminated


4 files changed, 46 insertions(+), 22 deletions(-)

src/codegen/c.zig+1-1
...@@ -3858,7 +3858,7 @@ fn airCmpOp(...@@ -3858,7 +3858,7 @@ fn airCmpOp(
3858 try reap(f, inst, &.{ data.lhs, data.rhs });3858 try reap(f, inst, &.{ data.lhs, data.rhs });
38593859
3860 const rhs_ty = f.air.typeOf(data.rhs);3860 const rhs_ty = f.air.typeOf(data.rhs);
3861 const need_cast = lhs_ty.isSinglePointer() != rhs_ty.isSinglePointer();3861 const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer();
3862 const writer = f.object.writer();3862 const writer = f.object.writer();
3863 const local = try f.allocLocal(inst, inst_ty);3863 const local = try f.allocLocal(inst, inst_ty);
3864 const v = try Vectorize.start(f, inst, writer, lhs_ty);3864 const v = try Vectorize.start(f, inst, writer, lhs_ty);
test/behavior.zig+1
...@@ -177,6 +177,7 @@ test {...@@ -177,6 +177,7 @@ test {
177 _ = @import("behavior/math.zig");177 _ = @import("behavior/math.zig");
178 _ = @import("behavior/maximum_minimum.zig");178 _ = @import("behavior/maximum_minimum.zig");
179 _ = @import("behavior/member_func.zig");179 _ = @import("behavior/member_func.zig");
180 _ = @import("behavior/memcpy.zig");
180 _ = @import("behavior/memset.zig");181 _ = @import("behavior/memset.zig");
181 _ = @import("behavior/merge_error_sets.zig");182 _ = @import("behavior/merge_error_sets.zig");
182 _ = @import("behavior/muladd.zig");183 _ = @import("behavior/muladd.zig");
test/behavior/memcpy.zig created+44
...@@ -0,0 +1,44 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5test "memcpy and memset intrinsics" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9
10 try testMemcpyMemset();
11 try comptime testMemcpyMemset();
12}
13
14fn testMemcpyMemset() !void {
15 var foo: [20]u8 = undefined;
16 var bar: [20]u8 = undefined;
17
18 @memset(&foo, 'A');
19 @memcpy(&bar, &foo);
20
21 try expect(bar[0] == 'A');
22 try expect(bar[11] == 'A');
23 try expect(bar[19] == 'A');
24}
25
26test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
30
31 try testMemcpyBothSinglePtrArrayOneIsNullTerminated();
32 try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated();
33}
34
35fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void {
36 var buf: [100]u8 = undefined;
37 const suffix = "hello";
38 @memcpy(buf[buf.len - suffix.len ..], suffix);
39 try expect(buf[95] == 'h');
40 try expect(buf[96] == 'e');
41 try expect(buf[97] == 'l');
42 try expect(buf[98] == 'l');
43 try expect(buf[99] == 'o');
44}
test/behavior/memset.zig-21
...@@ -142,24 +142,3 @@ test "memset with large array element, comptime known" {...@@ -142,24 +142,3 @@ test "memset with large array element, comptime known" {
142 for (buf[3]) |elem| try expect(elem == 0);142 for (buf[3]) |elem| try expect(elem == 0);
143 for (buf[4]) |elem| try expect(elem == 0);143 for (buf[4]) |elem| try expect(elem == 0);
144}144}
145
146test "memcpy and memset intrinsics" {
147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
150
151 try testMemcpyMemset();
152 try comptime testMemcpyMemset();
153}
154
155fn testMemcpyMemset() !void {
156 var foo: [20]u8 = undefined;
157 var bar: [20]u8 = undefined;
158
159 @memset(&foo, 'A');
160 @memcpy(&bar, &foo);
161
162 try expect(bar[0] == 'A');
163 try expect(bar[11] == 'A');
164 try expect(bar[19] == 'A');
165}