diff --git a/lib/compiler_rt/memcpy.zig b/lib/compiler_rt/memcpy.zig index 82c41c101e..97188ac65f 100644 --- a/lib/compiler_rt/memcpy.zig +++ b/lib/compiler_rt/memcpy.zig @@ -4,10 +4,29 @@ const builtin = @import("builtin"); comptime { if (builtin.object_format != .c) { - @export(&memcpy, .{ .name = "memcpy", .linkage = common.linkage, .visibility = common.visibility }); + const export_options: std.builtin.ExportOptions = .{ + .name = "memcpy", + .linkage = common.linkage, + .visibility = common.visibility, + }; + + if (builtin.mode == .ReleaseSmall) + @export(&memcpySmall, export_options) + else + @export(&memcpyFast, export_options); } } -fn memcpy(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { +fn memcpySmall(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { + @setRuntimeSafety(builtin.is_test); + + for (0..len) |i| { + dest.?[i] = src.?[i]; + } + + return dest; +} + +fn memcpyFast(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { return @call(.always_inline, @import("memmove.zig").memmove, .{ opt_dest, opt_src, len }); } diff --git a/lib/compiler_rt/memmove.zig b/lib/compiler_rt/memmove.zig index f16abc0e7b..408151e2a3 100644 --- a/lib/compiler_rt/memmove.zig +++ b/lib/compiler_rt/memmove.zig @@ -4,11 +4,37 @@ const builtin = @import("builtin"); comptime { if (builtin.object_format != .c) { - @export(&memmove, .{ .name = "memmove", .linkage = common.linkage, .visibility = common.visibility }); + const export_options: std.builtin.ExportOptions = .{ + .name = "memmove", + .linkage = common.linkage, + .visibility = common.visibility, + }; + + if (builtin.mode == .ReleaseSmall) + @export(&memmoveSmall, export_options) + else + @export(&memmoveFast, export_options); } } -pub fn memmove(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { +fn memmoveSmall(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { + const dest = opt_dest.?; + const src = opt_src.?; + + if (@intFromPtr(dest) < @intFromPtr(src)) { + for (0..len) |i| { + dest[i] = src[i]; + } + } else { + for (0..len) |i| { + dest[len - 1 - i] = src[len - 1 - i]; + } + } + + return dest; +} + +pub fn memmoveFast(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { // a port of https://github.com/facebook/folly/blob/1c8bc50e88804e2a7361a57cd9b551dd10f6c5fd/folly/memcpy.S if (len == 0) { @branchHint(.unlikely);