17
17
/// ```
18
18
#[ macro_export]
19
19
macro_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 {
20
29
( $name: ident) => { {
21
30
use $crate:: __macro_helpers:: { concat, panic, stringify, CachedClass , None , Some } ;
22
31
static CACHED_CLASS : CachedClass = CachedClass :: new( ) ;
@@ -25,7 +34,7 @@ macro_rules! class {
25
34
let cls = unsafe { CACHED_CLASS . get( name) } ;
26
35
match cls {
27
36
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) , ) ,
29
38
}
30
39
} } ;
31
40
}
@@ -165,18 +174,12 @@ macro_rules! __sel_inner {
165
174
166
175
#[ doc( hidden) ]
167
176
#[ macro_export]
168
- macro_rules! __sel_inner_statics_apple_generic {
177
+ macro_rules! __inner_statics_apple_generic {
169
178
{
179
+ @image_info;
170
180
$image_info_section: literal;
171
- $var_name_section: literal;
172
- $selector_ref_section: literal;
173
- $data: ident,
174
181
$( $idents: ident) +
175
182
} => {
176
- use $crate:: __macro_helpers:: { __hash_idents, u8 , UnsafeCell } ;
177
- use $crate:: ffi:: __ImageInfo;
178
- use $crate:: runtime:: Sel ;
179
-
180
183
/// We always emit the image info tag, since we need it to:
181
184
/// - End up in the same codegen unit as the other statics below.
182
185
/// - End up in the final binary so it can be read by dyld.
@@ -185,9 +188,22 @@ macro_rules! __sel_inner_statics_apple_generic {
185
188
/// reports `__DATA/__objc_imageinfo has unexpectedly large size XXX`,
186
189
/// but things still seems to work.
187
190
#[ 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
+ ) ]
189
195
#[ 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 ;
191
207
192
208
const X : & [ u8 ] = $data. as_bytes( ) ;
193
209
@@ -241,47 +257,108 @@ macro_rules! __sel_inner_statics_apple_generic {
241
257
UnsafeCell :: new( Sel :: __internal_from_ptr( NAME_DATA . as_ptr( ) . cast( ) ) )
242
258
} ;
243
259
} ;
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
+ } ;
244
284
}
245
285
286
+ // These sections are found by reading clang/LLVM sources
246
287
#[ doc( hidden) ]
247
288
#[ macro_export]
248
289
#[ 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 ;
253
294
"__DATA,__objc_imageinfo,regular,no_dead_strip" ;
295
+ $( $args) *
296
+ }
297
+ } ;
298
+ ( @sel $( $args: tt) * ) => {
299
+ $crate:: __inner_statics_apple_generic! {
300
+ @sel;
254
301
"__TEXT,__objc_methname,cstring_literals" ;
255
302
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip" ;
256
303
$( $args) *
257
304
}
258
305
} ;
306
+ ( @class $( $args: tt) * ) => {
307
+ $crate:: __inner_statics_apple_generic! {
308
+ @class;
309
+ "__DATA,__objc_classrefs,regular,no_dead_strip" ;
310
+ $( $args) *
311
+ }
312
+ } ;
259
313
}
260
314
261
315
#[ doc( hidden) ]
262
316
#[ macro_export]
263
317
#[ 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;
267
322
"__OBJC,__image_info,regular" ;
323
+ $( $args) *
324
+ }
325
+ } ;
326
+ ( @sel $( $args: tt) * ) => {
327
+ $crate:: __inner_statics_apple_generic! {
328
+ @sel;
268
329
"__TEXT,__cstring,cstring_literals" ;
269
330
"__OBJC,__message_refs,literal_pointers,no_dead_strip" ;
270
331
$( $args) *
271
332
}
272
333
} ;
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
+ } ;
273
341
}
274
342
275
343
#[ doc( hidden) ]
276
344
#[ macro_export]
277
345
#[ 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) * ) => {
280
351
// TODO
281
352
$crate:: __macro_helpers:: compile_error!(
282
353
"The `\" unstable-static-sel\" ` feature is not yet supported on GNUStep!"
283
354
)
284
355
} ;
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
+ } ;
285
362
}
286
363
287
364
#[ doc( hidden) ]
@@ -291,8 +368,9 @@ macro_rules! __sel_inner_statics {
291
368
not( feature = "unstable-static-sel-inlined" )
292
369
) ) ]
293
370
macro_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) +) ;
296
374
297
375
/// HACK: Wrap the access in a non-generic, `#[inline(never)]`
298
376
/// function to make the compiler group it into the same codegen unit
@@ -319,8 +397,44 @@ macro_rules! __sel_inner {
319
397
#[ macro_export]
320
398
#[ cfg( all( feature = "unstable-static-sel-inlined" ) ) ]
321
399
macro_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) ;
324
438
325
439
#[ allow( unused_unsafe) ]
326
440
// SAFETY: See above
0 commit comments