do I hate my life? idek

This commit is contained in:
2024-12-07 21:12:26 +01:00
parent d98b0c3a42
commit 52b1834520
2 changed files with 267 additions and 25 deletions

15
2024/04/p1/build.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euxo pipefail
rustup run nightly rustc \
--target x86_64-unknown-none \
-Crelocation-model=static \
\
-Copt-level=3 \
-Ctarget-cpu=native \
-Cpanic=abort \
-Cstrip=symbols \
-Coverflow_checks=n \
-Clto \
\
$* -o main main.rs

View File

@@ -1,30 +1,255 @@
use std::{
cmp,
fs::File,
io::Read,
time::{Duration, Instant},
};
#![no_std]
#![no_main]
#![feature(naked_functions)]
#![allow(static_mut_refs)]
fn main() -> std::io::Result<()> {
let args: Vec<_> = std::env::args().collect();
let filename = &args[1];
let runs: u32 = args[2]
use core::{
arch::{asm, naked_asm},
cmp,
ffi::CStr,
fmt::{self, Debug, Write},
mem, ops,
panic::PanicInfo,
usize,
};
// use std::{fs::File, io::Read};
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct CInstant {
secs: i64, // time_t
nanos: i64, // long
}
impl CInstant {
fn now() -> Self {
let clockid: isize = 1; // CLOCK_MONOTONIC (non-jumping-backwards uptime)
let instant = unsafe {
let mut instant: Self = mem::zeroed();
let mut result: isize;
asm!(
"syscall",
in("rax") 228,
in("rsi") &mut instant,
in("rdi") clockid,
lateout("rax") result,
out("rcx") _,
out("r11") _,
options(nostack)
);
if result < 0 {
Err(result)
} else {
Ok(instant)
}
};
instant.expect("cant even trust syscalls on stack nowadays")
}
pub fn as_nanos(self) -> i128 {
(self.secs as i128) * 1_000_000_000 + (self.nanos as i128)
}
}
impl ops::Sub for CInstant {
type Output = CDuration;
fn sub(self, rhs: Self) -> Self::Output {
CDuration::from(self.as_nanos() - rhs.as_nanos())
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct CDuration {
pub nanos: i128,
}
const IS_SUB_UNITS: &[char] = &['n', 'μ', 'm'];
impl Debug for CDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut i = 0;
let max_idx = 3;
let mut amount = self.nanos;
while amount >= 1000 && i < max_idx {
amount /= 1000;
i += 1;
}
write!(f, "{amount}")?;
if i != 3 {
write!(f, "{}", IS_SUB_UNITS[i])?;
}
write!(f, "s")
}
}
impl CDuration {
pub const ZERO: CDuration = CDuration::from(0);
pub const MAX: CDuration = CDuration::from(i128::MAX);
pub const fn from(nanos: i128) -> Self {
Self { nanos }
}
}
impl ops::DivAssign<u32> for CDuration {
fn div_assign(&mut self, rhs: u32) {
self.nanos /= rhs as i128
}
}
impl ops::Div<u32> for CDuration {
type Output = CDuration;
fn div(mut self, rhs: u32) -> Self::Output {
self /= rhs;
self
}
}
impl ops::AddAssign for CDuration {
fn add_assign(&mut self, rhs: Self) {
self.nanos += rhs.nanos;
}
}
impl ops::Neg for CDuration {
type Output = Self;
fn neg(mut self) -> Self::Output {
self.nanos = -self.nanos;
self
}
}
// FD
struct FDWriter(usize);
impl FDWriter {
pub const fn from_fd(fd: usize) -> Self {
Self(fd)
}
}
impl Write for FDWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
let result: isize;
asm!(
"syscall",
in("rax") 1, // write
in("rdi") self.0, // fd
in("rsi") s.as_ptr() as *const u8, // *data
in("rdx") s.as_bytes().len(), // data len
lateout("rax") result,
out("rcx") _,
out("r11") _,
options(nostack)
);
if result < 0 {
Err(fmt::Error)
} else {
Ok(())
}
}
}
}
#[naked]
#[no_mangle]
pub extern "C" fn _start() {
unsafe {
naked_asm!(
"mov {0}, rsp",
"jmp {1}",
sym STACK_START,
sym main
);
}
}
static mut ARGC: usize = 1;
static mut STACK_START: *const () = unsafe { mem::zeroed() };
fn get_arg(idx: usize) -> Option<&'static CStr> {
unsafe {
if idx >= ARGC {
return None;
}
let ptr = ((STACK_START as usize) + (idx * 8) + 8) as *const *const i8;
let cstr = core::ffi::CStr::from_ptr(*ptr);
Some(cstr)
}
}
pub fn exit(code: isize) -> ! {
unsafe {
asm!(
"syscall",
in("rax") 60,
in("rdi") code,
options(nostack, noreturn)
);
}
}
static mut STDOUT: FDWriter = FDWriter::from_fd(1);
static mut STDERR: FDWriter = FDWriter::from_fd(2);
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
unsafe {
_ = writeln!(&mut STDERR, "\x1b[1;31m{info:?}\x1b[0m");
}
exit(1);
}
pub fn unsafe_sized_slice_collect<T, I: Iterator<Item = T>>(slice: &mut [T], iter: I) -> usize {
let mut i = 0;
for e in iter {
slice[i] = e;
i += 1;
}
i
}
pub extern "C" fn main() -> ! {
unsafe {
ARGC = *(STACK_START as *const usize);
}
// let args: Vec<_> = std::env::args().collect();
// let filename = &args[1];
let runs: u32 = get_arg(1)
.expect("no arg 1")
.to_str()
.expect("invalid string encoding")
.parse()
.expect("did not receive a number as `runs` argument");
let mut contents = vec![];
let mut file = File::open(filename)?;
file.read_to_end(&mut contents)?;
let lines: Vec<_> = contents.split(|&b| b == b'\n').collect();
// let mut contents = vec![];
// let mut file = File::open(filename)?;
// file.read_to_end(&mut contents)?;
let contents: &[u8] = include_bytes!("../input.txt");
let mut max = Duration::ZERO;
let mut avg = Duration::ZERO;
let mut min = Duration::MAX;
let result = run(&lines);
let mut lines: [&[u8]; 1024] = [&[]; 1024];
let len = unsafe_sized_slice_collect(&mut lines, contents.split(|&b| b == b'\n'));
let mut max = CDuration::ZERO;
let mut avg = CDuration::ZERO;
let mut min = CDuration::MAX;
_ = writeln!(
unsafe { &mut STDOUT },
"\x1b[0;1;31;43m[W]\x1b[0;1;33m syscall time {:?}\x1b[0m",
-(CInstant::now() - CInstant::now())
);
let result = run(&lines, len);
for i in 0..runs {
let a = Instant::now();
let run_result = run(&lines);
let b = Instant::now();
let a = CInstant::now();
let run_result = run(&lines, len);
let b = CInstant::now();
if result != run_result {
panic!(
"supposed result is {} but this run got {} after {} runs",
@@ -38,13 +263,15 @@ fn main() -> std::io::Result<()> {
avg += d / runs;
}
println!("\x1b[0;34mtotal \x1b[1;33m{result}\x1b[0;34m\n runs \x1b[1;33m{runs:?}\x1b[0;34m\n avg. \x1b[1;35m{avg:?}\x1b[0;34m\n max. \x1b[1;31m{max:?}\x1b[0;34m\n min. \x1b[1;32m{min:?}\x1b[0m");
Ok(())
_ = writeln!(unsafe { &mut STDOUT }, "\x1b[0;34mtotal \x1b[1;33m{result}\x1b[0;34m\n runs \x1b[1;33m{runs:?}\x1b[0;34m\n avg. \x1b[1;35m{avg:?}\x1b[0;34m\n max. \x1b[1;31m{max:?}\x1b[0;34m\n min. \x1b[1;32m{min:?}\x1b[0m");
exit(0);
}
fn run(lines: &[&[u8]]) -> usize {
fn run(lines: &[&[u8]], len: usize) -> usize {
let mut t = 0;
for (i, ln) in lines.iter().enumerate() {
for i in 0..len {
let ln = lines[i];
for (j, &ch) in ln.iter().enumerate() {
if ch == b'X' {
for dir in [