@@ -16,6 +16,7 @@ use rustc_middle::mir::mono::MonoItem;
1616use rustc_middle:: ty:: layout:: { HasTypingEnv , LayoutOf } ;
1717use rustc_middle:: ty:: { self , Instance } ;
1818use rustc_middle:: { bug, span_bug} ;
19+ use rustc_span:: Symbol ;
1920use tracing:: { debug, instrument, trace} ;
2021
2122use crate :: common:: CodegenCx ;
@@ -331,6 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
331332 }
332333
333334 g
335+ } else if let Some ( classname) = fn_attrs. objc_class {
336+ self . get_objc_classref ( classname)
337+ } else if let Some ( methname) = fn_attrs. objc_selector {
338+ self . get_objc_selref ( methname)
334339 } else {
335340 check_and_apply_linkage ( self , fn_attrs, llty, sym, def_id)
336341 } ;
@@ -544,6 +549,165 @@ impl<'ll> CodegenCx<'ll, '_> {
544549 pub ( crate ) fn add_compiler_used_global ( & mut self , global : & ' ll Value ) {
545550 self . compiler_used_statics . push ( global) ;
546551 }
552+
553+ fn define_objc_classname ( & self , classname : & str ) -> & ' ll Value {
554+ // 32-bit x86 macOS only.
555+ assert_eq ! ( self . tcx. sess. target. arch, "x86" ) ;
556+ assert_eq ! ( self . tcx. sess. target. os, "macos" ) ;
557+
558+ let llval = self . null_terminate_const_bytes ( classname. as_bytes ( ) ) ;
559+ let llty = self . val_ty ( llval) ;
560+ let sym = self . generate_local_symbol_name ( "OBJC_CLASS_NAME_" ) ;
561+ let g = self . define_global ( & sym, llty) . unwrap_or_else ( || {
562+ bug ! ( "symbol `{}` is already defined" , sym) ;
563+ } ) ;
564+ set_global_alignment ( self , g, self . tcx . data_layout . i8_align . abi ) ;
565+ llvm:: set_initializer ( g, llval) ;
566+ llvm:: set_linkage ( g, llvm:: Linkage :: PrivateLinkage ) ;
567+ llvm:: set_section ( g, c"__TEXT,__cstring,cstring_literals" ) ;
568+ llvm:: LLVMSetGlobalConstant ( g, llvm:: True ) ;
569+ llvm:: LLVMSetUnnamedAddress ( g, llvm:: UnnamedAddr :: Global ) ;
570+ g
571+ }
572+
573+ fn get_objc_class_t ( & self ) -> & ' ll Type {
574+ if let Some ( class_t) = self . objc_class_t . get ( ) {
575+ return class_t;
576+ }
577+
578+ // Darwin-like targets other than 32-bit x86 macOS.
579+ assert ! ( self . tcx. sess. target. is_like_darwin) ;
580+ assert ! ( self . tcx. sess. target. arch != "x86" || self . tcx. sess. target. os != "macos" ) ;
581+
582+ let class_t = self . type_named_struct ( "struct._class_t" ) ;
583+ let els = [ self . type_ptr ( ) ; 5 ] ;
584+ let packed = false ;
585+ self . set_struct_body ( class_t, & els, packed) ;
586+
587+ self . objc_class_t . set ( Some ( class_t) ) ;
588+ class_t
589+ }
590+
591+ fn get_objc_classref ( & self , classname : Symbol ) -> & ' ll Value {
592+ let mut classrefs = self . objc_classrefs . borrow_mut ( ) ;
593+ if let Some ( classref) = classrefs. get ( & classname) . copied ( ) {
594+ return classref;
595+ }
596+
597+ let g = if self . tcx . sess . target . arch == "x86" && self . tcx . sess . target . os == "macos" {
598+ // 32-bit x86 macOS.
599+ let llval = self . define_objc_classname ( classname. as_str ( ) ) ;
600+ let llty = self . type_ptr ( ) ;
601+ let sym = self . generate_local_symbol_name ( "OBJC_CLASS_REFERENCES_" ) ;
602+ let g = self . define_global ( & sym, llty) . unwrap_or_else ( || {
603+ bug ! ( "symbol `{}` is already defined" , sym) ;
604+ } ) ;
605+ set_global_alignment ( self , g, self . tcx . data_layout . pointer_align ( ) . abi ) ;
606+ llvm:: set_initializer ( g, llval) ;
607+ llvm:: set_linkage ( g, llvm:: Linkage :: PrivateLinkage ) ;
608+ llvm:: set_section ( g, c"__OBJC,__cls_refs,literal_pointers" ) ;
609+ g
610+ } else {
611+ // Darwin-like targets other than 32-bit x86 macOS.
612+ assert ! ( self . tcx. sess. target. is_like_darwin) ;
613+ let llval = {
614+ let extern_sym = format ! ( "OBJC_CLASS_$_{}" , classname. as_str( ) ) ;
615+ let extern_llty = self . get_objc_class_t ( ) ;
616+ self . declare_global ( & extern_sym, extern_llty)
617+ } ;
618+ let llty = self . type_ptr ( ) ;
619+ let sym = self . generate_local_symbol_name ( "OBJC_CLASSLIST_REFERENCES_$_" ) ;
620+ let g = self . define_global ( & sym, llty) . unwrap_or_else ( || {
621+ bug ! ( "symbol `{}` is already defined" , sym) ;
622+ } ) ;
623+ set_global_alignment ( self , g, self . tcx . data_layout . pointer_align ( ) . abi ) ;
624+ llvm:: set_initializer ( g, llval) ;
625+ llvm:: set_linkage ( g, llvm:: Linkage :: InternalLinkage ) ;
626+ llvm:: set_section ( g, c"__DATA,__objc_classrefs,regular" ) ;
627+ g
628+ } ;
629+
630+ classrefs. insert ( classname, g) ;
631+ g
632+ }
633+
634+ fn get_objc_selref ( & self , methname : Symbol ) -> & ' ll Value {
635+ let mut selrefs = self . objc_selrefs . borrow_mut ( ) ;
636+ if let Some ( selref) = selrefs. get ( & methname) . copied ( ) {
637+ return selref;
638+ }
639+
640+ // Darwin-like targets only.
641+ assert ! ( self . tcx. sess. target. is_like_darwin) ;
642+ let is_x86_32_macos =
643+ self . tcx . sess . target . arch == "x86" && self . tcx . sess . target . os == "macos" ;
644+
645+ let methname_llval = self . null_terminate_const_bytes ( methname. as_str ( ) . as_bytes ( ) ) ;
646+ let methname_llty = self . val_ty ( methname_llval) ;
647+ let methname_sym = self . generate_local_symbol_name ( "OBJC_METH_VAR_NAME_" ) ;
648+ let methname_g = self . define_global ( & methname_sym, methname_llty) . unwrap_or_else ( || {
649+ bug ! ( "symbol `{}` is already defined" , methname_sym) ;
650+ } ) ;
651+ set_global_alignment ( self , methname_g, self . tcx . data_layout . i8_align . abi ) ;
652+ llvm:: set_initializer ( methname_g, methname_llval) ;
653+ llvm:: set_linkage ( methname_g, llvm:: Linkage :: PrivateLinkage ) ;
654+ if is_x86_32_macos {
655+ llvm:: set_section ( methname_g, c"__TEXT,__cstring,cstring_literals" ) ;
656+ } else {
657+ llvm:: set_section ( methname_g, c"__TEXT,__objc_methname,cstring_literals" ) ;
658+ }
659+ llvm:: LLVMSetGlobalConstant ( methname_g, llvm:: True ) ;
660+ llvm:: LLVMSetUnnamedAddress ( methname_g, llvm:: UnnamedAddr :: Global ) ;
661+
662+ let selref_llval = methname_g;
663+ let selref_llty = self . type_ptr ( ) ;
664+ let selref_sym = self . generate_local_symbol_name ( "OBJC_SELECTOR_REFERENCES_" ) ;
665+ let selref_g = self . define_global ( & selref_sym, selref_llty) . unwrap_or_else ( || {
666+ bug ! ( "symbol `{}` is already defined" , selref_sym) ;
667+ } ) ;
668+ set_global_alignment ( self , selref_g, self . tcx . data_layout . pointer_align ( ) . abi ) ;
669+ llvm:: set_initializer ( selref_g, selref_llval) ;
670+ if is_x86_32_macos {
671+ llvm:: set_linkage ( selref_g, llvm:: Linkage :: PrivateLinkage ) ;
672+ llvm:: set_section ( selref_g, c"__OBJC,__message_refs,literal_pointers" ) ;
673+ } else {
674+ llvm:: set_linkage ( selref_g, llvm:: Linkage :: InternalLinkage ) ;
675+ llvm:: set_section ( selref_g, c"__DATA,__objc_selrefs,literal_pointers" ) ;
676+ }
677+
678+ selrefs. insert ( methname, selref_g) ;
679+ selref_g
680+ }
681+
682+ pub ( crate ) fn define_objc_module_info ( & mut self ) {
683+ // 32-bit x86 macOS only.
684+ assert_eq ! ( self . tcx. sess. target. arch, "x86" ) ;
685+ assert_eq ! ( self . tcx. sess. target. os, "macos" ) ;
686+
687+ let llty = self . type_named_struct ( "struct._objc_module" ) ;
688+ let i32_llty = self . type_i32 ( ) ;
689+ let ptr_llty = self . type_ptr ( ) ;
690+ let packed = false ;
691+ self . set_struct_body ( llty, & [ i32_llty, i32_llty, ptr_llty, ptr_llty] , packed) ;
692+
693+ let version = self . const_uint ( i32_llty, 7 ) ;
694+ let size = self . const_uint ( i32_llty, 16 ) ;
695+ let name = self . define_objc_classname ( "" ) ;
696+ let symtab = self . const_null ( ptr_llty) ;
697+ let packed = false ;
698+ let llval = self . const_struct ( & [ version, size, name, symtab] , packed) ;
699+
700+ let sym = "OBJC_MODULES" ;
701+ let g = self . define_global ( & sym, llty) . unwrap_or_else ( || {
702+ bug ! ( "symbol `{}` is already defined" , sym) ;
703+ } ) ;
704+ set_global_alignment ( self , g, self . tcx . data_layout . pointer_align ( ) . abi ) ;
705+ llvm:: set_initializer ( g, llval) ;
706+ llvm:: set_linkage ( g, llvm:: Linkage :: PrivateLinkage ) ;
707+ llvm:: set_section ( g, c"__OBJC,__module_info,regular,no_dead_strip" ) ;
708+
709+ self . add_compiler_used_global ( g) ;
710+ }
547711}
548712
549713impl < ' ll > StaticCodegenMethods for CodegenCx < ' ll , ' _ > {
0 commit comments