|
| 1 | +# TCR: x86_64-*-lilium-std |
| 2 | + |
| 3 | +## Basic Properties |
| 4 | + |
| 5 | +This target is for the Lilium OS using the System V ABI on x86_64. Pointers are 8 bytes in size, the target supports `std`, and unwinding is supported. |
| 6 | + |
| 7 | +The target supports any value for the vendor field. The standard vendor is `pc`, and all other vendors are aliases that differ only in the `target_vendor` cfg which is set to the value of this field. |
| 8 | + |
| 9 | +The standard cfg values are |
| 10 | +```rust |
| 11 | +target_abi="" |
| 12 | +target_arch="x86_64" |
| 13 | +target_endian="little" |
| 14 | +target_env="std" |
| 15 | +target_family="lilium" |
| 16 | +target_has_atomic |
| 17 | +target_has_atomic="16" |
| 18 | +target_has_atomic="32" |
| 19 | +target_has_atomic="64" |
| 20 | +target_has_atomic="8" |
| 21 | +target_has_atomic="ptr" |
| 22 | +target_has_atomic_equal_alignment="16" |
| 23 | +target_has_atomic_equal_alignment="32" |
| 24 | +target_has_atomic_equal_alignment="64" |
| 25 | +target_has_atomic_equal_alignment="8" |
| 26 | +target_has_atomic_equal_alignment="ptr" |
| 27 | +target_has_atomic_load_store |
| 28 | +target_has_atomic_load_store="16" |
| 29 | +target_has_atomic_load_store="32" |
| 30 | +target_has_atomic_load_store="64" |
| 31 | +target_has_atomic_load_store="8" |
| 32 | +target_has_atomic_load_store="ptr" |
| 33 | +target_os="lilium" |
| 34 | +target_pointer_width="64" |
| 35 | +target_thread_local |
| 36 | +``` |
| 37 | + |
| 38 | +The type aliases used for `core::ffi` types are: |
| 39 | +```rust |
| 40 | +pub type c_char = u8; |
| 41 | +pub type c_double = f64; |
| 42 | +pub type c_float = f32; |
| 43 | +pub type c_int = i32; |
| 44 | +pub type c_long = i64; |
| 45 | +pub type c_longlong = i64; |
| 46 | +pub type c_schar = i8; |
| 47 | +pub type c_short = i16; |
| 48 | +pub type c_uchar = u8; |
| 49 | +pub type c_uint = u32; |
| 50 | +pub type c_ulong = u64; |
| 51 | +pub type c_ulonglong = u64; |
| 52 | +pub type c_ushort = u16; |
| 53 | +pub type c_ptrdiff_t = isize; |
| 54 | +pub type c_size_t = usize; |
| 55 | +pub type c_ssize_t = isize; |
| 56 | +``` |
| 57 | + |
| 58 | +## Language Feature Interactions |
| 59 | + |
| 60 | +The following special `extern` ABIs are supported. Each ABI supports a `-unwind` variant: |
| 61 | +* `extern "win64"` |
| 62 | +* `extern "sysv64"` |
| 63 | +* `extern "vectorcall"` |
| 64 | +* `extern "efiabi"` |
| 65 | + |
| 66 | +The `extern "C"` and `extern "system"` ABIs match `extern "sysv64"`. |
| 67 | + |
| 68 | +All x86_64 standard target features are supported. The default target features are: |
| 69 | +* `sse` |
| 70 | +* `sse2` |
| 71 | +* `fxsr` |
| 72 | + |
| 73 | +## Target-specific Modules |
| 74 | + |
| 75 | +The standard `core::arch::x86_64` module is defined. |
| 76 | + |
| 77 | +The `std::ffi::OsStr` type is guaranteed to store valid UTF-8. Invalid UTF-8 in strings is rejected by kernel interfaces, and is not produced by any kernel interface that returns succesfully. |
| 78 | + |
| 79 | +A new `std::os::lilium` module is defined, to support OS-Specific Facilities on Lilium. The initial API Surface is: |
| 80 | +```rust |
| 81 | +// std::os::lilium |
| 82 | + |
| 83 | +pub trait OsStrExt : Sealed{ |
| 84 | + /// Infallibly converts from an [`OsStr`] to a [`str`] |
| 85 | + fn as_str(&self) -> &str; |
| 86 | + /// Infallibly converts from a mutable [`OsStr`] to a [`str`] |
| 87 | + fn as_str_mut(&mut self) -> &mut str; |
| 88 | + /// Infallibly converts from a [`str`] to an [`OsStr`] |
| 89 | + fn from_str(st: &str) -> &Self; |
| 90 | + /// Infallibly converts from a mutable [`str`] to an [`OsStr`] |
| 91 | + fn from_str_mut(st: &mut str) -> &mut Self; |
| 92 | +} |
| 93 | + |
| 94 | +impl OsStrExt for std::ffi::OsStr; |
| 95 | + |
| 96 | +pub trait OsStringExt : Sealed{ |
| 97 | + /// Infallibly converts from an [`OsString`] to a [`String`] |
| 98 | + fn into_string(self) -> String; |
| 99 | +} |
| 100 | + |
| 101 | +impl OsStringExt for std::ffi::OsString; |
| 102 | + |
| 103 | +#[repr(C,align(16))] |
| 104 | +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] |
| 105 | +pub struct OsUuid{ |
| 106 | + pub lo: u64, |
| 107 | + pub hi: u64, |
| 108 | +} |
| 109 | + |
| 110 | +pub mod except{ |
| 111 | + #[repr(C)] |
| 112 | + #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
| 113 | + pub struct ExceptionStatusInfo { |
| 114 | + pub except_code: OsUuid, |
| 115 | + pub except_info: u64, |
| 116 | + pub except_reason: u64, |
| 117 | + } |
| 118 | +} |
| 119 | + |
| 120 | +pub mod handle{ |
| 121 | + /// Type representing a pointer to a handle, for doing raw operations on OS Primitives. |
| 122 | + #[repr(transparent)] |
| 123 | + pub struct RawHandlePtr<T>(*mut T); |
| 124 | + |
| 125 | + pub trait HandleType: Sealed{} |
| 126 | + |
| 127 | + pub struct AsRawHandle<T: HandleType>{ |
| 128 | + fn as_raw_handle(&self) -> RawHandlePtr<T>; |
| 129 | + } |
| 130 | + |
| 131 | + pub struct FromRawHandle<T: HandleType> { |
| 132 | + unsafe fn from_raw_handle(hdl: RawHandlePtr<T>) -> Self; |
| 133 | + } |
| 134 | +} |
| 135 | + |
| 136 | +pub mod io{ |
| 137 | + pub struct IOHandle(/*private fields*/); |
| 138 | + |
| 139 | + impl HandleType for IOHandle{} |
| 140 | + |
| 141 | + impl AsRawHandle<IOHandle> for std::fs::File; |
| 142 | + impl AsRawHandle<IOHandle> for std::net::TcpStream; |
| 143 | + impl AsRawHandle<IOHandle> for std::net::UdpSocket; |
| 144 | + impl AsRawHandle<IOHandle> for std::io::Stdin; |
| 145 | + impl AsRawHandle<IOHandle> for std::io::StdinLock; |
| 146 | + impl AsRawHandle<IOHandle> for std::io::Stderr; |
| 147 | + impl AsRawHandle<IOHandle> for std::io::StderrLock; |
| 148 | + impl AsRawHandle<IOHandle> for std::io::Stdout; |
| 149 | + impl AsRawHandle<IOHandle> for std::io::StdoutLock; |
| 150 | + impl AsRawHandle<IOHandle> for std::process::ChildStdin; |
| 151 | + impl AsRawHandle<IOHandle> for std::process::ChildStdout; |
| 152 | + impl AsRawHandle<IOHandle> for std::process::ChildStderr; |
| 153 | + |
| 154 | + impl FromRawHandle<IOHandle> for std::process::Stdio; |
| 155 | + |
| 156 | +} |
| 157 | + |
| 158 | +pub mod fs{ |
| 159 | + pub struct FileHandle(/*private fields*/); |
| 160 | + |
| 161 | + impl HandleType for FileHandle; |
| 162 | + |
| 163 | + impl AsRawHandle<FileHandle> for std::fs::File; |
| 164 | + impl FromRawHandle<FileHandle> for std::fs::File; |
| 165 | + impl AsRawHandle<FileHandle> for std::fs::ReadDir; |
| 166 | + impl FromRawHandle<FileHandle> for std::fs::ReadDir{ |
| 167 | + /// Constructs a new [`ReadDir`] from the specified handle. |
| 168 | + /// |
| 169 | + /// ## Note |
| 170 | + /// If the `hdl` originally came from a [`ReadDir`], this method will return a fresh iterator that will iterate from the beginning |
| 171 | + unsafe fn from_raw_handle(hdl: RawHandlePtr<FileHandle>) -> Self; |
| 172 | + } |
| 173 | + |
| 174 | + pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> Result<()>; |
| 175 | + |
| 176 | + /// Creates a new weak link |
| 177 | + /// |
| 178 | + /// Weak Links are features of the Lilium Filesystem, allowing a weak reference to a filesystem object. |
| 179 | + /// They act similiarily to hard links (cannot cross filesystems), but does not keep a hold on the object data (or most metadata). |
| 180 | + /// |
| 181 | + /// Weak links are generally not needed for most use cases. |
| 182 | + pub fn weak_link<P: AsRef<Path>, Q: AsRef<Path>>(original:P, link: Q) -> Result<()>; |
| 183 | +} |
| 184 | + |
| 185 | +pub mod thread{ |
| 186 | + pub struct ThreadHandle(/*private fields*/); |
| 187 | + |
| 188 | + impl HandleType for ThreadHandle; |
| 189 | + impl AsRawHandle<ThreadHandle> for std::thread::Thread; |
| 190 | + impl<T> AsRawHandle<ThreadHandle> for std::thread::JoinHandle<T>; |
| 191 | + impl<'scope, T> AsRawHandle<ThreadHandle> for std::thread::ScopedJoinHandle<'scope, T>; |
| 192 | +} |
| 193 | + |
| 194 | +pub mod process{ |
| 195 | + pub struct ProcessHandle(/*private fields*/); |
| 196 | + impl HandleType for ProcessHandle{} |
| 197 | + |
| 198 | + impl AsRawHandle<ProcessHandle> for std::process::Child; |
| 199 | + |
| 200 | + impl FromRawHandle<ProcessHandle> for std::process::Child; |
| 201 | + |
| 202 | + pub trait ExitStatusExt: Sealed{ |
| 203 | + fn exception(&self) -> Option<ExceptionStatusInfo>; |
| 204 | + } |
| 205 | + |
| 206 | + pub trait CommandExt : Sealed{ |
| 207 | + fn arg0<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self; |
| 208 | + } |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +The `*Handle` types are opaque in the OS design, but are provided to allow third party crates that provide more comprehensive access to the Lilium SCI and USI to use or access standard types. |
| 213 | + |
| 214 | +### Platform Specific Behaviour |
| 215 | + |
| 216 | +The following documents the initial implementation correspondance of certain standard library functions to Lilium. None of these are guarantees |
| 217 | + |
| 218 | +#### `std::io::copy` |
| 219 | + |
| 220 | +This corresponds to calling the SCI function `IOCopyFull` if possible. Support is available based on implementation of the `AsRawHandle<IOHandle>` trait. |
| 221 | +If the stream being read is larger than `u64::MAX` bytes, and the stream being written to accepts the full size copy, returns `u64::MAX` |
| 222 | + |
| 223 | +#### `std::fs::copy` |
| 224 | + |
| 225 | +This corresponds to calling the SCI function `CopyObject` and specifying all streams are to gbe copied. |
| 226 | +The return value is the total size of all streams copied. Like `std::io::copy` if that value exceeds `u64::MAX` bytes, it returns `u64::MAX`. |
| 227 | + Note that if the stream copied carries out of band data (such as a device file) only the size of the actual stream (not the out-of-band data) is counted. |
| 228 | + For example, copying |
| 229 | + |
| 230 | +#### `std::env::var` |
| 231 | + |
| 232 | +This corresponds to calling the SCI function `GetEnvironmentVariable` with a null map (the default map for the process). |
| 233 | + |
| 234 | +Due to the fact that the kernel will only yield (and permit) UTF-8 values for environment variables, this function will never return `std::env::VarError::NotUnicode`. |
| 235 | + |
| 236 | +#### `std::io::IsTerminal` |
| 237 | + |
| 238 | +The `is_terminal` method corresponds to querying the `Interactive` device feature on the device corresponding with the object's `IOHandle` (with flags set to 0). The device is obtained from the raw `IOHandle` as follows: |
| 239 | +* If the Handle is a `DeviceHandle`, uses it directly in `TestDeviceFeature` |
| 240 | +* If the Handle is a `FileHandle`, the `DeviceHandle` is obtained using `OpenDeviceFromFile`. If this succeeds, the result is used in `TestDeviceFeature` |
| 241 | +* If it's neither a `FileHandle` nor a `DeviceHandle` or it is a `FileHandle` and `OpenDeviceFromFile` fails, the function returns `false`. |
| 242 | + |
| 243 | +The function returns `true` iff the call to `TestDeviceFeature` succeeds. |
| 244 | + |
| 245 | +## Deviations |
| 246 | + |
| 247 | +The Lilium OS is a non-Unix-like non-Windows OS - it does not support POSIX-like interfaces, or win32 api. |
| 248 | +It is thus incompatible with any platform-dependant code in existance today. |
| 249 | +The OS was specificially designed to not be constrained by POSIX, allowing more interesting design space to be explored in its design. The Rust design, and the implementation of the platform in lccc reflects this unique design, rather than trying to incompletely weld an interface compatible with most Rust programs (those using `std::os::unix`) onto an incompatible OS Interface. |
| 250 | + |
| 251 | +A new value for `target_family`, `"lilium"` is used by the target. This reflects the uniqueness of its interface, and the possibility of other kernels matching the published standard kernel interface. |
| 252 | + |
| 253 | +Like most targets supported by lccc, the `target_vendor` cfg is determined by the target name, rather than using a fixed value for all of the covered targets. |
0 commit comments