1717/// ```
1818#[ macro_export]
1919macro_rules! class {
20+ ( $name: ident) => { {
21+ $crate:: __class_inner!( $name)
22+ } } ;
23+ }
24+
25+ #[ doc( hidden) ]
26+ #[ macro_export]
27+ #[ cfg( not( feature = "unstable-static-class" ) ) ]
28+ macro_rules! __class_inner {
2029 ( $name: ident) => { {
2130 use $crate:: __macro_helpers:: { concat, panic, stringify, CachedClass , None , Some } ;
2231 static CACHED_CLASS : CachedClass = CachedClass :: new( ) ;
@@ -25,7 +34,7 @@ macro_rules! class {
2534 let cls = unsafe { CACHED_CLASS . get( name) } ;
2635 match cls {
2736 Some ( cls) => cls,
28- None => panic!( "Class with name {} could not be found" , stringify!( $name) ) ,
37+ None => panic!( "Class with name {} could not be found" , stringify!( $name) , ) ,
2938 }
3039 } } ;
3140}
@@ -165,18 +174,12 @@ macro_rules! __sel_inner {
165174
166175#[ doc( hidden) ]
167176#[ macro_export]
168- macro_rules! __sel_inner_statics_apple_generic {
177+ macro_rules! __inner_statics_apple_generic {
169178 {
179+ @image_info;
170180 $image_info_section: literal;
171- $var_name_section: literal;
172- $selector_ref_section: literal;
173- $data: ident,
174181 $( $idents: ident) +
175182 } => {
176- use $crate:: __macro_helpers:: { __hash_idents, u8 , UnsafeCell } ;
177- use $crate:: ffi:: __ImageInfo;
178- use $crate:: runtime:: Sel ;
179-
180183 /// We always emit the image info tag, since we need it to:
181184 /// - End up in the same codegen unit as the other statics below.
182185 /// - End up in the final binary so it can be read by dyld.
@@ -185,9 +188,22 @@ macro_rules! __sel_inner_statics_apple_generic {
185188 /// reports `__DATA/__objc_imageinfo has unexpectedly large size XXX`,
186189 /// but things still seems to work.
187190 #[ link_section = $image_info_section]
188- #[ export_name = concat!( "\x01 L_OBJC_IMAGE_INFO_" , __hash_idents!( $( $idents) +) ) ]
191+ #[ export_name = $crate:: __macro_helpers:: concat!(
192+ "\x01 L_OBJC_IMAGE_INFO_" ,
193+ $crate:: __macro_helpers:: __hash_idents!( $( $idents) +)
194+ ) ]
189195 #[ used] // Make sure this reaches the linker
190- static _IMAGE_INFO: __ImageInfo = __ImageInfo:: system( ) ;
196+ static _IMAGE_INFO: $crate:: ffi:: __ImageInfo = $crate:: ffi:: __ImageInfo:: system( ) ;
197+ } ;
198+ {
199+ @sel;
200+ $var_name_section: literal;
201+ $selector_ref_section: literal;
202+ $data: ident,
203+ $( $idents: ident) +
204+ } => {
205+ use $crate:: __macro_helpers:: { __hash_idents, u8 , UnsafeCell } ;
206+ use $crate:: runtime:: Sel ;
191207
192208 const X : & [ u8 ] = $data. as_bytes( ) ;
193209
@@ -241,47 +257,108 @@ macro_rules! __sel_inner_statics_apple_generic {
241257 UnsafeCell :: new( Sel :: __internal_from_ptr( NAME_DATA . as_ptr( ) . cast( ) ) )
242258 } ;
243259 } ;
260+ {
261+ @class;
262+ $class_ref_section: literal;
263+ $name: ident
264+ } => {
265+ use $crate:: __macro_helpers:: { concat, stringify, __hash_idents, UnsafeCell } ;
266+ use $crate:: runtime:: Class ;
267+
268+ // TODO
269+ extern "C" {
270+ // TODO: Weak linkage?
271+ // https://stackoverflow.com/a/16936512
272+ // http://sealiesoftware.com/blog/archive/2010/4/8/Do-it-yourself_Objective-C_weak_import.html
273+ #[ link_name = concat!( "OBJC_CLASS_$_" , stringify!( $name) ) ]
274+ static CLASS : Class ;
275+ }
276+
277+ // TODO
278+ #[ link_section = $class_ref_section]
279+ #[ export_name = concat!( "\x01 L_OBJC_CLASSLIST_REFERENCES_$_" , __hash_idents!( $name) ) ]
280+ static mut REF : UnsafeCell <& Class > = unsafe {
281+ UnsafeCell :: new( & CLASS )
282+ } ;
283+ } ;
244284}
245285
286+ // These sections are found by reading clang/LLVM sources
246287#[ doc( hidden) ]
247288#[ macro_export]
248289#[ cfg( all( feature = "apple" , not( all( target_os = "macos" , target_arch = "x86" ) ) ) ) ]
249- macro_rules! __sel_inner_statics {
250- ( $( $args: tt) * ) => {
251- // Found by reading clang/LLVM sources
252- $crate :: __sel_inner_statics_apple_generic! {
290+ macro_rules! __inner_statics {
291+ ( @image_info $( $args: tt) * ) => {
292+ $crate :: __inner_statics_apple_generic! {
293+ @image_info ;
253294 "__DATA,__objc_imageinfo,regular,no_dead_strip" ;
295+ $( $args) *
296+ }
297+ } ;
298+ ( @sel $( $args: tt) * ) => {
299+ $crate:: __inner_statics_apple_generic! {
300+ @sel;
254301 "__TEXT,__objc_methname,cstring_literals" ;
255302 "__DATA,__objc_selrefs,literal_pointers,no_dead_strip" ;
256303 $( $args) *
257304 }
258305 } ;
306+ ( @class $( $args: tt) * ) => {
307+ $crate:: __inner_statics_apple_generic! {
308+ @class;
309+ "__DATA,__objc_classrefs,regular,no_dead_strip" ;
310+ $( $args) *
311+ }
312+ } ;
259313}
260314
261315#[ doc( hidden) ]
262316#[ macro_export]
263317#[ cfg( all( feature = "apple" , target_os = "macos" , target_arch = "x86" ) ) ]
264- macro_rules! __sel_inner_statics {
265- ( $( $args: tt) * ) => {
266- $crate:: __sel_inner_statics_apple_generic! {
318+ macro_rules! __inner_statics {
319+ ( @image_info $( $args: tt) * ) => {
320+ $crate:: __inner_statics_apple_generic! {
321+ @image_info;
267322 "__OBJC,__image_info,regular" ;
323+ $( $args) *
324+ }
325+ } ;
326+ ( @sel $( $args: tt) * ) => {
327+ $crate:: __inner_statics_apple_generic! {
328+ @sel;
268329 "__TEXT,__cstring,cstring_literals" ;
269330 "__OBJC,__message_refs,literal_pointers,no_dead_strip" ;
270331 $( $args) *
271332 }
272333 } ;
334+ ( @class $( $args: tt) * ) => {
335+ // TODO
336+ $crate:: __macro_helpers:: compile_error!(
337+ "The `\" unstable-static-class\" ` feature is not yet supported on 32bit macOS!"
338+ )
339+ // TODO: module info
340+ } ;
273341}
274342
275343#[ doc( hidden) ]
276344#[ macro_export]
277345#[ cfg( not( feature = "apple" ) ) ]
278- macro_rules! __sel_inner_statics {
279- ( $( $args: tt) * ) => {
346+ macro_rules! __inner_statics {
347+ ( @image_info $( $args: tt) * ) => {
348+ // TODO
349+ } ;
350+ ( @sel $( $args: tt) * ) => {
280351 // TODO
281352 $crate:: __macro_helpers:: compile_error!(
282353 "The `\" unstable-static-sel\" ` feature is not yet supported on GNUStep!"
283354 )
284355 } ;
356+ ( @class $( $args: tt) * ) => {
357+ // TODO
358+ $crate:: __macro_helpers:: compile_error!(
359+ "The `\" unstable-static-class\" ` feature is not yet supported on GNUStep!"
360+ )
361+ } ;
285362}
286363
287364#[ doc( hidden) ]
@@ -291,8 +368,9 @@ macro_rules! __sel_inner_statics {
291368 not( feature = "unstable-static-sel-inlined" )
292369) ) ]
293370macro_rules! __sel_inner {
294- ( $( $args: tt) * ) => { {
295- $crate:: __sel_inner_statics!( $( $args) * ) ;
371+ ( $data: ident, $( $idents: ident) +) => { {
372+ $crate:: __inner_statics!( @image_info $( $idents) +) ;
373+ $crate:: __inner_statics!( @sel $data, $( $idents) +) ;
296374
297375 /// HACK: Wrap the access in a non-generic, `#[inline(never)]`
298376 /// function to make the compiler group it into the same codegen unit
@@ -319,8 +397,44 @@ macro_rules! __sel_inner {
319397#[ macro_export]
320398#[ cfg( all( feature = "unstable-static-sel-inlined" ) ) ]
321399macro_rules! __sel_inner {
322- ( $( $args: tt) * ) => { {
323- $crate:: __sel_inner_statics!( $( $args) * ) ;
400+ ( $data: ident, $( $idents: ident) +) => { {
401+ $crate:: __inner_statics!( @image_info $( $idents) +) ;
402+ $crate:: __inner_statics!( @sel $data, $( $idents) +) ;
403+
404+ #[ allow( unused_unsafe) ]
405+ // SAFETY: See above
406+ unsafe { * REF . get( ) }
407+ } } ;
408+ }
409+
410+ #[ doc( hidden) ]
411+ #[ macro_export]
412+ #[ cfg( all(
413+ feature = "unstable-static-class" ,
414+ not( feature = "unstable-static-class-inlined" )
415+ ) ) ]
416+ macro_rules! __class_inner {
417+ ( $name: ident) => { {
418+ $crate:: __inner_statics!( @image_info $name) ;
419+ $crate:: __inner_statics!( @class $name) ;
420+
421+ // SAFETY: Same as __sel_inner
422+ #[ inline( never) ]
423+ fn objc_static_workaround( ) -> & ' static Class {
424+ unsafe { * REF . get( ) }
425+ }
426+
427+ objc_static_workaround( )
428+ } } ;
429+ }
430+
431+ #[ doc( hidden) ]
432+ #[ macro_export]
433+ #[ cfg( all( feature = "unstable-static-class-inlined" ) ) ]
434+ macro_rules! __class_inner {
435+ ( $name: ident) => { {
436+ $crate:: __inner_statics!( @image_info $name) ;
437+ $crate:: __inner_statics!( @class $name) ;
324438
325439 #[ allow( unused_unsafe) ]
326440 // SAFETY: See above
0 commit comments