Issue 56034
Summary Add support for _objc_msgSend stubs from Xcode 14
Labels lld:MachO
Assignees keith
Reporter keith
    In Xcode 14 / ld 816 Apple implemented a size / performance optimization where they deduplicate _objc_msgSend setup infrastructure by Objective-C selectors. This comes in the form of undefined symbols in each object file:

```objc
@import Foundation;

@interface Foo : NSObject
@end

@implementation Foo
- (void)bar {
    NSLog(@"%@", self);
}

@end

int main() {
    Foo *foo = [[Foo alloc] init];
    [foo bar];
    return 0;
}
```

```
% DEVELOPER_DIR=/Applications/Xcode-14.0.0-beta1.app clang foo.m -o foo.o -fmodules -c
% nm easy.o | grep objc_msg
                 U _objc_msgSend$bar
```

Then the linker inserts these stubs during link, one for each selector string after the `$` (see the final symbol):

```
% nm -format=darwin foo
0000000100003ecc (__TEXT,__text) non-external -[Foo bar]
                 (undefined) external _NSLog (from Foundation)
00000001000080c8 (__DATA,__objc_data) external _OBJC_CLASS_$_Foo
                 (undefined) external _OBJC_CLASS_$_NSObject (from libobjc)
00000001000080a0 (__DATA,__objc_data) external _OBJC_METACLASS_$_Foo
                 (undefined) external _OBJC_METACLASS_$_NSObject (from libobjc)
0000000100003f80 (__TEXT,__objc_methlist) non-external __OBJC_$_INSTANCE_METHODS_Foo
0000000100008048 (__DATA,__objc_const) non-external __OBJC_CLASS_RO_$_Foo
0000000100008000 (__DATA,__objc_const) non-external __OBJC_METACLASS_RO_$_Foo
                 (undefined) external ___CFConstantStringClassReference (from CoreFoundation)
0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
                 (undefined) external __objc_empty_cache (from libobjc)
0000000100003f04 (__TEXT,__text) external _main
                 (undefined) external _objc_alloc_init (from libobjc)
                 (undefined) external _objc_msgSend (from libobjc)
0000000100003f60 (__TEXT,__objc_stubs) non-external (was a private external) _objc_msgSend$bar
```

This new feature is enabled by default in Apple clang 14, and doesn't seem to be in Apple's public fork. It can be disabled in the meantime by passing `-fno-objc-msgsend-selector-stubs` to all clang compiles.

The reason behind this feature is explained in [this WWDC session](https://developer.apple.com/wwdc22/110363) but the gist is them trying to dedup the duplicate setup code that was previously inlined for each objc_msgSend call.

The implementation of these symbols is also described in that session, the linker has 2 modes, the default mode (which is the same as passing `-objc_stubs_fast`) produces this asm on arm64:

```s
_objc_msgSend$bar:
adrp       x1, #0x100008000                            ; 0x100008090@PAGE, CODE XREF=_main+48
ldr        x1, [x1, #0x90]                             ; 0x100008090@PAGEOFF, "bar",@selector(bar)
adrp       x16, #0x100004000                           ; 0x100004010@PAGE
ldr        x16, [x16, #0x10]                           ; 0x100004010@PAGEOFF, _objc_msgSend_100004010,_objc_msgSend
br         x16                                         ; _objc_msgSend
```

Where the other mode optimizing for size, controlled by passing `-objc_stubs_small` produces this asm on arm64:

```s
_objc_msgSend$bar:
adrp       x1, #0x100008000                            ; 0x100008090@PAGE, CODE XREF=_main+48
ldr        x1, [x1, #0x90]                             ; 0x100008090@PAGEOFF, argument "selector" for method imp___stubs__objc_msgSend, "bar",@selector(bar)
b          imp___stubs__objc_msgSend                   ; objc_msgSend
```

The major difference here being the extra inline instruction size, vs the extra jump to the objc_msgSend stub.

Some other various notes:

- Apple implements these stubs in the `__TEXT,__objc_stubs` section
- The addresses of the selector loads points to the selectors in the `__selrefs` section which lld does not currently implement
- Passing `-fno-objc-msgsend-selector-stubs` to all clang invocations is the only way I see to disable (note this flag is undocumented)
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to