<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/93410>93410</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Building the RPCS3 emulator with LTO "forced on" breaks on the link step
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          KyunLFA
      </td>
    </tr>
</table>

<pre>
    Admittedly this is a corner case as RPCS3 explicitly disallows LTO in their CMakeFiles as an old "bugfix" for a previous case where Qt apps would work properly in runtime when LTO'd, so I'd understand if this is deemed out of scope. That said, by bypassing that check and trying to build with LTO anyway, Clang fails at the link step with any linker and both Thin and Full LTO, **yet GCC passes and produces a working binary, which is the sole reason I decided to create this issue (had GCC also failed, I would assume it'd simply be a RPCS3 bug)**. Clang+LLD work fine when LTO is set to off.

With ThinLTO, lld (below it says "ld" but I've symlinked ld.lld to /usr/bin/ld) produces various link errors relating to Qt (that I assume is a mere coincidence) that I cannot reproduce with a similar project (also an emulator, C++ and Qt), the PS2 emulator PCSX2. Here are a few of the link errors, which are far too many to paste here:

```
ld: error: cannot preempt symbol: typeinfo for QCoreApplication
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>>               lto.tmp:(typeinfo for headless_application)

ld: error: cannot preempt symbol: QObject::metaObject() const
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QCoreApplication::event(QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::eventFilter(QObject*, QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>>               lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::timerEvent(QTimerEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::childEvent(QChildEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::customEvent(QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::connectNotify(QMetaMethod const&)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>>               lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QObject::disconnectNotify(QMetaMethod const&)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QCoreApplication::notify(QObject*, QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>>               lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QCoreApplication::compressEvent(QEvent*, QObject*, QPostEventList*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>>               lto.tmp:(vtable for headless_application)

ld: error: cannot preempt symbol: QCoreApplication::staticMetaObject
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by mocs_compilation.cpp
>>> lto.tmp:(headless_application::staticMetaObject)

ld: error: cannot preempt symbol: QObject::qt_metacast(char const*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::qt_metacall(QMetaObject::Call, int, void**)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::event(QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::timerEvent(QTimerEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::childEvent(QChildEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::customEvent(QEvent*)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::connectNotify(QMetaMethod const&)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: cannot preempt symbol: QObject::disconnectNotify(QMetaMethod const&)
>>> defined in /usr/lib/libQt6Core.so.6.7.1
>>> referenced by basic_keyboard_handler.cpp
>>>               lto.tmp:(vtable for basic_keyboard_handler)

ld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors)
```

I've also tried downgrading to Qt 6.6.3 which RPCS3 is intended to be used with as of now, with no change in this behavior.

With FullLTO, any linker will keep using RAM indefinitely. I know because I've built bigger programs that need a lot of RAM to compile, yet RPCS3 which is not that large comparatively, will keep wasting the entirety of my RAM, a whopping 192GB that is 96GB main memory + 96GB zRAM. Again, this behavior does not appear when using GCC instead of Clang.

Tested when building [RPCS3 from git source](https://github.com/RPCS3/rpcs3.git).

To test it yourself, patch into the RPCS3 tree:

```
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -116,20 +116,6 @@
 
 add_subdirectory(3rdparty)
 
-if (DISABLE_LTO)
-    if (CMAKE_C_FLAGS)
-        string(REGEX REPLACE "-flto[^ ]*" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
-    endif()
-    if (CMAKE_CXX_FLAGS)
-        string(REGEX REPLACE "-flto[^ ]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
- endif()
-endif()
-
-string(FIND "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}" "-flto" FOUND_LTO)
-if (NOT FOUND_LTO EQUAL -1)
-    message(FATAL_ERROR "RPCS3 doesn't support building with LTO, use -DDISABLE_LTO=TRUE to force-disable it")
-endif()
-
 if(NOT WIN32)
     add_compile_options(-pthread)
 endif()
```

If this turns out to be a bug solely on the RPCS3 side, I apologize in advance for wasting time.

LLVM versions tested: 19.0.0git ([e83f5c15003516d5e1e677890ddbbd44be8151f](https://github.com/llvm/llvm-project/commit/be83f5c15003516d5e1e677890ddbbd44be8151f)), 18.1.6, 17.0.6, no change in observed behavior
GCC version used (verified that this works with LTO): 14.1.1 20240522
Binutils version: 2.42.0
CFLAGS & CXXFLAGS: "-O3 -flto -march=znver4"
LDFLAGS: unset, except when specifying the linker with -fuse-ld
Host: AMD64 (Ryzen 9 7900X)
Distribution: CachyOS
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWllz27iT_zT0S5dYInQ_-EFnxjVyHDueHb-5QKIpYg0CXACUwnz6rQYp2Uo819ZmnNQ_LlniAfTx64tAkzsndxrxMhototHqgte-MPby16bW2838IjWiuZyLUnqPQjXgC-lAOuCQGavRQsYdAndw92H5cQD4qVIyk141IKTjSpmDg-39DUgNvkBpYXnNn3AjFTqaxTUYJSBiLK13ufwUMQa5scChsriXpnYtg0OBFuHWA68qBwdTKwEHY5-gsqZCqxpiYGvtZRkGa2IasYmI2BKcgSs6hloLtM5zLUDmJ1UEYokCTO3B5OAyU2EM9wX34LgMBNIG0qYipPQOPN3JCsyegAh524SrBtJaklTSF0FjrpsDb2j6UnG9g5xL5YB7wgGU1E_gPFbteK6bcAltoJkaX8B9IXU429RKteosIWLziM0b9PBuuQQSiXDUgnAQdUYnARcSKZWa2yDAoZBZQaoSa2cUgkXujIYrEJhJgYLkzyxyj0dYXI0QsWnBRWDFlTNBBQyIXHU24M7VJYL0AV8ny0o1kCLwzh_SehexWSt13AIRscV2u2qtl0v9bC4S0KEnUUyex1F_FfXn7ffvsgOkg0EFn5mmqMwBJBmqceRESpADpbUPBt8juKYMuApQIqZZ3kDENrWzEdukUkdsQ3Nmz_jtuQ1uFyyE1hrrwKLivrPyrSfOwQmuTuoT7CV5aGakJkB1hkS1G5ZxrY0Hix2XzuiEl1TcEvP_xiwQDjhzDVjWintjg_9EbBGxRbDzrQ94LoMpP3xkp4HwYfnxgcXwC4nB6R9yPJBHn_yt1ebZIWhUzi14Y6AkF_SGXMojULRFg_lLE0TjfvcJp0pEg3lLkQ46DSuLWFaeYE-Nohu-qVDq3ISovl0ai_OKUgT30uiO8mDdfkAgOYSgWD4ZScm0_b71Y5oeOxOP40mcfDnZYo6WgBcUr6XJ3GNmykqqwCrOqurLGed_ypvYlxWpzaZnYhfIhULnHvkL0dnsJTp_F47bm5QsTUwG8xI9787ZlNwlM9r5bwhKyp3MHp-wSQ234rHgWii0_xCaveepwgDM6_T-r9B86RwBI9yjJnhu1-3B_Jn6W7nNH6HxrdwkQLCRyhO00-MtQmIJ3xEsf89lvhVIVPjt-ugs9y_OvgNo_m0wskIqcQJj-eLsPxGM2nlTrn_mkcxojZl_b7zMG4LiGj2_Rl8Y0VUeNn57VN42jQjpfgyY_g1gXi3I-oTLz0L0p0CRlBadeyXzLOEL8D4Y58PtrXQ_QXwBovPcy-z6-UH5O4q6V5V_Xer_h8z0P_6R1gsZJweZZgW3x2z0jb3l-140vAqRUse8_fL2MlxfgqQoXMLeSNFuTPzE703WWj8OMG-2uPhxIHqzJccPBNFbLER-IHje_Ln7x8Hqu1imfA9wnbauu516bBtVoevjTVVJvQNtDhCxae0Qer0wrqdkKX00WPXBG3CIwJU6bY_PXt3wbr-7tkLYpfdWogBhDnpnuXhuD4zjcTzottjbLoh09NCBumu0pAi1w65VxB2YnGQM-_J0RRvICq532DbNpIMUC76Xxn7dE9nUSnU9kRc9pINUCp4QK6hDy-pufg1SB9NLj6qJ4QqeCJYUM064dGqltVQeUrnbYWhK7CwvXdvE0IgCOCgTmmRE0Bton5aRuDfoO2VPzSby4zBXcbvDMJhb7uUeVduVOkl54K5trxQIqL206BtiUzbEKSgHh6IzZzJj7xYtYelgNn63gJJLDSWWxjYQsUV78fPd_DqG-Y5L3fZLXgAJwmArIK8q5LbtQbVgvVvSI6LzyAXJEHpWZ8Dfo_NkPZoSen40KxotWvVza0rYSQ_O1DbDaLSipYL3lQsOv4nYZid9UadxZsqIbcKsiG1slblBvJO0WDhnZ8Cj8yA9NKa2DlVO-lTcE8zamwBby9xb_Iu-Ta_XAx6xTWjD0mrTxf7TcVkV2kwEYPpHI4b9aNiHXpKMI7ZkfUK7PR5De68dB90PF-LR1amQFjNvLOWpgRUVt745xVk3tidzitLV1cf5Yrt-DE7djehR1mhvL6_nv64fl4-b7fzdx_MB9Oe8lXoXsend-t36Ae7WH7bz5Roixnq58ia0uNcQbDKPGKMb9HNGFSI2jCaLc06T1Tkz1ELmbdfmj2R8ePg2Uh7pnst54nYm6ddifn2l-zkJtbl6v2pZvgbDn3BlzxowBpub396vzs3YwvP-5v75Jqxvf5tvoZeco1Sic3yHJM38fr59XN_d3dwR-dbNKXp1xCYeXF1VxvrnODy23ylEQsZfvfSower-7rc1pa7c2Ax7QrpQfijq2F-DBOEqKfD71fvB84RgVfL1LiE-mspLo13Epr3KFxa5eB77FfHXC033foKvrXbh3YS2cHBI613o4asGjH4R-04KbFvzvDLK7OTnUEC42HOdtRX2lGdliWc5Zrv9r2vYo3UkdUg3GOpsMov7cZ-yGQk8WuB0kI-yZNTvD0bJWIwwwfFkMp31hUhTMRymOE1GSf6XSU-p_fGn1zW_I7bJTEllmW3Sv8uHzbpueDKNk3gcjiZxvz06q6MmdWj39ODSlYBWcUr2nd5tTaZHErQyp9IeakywwsHYJ_fCt2YBnGGcxAmwPhv2R4y1BBdS114qd6RKA1k8ZHFn3eUxdsewfHhog2cwD5FzM4AQPdAruc2KaLD6rPdoh9GR9nZ1Gl9rh2EXAz9lWPm2GLkKM5k3x0p6ehjwBfTy2mFPiZbQL8bRgyTMr1fjIal813xGDTOYzPr9h5NjriQlhbTuNrZgybOiufl4IS4HYjaY8Qu8TCbJeMJGk8nworhMWcZGfJzwNEtHIu8Pp7NBP0vS4WCYTVI2uJCXHVjjhCXjZBjn6XiQz3CUJJjmyVBEwz6WXKqYPCM2dncRXkS5nA2GSf9C8RSVCy8qMabx0L6lQvCMVhf2MnhTWu9cNOyrULdOVLz0Ci8XxyTxHDSntydOr-1EjIXcIMDo8DKJRf7kjqF2em_norbq8h97eBDYRWzTKrS_ZP8bAAD__0Aol9U">