Commit f5edaa96dd

Luuk de Gram <luuk@degram.dev>
2022-05-28 15:42:05
compiler_rt: Move mem implementations from c.zig
This moves functions that LLVM generates calls to, to the compiler_rt implementation itself, rather than c.zig. This is a prerequisite for native backends to link with compiler-rt. This also allows native backends to generate calls to `memcpy` and the like.
1 parent 8bb2e96
lib/compiler_rt/bcmp.zig
@@ -0,0 +1,30 @@
+const std = @import("std");
+const common = @import("./common.zig");
+
+comptime {
+    @export(bcmp, .{ .name = "bcmp", .linkage = common.linkage });
+}
+
+pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int {
+    @setRuntimeSafety(false);
+
+    var index: usize = 0;
+    while (index != n) : (index += 1) {
+        if (vl[index] != vr[index]) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+test "bcmp" {
+    const base_arr = &[_]u8{ 1, 1, 1 };
+    const arr1 = &[_]u8{ 1, 1, 1 };
+    const arr2 = &[_]u8{ 1, 0, 1 };
+    const arr3 = &[_]u8{ 1, 2, 1 };
+
+    try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
+    try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0);
+    try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0);
+}
lib/compiler_rt/memcmp.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+const common = @import("./common.zig");
+
+comptime {
+    @export(memcmp, .{ .name = "memcmp", .linkage = common.linkage });
+}
+
+pub fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int {
+    @setRuntimeSafety(false);
+
+    var index: usize = 0;
+    while (index != n) : (index += 1) {
+        const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]);
+        if (compare_val != 0) {
+            return compare_val;
+        }
+    }
+
+    return 0;
+}
+
+test "memcmp" {
+    const base_arr = &[_]u8{ 1, 1, 1 };
+    const arr1 = &[_]u8{ 1, 1, 1 };
+    const arr2 = &[_]u8{ 1, 0, 1 };
+    const arr3 = &[_]u8{ 1, 2, 1 };
+
+    try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
+    try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0);
+    try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0);
+}
lib/compiler_rt/memcpy.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+const common = @import("./common.zig");
+
+comptime {
+    @export(memcpy, .{ .name = "memcpy", .linkage = common.linkage });
+}
+
+pub fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
+    @setRuntimeSafety(false);
+
+    if (len != 0) {
+        var d = dest.?;
+        var s = src.?;
+        var n = len;
+        while (true) {
+            d[0] = s[0];
+            n -= 1;
+            if (n == 0) break;
+            d += 1;
+            s += 1;
+        }
+    }
+
+    return dest;
+}
lib/compiler_rt/memmove.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+const common = @import("./common.zig");
+
+comptime {
+    @export(memmove, .{ .name = "memmove", .linkage = common.linkage });
+}
+
+pub fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 {
+    @setRuntimeSafety(false);
+
+    if (@ptrToInt(dest) < @ptrToInt(src)) {
+        var index: usize = 0;
+        while (index != n) : (index += 1) {
+            dest.?[index] = src.?[index];
+        }
+    } else {
+        var index = n;
+        while (index != 0) {
+            index -= 1;
+            dest.?[index] = src.?[index];
+        }
+    }
+
+    return dest;
+}
lib/compiler_rt/memset.zig
@@ -0,0 +1,30 @@
+const std = @import("std");
+const common = @import("./common.zig");
+
+comptime {
+    @export(memset, .{ .name = "memset", .linkage = common.linkage });
+    @export(__memset, .{ .name = "__memset", .linkage = common.linkage });
+}
+
+pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
+    @setRuntimeSafety(false);
+
+    if (len != 0) {
+        var d = dest.?;
+        var n = len;
+        while (true) {
+            d[0] = c;
+            n -= 1;
+            if (n == 0) break;
+            d += 1;
+        }
+    }
+
+    return dest;
+}
+
+pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
+    if (dest_n < n)
+        @panic("buffer overflow");
+    return memset(dest, c, n);
+}
lib/c.zig
@@ -1,8 +1,6 @@
 //! This is Zig's multi-target implementation of libc.
 //! When builtin.link_libc is true, we need to export all the functions and
 //! provide an entire C API.
-//! Otherwise, only the functions which LLVM generates calls to need to be generated,
-//! such as memcpy, memset, and some math functions.
 
 const std = @import("std");
 const builtin = @import("builtin");
@@ -35,13 +33,6 @@ comptime {
         @export(clone, .{ .name = "clone" });
     }
 
-    @export(memset, .{ .name = "memset", .linkage = .Strong });
-    @export(__memset, .{ .name = "__memset", .linkage = .Strong });
-    @export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
-    @export(memmove, .{ .name = "memmove", .linkage = .Strong });
-    @export(memcmp, .{ .name = "memcmp", .linkage = .Strong });
-    @export(bcmp, .{ .name = "bcmp", .linkage = .Strong });
-
     if (builtin.link_libc) {
         @export(strcmp, .{ .name = "strcmp", .linkage = .Strong });
         @export(strncmp, .{ .name = "strncmp", .linkage = .Strong });
@@ -75,116 +66,6 @@ fn wasm_start() callconv(.C) void {
     _ = main(0, undefined);
 }
 
-fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
-    @setRuntimeSafety(false);
-
-    if (len != 0) {
-        var d = dest.?;
-        var n = len;
-        while (true) {
-            d[0] = c;
-            n -= 1;
-            if (n == 0) break;
-            d += 1;
-        }
-    }
-
-    return dest;
-}
-
-fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
-    if (dest_n < n)
-        @panic("buffer overflow");
-    return memset(dest, c, n);
-}
-
-fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
-    @setRuntimeSafety(false);
-
-    if (len != 0) {
-        var d = dest.?;
-        var s = src.?;
-        var n = len;
-        while (true) {
-            d[0] = s[0];
-            n -= 1;
-            if (n == 0) break;
-            d += 1;
-            s += 1;
-        }
-    }
-
-    return dest;
-}
-
-fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 {
-    @setRuntimeSafety(false);
-
-    if (@ptrToInt(dest) < @ptrToInt(src)) {
-        var index: usize = 0;
-        while (index != n) : (index += 1) {
-            dest.?[index] = src.?[index];
-        }
-    } else {
-        var index = n;
-        while (index != 0) {
-            index -= 1;
-            dest.?[index] = src.?[index];
-        }
-    }
-
-    return dest;
-}
-
-fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int {
-    @setRuntimeSafety(false);
-
-    var index: usize = 0;
-    while (index != n) : (index += 1) {
-        const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]);
-        if (compare_val != 0) {
-            return compare_val;
-        }
-    }
-
-    return 0;
-}
-
-test "memcmp" {
-    const base_arr = &[_]u8{ 1, 1, 1 };
-    const arr1 = &[_]u8{ 1, 1, 1 };
-    const arr2 = &[_]u8{ 1, 0, 1 };
-    const arr3 = &[_]u8{ 1, 2, 1 };
-
-    try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
-    try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0);
-    try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0);
-}
-
-fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int {
-    @setRuntimeSafety(false);
-
-    var index: usize = 0;
-    while (index != n) : (index += 1) {
-        if (vl[index] != vr[index]) {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-test "bcmp" {
-    const base_arr = &[_]u8{ 1, 1, 1 };
-    const arr1 = &[_]u8{ 1, 1, 1 };
-    const arr2 = &[_]u8{ 1, 0, 1 };
-    const arr3 = &[_]u8{ 1, 2, 1 };
-
-    try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
-    try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0);
-    try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0);
-}
-
 var _fltused: c_int = 1;
 
 fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {
lib/compiler_rt.zig
@@ -198,4 +198,10 @@ comptime {
     _ = @import("compiler_rt/aulldiv.zig");
     _ = @import("compiler_rt/aullrem.zig");
     _ = @import("compiler_rt/clear_cache.zig");
+
+    _ = @import("compiler_rt/memcpy.zig");
+    _ = @import("compiler_rt/memset.zig");
+    _ = @import("compiler_rt/memmove.zig");
+    _ = @import("compiler_rt/cmp.zig");
+    _ = @import("compiler_rt/bcmp.zig");
 }