| 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,8 +1,6 @@ |
| 1 | //! This is Zig's multi-target implementation of libc. | 1 | //! This is Zig's multi-target implementation of libc. |
| 2 | //! When builtin.link_libc is true, we need to export all the functions and | 2 | //! When builtin.link_libc is true, we need to export all the functions and |
| 3 | //! provide an entire C API. | 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 | const std = @import("std"); | 5 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| ... | @@ -35,13 +33,6 @@ comptime { | ... | @@ -35,13 +33,6 @@ comptime { |
| 35 | @export(clone, .{ .name = "clone" }); | 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 | if (builtin.link_libc) { | 36 | if (builtin.link_libc) { |
| 46 | @export(strcmp, .{ .name = "strcmp", .linkage = .Strong }); | 37 | @export(strcmp, .{ .name = "strcmp", .linkage = .Strong }); |
| 47 | @export(strncmp, .{ .name = "strncmp", .linkage = .Strong }); | 38 | @export(strncmp, .{ .name = "strncmp", .linkage = .Strong }); |
| ... | @@ -75,116 +66,6 @@ fn wasm_start() callconv(.C) void { | ... | @@ -75,116 +66,6 @@ fn wasm_start() callconv(.C) void { |
| 75 | _ = main(0, undefined); | 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 | var _fltused: c_int = 1; | 69 | var _fltused: c_int = 1; |
| 189 | 70 | ||
| 190 | fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 { | 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,4 +208,10 @@ comptime { |
| 208 | _ = @import("compiler_rt/aulldiv.zig"); | 208 | _ = @import("compiler_rt/aulldiv.zig"); |
| 209 | _ = @import("compiler_rt/aullrem.zig"); | 209 | _ = @import("compiler_rt/aullrem.zig"); |
| 210 | _ = @import("compiler_rt/clear_cache.zig"); | 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,9 +18,6 @@ pub fn build(b: *Builder) void { |
| 18 | lib.strip = false; | 18 | lib.strip = false; |
| 19 | 19 | ||
| 20 | const check = lib.checkObject(.wasm); | 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 | check.checkStart("Section custom"); | 21 | check.checkStart("Section custom"); |
| 25 | check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved | 22 | check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved |
| 26 | 23 |