[all-commits] [llvm/llvm-project] 6758be: [ObjC] Support emission of selector stubs calls in...

Akira Hatanaka via All-commits all-commits at lists.llvm.org
Wed Mar 11 13:21:32 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 6758becb8f19593f5341b2e4d575dbf411ad706e
      https://github.com/llvm/llvm-project/commit/6758becb8f19593f5341b2e4d575dbf411ad706e
  Author: Akira Hatanaka <ahatanak at gmail.com>
  Date:   2026-03-11 (Wed, 11 Mar 2026)

  Changed paths:
    M clang/include/clang/Basic/CodeGenOptions.def
    M clang/include/clang/Options/Options.td
    M clang/lib/CodeGen/CGObjCMac.cpp
    M clang/lib/Driver/ToolChains/Clang.cpp
    M clang/lib/Driver/ToolChains/Darwin.cpp
    A clang/test/CodeGenObjC/method-selector-stub.m
    A clang/test/Driver/darwin-objc-selector-stubs.m

  Log Message:
  -----------
  [ObjC] Support emission of selector stubs calls instead of objc_msgSend. (#183922)

This optimizes objc_msgSend calls by emitting "selector stubs" instead.

Usually, the linker redirects calls to external symbols to a symbol stub
it generates, which loads the target function's address from the GOT and
branches to it:

  <symbol stub for _func:>
    adrp x16, _func at GOTPAGE
    ldr x16, [x16, _func at GOTPAGEOFF]
    br x16

with msgSend selector stubs, we extend that to compute the selector as
well:

  <selector stub for "foo":>
    adrp x1, <selector ref for "foo">@PAGE
    ldr x1, [x1, <selector ref for "foo">@PAGEOFF]
    adrp x16, _objc_msgSend at GOTPAGE
    ldr x16, [x16, _objc_msgSend at GOTPAGEOFF]
    br x16

This lets us avoid loading the selector in the compiler, hopefully
leading to codesize reductions.

We're considering two kinds of stubs, the combined one above with the
objc_msgSend dispatch included, or a shorter one that forwards to the
existing stub for objc_msgSend. That's a decision to be made in the
linker.

Concretely, instead of something like:

  %sel = load i8*, i8** @<selector ref for "foo">
  call ... @objc_msgSend(i8* self, i8* sel)

we emit a call to a newly-declared external "function":

  call ... @"objc_msgSend$foo"(i8* self, i8* undef)

where "objc_msgSend$foo" is treated as any other external symbol
reference throughout the compiler, and, at link-time, is recognized by
the linker as a selector stub.

There are other ways to implement this. An obvious one is to combine
away the objc_msgSend(self, load(sel)) pattern at the IR level.

Both seem feasible, but the IRGen approach might save us a tiny bit of
compile-time, with the assumption that loads need more mid-level
analysis than boring external functions.

This optimization requires linker version 811.2 or newer for arm64,
arm64e, and arm64_32.

rdar://84437635



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list