1#![doc = include_str!("../docs/BUILD.md")]
2#![doc = include_str!("../docs/PREAMBLE.md")]
4#![allow(unsafe_code)]
5#![cfg_attr(linktime_used_linker, doc(test(attr(feature(used_with_arg)))))]
6#![no_std]
7
8#[doc = include_str!("../docs/LIFE_BEFORE_MAIN.md")]
9pub mod life_before_main {}
10
11#[cfg(target_family = "wasm")]
12mod wasm;
13
14#[cfg(target_family = "wasm")]
15extern crate alloc;
16
17pub mod declarative {
24 pub use crate::__in_section_parse as in_section;
25 pub use crate::__section_parse as section;
26}
27
28#[doc(hidden)]
29pub mod __support {
30 pub use crate::__add_section_link_attribute as add_section_link_attribute;
31 pub use crate::__def_section_name as def_section_name;
32 pub use crate::__get_section as get_section;
33 pub use crate::__in_section_crate as in_section_crate;
34 pub use crate::__in_section_parse as in_section_parse;
35 pub use crate::__section_parse as section_parse;
36
37 #[cfg(feature = "proc_macro")]
38 pub use linktime_proc_macro::hash;
39 #[cfg(feature = "proc_macro")]
40 pub use linktime_proc_macro::ident_concat;
41
42 #[cfg(target_family = "wasm")]
43 extern "C" {
44 pub(crate) fn read_custom_section(
46 name: *const u8,
47 name_length: usize,
48 target_address: *mut u8,
49 target_address_length: usize,
50 ) -> usize;
51 }
52
53 #[cfg(target_family = "wasm")]
54 pub use crate::wasm::{register_wasm_link_section_item, LinkSectionRawInfo};
55
56 #[cfg(all(not(miri), target_os = "windows"))]
57 pub use section::Alignment;
58
59 #[macro_export]
61 #[doc(hidden)]
62 macro_rules! __def_section_name {
63 (
64 {$(
65 $__section:ident $__type:ident => $__prefix:tt __ $__suffix:tt;
66 )*}
67 AUXILIARY = $__aux_sep:literal;
68 MAX_LENGTH = $__max_length:literal;
69 HASH_LENGTH = $__hash_length:literal;
70 VALID_SECTION_CHARS = $__valid_section_chars:literal;
71 ) => {
72 #[macro_export]
74 #[doc(hidden)]
75 macro_rules! __section_name {
76 $(
77 (raw $__section $__type $name:ident) => {
78 concat!(concat! $__prefix, stringify!($name), concat! $__suffix);
79 };
80 (raw $__section $__type $name:ident $aux:ident) => {
81 concat!(concat! $__prefix, stringify!($name), $__aux_sep, stringify!($aux), concat! $__suffix);
82 };
83 ($pattern:tt $__section $__type $name:ident) => {
84 $crate::__support::hash!($pattern ($__prefix) $name ($__suffix) $__hash_length $__max_length $__valid_section_chars);
85 };
86 ($pattern:tt $__section $__type $name:ident $aux:ident) => {
87 $crate::__support::hash!($pattern ($__prefix) ($name $__aux_sep $aux) ($__suffix) $__hash_length $__max_length $__valid_section_chars);
88 };
89 )*
90 ($pattern:tt $unknown_section:ident $unknown_type:ident $name:ident) => {
91 const _: () = {
92 compile_error!(concat!("Unknown section type: `", stringify!($unknown_section), "/", stringify!($unknown_type), "`"));
93 };
94 };
95 }
96 };
97 }
98
99 #[cfg(not(linktime_used_linker))]
100 #[doc(hidden)]
101 #[macro_export]
102 macro_rules! __add_used {
103 (
104 $section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
105 $(#[$meta:meta])*
106 $vis:vis static $ident:ident : $($static:tt)*
107 ) => {
108 $crate::__add_section_link_attribute_impl!(
109 $section $type $name $($aux)? #[$attr = __]
110 $(#[$meta])*
111 #[used]
112 #[cfg_attr(target_os = "aix", export_name = concat!("_", env!("CARGO_PKG_NAME"), "_",
113 ::core::module_path!(), "_",
114 stringify!($ident),
115 "_L", line!(), "C", column!()))]
116 $vis static $ident : $($static)*
117 );
118 };
119 }
120
121 #[cfg(linktime_used_linker)]
122 #[doc(hidden)]
123 #[macro_export]
124 macro_rules! __add_used {
125 (
126 $section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
127 $(#[$meta:meta])*
128 $vis:vis static $ident:ident : $($static:tt)*
129 ) => {
130 $crate::__add_section_link_attribute_impl!(
131 $section $type $name $($aux)? #[$attr = __]
132 $(#[$meta])*
133 #[used(linker)]
134 #[cfg_attr(target_os = "aix", export_name = concat!("_", env!("CARGO_PKG_NAME"), "_",
135 ::core::module_path!(), "_",
136 stringify!($ident),
137 "_L", line!(), "C", column!()))]
138 $vis static $ident : $($static)*
139 );
140 };
141 }
142
143 #[doc(hidden)]
144 #[macro_export]
145 macro_rules! __add_section_link_attribute(
146 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
147 $(#[$meta:meta])*
148 $vis:vis static $($static:tt)*
149 ) => {
150 $crate::__add_used!(
151 $section $type $name $($aux)? #[$attr = __]
152 $(#[$meta])*
153 $vis static $($static)*
154 );
155 };
156 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
157 extern "C" {
158 $(#[$meta:meta])*
159 $vis:vis static $($static:tt)*
160 }
161 ) => {
162 extern "C" {
163 $crate::__add_section_link_attribute_impl!(
164 $section $type $name $($aux)? #[$attr = __]
165 $(#[$meta])*
166 #[allow(unsafe_code)]
167 $vis static $($static)*
168 );
169 }
170 };
171 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
172 $($item:tt)*) => {
173 $crate::__add_section_link_attribute_impl!(
174 $section $type $name $($aux)? #[$attr = __]
175 #[allow(unsafe_code)]
176 $($item)*
177 );
178 };
179 );
180
181 #[cfg(feature = "proc_macro")]
182 #[doc(hidden)]
183 #[macro_export]
184 macro_rules! __add_section_link_attribute_impl(
185 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __] $($item:tt)*) => {
186 $crate::__section_name!(
187 (#[$attr = __] #[allow(unsafe_code)] $($item)*)
188 $section $type $name $($aux)?
189 );
190 }
191 );
192
193 #[cfg(not(feature = "proc_macro"))]
194 #[doc(hidden)]
195 #[macro_export]
196 macro_rules! __add_section_link_attribute_impl(
197 ($section:ident $type:ident $name:ident #[$attr:ident = __] $($item:tt)*) => {
198 #[$attr = $crate::__section_name!(
199 raw $section $type $name
200 )] $($item)*
201 }
202 );
203
204 #[cfg(target_vendor = "apple")]
206 def_section_name! {
207 {
208 data bare => ("__DATA,") __ ();
209 code bare => ("__TEXT,") __ ();
210 data section => ("__DATA,") __ (",regular,no_dead_strip");
211 code section => ("__TEXT,") __ (",regular,pure_instructions");
212 data start => ("\x01section$start$__DATA$") __ ();
213 data end => ("\x01section$end$__DATA$") __ ();
214 }
215 AUXILIARY = "_";
216 MAX_LENGTH = 16;
217 HASH_LENGTH = 6;
218 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
219 }
220
221 #[cfg(target_family = "wasm")]
222 def_section_name! {
223 {
224 data bare => (".data", ".link_section.") __ ();
225 data section => (".data", ".link_section.") __ ();
226 code bare => (".text", ".link_section.") __ ();
227 code section => (".text", ".link_section.") __ ();
228 data bounds => (".data", ".link_section.") __ (".bounds");
229 }
230 AUXILIARY = ".";
231 MAX_LENGTH = 16;
232 HASH_LENGTH = 6;
233 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
234 }
235
236 #[cfg(all(
237 not(target_vendor = "apple"),
238 not(target_os = "windows"),
239 not(target_family = "wasm")
240 ))]
241 def_section_name! {
242 {
243 data bare => ("_data", "_link_section_") __ ();
244 data section => ("_data", "_link_section_") __ ();
245 data start => ("__start_", "_data", "_link_section_") __ ();
246 data end => ("__stop_", "_data", "_link_section_") __ ();
247 code bare => ("_text", "_link_section_") __ ();
248 code section => ("_text", "_link_section_") __ ();
249 code start => ("__start_", "_text", "_link_section_") __ ();
250 code end => ("__stop_", "_text", "_link_section_") __ ();
251 }
252 AUXILIARY = "_";
253 MAX_LENGTH = 64;
254 HASH_LENGTH = 10;
255 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
256 }
257
258 #[cfg(target_os = "windows")]
259 def_section_name! {
260 {
261 data bare => (".data", "$") __ ();
262 data section => (".data", "$") __ ("$b");
263 data start => (".data", "$") __ ("$a");
264 data end => (".data", "$") __ ("$c");
265 code bare => (".text", "$") __ ();
266 code section => (".text", "$") __ ("$b");
267 code start => (".text", "$") __ ("$a");
268 code end => (".text", "$") __ ("$c");
269 }
270 AUXILIARY = "$d$";
271 MAX_LENGTH = 64;
272 HASH_LENGTH = 10;
273 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
274 }
275
276 #[cfg(not(feature = "proc_macro"))]
277 #[doc(hidden)]
278 #[macro_export]
279 macro_rules! __declare_macro {
280 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
281 #[doc(hidden)]
284 $vis use $crate::$generic_macro as $ident;
285 };
286 }
287
288 #[cfg(feature = "proc_macro")]
289 #[doc(hidden)]
290 #[macro_export]
291 macro_rules! __declare_macro {
292 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
293 $crate::__support::ident_concat!(
294 (#[macro_export]
295 #[doc(hidden)]
296 macro_rules!) (__ $ident __link_section_private_macro__) ({
297 ($passthru:tt) => {
298 $crate::$generic_macro!($passthru $args);
299 };
300 })
301 );
302
303 $crate::__support::ident_concat!(
304 (#[doc(hidden)] pub use) (__ $ident __link_section_private_macro__) (as $ident;)
305 );
306 }
307 }
308
309 #[macro_export]
311 #[doc(hidden)]
312 macro_rules! __section_parse {
313 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
315 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
316 };
317 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
319 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
320 };
321 (@parsed #[section(aux = $name:ident, no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
323 $crate::__section_parse!(@generate #[section(aux = $name)] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
324 };
325 (@parsed #[section(no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
326 $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
327 };
328 (@parsed #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
329 $crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
330 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
331 };
332 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
333 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
334
335 impl ::core::iter::IntoIterator for $ident {
336 type Item = &'static $generic_ty;
337 type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
338 fn into_iter(self) -> Self::IntoIter {
339 $ident.as_slice().iter()
340 }
341 }
342 };
343 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
344 $(#[$meta])*
345 #[allow(non_camel_case_types)]
346 $vis struct $ident;
347
348 impl $crate::__support::SectionItemType for $ident {
349 type Item = $generic_ty;
350 }
351
352 impl ::core::fmt::Debug for $ident {
353 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
354 ::core::ops::Deref::deref(self).fmt(f)
355 }
356 }
357
358 impl ::core::ops::Deref for $ident {
359 type Target = $ty;
360 fn deref(&self) -> &Self::Target {
361 self.const_deref()
362 }
363 }
364
365 $crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
366 };
367 (@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
368 impl $ident {
369 pub const fn const_deref(&self) -> &$ty {
372 static SECTION: $ty = {
373 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
374 let name = $crate::__section_name!(
375 raw data bare $ident
376 );
377 unsafe { <$ty>::new(name, section) }
378 };
379 &SECTION
380 }
381 }
382 };
383 (@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
384 impl $ident {
385 pub const fn const_deref(&self) -> &$ty {
388 static SECTION: $ty = {
389 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
390 let name = $crate::__section_name!(
391 raw data bare $aux $ident );
393 unsafe { <$ty>::new(name, section) }
394 };
395 &SECTION
396 }
397 }
398 };
399 }
400
401 #[cfg(miri)]
402 mod section {
403 #[doc(hidden)]
404 #[macro_export]
405 macro_rules! __get_section {
406 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {{
407 $crate::__support::PtrBounds::new(core::ptr::null_mut(), core::ptr::null_mut())
408 }};
409 }
410
411 pub type Bounds = crate::__support::PtrBounds;
412 }
413
414 #[cfg(all(not(miri), target_family = "wasm"))]
415 mod section {
416 #[doc(hidden)]
417 #[macro_export]
418 macro_rules! __get_section {
419 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
420 {
421 static __LINK_SECTION_NAME: &'static str = $crate::__section_name!(
422 raw data bare $ident $($aux)?
423 );
424 $crate::__support::add_section_link_attribute!(
425 data bounds $ident $($aux)?
426 #[export_name = __]
427 #[used]
428 static __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo = $crate::__support::LinkSectionRawInfo::new::<$generic_ty>(__LINK_SECTION_NAME);
429 );
430
431 unsafe { $crate::__support::Bounds::new(&raw const __LINK_SECTION_INFO) }
432 }
433 }
434 }
435
436 pub use crate::wasm::Bounds;
437 }
438
439 #[cfg(all(not(miri), target_os = "windows"))]
443 mod section {
444 #[doc(hidden)]
445 #[macro_export]
446 macro_rules! __get_section {
447 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
448 {
449 use $crate::__support::Alignment;
450 use $crate::__support::PtrBounds;
451 use $crate::__support::add_section_link_attribute;
452 use core::mem;
453
454 add_section_link_attribute!(
455 data start $ident $($aux)?
456 #[link_section = __]
457 static __START: Alignment<$generic_ty> = Alignment::new();
458 );
459 add_section_link_attribute!(
460 data end $ident $($aux)?
461 #[link_section = __]
462 static __END: Alignment<$generic_ty> = Alignment::new();
463 );
464
465 PtrBounds::new(
466 unsafe {
467 let start = &raw const __START;
468 start.cast::<u8>().add(mem::size_of::<Alignment<$generic_ty>>()) as *const()
469 },
470 unsafe { &raw const __END as *const () },
471 )
472 }
473 }
474 }
475
476 #[repr(C)]
479 pub struct Alignment<T> {
480 _align: [T; 0],
481 _padding: u8,
482 }
483
484 #[allow(clippy::new_without_default)]
485 impl<T> Alignment<T> {
486 pub const fn new() -> Self {
487 Self {
488 _align: [],
489 _padding: 0,
490 }
491 }
492 }
493
494 pub type Bounds = crate::__support::PtrBounds;
495 }
496
497 #[cfg(all(not(miri), not(target_family = "wasm"), not(target_os = "windows")))]
503 mod section {
504 #[doc(hidden)]
505 #[macro_export]
506 macro_rules! __get_section {
507 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
508 {
509 $crate::__support::add_section_link_attribute!(
512 data start $ident $($aux)?
513 #[link_name = __]
514 extern "C" {
515 static __START: u8;
516 }
517 );
518 $crate::__support::add_section_link_attribute!(
519 data end $ident $($aux)?
520 #[link_name = __]
521 extern "C" {
522 static __END: u8;
523 }
524 );
525
526 $crate::__support::PtrBounds::new(
527 unsafe { &raw const __START as *const () },
529 unsafe { &raw const __END as *const () },
530 )
531 }
532 }
533 }
534
535 pub type Bounds = crate::__support::PtrBounds;
536 }
537
538 #[macro_export]
540 #[doc(hidden)]
541 macro_rules! __in_section_parse {
542 (#[in_section(unsafe, type = $stored_ty:ty, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
549 $crate::__support::in_section_crate!((type = $stored_ty), $ident, $($aux)?, $ident, ($($item)*));
550 };
551 (#[in_section(unsafe, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
552 $crate::__support::in_section_crate!(data, $ident, $($aux)?, $ident, ($($item)*));
553 };
554 (#[in_section( $($path:tt)* )] $($item:tt)*) => {
555 $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
556 };
557 (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
558 $orig_path ! (
559 (v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
560 );
561 };
562 (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
563 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
564 };
565 (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
566 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
567 };
568 }
569
570 #[macro_export]
571 #[doc(hidden)]
572 macro_rules! __in_section_helper_macro_generic {
573 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
574 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
575 };
576 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
577 $crate::__support::in_section_crate!(section, $ident, $aux, $path, $item);
578 };
579 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
580 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
581 };
582 ((v=$v:literal $rest:tt)) => {
583 const _: () = {
584 compile_error!(concat!(
585 "link-section: Unsupported version: `",
586 stringify!($v),
587 "`: ",
588 stringify!($rest)
589 ));
590 };
591 };
592 }
593
594 #[macro_export]
595 #[doc(hidden)]
596 macro_rules! __in_section_helper_macro_no_generic {
597 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
598 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
599 };
600 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
601 $crate::__support::in_section_crate!(data, $ident, $aux, $path, $item);
602 };
603 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
604 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
605 };
606 ((v=$v:literal $rest:tt)) => {
607 const _: () = {
608 compile_error!(concat!(
609 "link-section: Unsupported version: `",
610 stringify!($v),
611 "`: ",
612 stringify!($rest)
613 ));
614 };
615 };
616 }
617
618 #[macro_export]
619 #[doc(hidden)]
620 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
621 macro_rules! __in_section_crate {
622 (@type_select section $path:path, $item_ty:ty) => {
623 <$path as $crate::__support::SectionItemType>::Item
624 };
625 (@type_select data $path:path, $item_ty:ty) => {
626 $item_ty
627 };
628 (@type_select (type = $stored_ty:ty) $path:path, $item_ty:ty) => {
629 $stored_ty
630 };
631 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
632 $crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
633 const _: fn($($args)*) $(-> $ret)? = $ident_fn;
634 ));
635 $crate::__add_section_link_attribute!(
636 code section $ident $($aux)?
637 #[link_section = __]
638 $(#[$meta])*
639 $vis fn $ident_fn($($args)*) $(-> $ret)? $body
640 );
641 };
642 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
643 $crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
644 $(#[$meta])*
645 const _: fn($($args)*) $(-> $ret)? = $ident_fn;
646 ));
647 };
648 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
649 #[cfg(target_family = "wasm")]
650 compile_error!("static items are not supported on WASM: use const items instead");
651
652 #[cfg(not(target_family = "wasm"))]
653 $crate::__add_section_link_attribute!(
654 data section $ident $($aux)?
655 #[link_section = __]
656 $(#[$meta])*
657 $vis static $ident_static: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
658 );
659 };
660 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const $name:ident: $ty:ty = $value:expr;)) => {
661 $(#[$meta])* $vis const $name: $ty = {
662 type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
663 const __LINK_SECTION_CONST_ITEM_VALUE: __InSecStoredTy = $value;
664
665 #[cfg(target_family = "wasm")]
666 {
667 $crate::__add_section_link_attribute!(
669 data section $ident $($aux)?
670 #[link_section = __]
671 $vis static __LINK_SECTION_CONST_ITEM: u8 = 0;
672 );
673
674 $crate::__add_section_link_attribute!(
675 data bounds $ident $($aux)?
676 #[link_name = __]
677 extern "C" {
678 static __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo;
679 }
680 );
681
682 #[link_section = ".init_array.0"]
683 static __LINK_SECTION_ITEM_FN_REF: extern "C" fn() = {
684 extern "C" fn __LINK_SECTION_ITEM_FN() {
685 static DISARMED: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
686 if DISARMED.swap(true, ::core::sync::atomic::Ordering::Relaxed) {
687 return;
688 }
689 unsafe {
690 let ptr = $crate::__support::register_wasm_link_section_item(&raw const __LINK_SECTION_INFO);
691 ::core::ptr::write(ptr as *mut __InSecStoredTy, __LINK_SECTION_CONST_ITEM_VALUE);
692 }
693 }
694 __LINK_SECTION_ITEM_FN
695 };
696 }
697
698 #[cfg(not(target_family = "wasm"))]
699 $crate::__add_section_link_attribute!(
700 data section $ident $($aux)?
701 #[link_section = __]
702 $(#[$meta])*
703 $vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = __LINK_SECTION_CONST_ITEM_VALUE;
704 );
705
706 __LINK_SECTION_CONST_ITEM_VALUE
707 };
708 };
709 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const _: $ty:ty = $value:expr;)) => {
711 $(#[$meta])* $vis const _: () = {
712 type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
713 $crate::__add_section_link_attribute!(
714 data section $ident $($aux)?
715 #[link_section = __]
716 $(#[$meta])*
717 $vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = $value;
718 );
719 };
720 };
721 (data, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $item:item)) => {
722 $crate::__add_section_link_attribute!(
723 data section $ident $($aux)?
724 #[link_section = __]
725 $(#[$meta])*
726 $item
727 );
728 };
729 }
730
731 pub trait SectionItemType {
732 type Item;
733 }
734
735 impl<T> SectionItemType for super::TypedSection<T> {
736 type Item = T;
737 }
738
739 pub struct PtrBounds {
740 pub start: *const (),
741 pub end: *const (),
742 }
743
744 impl PtrBounds {
745 pub const fn new(start: *const (), end: *const ()) -> Self {
746 Self { start, end }
747 }
748
749 #[inline(always)]
750 pub const fn start_ptr(&self) -> *const () {
751 self.start
752 }
753 #[inline(always)]
754 pub const fn end_ptr(&self) -> *const () {
755 self.end
756 }
757 #[inline(always)]
758 pub const fn byte_len(&self) -> usize {
759 unsafe { (self.end.cast::<u8>()).offset_from(self.start.cast::<u8>()) as usize }
762 }
763 }
764
765 pub use section::Bounds;
766}
767
768#[cfg(feature = "proc_macro")]
795pub use ::linktime_proc_macro::section;
796
797#[cfg(feature = "proc_macro")]
804pub use ::linktime_proc_macro::in_section;
805
806#[repr(C)]
809pub struct Section {
810 name: &'static str,
811 bounds: __support::Bounds,
812}
813
814impl Section {
815 #[doc(hidden)]
816 pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
817 Self { name, bounds }
818 }
819
820 #[inline]
822 pub fn byte_len(&self) -> usize {
823 self.bounds.byte_len()
824 }
825
826 #[inline]
828 pub fn start_ptr(&self) -> *const () {
829 self.bounds.start_ptr()
830 }
831 #[inline]
833 pub fn end_ptr(&self) -> *const () {
834 self.bounds.end_ptr()
835 }
836}
837
838impl ::core::fmt::Debug for Section {
839 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
840 f.debug_struct("Section")
841 .field("name", &self.name)
842 .field("start", &self.start_ptr())
843 .field("end", &self.end_ptr())
844 .field("byte_len", &self.byte_len())
845 .finish()
846 }
847}
848
849unsafe impl Sync for Section {}
850unsafe impl Send for Section {}
851
852#[repr(C)]
855pub struct TypedSection<T: 'static> {
856 name: &'static str,
857 bounds: __support::Bounds,
858 _phantom: ::core::marker::PhantomData<T>,
859}
860
861impl<T: 'static> TypedSection<T> {
862 #[doc(hidden)]
863 pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
864 Self {
865 name,
866 bounds,
867 _phantom: ::core::marker::PhantomData,
868 }
869 }
870
871 #[inline(always)]
873 pub fn start_ptr(&self) -> *const T {
874 self.bounds.start_ptr() as *const T
875 }
876
877 #[inline(always)]
879 pub fn end_ptr(&self) -> *const T {
880 self.bounds.end_ptr() as *const T
881 }
882
883 #[inline]
885 pub fn start_ptr_mut(&self) -> *mut T {
886 self.bounds.start_ptr() as *mut T
887 }
888
889 #[inline]
891 pub fn end_ptr_mut(&self) -> *mut T {
892 self.bounds.end_ptr() as *mut T
893 }
894
895 #[inline(always)]
897 pub const fn stride(&self) -> usize {
898 assert!(
899 ::core::mem::size_of::<T>() > 0
900 && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
901 );
902 ::core::mem::size_of::<T>()
903 }
904
905 #[inline]
907 pub fn byte_len(&self) -> usize {
908 self.bounds.byte_len()
909 }
910
911 #[inline]
913 pub fn len(&self) -> usize {
914 self.byte_len() / self.stride()
915 }
916
917 #[inline]
919 pub fn is_empty(&self) -> bool {
920 self.len() == 0
921 }
922
923 #[inline]
925 pub fn as_slice(&self) -> &[T] {
926 if self.is_empty() {
927 &[]
928 } else {
929 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
930 }
931 }
932
933 #[inline]
935 pub fn offset_of(&self, item: &T) -> Option<usize> {
936 let ptr = item as *const T;
937 if ptr < self.start_ptr() || ptr >= self.end_ptr() {
938 None
939 } else {
940 Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
941 }
942 }
943
944 #[allow(clippy::mut_from_ref)]
951 #[inline]
952 pub unsafe fn as_mut_slice(&self) -> &mut [T] {
953 if self.is_empty() {
954 &mut []
955 } else {
956 unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
957 }
958 }
959}
960
961impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
962 type Item = &'a T;
963 type IntoIter = ::core::slice::Iter<'a, T>;
964 fn into_iter(self) -> Self::IntoIter {
965 self.as_slice().iter()
966 }
967}
968
969impl<T> ::core::ops::Deref for TypedSection<T> {
970 type Target = [T];
971 fn deref(&self) -> &Self::Target {
972 self.as_slice()
973 }
974}
975
976impl<T> ::core::fmt::Debug for TypedSection<T> {
977 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
978 f.debug_struct("TypedSection")
979 .field("name", &self.name)
980 .field("start", &self.start_ptr())
981 .field("end", &self.end_ptr())
982 .field("len", &self.len())
983 .field("stride", &self.stride())
984 .finish()
985 }
986}
987
988unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
989unsafe impl<T> Send for TypedSection<T> where T: Send {}