forked from OSchip/llvm-project
2f65166056
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 |
||
---|---|---|
.. | ||
COFF | ||
ELF | ||
MachO | ||
MinGW | ||
Unit | ||
darwin | ||
mach-o | ||
wasm | ||
CMakeLists.txt | ||
lit.cfg.py | ||
lit.site.cfg.py.in |