|
Revision tags: llvmorg-20.1.0, llvmorg-20.1.0-rc3, llvmorg-20.1.0-rc2, llvmorg-20.1.0-rc1, llvmorg-21-init, llvmorg-19.1.7, llvmorg-19.1.6, llvmorg-19.1.5, llvmorg-19.1.4, llvmorg-19.1.3, llvmorg-19.1.2, llvmorg-19.1.1, llvmorg-19.1.0, llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3, llvmorg-19.1.0-rc2, llvmorg-19.1.0-rc1, llvmorg-20-init, llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6, llvmorg-18.1.5, llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2, llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4, llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1, llvmorg-19-init, llvmorg-17.0.6, llvmorg-17.0.5, llvmorg-17.0.4, llvmorg-17.0.3, llvmorg-17.0.2, llvmorg-17.0.1, llvmorg-17.0.0, llvmorg-17.0.0-rc4, llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2, llvmorg-17.0.0-rc1, llvmorg-18-init, llvmorg-16.0.6, llvmorg-16.0.5, llvmorg-16.0.4, llvmorg-16.0.3, llvmorg-16.0.2, llvmorg-16.0.1, llvmorg-16.0.0, llvmorg-16.0.0-rc4, llvmorg-16.0.0-rc3, llvmorg-16.0.0-rc2, llvmorg-16.0.0-rc1, llvmorg-17-init, llvmorg-15.0.7, llvmorg-15.0.6, llvmorg-15.0.5, llvmorg-15.0.4, llvmorg-15.0.3, llvmorg-15.0.2, llvmorg-15.0.1, llvmorg-15.0.0, llvmorg-15.0.0-rc3, llvmorg-15.0.0-rc2, llvmorg-15.0.0-rc1, llvmorg-16-init, llvmorg-14.0.6, llvmorg-14.0.5, llvmorg-14.0.4, llvmorg-14.0.3, llvmorg-14.0.2, llvmorg-14.0.1, llvmorg-14.0.0, llvmorg-14.0.0-rc4, llvmorg-14.0.0-rc3, llvmorg-14.0.0-rc2, llvmorg-14.0.0-rc1, llvmorg-15-init, llvmorg-13.0.1, llvmorg-13.0.1-rc3, llvmorg-13.0.1-rc2, llvmorg-13.0.1-rc1, llvmorg-13.0.0, llvmorg-13.0.0-rc4, llvmorg-13.0.0-rc3, llvmorg-13.0.0-rc2, llvmorg-13.0.0-rc1, llvmorg-14-init, llvmorg-12.0.1, llvmorg-12.0.1-rc4, llvmorg-12.0.1-rc3, llvmorg-12.0.1-rc2, llvmorg-12.0.1-rc1, llvmorg-12.0.0, llvmorg-12.0.0-rc5, llvmorg-12.0.0-rc4 |
| #
2f651660 |
| 16-Mar-2021 |
Nathan Lanza <[email protected]> |
[lld:elf] Weaken the requirement for a computed binding to be STB_LOCAL
Given the following scenario:
``` // Cat.cpp struct Animal { virtual void makeNoise() const = 0; }; struct Cat : Animal { voi
[lld:elf] Weaken the requirement for a computed binding to be STB_LOCAL
Given the following scenario:
``` // Cat.cpp struct Animal { virtual void makeNoise() const = 0; }; struct Cat : Animal { void makeNoise() const override; };
extern "C" int puts(char const *); void Cat::makeNoise() const { puts("Meow"); } void doThingWithCat(Animal *a) { static_cast<Cat *>(a)->makeNoise(); }
// CatUser.cpp struct Animal { virtual void makeNoise() const = 0; }; struct Cat : Animal { void makeNoise() const override; };
void doThingWithCat(Animal *a);
void useDoThingWithCat() { Cat *d = new Cat; doThingWithCat(d); }
// cat.ver { global: _Z17useDoThingWithCatv; local: *; };
$ clang++ Cat.cpp CatUser.cpp -fpic -flto=thin -fwhole-program-vtables -shared -O3 -fuse-ld=lld -Wl,--lto-whole-program-visibility -Wl,--version-script,cat.ver ```
We cannot devirtualize `Cat::makeNoise`. The issue is complex:
Due to `-fsplit-lto-unit` and usage of type metadata, we place the Cat vtable declaration into module 0 and the Cat vtable definition with type metadata into module 1, causing duplicate entries (Undefined followed by Defined) in the `lto::InputFile::symbols()` output. In `BitcodeFile::parse`, after processing the `Undefined` then the `Defined`, the final state is `Defined`. In `BitcodeCompiler::add`, for the first symbol, `computeBinding` returns `STB_LOCAL`, then we reset it to `Undefined` because it is prevailing (`versionId` is `preserved`). For the second symbol, because the state is now `Undefined`, `computeBinding` returns `STB_GLOBAL`, causing `ExportDynamic` to be true and suppressing devirtualization.
In D77280, the `computeBinding` change used a stricter `isDefined()` condition to make weak``Lazy` symbol work. This patch relaxes the condition to weaker `!isLazy()` to keep it working while making the devirtualization work as well.
Differential Revision: https://reviews.llvm.org/D98686
show more ...
|