authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-17 18:12:22-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-17 18:12:22-04:00
logce3ffa5e1b30b3ad5fb38639c7e3036d328a598e
treea8850fe839f3166f9d5d4e8f722b44aa4f90c459
parent8aa21ade8cd7aca072d3e41c3f31cee179ec6415
parent74108bb9c0be84004d473f9fdf4cb669f071cfd7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11747 from Luukdegram/compiler-rt

compiler_rt: Move mem implementations from c.zig

8 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 and2//! 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.
64
7const std = @import("std");5const std = @import("std");
8const builtin = @import("builtin");6const 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 }
3735
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}
7768
78fn 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
95fn __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
101fn 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
120fn 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
139fn 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
153test "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
164fn 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
177test "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
188var _fltused: c_int = 1;69var _fltused: c_int = 1;
18970
190fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {71fn 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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4comptime {
5 @export(bcmp, .{ .name = "bcmp", .linkage = common.linkage });
6}
7
8pub 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
21test "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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4comptime {
5 @export(memcmp, .{ .name = "memcmp", .linkage = common.linkage });
6}
7
8pub 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
22test "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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4comptime {
5 @export(memcpy, .{ .name = "memcpy", .linkage = common.linkage });
6}
7
8pub 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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4comptime {
5 @export(memmove, .{ .name = "memmove", .linkage = common.linkage });
6}
7
8pub 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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4comptime {
5 @export(memset, .{ .name = "memset", .linkage = common.linkage });
6 @export(__memset, .{ .name = "__memset", .linkage = common.linkage });
7}
8
9pub 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
26pub 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;
1919
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 resolved22 check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved
2623