zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 73d3fb9883c1d89fd1460a18f186a1737613bfbc (tree)
parent 6261c1373168b265047db5704d9d0fd5f2e458f2
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Thu, 27 Apr 2023 14:01:16 -0700

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

Diffstat:
Msrc/codegen/c.zig | 2+-
Mtest/behavior.zig | 1+
Atest/behavior/memcpy.zig | 44++++++++++++++++++++++++++++++++++++++++++++
Mtest/behavior/memset.zig | 21---------------------
4 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/src/codegen/c.zig b/src/codegen/c.zig @@ -3858,7 +3858,7 @@ fn airCmpOp( try reap(f, inst, &.{ data.lhs, data.rhs }); const rhs_ty = f.air.typeOf(data.rhs); - const need_cast = lhs_ty.isSinglePointer() != rhs_ty.isSinglePointer(); + const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer(); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, writer, lhs_ty); diff --git a/test/behavior.zig b/test/behavior.zig @@ -177,6 +177,7 @@ test { _ = @import("behavior/math.zig"); _ = @import("behavior/maximum_minimum.zig"); _ = @import("behavior/member_func.zig"); + _ = @import("behavior/memcpy.zig"); _ = @import("behavior/memset.zig"); _ = @import("behavior/merge_error_sets.zig"); _ = @import("behavior/muladd.zig"); diff --git a/test/behavior/memcpy.zig b/test/behavior/memcpy.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const expect = std.testing.expect; + +test "memcpy and memset intrinsics" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + + try testMemcpyMemset(); + try comptime testMemcpyMemset(); +} + +fn testMemcpyMemset() !void { + var foo: [20]u8 = undefined; + var bar: [20]u8 = undefined; + + @memset(&foo, 'A'); + @memcpy(&bar, &foo); + + try expect(bar[0] == 'A'); + try expect(bar[11] == 'A'); + try expect(bar[19] == 'A'); +} + +test "@memcpy with both operands single-ptr-to-array, one is null-terminated" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; + + try testMemcpyBothSinglePtrArrayOneIsNullTerminated(); + try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated(); +} + +fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void { + var buf: [100]u8 = undefined; + const suffix = "hello"; + @memcpy(buf[buf.len - suffix.len ..], suffix); + try expect(buf[95] == 'h'); + try expect(buf[96] == 'e'); + try expect(buf[97] == 'l'); + try expect(buf[98] == 'l'); + try expect(buf[99] == 'o'); +} diff --git a/test/behavior/memset.zig b/test/behavior/memset.zig @@ -142,24 +142,3 @@ test "memset with large array element, comptime known" { for (buf[3]) |elem| try expect(elem == 0); for (buf[4]) |elem| try expect(elem == 0); } - -test "memcpy and memset intrinsics" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - - try testMemcpyMemset(); - try comptime testMemcpyMemset(); -} - -fn testMemcpyMemset() !void { - var foo: [20]u8 = undefined; - var bar: [20]u8 = undefined; - - @memset(&foo, 'A'); - @memcpy(&bar, &foo); - - try expect(bar[0] == 'A'); - try expect(bar[11] == 'A'); - try expect(bar[19] == 'A'); -}