Skip to main content

rustubs/
black_magic.rs

1//! collection of hacks
2use core::{cell::SyncUnsafeCell, slice};
3
4pub unsafe fn make_static(r: &[u8]) -> &'static [u8] {
5	return slice::from_raw_parts(&r[0] as *const u8, r.len());
6}
7
8// an empty struct
9pub struct Void;
10impl Void {
11	pub const fn new() -> Self { Self {} }
12}
13
14/// A unprotectected global object on a "I know what I'm doing basis".
15/// every reference to such object must be marked unsafe.
16pub struct Ether<T> {
17	data: SyncUnsafeCell<T>,
18}
19
20unsafe impl<T> Sync for Ether<T> {}
21
22impl<T> Ether<T> {
23	pub const fn new(data: T) -> Self {
24		Self { data: SyncUnsafeCell::new(data) }
25	}
26
27	pub const unsafe fn get_ref(&self) -> &T { &*self.data.get() }
28	pub const unsafe fn get_ref_mut(&self) -> &mut T { &mut *self.data.get() }
29}
30
31/// flush a volatile variable: rust doesn't have a volatile keyword. When a
32/// "const static" variable is expected to be written externally the optimized
33/// code may go wrong.
34pub fn flush<T>(thing: &T) -> T {
35	unsafe { core::ptr::read_volatile(thing as *const T) }
36}
37
38/// macro to declare a external symbol: cast its address into e.g. u64.
39/// useful for getting the address of a tag in asm.
40/// ```
41/// tag:
42///     // something
43/// ```
44///
45/// EXTERN_SYM_PTR!(_TAG, tag)
46///
47/// becomes
48///
49/// ```rust
50/// extern "C" {
51///    fn tag();
52/// }
53/// const TAG: *const () = tag as *const ();
54/// ```
55#[macro_export]
56macro_rules! EXTERN_SYM_PTR {
57	($vis:vis $name:ident ,  $ext:ident) => {
58		extern "C" {
59			fn $ext();
60		}
61		$vis const $name:*const () = $ext as *const ();
62	};
63
64	($vis:vis $name:ident : $ty:ty = $ext:ident) => {
65		extern "C" {
66			fn $ext();
67		}
68		$vis const $name:*const () = $ext as *const () as $ty;
69	};
70
71}