#![no_core] #![no_main] #![feature(no_core, lang_items, auto_traits)] #![allow(internal_features)] // These three marker traits are the minimum language items needed when core is // not linked. They are compiler contracts, not a replacement for core. #[lang = "pointee_sized"] trait PointeeSized {} #[lang = "meta_sized"] trait MetaSized: PointeeSized {} #[lang = "sized"] trait Sized: MetaSized {} #[lang = "copy"] trait Copy {} #[lang = "freeze"] unsafe auto trait Freeze {} #[lang = "eh_personality"] extern "C" fn eh_personality() {} #[lang = "panic_info"] struct PanicInfo; #[lang = "panic_impl"] fn panic_impl(_: &PanicInfo) -> ! { loop {} } #[lang = "panic_cannot_unwind"] fn panic_cannot_unwind() -> ! { loop {} } #[cfg(unix)] unsafe extern "C" { fn write(fd: i32, buffer: *const u8, count: usize) -> isize; } #[cfg(windows)] unsafe extern "system" { fn GetStdHandle(which: u32) -> *mut u8; fn WriteFile( handle: *mut u8, buffer: *const u8, count: u32, written: *mut u32, overlapped: *mut u8, ) -> i32; fn ExitProcess(status: u32) -> !; } // A string slice is a (pointer, length) pair. This keeps the public helper // ergonomic without importing core just to call str::as_ptr and str::len. #[repr(C)] union StringParts<'a> { string: &'a str, bytes: (*const u8, usize), } fn write_stdout(message: &str) { let (buffer, length) = unsafe { StringParts { string: message }.bytes }; unsafe { #[cfg(unix)] { write(1, buffer, length); } #[cfg(windows)] { let handle = GetStdHandle(0xffff_fff5); // STD_OUTPUT_HANDLE let mut written: u32 = 0; WriteFile(handle, buffer, length as u32, &mut written, 0 as *mut u8); } } } #[cfg(unix)] #[no_mangle] pub extern "C" fn main() -> i32 { write_stdout("Hello\n"); 0 } #[cfg(windows)] #[no_mangle] pub extern "system" fn mainCRTStartup() -> ! { write_stdout("Hello\n"); unsafe { ExitProcess(0) } }