diff --git a/Cargo.lock b/Cargo.lock index f84fb01..bc92513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "c" -version = "0.1.0" -dependencies = [ - "libuwuc", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -21,3 +14,10 @@ version = "0.1.0" dependencies = [ "cfg-if", ] + +[[package]] +name = "rawc" +version = "0.1.0" +dependencies = [ + "libuwuc", +] diff --git a/Cargo.toml b/Cargo.toml index 8c4c872..dd2f850 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["libuwuc", "c"] +members = ["libuwuc", "rawc"] resolver = "2" [profile.dev] diff --git a/c/src/lib.rs b/c/src/lib.rs deleted file mode 100644 index eda08d2..0000000 --- a/c/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![no_std] - -mod string; - -// libcore seems to require this symbol, even though it's unused. -#[no_mangle] -fn rust_eh_personality() { - unsafe { - libuwuc::trap!(); - } -} diff --git a/c/src/string.rs b/c/src/string.rs deleted file mode 100644 index 9d9de25..0000000 --- a/c/src/string.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[no_mangle] -pub(crate) unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) { - for i in 0..len { - unsafe { - *ptr.add(i) = constant; - } - } -} - -#[no_mangle] -pub(crate) unsafe extern "C" fn strlen(s: *const u8) -> usize { - libuwuc::mem::strlen(s) -} \ No newline at end of file diff --git a/example-user/Cargo.lock b/example-user/Cargo.lock index a29e252..6930e5d 100644 --- a/example-user/Cargo.lock +++ b/example-user/Cargo.lock @@ -2,13 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "c" -version = "0.1.0" -dependencies = [ - "libuwuc", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -19,8 +12,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "example-user" version = "0.1.0" dependencies = [ - "c", "libuwuc", + "rawc", ] [[package]] @@ -29,3 +22,10 @@ version = "0.1.0" dependencies = [ "cfg-if", ] + +[[package]] +name = "rawc" +version = "0.1.0" +dependencies = [ + "libuwuc", +] diff --git a/example-user/Cargo.toml b/example-user/Cargo.toml index 4261887..10dd892 100644 --- a/example-user/Cargo.toml +++ b/example-user/Cargo.toml @@ -14,5 +14,5 @@ panic = "abort" panic = "abort" [dependencies] -c = { path = "../c" } +rawc = { path = "../rawc" } libuwuc = { path = "../libuwuc" } \ No newline at end of file diff --git a/example-user/src/main.rs b/example-user/src/main.rs index cfa6653..80fade8 100644 --- a/example-user/src/main.rs +++ b/example-user/src/main.rs @@ -6,19 +6,7 @@ use core::ffi::c_char; use libuwuc::{println, utils::SharedThinCstr}; -extern crate c; - -#[panic_handler] -#[cfg(not(test))] -fn handler(arg: &core::panic::PanicInfo) -> ! { - let args = format_args!(""); - let payload = arg.message().unwrap_or(&args); - libuwuc::io::println!("panicked: {payload}"); - if let Some(loc) = arg.location() { - libuwuc::io::println!(" at {}:{}:{}", loc.file(), loc.line(), loc.column()); - } - libuwuc::start::exit(1); -} +extern crate rawc; #[no_mangle] extern "C" fn main(_argc: i32, _argv: *const *const c_char) -> i32 { diff --git a/hello.c b/hello.c new file mode 100644 index 0000000..0cd9260 --- /dev/null +++ b/hello.c @@ -0,0 +1,5 @@ +#include + +int main(int argc, char *argv[]) { + puts("Hello, world!"); +} diff --git a/libuwuc/src/io/mod.rs b/libuwuc/src/io/mod.rs index 1db3bd4..0edcb30 100644 --- a/libuwuc/src/io/mod.rs +++ b/libuwuc/src/io/mod.rs @@ -1,25 +1,19 @@ +use core::ffi::c_char; + use crate::sys::syscall; pub const STDIN: i32 = 0; pub const STDOUT: i32 = 1; pub const STDERR: i32 = 2; +pub const EOF: i32 = -1; + #[doc(hidden)] pub struct Printer; impl core::fmt::Write for Printer { - fn write_str(&mut self, mut s: &str) -> core::fmt::Result { - unsafe { - while s.len() > 0 { - let result = - syscall::syscall!(syscall::SYS_WRITE, STDOUT, s.as_ptr(), s.len()) as i64; - if result < 0 { - return Err(core::fmt::Error); - } - s = &s[(result as usize)..]; - } - } - Ok(()) + fn write_str(&mut self, s: &str) -> core::fmt::Result { + unsafe { write_all(STDOUT, s.as_bytes()).map_err(|_| core::fmt::Error) } } } @@ -33,3 +27,27 @@ macro_rules! println { }; } pub use println; + +pub unsafe fn write_all(fd: i32, mut buf: &[u8]) -> Result<(), i64> { + while buf.len() > 0 { + let result = syscall::syscall!(syscall::SYS_WRITE, fd, buf.as_ptr(), buf.len()) as i64; + if result < 0 { + return Err(result); + } + buf = &buf[(result as usize)..]; + } + Ok(()) +} + +pub unsafe fn puts(s: *const c_char) -> i32 { + let len = crate::mem::strlen(s as _); + let result = write_all(STDOUT, core::slice::from_raw_parts(s as _, len)); + if result.is_err() { + return EOF; + } + let result = write_all(STDOUT, &[b'\n']); + if result.is_err() { + return EOF; + } + 1 +} diff --git a/libuwuc/src/mem.rs b/libuwuc/src/mem.rs index 82a57ad..d6e0849 100644 --- a/libuwuc/src/mem.rs +++ b/libuwuc/src/mem.rs @@ -7,6 +7,30 @@ pub unsafe fn memset(ptr: *mut u8, constant: u8, len: usize) { } } +#[inline] +pub unsafe fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 { + for i in 0..size { + dest.add(i).write(src.add(i).read()); + } + + dest +} + +#[inline] +pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 { + for i in 0..size { + let a = s1.add(i).read(); + let b = s2.add(i).read(); + + let cmp = a.cmp(&b) as i8; + if cmp != 0 { + return cmp as i32; + } + } + + 0 +} + #[inline] pub unsafe fn strlen(mut s: *const u8) -> usize { let mut len = 0; diff --git a/c/Cargo.toml b/rawc/Cargo.toml similarity index 80% rename from c/Cargo.toml rename to rawc/Cargo.toml index 1bf245a..c54d76a 100644 --- a/c/Cargo.toml +++ b/rawc/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "c" +name = "rawc" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -crate-type = ["rlib"] +crate-type = ["staticlib", "rlib"] [dependencies] diff --git a/rawc/src/lib.rs b/rawc/src/lib.rs new file mode 100644 index 0000000..a773553 --- /dev/null +++ b/rawc/src/lib.rs @@ -0,0 +1,25 @@ +#![no_std] +#![feature(panic_info_message)] + +mod stdio; +mod string; + +// libcore seems to require this symbol, even though it's unused. +#[no_mangle] +fn rust_eh_personality() { + unsafe { + libuwuc::trap!(); + } +} + +#[panic_handler] +#[cfg(not(test))] +fn handler(arg: &core::panic::PanicInfo) -> ! { + let args = format_args!(""); + let payload = arg.message().unwrap_or(&args); + libuwuc::io::println!("panicked: {payload}"); + if let Some(loc) = arg.location() { + libuwuc::io::println!(" at {}:{}:{}", loc.file(), loc.line(), loc.column()); + } + libuwuc::start::exit(1); +} diff --git a/rawc/src/stdio.rs b/rawc/src/stdio.rs new file mode 100644 index 0000000..16981ae --- /dev/null +++ b/rawc/src/stdio.rs @@ -0,0 +1,6 @@ +use core::ffi::c_char; + +#[no_mangle] +pub unsafe extern "C" fn puts(s: *const c_char) -> i32 { + libuwuc::io::puts(s) +} diff --git a/rawc/src/string.rs b/rawc/src/string.rs new file mode 100644 index 0000000..c98b8b7 --- /dev/null +++ b/rawc/src/string.rs @@ -0,0 +1,25 @@ +#[no_mangle] +pub unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) { + libuwuc::mem::memset(ptr, constant, len) +} + +#[no_mangle] +pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 { + libuwuc::mem::memcpy(dest, src, size) +} + +#[no_mangle] +pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 { + libuwuc::mem::memcmp(s1, s2, size) +} + + +#[no_mangle] +pub unsafe fn bcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 { + libuwuc::mem::memcmp(s1, s2, size) +} + +#[no_mangle] +pub unsafe extern "C" fn strlen(s: *const u8) -> usize { + libuwuc::mem::strlen(s) +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..c8ef6c2 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2023-09-30" diff --git a/shell.nix b/shell.nix index 6fa913e..b461ab8 100644 --- a/shell.nix +++ b/shell.nix @@ -1,6 +1,7 @@ { pkgs ? import { } }: pkgs.mkShell { buildInputs = with pkgs; [ rustup + gcc ]; shellHook = '' export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin diff --git a/test_c.sh b/test_c.sh new file mode 100755 index 0000000..37aa8c7 --- /dev/null +++ b/test_c.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +cargo build +./uwuc-gcc hello.c -o target/hello +./target/hello diff --git a/uwuc-gcc b/uwuc-gcc new file mode 100755 index 0000000..a3839e1 --- /dev/null +++ b/uwuc-gcc @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +args=("-nodefaultlibs" "-nostdlib" "-L${SCRIPT_DIR}/target/debug" "-lrawc") + +exec gcc "$@" "${args[@]}"