mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge pull request #11747 from Luukdegram/compiler-rt
compiler_rt: Move mem implementations from c.zig
This commit is contained in:
commit
ce3ffa5e1b
8 changed files with 147 additions and 122 deletions
119
lib/c.zig
119
lib/c.zig
|
|
@ -1,8 +1,6 @@
|
||||||
//! This is Zig's multi-target implementation of libc.
|
//! This is Zig's multi-target implementation of libc.
|
||||||
//! When builtin.link_libc is true, we need to export all the functions and
|
//! When builtin.link_libc is true, we need to export all the functions and
|
||||||
//! provide an entire C API.
|
//! 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 std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
@ -35,13 +33,6 @@ comptime {
|
||||||
@export(clone, .{ .name = "clone" });
|
@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) {
|
if (builtin.link_libc) {
|
||||||
@export(strcmp, .{ .name = "strcmp", .linkage = .Strong });
|
@export(strcmp, .{ .name = "strcmp", .linkage = .Strong });
|
||||||
@export(strncmp, .{ .name = "strncmp", .linkage = .Strong });
|
@export(strncmp, .{ .name = "strncmp", .linkage = .Strong });
|
||||||
|
|
@ -75,116 +66,6 @@ fn wasm_start() callconv(.C) void {
|
||||||
_ = main(0, undefined);
|
_ = 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;
|
var _fltused: c_int = 1;
|
||||||
|
|
||||||
fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {
|
fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {
|
||||||
|
|
|
||||||
|
|
@ -208,4 +208,10 @@ comptime {
|
||||||
_ = @import("compiler_rt/aulldiv.zig");
|
_ = @import("compiler_rt/aulldiv.zig");
|
||||||
_ = @import("compiler_rt/aullrem.zig");
|
_ = @import("compiler_rt/aullrem.zig");
|
||||||
_ = @import("compiler_rt/clear_cache.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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
lib/compiler_rt/bcmp.zig
Normal file
30
lib/compiler_rt/bcmp.zig
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
31
lib/compiler_rt/memcmp.zig
Normal file
31
lib/compiler_rt/memcmp.zig
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
25
lib/compiler_rt/memcpy.zig
Normal file
25
lib/compiler_rt/memcpy.zig
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
25
lib/compiler_rt/memmove.zig
Normal file
25
lib/compiler_rt/memmove.zig
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
30
lib/compiler_rt/memset.zig
Normal file
30
lib/compiler_rt/memset.zig
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -18,9 +18,6 @@ pub fn build(b: *Builder) void {
|
||||||
lib.strip = false;
|
lib.strip = false;
|
||||||
|
|
||||||
const check = lib.checkObject(.wasm);
|
const check = lib.checkObject(.wasm);
|
||||||
check.checkStart("Section import");
|
|
||||||
check.checkNext("entries 1"); // __truncsfhf2 should have been resolved, so only 1 import (compiler-rt's memcpy).
|
|
||||||
|
|
||||||
check.checkStart("Section custom");
|
check.checkStart("Section custom");
|
||||||
check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved
|
check.checkNext("name __truncsfhf2"); // Ensure it was imported and resolved
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue