| author | |
| committer | |
| log | ce3ffa5e1b30b3ad5fb38639c7e3036d328a598e |
| tree | a8850fe839f3166f9d5d4e8f722b44aa4f90c459 |
| parent | 8aa21ade8cd7aca072d3e41c3f31cee179ec6415 |
| parent | 74108bb9c0be84004d473f9fdf4cb669f071cfd7 |
| signature |
compiler_rt: Move mem implementations from c.zig8 files changed, 147 insertions(+), 122 deletions(-)
lib/c.zig-119| ... | ... | @@ -1,8 +1,6 @@ |
| 1 | 1 | //! This is Zig's multi-target implementation of libc. |
| 2 | 2 | //! When builtin.link_libc is true, we need to export all the functions and |
| 3 | 3 | //! provide an entire C API. |
| 4 | //! Otherwise, only the functions which LLVM generates calls to need to be generated, | |
| 5 | //! such as memcpy, memset, and some math functions. | |
| 6 | 4 | |
| 7 | 5 | const std = @import("std"); |
| 8 | 6 | const builtin = @import("builtin"); |
| ... | ... | @@ -35,13 +33,6 @@ comptime { |
| 35 | 33 | @export(clone, .{ .name = "clone" }); |
| 36 | 34 | } |
| 37 | 35 | |
| 38 | @export(memset, .{ .name = "memset", .linkage = .Strong }); | |
| 39 | @export(__memset, .{ .name = "__memset", .linkage = .Strong }); | |
| 40 | @export(memcpy, .{ .name = "memcpy", .linkage = .Strong }); | |
| 41 | @export(memmove, .{ .name = "memmove", .linkage = .Strong }); | |
| 42 | @export(memcmp, .{ .name = "memcmp", .linkage = .Strong }); | |
| 43 | @export(bcmp, .{ .name = "bcmp", .linkage = .Strong }); | |
| 44 | ||
| 45 | 36 | if (builtin.link_libc) { |
| 46 | 37 | @export(strcmp, .{ .name = "strcmp", .linkage = .Strong }); |
| 47 | 38 | @export(strncmp, .{ .name = "strncmp", .linkage = .Strong }); |
| ... | ... | @@ -75,116 +66,6 @@ fn wasm_start() callconv(.C) void { |
| 75 | 66 | _ = main(0, undefined); |
| 76 | 67 | } |
| 77 | 68 | |
| 78 | fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 { | |
| 79 | @setRuntimeSafety(false); | |
| 80 | ||
| 81 | if (len != 0) { | |
| 82 | var d = dest.?; | |
| 83 | var n = len; | |
| 84 | while (true) { | |
| 85 | d[0] = c; | |
| 86 | n -= 1; | |
| 87 | if (n == 0) break; | |
| 88 | d += 1; | |
| 89 | } | |
| 90 | } | |
| 91 | ||
| 92 | return dest; | |
| 93 | } | |
| 94 | ||
| 95 | fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 { | |
| 96 | if (dest_n < n) | |
| 97 | @panic("buffer overflow"); | |
| 98 | return memset(dest, c, n); | |
| 99 | } | |
| 100 | ||
| 101 | fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { | |
| 102 | @setRuntimeSafety(false); | |
| 103 | ||
| 104 | if (len != 0) { | |
| 105 | var d = dest.?; | |
| 106 | var s = src.?; | |
| 107 | var n = len; | |
| 108 | while (true) { | |
| 109 | d[0] = s[0]; | |
| 110 | n -= 1; | |
| 111 | if (n == 0) break; | |
| 112 | d += 1; | |
| 113 | s += 1; | |
| 114 | } | |
| 115 | } | |
| 116 | ||
| 117 | return dest; | |
| 118 | } | |
| 119 | ||
| 120 | fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 { | |
| 121 | @setRuntimeSafety(false); | |
| 122 | ||
| 123 | if (@ptrToInt(dest) < @ptrToInt(src)) { | |
| 124 | var index: usize = 0; | |
| 125 | while (index != n) : (index += 1) { | |
| 126 | dest.?[index] = src.?[index]; | |
| 127 | } | |
| 128 | } else { | |
| 129 | var index = n; | |
| 130 | while (index != 0) { | |
| 131 | index -= 1; | |
| 132 | dest.?[index] = src.?[index]; | |
| 133 | } | |
| 134 | } | |
| 135 | ||
| 136 | return dest; | |
| 137 | } | |
| 138 | ||
| 139 | fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int { | |
| 140 | @setRuntimeSafety(false); | |
| 141 | ||
| 142 | var index: usize = 0; | |
| 143 | while (index != n) : (index += 1) { | |
| 144 | const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]); | |
| 145 | if (compare_val != 0) { | |
| 146 | return compare_val; | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | return 0; | |
| 151 | } | |
| 152 | ||
| 153 | test "memcmp" { | |
| 154 | const base_arr = &[_]u8{ 1, 1, 1 }; | |
| 155 | const arr1 = &[_]u8{ 1, 1, 1 }; | |
| 156 | const arr2 = &[_]u8{ 1, 0, 1 }; | |
| 157 | const arr3 = &[_]u8{ 1, 2, 1 }; | |
| 158 | ||
| 159 | try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); | |
| 160 | try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0); | |
| 161 | try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0); | |
| 162 | } | |
| 163 | ||
| 164 | fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int { | |
| 165 | @setRuntimeSafety(false); | |
| 166 | ||
| 167 | var index: usize = 0; | |
| 168 | while (index != n) : (index += 1) { | |
| 169 | if (vl[index] != vr[index]) { | |
| 170 | return 1; | |
| 171 | } | |
| 172 | } | |
| 173 | ||
| 174 | return 0; | |
| 175 | } | |
| 176 | ||
| 177 | test "bcmp" { | |
| 178 | const base_arr = &[_]u8{ 1, 1, 1 }; | |
| 179 | const arr1 = &[_]u8{ 1, 1, 1 }; | |
| 180 | const arr2 = &[_]u8{ 1, 0, 1 }; | |
| 181 | const arr3 = &[_]u8{ 1, 2, 1 }; | |
| 182 | ||
| 183 | try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); | |
| 184 | try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0); | |
| 185 | try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0); | |
| 186 | } | |
| 187 | ||
| 188 | 69 | var _fltused: c_int = 1; |
| 189 | 70 | |
| 190 | 71 | fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 { |
lib/compiler_rt.zig+6| ... | ... | @@ -208,4 +208,10 @@ comptime { |
| 208 | 208 | _ = @import("compiler_rt/aulldiv.zig"); |
| 209 | 209 | _ = @import("compiler_rt/aullrem.zig"); |
| 210 | 210 | _ = @import("compiler_rt/clear_cache.zig"); |
| 211 | ||
| 212 | _ = @import("compiler_rt/memcpy.zig"); | |
| 213 | _ = @import("compiler_rt/memset.zig"); | |
| 214 | _ = @import("compiler_rt/memmove.zig"); | |
| 215 | _ = @import("compiler_rt/cmp.zig"); | |
| 216 | _ = @import("compiler_rt/bcmp.zig"); | |
| 211 | 217 | } |
lib/compiler_rt/bcmp.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | @export(bcmp, .{ .name = "bcmp", .linkage = common.linkage }); | |
| 6 | } | |
| 7 | ||
| 8 | pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int { | |
| 9 | @setRuntimeSafety(false); | |
| 10 | ||
| 11 | var index: usize = 0; | |
| 12 | while (index != n) : (index += 1) { | |
| 13 | if (vl[index] != vr[index]) { | |
| 14 | return 1; | |
| 15 | } | |
| 16 | } | |
| 17 | ||
| 18 | return 0; | |
| 19 | } | |
| 20 | ||
| 21 | test "bcmp" { | |
| 22 | const base_arr = &[_]u8{ 1, 1, 1 }; | |
| 23 | const arr1 = &[_]u8{ 1, 1, 1 }; | |
| 24 | const arr2 = &[_]u8{ 1, 0, 1 }; | |
| 25 | const arr3 = &[_]u8{ 1, 2, 1 }; | |
| 26 | ||
| 27 | try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); | |
| 28 | try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0); | |
| 29 | try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0); | |
| 30 | } |
lib/compiler_rt/memcmp.zig created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | @export(memcmp, .{ .name = "memcmp", .linkage = common.linkage }); | |
| 6 | } | |
| 7 | ||
| 8 | pub fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int { | |
| 9 | @setRuntimeSafety(false); | |
| 10 | ||
| 11 | var index: usize = 0; | |
| 12 | while (index != n) : (index += 1) { | |
| 13 | const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]); | |
| 14 | if (compare_val != 0) { | |
| 15 | return compare_val; | |
| 16 | } | |
| 17 | } | |
| 18 | ||
| 19 | return 0; | |
| 20 | } | |
| 21 | ||
| 22 | test "memcmp" { | |
| 23 | const base_arr = &[_]u8{ 1, 1, 1 }; | |
| 24 | const arr1 = &[_]u8{ 1, 1, 1 }; | |
| 25 | const arr2 = &[_]u8{ 1, 0, 1 }; | |
| 26 | const arr3 = &[_]u8{ 1, 2, 1 }; | |
| 27 | ||
| 28 | try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); | |
| 29 | try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0); | |
| 30 | try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0); | |
| 31 | } |
lib/compiler_rt/memcpy.zig created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | @export(memcpy, .{ .name = "memcpy", .linkage = common.linkage }); | |
| 6 | } | |
| 7 | ||
| 8 | pub fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 { | |
| 9 | @setRuntimeSafety(false); | |
| 10 | ||
| 11 | if (len != 0) { | |
| 12 | var d = dest.?; | |
| 13 | var s = src.?; | |
| 14 | var n = len; | |
| 15 | while (true) { | |
| 16 | d[0] = s[0]; | |
| 17 | n -= 1; | |
| 18 | if (n == 0) break; | |
| 19 | d += 1; | |
| 20 | s += 1; | |
| 21 | } | |
| 22 | } | |
| 23 | ||
| 24 | return dest; | |
| 25 | } |
lib/compiler_rt/memmove.zig created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | @export(memmove, .{ .name = "memmove", .linkage = common.linkage }); | |
| 6 | } | |
| 7 | ||
| 8 | pub fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 { | |
| 9 | @setRuntimeSafety(false); | |
| 10 | ||
| 11 | if (@ptrToInt(dest) < @ptrToInt(src)) { | |
| 12 | var index: usize = 0; | |
| 13 | while (index != n) : (index += 1) { | |
| 14 | dest.?[index] = src.?[index]; | |
| 15 | } | |
| 16 | } else { | |
| 17 | var index = n; | |
| 18 | while (index != 0) { | |
| 19 | index -= 1; | |
| 20 | dest.?[index] = src.?[index]; | |
| 21 | } | |
| 22 | } | |
| 23 | ||
| 24 | return dest; | |
| 25 | } |
lib/compiler_rt/memset.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | @export(memset, .{ .name = "memset", .linkage = common.linkage }); | |
| 6 | @export(__memset, .{ .name = "__memset", .linkage = common.linkage }); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 { | |
| 10 | @setRuntimeSafety(false); | |
| 11 | ||
| 12 | if (len != 0) { | |
| 13 | var d = dest.?; | |
| 14 | var n = len; | |
| 15 | while (true) { | |
| 16 | d[0] = c; | |
| 17 | n -= 1; | |
| 18 | if (n == 0) break; | |
| 19 | d += 1; | |
| 20 | } | |
| 21 | } | |
| 22 | ||
| 23 | return dest; | |
| 24 | } | |
| 25 | ||
| 26 | pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 { | |
| 27 | if (dest_n < n) | |
| 28 | @panic("buffer overflow"); | |
| 29 | return memset(dest, c, n); | |
| 30 | } |
test/link/wasm/archive/build.zig-3| ... | ... | @@ -18,9 +18,6 @@ pub fn build(b: *Builder) void { |
| 18 | 18 | lib.strip = false; |
| 19 | 19 | |
| 20 | 20 | const check = lib.checkObject(.wasm); |
| 21 | check.checkStart("Section import"); | |
| 22 | check.checkNext("entries 1"); // __truncsfhf2 should have been resolved, so only 1 import (compiler-rt's memcpy). | |
| 23 | ||
| 24 | 21 | check.checkStart("Section custom"); |
| 25 | 22 | check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved |
| 26 | 23 |