Skip to content

add implementations of memcpy et al #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ version = "0.1.0"
rustc-cfg = "0.2.0"
gcc = "0.3.36"

[dependencies]

[dependencies.rlibc]
git = "https://github.com/alexcrichton/rlibc"
optional = true

[dev-dependencies]
quickcheck = "0.3.1"
rand = "0.3.14"
Expand All @@ -26,7 +20,8 @@ c = []
# Mark this crate as the #![compiler_builtins] crate
compiler-builtins = []
default = ["compiler-builtins"]
# Include implementations of memory operations like memcpy
mem = []
rustbuild = ["compiler-builtins"]
weak = ["rlibc/weak"]

[workspace]
4 changes: 4 additions & 0 deletions src/arm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use core::intrinsics;

#[cfg(feature = "mem")]
use mem::{memcpy, memmove, memset};

// NOTE This function and the ones below are implemented using assembly because they using a custom
// calling convention which can't be implemented using a normal Rust function
#[naked]
Expand Down Expand Up @@ -100,6 +103,7 @@ pub extern "C" fn __aeabi_uidiv(a: u32, b: u32) -> u32 {
::int::udiv::__udivsi3(a, b)
}

#[cfg(not(feature = "mem"))]
extern "C" {
fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#![feature(asm)]
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(linkage)]
#![feature(naked_functions)]
#![feature(staged_api)]
#![no_builtins]
Expand Down Expand Up @@ -102,16 +101,16 @@ extern crate compiler_rt;
#[cfg(test)]
extern crate rand;

#[cfg(feature = "weak")]
extern crate rlibc;

#[cfg(test)]
#[macro_use]
mod qc;

pub mod int;
pub mod float;

#[cfg(feature = "mem")]
pub mod mem;

#[cfg(target_arch = "arm")]
pub mod arm;

Expand Down
59 changes: 59 additions & 0 deletions src/mem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8,
src: *const u8,
n: usize)
-> *mut u8 {
let mut i = 0;
while i < n {
*dest.offset(i as isize) = *src.offset(i as isize);
i += 1;
}
dest
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8,
src: *const u8,
n: usize)
-> *mut u8 {
if src < dest as *const u8 {
// copy from end
let mut i = n;
while i != 0 {
i -= 1;
*dest.offset(i as isize) = *src.offset(i as isize);
}
} else {
// copy from beginning
let mut i = 0;
while i < n {
*dest.offset(i as isize) = *src.offset(i as isize);
i += 1;
}
}
dest
}

#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why c is i32? Will it work on all architectures? maybe it should be isize or usize?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be c_int but it's better not to depend on libc, which is where c_int is defined. Right now, c_int is defined as type c_int = i32 in libc.

Will it work on all architectures?

That's a good question. AVR seems to define int as 16-bit. I don't know about MSP430. You probably know that better. It's likely that all these implementations don't work correctly on architectures where sizeof(usize) is neither 32 or 64.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, on MSP430 int is 16bit. And I would like to have a working memset on MSP430. My point is that if you make it isize instead of i32 it will be compatible with all architectures that rust supports AFAIK.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But 64-bit architectures expect c to be i32 (c_int is 32-bit on 64 and 32 bit architectures).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both x86_64 and AArch64 do not care if you pass a 64bit or 32bit value inside their 64bit registers. And the receiving code does cast to i8 anyway.

let mut i = 0;
while i < n {
*s.offset(i as isize) = c as u8;
i += 1;
}
s
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
let mut i = 0;
while i < n {
let a = *s1.offset(i as isize);
let b = *s2.offset(i as isize);
if a != b {
return a as i32 - b as i32;
}
i += 1;
}
0
}