diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2016-04-28 17:09:37 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2016-04-28 17:09:37 +0000 |
commit | 5b0d0a649542308a8d3af58540e0c2e982d3fd57 (patch) | |
tree | d0927964549760317aee7a9adaf56df59fe57f1c /docs/LTOVisibility.rst | |
parent | 3d23e02ac6aa31efbaed83db5f16efe423d1a65f (diff) |
Re-apply r267784, r267824 and r267830.
I have updated the compiler-rt tests.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267903 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'docs/LTOVisibility.rst')
-rw-r--r-- | docs/LTOVisibility.rst | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/docs/LTOVisibility.rst b/docs/LTOVisibility.rst new file mode 100644 index 0000000000..21a3157c83 --- /dev/null +++ b/docs/LTOVisibility.rst @@ -0,0 +1,111 @@ +============== +LTO Visibility +============== + +*LTO visibility* is a property of an entity that specifies whether it can be +referenced from outside the current LTO unit. A *linkage unit* is a set of +translation units linked together into an executable or DSO, and a linkage +unit's *LTO unit* is the subset of the linkage unit that is linked together +using link-time optimization; in the case where LTO is not being used, the +linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit. + +The LTO visibility of a class is used by the compiler to determine which +classes the virtual function call optimization and control flow integrity +features apply to. These features use whole-program information, so they +require the entire class hierarchy to be visible in order to work correctly. + +If any translation unit in the program uses either of the virtual function +call optimization or control flow integrity features, it is effectively an +ODR violation to define a class with hidden LTO visibility in multiple linkage +units. A class with public LTO visibility may be defined in multiple linkage +units, but the tradeoff is that the virtual function call optimization and +control flow integrity features can only be applied to classes with hidden LTO +visibility. A class's LTO visibility is treated as an ODR-relevant property +of its definition, so it must be consistent between translation units. + +In translation units built with LTO, LTO visibility is based on symbol +visibility or, on the Windows platform, the dllimport and dllexport +attributes. When targeting non-Windows platforms, classes with a visibility +other than hidden visibility receive public LTO visibility. When targeting +Windows, classes with dllimport or dllexport attributes receive public LTO +visibility. All other classes receive hidden LTO visibility. Classes with +internal linkage (e.g. classes declared in unnamed namespaces) also receive +hidden LTO visibility. + +A class defined in a translation unit built without LTO receives public +LTO visibility regardless of its object file visibility, linkage or other +attributes. + +This mechanism will produce the correct result in most cases, but there are +two cases where it may wrongly infer hidden LTO visibility. + +1. As a corollary of the above rules, if a linkage unit is produced from a + combination of LTO object files and non-LTO object files, any hidden + visibility class defined in both a translation unit built with LTO and + a translation unit built without LTO must be defined with public LTO + visibility in order to avoid an ODR violation. + +2. Some ABIs provide the ability to define an abstract base class without + visibility attributes in multiple linkage units and have virtual calls + to derived classes in other linkage units work correctly. One example of + this is COM on Windows platforms. If the ABI allows this, any base class + used in this way must be defined with public LTO visibility. + +Classes that fall into either of these categories can be marked up with the +``[[clang::lto_visibility_public]]`` attribute. To specifically handle the +COM case, classes with the ``__declspec(uuid())`` attribute receive public +LTO visibility. On Windows platforms, clang-cl's ``/MT`` and ``/MTd`` +flags statically link the program against a prebuilt standard library; +these flags imply public LTO visibility for every class declared in the +``std`` and ``stdext`` namespaces. + +Example +======= + +The following example shows how LTO visibility works in practice in several +cases involving two linkage units, ``main`` and ``dso.so``. + +.. code-block:: none + + +-----------------------------------------------------------+ +----------------------------------------------------+ + | main (clang++ -fvisibility=hidden): | | dso.so (clang++ -fvisibility=hidden): | + | | | | + | +-----------------------------------------------------+ | | struct __attribute__((visibility("default"))) C { | + | | LTO unit (clang++ -fvisibility=hidden -flto): | | | virtual void f(); | + | | | | | } | + | | struct A { ... }; | | | void C::f() {} | + | | struct [[clang::lto_visibility_public]] B { ... }; | | | struct D { | + | | struct __attribute__((visibility("default"))) C { | | | virtual void g() = 0; | + | | virtual void f(); | | | }; | + | | }; | | | struct E : D { | + | | struct [[clang::lto_visibility_public]] D { | | | virtual void g() { ... } | + | | virtual void g() = 0; | | | }; | + | | }; | | | __attribute__(visibility("default"))) D *mkE() { | + | | | | | return new E; | + | +-----------------------------------------------------+ | | } | + | | | | + | struct B { ... }; | +----------------------------------------------------+ + | | + +-----------------------------------------------------------+ + +We will now describe the LTO visibility of each of the classes defined in +these linkage units. + +Class ``A`` is not defined outside of ``main``'s LTO unit, so it can have +hidden LTO visibility. This is inferred from the object file visibility +specified on the command line. + +Class ``B`` is defined in ``main``, both inside and outside its LTO unit. The +definition outside the LTO unit has public LTO visibility, so the definition +inside the LTO unit must also have public LTO visibility in order to avoid +an ODR violation. + +Class ``C`` is defined in both ``main`` and ``dso.so`` and therefore must +have public LTO visibility. This is correctly inferred from the ``visibility`` +attribute. + +Class ``D`` is an abstract base class with a derived class ``E`` defined +in ``dso.so``. This is an example of the COM scenario; the definition of +``D`` in ``main``'s LTO unit must have public LTO visibility in order to be +compatible with the definition of ``D`` in ``dso.so``, which is observable +by calling the function ``mkE``. |