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_vendor = "pc"))]
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 $($static:tt)*
107 ) => {
108 $crate::__add_section_link_attribute_impl!(
109 $section $type $name $($aux)? #[$attr = __]
110 $(#[$meta])*
111 #[used]
112 $vis static $($static)*
113 );
114 };
115 }
116
117 #[cfg(linktime_used_linker)]
118 #[doc(hidden)]
119 #[macro_export]
120 macro_rules! __add_used {
121 (
122 $section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
123 $(#[$meta:meta])*
124 $vis:vis static $($static:tt)*
125 ) => {
126 $crate::__add_section_link_attribute_impl!(
127 $section $type $name $($aux)? #[$attr = __]
128 $(#[$meta])*
129 #[used(linker)]
130 $vis static $($static)*
131 );
132 };
133 }
134
135 #[doc(hidden)]
136 #[macro_export]
137 macro_rules! __add_section_link_attribute(
138 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
139 $(#[$meta:meta])*
140 $vis:vis static $($static:tt)*
141 ) => {
142 $crate::__add_used!(
143 $section $type $name $($aux)? #[$attr = __]
144 $(#[$meta])*
145 $vis static $($static)*
146 );
147 };
148 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
149 extern "C" {
150 $(#[$meta:meta])*
151 $vis:vis static $($static:tt)*
152 }
153 ) => {
154 extern "C" {
155 $crate::__add_section_link_attribute_impl!(
156 $section $type $name $($aux)? #[$attr = __]
157 $(#[$meta])*
158 #[allow(unsafe_code)]
159 $vis static $($static)*
160 );
161 }
162 };
163 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
164 $($item:tt)*) => {
165 $crate::__add_section_link_attribute_impl!(
166 $section $type $name $($aux)? #[$attr = __]
167 #[allow(unsafe_code)]
168 $($item)*
169 );
170 };
171 );
172
173 #[cfg(feature = "proc_macro")]
174 #[doc(hidden)]
175 #[macro_export]
176 macro_rules! __add_section_link_attribute_impl(
177 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __] $($item:tt)*) => {
178 $crate::__section_name!(
179 (#[$attr = __] #[allow(unsafe_code)] $($item)*)
180 $section $type $name $($aux)?
181 );
182 }
183 );
184
185 #[cfg(not(feature = "proc_macro"))]
186 #[doc(hidden)]
187 #[macro_export]
188 macro_rules! __add_section_link_attribute_impl(
189 ($section:ident $type:ident $name:ident #[$attr:ident = __] $($item:tt)*) => {
190 #[$attr = $crate::__section_name!(
191 raw $section $type $name
192 )] $($item)*
193 }
194 );
195
196 #[cfg(target_vendor = "apple")]
198 def_section_name! {
199 {
200 data bare => ("__DATA,") __ ();
201 code bare => ("__TEXT,") __ ();
202 data section => ("__DATA,") __ (",regular,no_dead_strip");
203 code section => ("__TEXT,") __ (",regular,pure_instructions");
204 data start => ("\x01section$start$__DATA$") __ ();
205 data end => ("\x01section$end$__DATA$") __ ();
206 }
207 AUXILIARY = "_";
208 MAX_LENGTH = 16;
209 HASH_LENGTH = 6;
210 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
211 }
212
213 #[cfg(target_family = "wasm")]
214 def_section_name! {
215 {
216 data bare => (".data", ".link_section.") __ ();
217 data section => (".data", ".link_section.") __ ();
218 code bare => (".text", ".link_section.") __ ();
219 code section => (".text", ".link_section.") __ ();
220 data bounds => (".data", ".link_section.") __ (".bounds");
221 }
222 AUXILIARY = ".";
223 MAX_LENGTH = 16;
224 HASH_LENGTH = 6;
225 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
226 }
227
228 #[cfg(all(
229 not(target_vendor = "apple"),
230 not(target_vendor = "pc"),
231 not(target_family = "wasm")
232 ))]
233 def_section_name! {
234 {
235 data bare => ("_data", "_link_section_") __ ();
236 data section => ("_data", "_link_section_") __ ();
237 data start => ("__start_", "_data", "_link_section_") __ ();
238 data end => ("__stop_", "_data", "_link_section_") __ ();
239 code bare => ("_text", "_link_section_") __ ();
240 code section => ("_text", "_link_section_") __ ();
241 code start => ("__start_", "_text", "_link_section_") __ ();
242 code end => ("__stop_", "_text", "_link_section_") __ ();
243 }
244 AUXILIARY = "_";
245 MAX_LENGTH = 64;
246 HASH_LENGTH = 10;
247 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
248 }
249
250 #[cfg(target_vendor = "pc")]
251 def_section_name! {
252 {
253 data bare => (".data", "$") __ ();
254 data section => (".data", "$") __ ("$b");
255 data start => (".data", "$") __ ("$a");
256 data end => (".data", "$") __ ("$c");
257 code bare => (".text", "$") __ ();
258 code section => (".text", "$") __ ("$b");
259 code start => (".text", "$") __ ("$a");
260 code end => (".text", "$") __ ("$c");
261 }
262 AUXILIARY = "$d$";
263 MAX_LENGTH = 64;
264 HASH_LENGTH = 10;
265 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
266 }
267
268 #[cfg(not(feature = "proc_macro"))]
269 #[doc(hidden)]
270 #[macro_export]
271 macro_rules! __declare_macro {
272 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
273 #[doc(hidden)]
276 $vis use $crate::$generic_macro as $ident;
277 };
278 }
279
280 #[cfg(feature = "proc_macro")]
281 #[doc(hidden)]
282 #[macro_export]
283 macro_rules! __declare_macro {
284 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
285 $crate::__support::ident_concat!(
286 (#[macro_export]
287 #[doc(hidden)]
288 macro_rules!) (__ $ident __link_section_private_macro__) ({
289 ($passthru:tt) => {
290 $crate::$generic_macro!($passthru $args);
291 };
292 })
293 );
294
295 $crate::__support::ident_concat!(
296 (#[doc(hidden)] pub use) (__ $ident __link_section_private_macro__) (as $ident;)
297 );
298 }
299 }
300
301 #[macro_export]
303 #[doc(hidden)]
304 macro_rules! __section_parse {
305 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
307 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
308 };
309 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
311 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
312 };
313 (@parsed #[section(aux = $name:ident, no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
315 $crate::__section_parse!(@generate #[section(aux = $name)] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
316 };
317 (@parsed #[section(no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
318 $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
319 };
320 (@parsed #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
321 $crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
322 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
323 };
324 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
325 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
326
327 impl ::core::iter::IntoIterator for $ident {
328 type Item = &'static $generic_ty;
329 type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
330 fn into_iter(self) -> Self::IntoIter {
331 $ident.as_slice().iter()
332 }
333 }
334 };
335 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
336 $(#[$meta])*
337 #[allow(non_camel_case_types)]
338 $vis struct $ident;
339
340 impl $crate::__support::SectionItemType for $ident {
341 type Item = $generic_ty;
342 }
343
344 impl ::core::fmt::Debug for $ident {
345 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
346 ::core::ops::Deref::deref(self).fmt(f)
347 }
348 }
349
350 impl ::core::ops::Deref for $ident {
351 type Target = $ty;
352 fn deref(&self) -> &Self::Target {
353 self.const_deref()
354 }
355 }
356
357 $crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
358 };
359 (@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
360 impl $ident {
361 pub const fn const_deref(&self) -> &$ty {
364 static SECTION: $ty = {
365 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
366 let name = $crate::__section_name!(
367 raw data bare $ident
368 );
369 unsafe { <$ty>::new(name, section) }
370 };
371 &SECTION
372 }
373 }
374 };
375 (@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
376 impl $ident {
377 pub const fn const_deref(&self) -> &$ty {
380 static SECTION: $ty = {
381 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
382 let name = $crate::__section_name!(
383 raw data bare $aux $ident );
385 unsafe { <$ty>::new(name, section) }
386 };
387 &SECTION
388 }
389 }
390 };
391 }
392
393 #[cfg(miri)]
394 mod section {
395 #[doc(hidden)]
396 #[macro_export]
397 macro_rules! __get_section {
398 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {{
399 $crate::__support::PtrBounds::new(core::ptr::null_mut(), core::ptr::null_mut())
400 }};
401 }
402
403 pub type Bounds = crate::__support::PtrBounds;
404 }
405
406 #[cfg(all(not(miri), target_family = "wasm"))]
407 mod section {
408 #[doc(hidden)]
409 #[macro_export]
410 macro_rules! __get_section {
411 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
412 {
413 static __LINK_SECTION_NAME: &'static str = $crate::__section_name!(
414 raw data bare $ident $($aux)?
415 );
416 $crate::__support::add_section_link_attribute!(
417 data bounds $ident $($aux)?
418 #[export_name = __]
419 #[used]
420 static mut __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo = $crate::__support::LinkSectionRawInfo::new::<$generic_ty>(__LINK_SECTION_NAME);
421 );
422
423 unsafe { $crate::__support::Bounds::new(&raw mut __LINK_SECTION_INFO) }
424 }
425 }
426 }
427
428 pub use crate::wasm::Bounds;
429 }
430
431 #[cfg(all(not(miri), target_vendor = "pc"))]
435 mod section {
436 #[doc(hidden)]
437 #[macro_export]
438 macro_rules! __get_section {
439 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
440 {
441 use $crate::__support::Alignment;
442 use $crate::__support::PtrBounds;
443 use $crate::__support::add_section_link_attribute;
444 use core::mem;
445
446 add_section_link_attribute!(
447 data start $ident $($aux)?
448 #[link_section = __]
449 static __START: Alignment<$generic_ty> = Alignment::new();
450 );
451 add_section_link_attribute!(
452 data end $ident $($aux)?
453 #[link_section = __]
454 static __END: Alignment<$generic_ty> = Alignment::new();
455 );
456
457 PtrBounds::new(
458 unsafe {
459 let start = &raw const __START;
460 start.cast::<u8>().add(mem::size_of::<Alignment<$generic_ty>>()) as *const()
461 },
462 unsafe { &raw const __END as *const () },
463 )
464 }
465 }
466 }
467
468 #[repr(C)]
471 pub struct Alignment<T> {
472 _align: [T; 0],
473 _padding: u8,
474 }
475
476 #[allow(clippy::new_without_default)]
477 impl<T> Alignment<T> {
478 pub const fn new() -> Self {
479 Self {
480 _align: [],
481 _padding: 0,
482 }
483 }
484 }
485
486 pub type Bounds = crate::__support::PtrBounds;
487 }
488
489 #[cfg(all(not(miri), not(target_family = "wasm"), not(target_vendor = "pc")))]
495 mod section {
496 #[doc(hidden)]
497 #[macro_export]
498 macro_rules! __get_section {
499 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
500 {
501 $crate::__support::add_section_link_attribute!(
504 data start $ident $($aux)?
505 #[link_name = __]
506 extern "C" {
507 static __START: u8;
508 }
509 );
510 $crate::__support::add_section_link_attribute!(
511 data end $ident $($aux)?
512 #[link_name = __]
513 extern "C" {
514 static __END: u8;
515 }
516 );
517
518 $crate::__support::PtrBounds::new(
519 unsafe { &raw const __START as *const () },
521 unsafe { &raw const __END as *const () },
522 )
523 }
524 }
525 }
526
527 pub type Bounds = crate::__support::PtrBounds;
528 }
529
530 #[macro_export]
532 #[doc(hidden)]
533 macro_rules! __in_section_parse {
534 (#[in_section(unsafe, type = $stored_ty:ty, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
541 $crate::__support::in_section_crate!((type = $stored_ty), $ident, $($aux)?, $ident, ($($item)*));
542 };
543 (#[in_section(unsafe, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
544 $crate::__support::in_section_crate!(data, $ident, $($aux)?, $ident, ($($item)*));
545 };
546 (#[in_section( $($path:tt)* )] $($item:tt)*) => {
547 $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
548 };
549 (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
550 $orig_path ! (
551 (v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
552 );
553 };
554 (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
555 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
556 };
557 (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
558 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
559 };
560 }
561
562 #[macro_export]
563 #[doc(hidden)]
564 macro_rules! __in_section_helper_macro_generic {
565 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
566 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
567 };
568 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
569 $crate::__support::in_section_crate!(section, $ident, $aux, $path, $item);
570 };
571 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
572 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
573 };
574 ((v=$v:literal $rest:tt)) => {
575 const _: () = {
576 compile_error!(concat!(
577 "link-section: Unsupported version: `",
578 stringify!($v),
579 "`: ",
580 stringify!($rest)
581 ));
582 };
583 };
584 }
585
586 #[macro_export]
587 #[doc(hidden)]
588 macro_rules! __in_section_helper_macro_no_generic {
589 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
590 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
591 };
592 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
593 $crate::__support::in_section_crate!(data, $ident, $aux, $path, $item);
594 };
595 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
596 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
597 };
598 ((v=$v:literal $rest:tt)) => {
599 const _: () = {
600 compile_error!(concat!(
601 "link-section: Unsupported version: `",
602 stringify!($v),
603 "`: ",
604 stringify!($rest)
605 ));
606 };
607 };
608 }
609
610 #[macro_export]
611 #[doc(hidden)]
612 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
613 macro_rules! __in_section_crate {
614 (@type_select section $path:path, $item_ty:ty) => {
615 <$path as $crate::__support::SectionItemType>::Item
616 };
617 (@type_select data $path:path, $item_ty:ty) => {
618 $item_ty
619 };
620 (@type_select (type = $stored_ty:ty) $path:path, $item_ty:ty) => {
621 $stored_ty
622 };
623 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
624 $crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
625 const _: fn($($args)*) $(-> $ret)? = $ident_fn;
626 ));
627 $crate::__add_section_link_attribute!(
628 code section $ident $($aux)?
629 #[link_section = __]
630 $(#[$meta])*
631 $vis fn $ident_fn($($args)*) $(-> $ret)? $body
632 );
633 };
634 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
635 $crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
636 $(#[$meta])*
637 const _: fn($($args)*) $(-> $ret)? = $ident_fn;
638 ));
639 };
640 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
641 #[cfg(target_family = "wasm")]
642 compile_error!("static items are not supported on WASM: use const items instead");
643
644 #[cfg(not(target_family = "wasm"))]
645 $crate::__add_section_link_attribute!(
646 data section $ident $($aux)?
647 #[link_section = __]
648 $(#[$meta])*
649 $vis static $ident_static: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
650 );
651 };
652 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const $name:ident: $ty:ty = $value:expr;)) => {
653 $(#[$meta])* $vis const $name: $ty = {
654 type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
655 const __LINK_SECTION_CONST_ITEM_VALUE: __InSecStoredTy = $value;
656
657 #[cfg(target_family = "wasm")]
658 {
659 $crate::__add_section_link_attribute!(
661 data section $ident $($aux)?
662 #[link_section = __]
663 $vis static __LINK_SECTION_CONST_ITEM: u8 = 0;
664 );
665
666 $crate::__add_section_link_attribute!(
667 data bounds $ident $($aux)?
668 #[link_name = __]
669 extern "C" {
670 static mut __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo;
671 }
672 );
673
674 #[link_section = ".init_array.0"]
675 static mut __LINK_SECTION_ITEM_FN_REF: extern "C" fn() = {
676 extern "C" fn __LINK_SECTION_ITEM_FN() {
677 static DISARMED: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
678 if DISARMED.swap(true, ::core::sync::atomic::Ordering::Relaxed) {
679 return;
680 }
681 unsafe {
682 let ptr = $crate::__support::register_wasm_link_section_item(&raw mut __LINK_SECTION_INFO);
683 ::core::ptr::write(ptr as *mut __InSecStoredTy, __LINK_SECTION_CONST_ITEM_VALUE);
684 }
685 }
686 __LINK_SECTION_ITEM_FN
687 };
688 }
689
690 #[cfg(not(target_family = "wasm"))]
691 $crate::__add_section_link_attribute!(
692 data section $ident $($aux)?
693 #[link_section = __]
694 $(#[$meta])*
695 $vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = __LINK_SECTION_CONST_ITEM_VALUE;
696 );
697
698 __LINK_SECTION_CONST_ITEM_VALUE
699 };
700 };
701 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const _: $ty:ty = $value:expr;)) => {
703 $(#[$meta])* $vis const _: () = {
704 type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
705 $crate::__add_section_link_attribute!(
706 data section $ident $($aux)?
707 #[link_section = __]
708 $(#[$meta])*
709 $vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = $value;
710 );
711 };
712 };
713 (data, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $item:item)) => {
714 $crate::__add_section_link_attribute!(
715 data section $ident $($aux)?
716 #[link_section = __]
717 $(#[$meta])*
718 $item
719 );
720 };
721 }
722
723 pub trait SectionItemType {
724 type Item;
725 }
726
727 impl<T> SectionItemType for super::TypedSection<T> {
728 type Item = T;
729 }
730
731 pub struct PtrBounds {
732 pub start: *const (),
733 pub end: *const (),
734 }
735
736 impl PtrBounds {
737 pub const fn new(start: *const (), end: *const ()) -> Self {
738 Self { start, end }
739 }
740
741 #[inline(always)]
742 pub const fn start_ptr(&self) -> *const () {
743 self.start
744 }
745 #[inline(always)]
746 pub const fn end_ptr(&self) -> *const () {
747 self.end
748 }
749 #[inline(always)]
750 pub const fn byte_len(&self) -> usize {
751 unsafe { (self.end.cast::<u8>()).offset_from(self.start.cast::<u8>()) as usize }
754 }
755 }
756
757 pub use section::Bounds;
758}
759
760#[cfg(feature = "proc_macro")]
787pub use ::linktime_proc_macro::section;
788
789#[cfg(feature = "proc_macro")]
796pub use ::linktime_proc_macro::in_section;
797
798#[repr(C)]
801pub struct Section {
802 name: &'static str,
803 bounds: __support::Bounds,
804}
805
806impl Section {
807 #[doc(hidden)]
808 pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
809 Self { name, bounds }
810 }
811
812 #[inline]
814 pub fn byte_len(&self) -> usize {
815 self.bounds.byte_len()
816 }
817
818 #[inline]
820 pub fn start_ptr(&self) -> *const () {
821 self.bounds.start_ptr()
822 }
823 #[inline]
825 pub fn end_ptr(&self) -> *const () {
826 self.bounds.end_ptr()
827 }
828}
829
830impl ::core::fmt::Debug for Section {
831 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
832 f.debug_struct("Section")
833 .field("name", &self.name)
834 .field("start", &self.start_ptr())
835 .field("end", &self.end_ptr())
836 .field("byte_len", &self.byte_len())
837 .finish()
838 }
839}
840
841unsafe impl Sync for Section {}
842unsafe impl Send for Section {}
843
844#[repr(C)]
847pub struct TypedSection<T: 'static> {
848 name: &'static str,
849 bounds: __support::Bounds,
850 _phantom: ::core::marker::PhantomData<T>,
851}
852
853impl<T: 'static> TypedSection<T> {
854 #[doc(hidden)]
855 pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
856 Self {
857 name,
858 bounds,
859 _phantom: ::core::marker::PhantomData,
860 }
861 }
862
863 #[inline(always)]
865 pub fn start_ptr(&self) -> *const T {
866 self.bounds.start_ptr() as *const T
867 }
868
869 #[inline(always)]
871 pub fn end_ptr(&self) -> *const T {
872 self.bounds.end_ptr() as *const T
873 }
874
875 #[inline]
877 pub fn start_ptr_mut(&self) -> *mut T {
878 self.bounds.start_ptr() as *mut T
879 }
880
881 #[inline]
883 pub fn end_ptr_mut(&self) -> *mut T {
884 self.bounds.end_ptr() as *mut T
885 }
886
887 #[inline(always)]
889 pub const fn stride(&self) -> usize {
890 assert!(
891 ::core::mem::size_of::<T>() > 0
892 && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
893 );
894 ::core::mem::size_of::<T>()
895 }
896
897 #[inline]
899 pub fn byte_len(&self) -> usize {
900 self.bounds.byte_len()
901 }
902
903 #[inline]
905 pub fn len(&self) -> usize {
906 self.byte_len() / self.stride()
907 }
908
909 #[inline]
911 pub fn is_empty(&self) -> bool {
912 self.len() == 0
913 }
914
915 #[inline]
917 pub fn as_slice(&self) -> &[T] {
918 if self.is_empty() {
919 &[]
920 } else {
921 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
922 }
923 }
924
925 #[inline]
927 pub fn offset_of(&self, item: &T) -> Option<usize> {
928 let ptr = item as *const T;
929 if ptr < self.start_ptr() || ptr >= self.end_ptr() {
930 None
931 } else {
932 Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
933 }
934 }
935
936 #[allow(clippy::mut_from_ref)]
943 #[inline]
944 pub unsafe fn as_mut_slice(&self) -> &mut [T] {
945 if self.is_empty() {
946 &mut []
947 } else {
948 unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
949 }
950 }
951}
952
953impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
954 type Item = &'a T;
955 type IntoIter = ::core::slice::Iter<'a, T>;
956 fn into_iter(self) -> Self::IntoIter {
957 self.as_slice().iter()
958 }
959}
960
961impl<T> ::core::ops::Deref for TypedSection<T> {
962 type Target = [T];
963 fn deref(&self) -> &Self::Target {
964 self.as_slice()
965 }
966}
967
968impl<T> ::core::fmt::Debug for TypedSection<T> {
969 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
970 f.debug_struct("TypedSection")
971 .field("name", &self.name)
972 .field("start", &self.start_ptr())
973 .field("end", &self.end_ptr())
974 .field("len", &self.len())
975 .field("stride", &self.stride())
976 .finish()
977 }
978}
979
980unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
981unsafe impl<T> Send for TypedSection<T> where T: Send {}