1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
|
LLVM Interface Export Annotations
=================================
Symbols that are part of LLVM's public interface must be explicitly annotated
to support shared library builds with hidden default symbol visibility. This
document provides background and guidelines for annotating the codebase.
LLVM Shared Library
-------------------
LLVM builds as a static library by default, but it can also be built as a shared
library with the following configuration:
::
LLVM_BUILD_LLVM_DYLIB=On
LLVM_LINK_LLVM_DYLIB=On
There are three shared library executable formats we're interested in: PE
Dynamic Link Library (.dll) on Windows, Mach-O Shared Object (.dylib) on Apple
systems, and ELF Shared Object (.so) on Linux, BSD and other Unix-like systems.
ELF and Mach-O Shared Object files can be built with no additional setup or
configuration. This is because all global symbols in the library are exported by
default -- the same as when building a static library. However, when building a
DLL for Windows, the situation is more complex:
- Symbols are not exported from a DLL by default. Symbols must be annotated with
``__declspec(dllexport)`` when building the library to be externally visible.
- Symbols imported from a Windows DLL should generally be annotated with
``__declspec(dllimport)`` when compiling clients.
- A single Windows DLL can export a maximum of 65,535 symbols.
Because of the requirements for Windows DLLs, additional work must be done to
ensure the proper set of public symbols is exported and visible to clients.
Annotation Macros
-----------------
The distinct DLL import and export annotations required for Windows DLLs
typically lead developers to define a preprocessor macro for annotating
exported symbols in header public files. The custom macro resolves to the
**export** annotation when building the library and the **import** annotation
when building the client.
We have defined the ``LLVM_ABI`` macro in `llvm/Support/Compiler.h
<https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Support/Compiler.h#L152>`__
for this purpose:
.. code:: cpp
#if defined(LLVM_EXPORTS)
#define LLVM_ABI __declspec(dllexport)
#else
#define LLVM_ABI __declspec(dllimport)
#endif
Windows DLL symbol visibility requirements are approximated on ELF and Mach-O
shared library builds by setting default symbol visibility to hidden
(``-fvisibility-default=hidden``) when building with the following
configuration:
::
LLVM_BUILD_LLVM_DYLIB_VIS=On
For an ELF or Mach-O platform with this setting, the ``LLVM_ABI`` macro is
defined to override the default hidden symbol visibility:
.. code:: cpp
#define LLVM_ABI __attribute__((visibility("default")))
In addition to ``LLVM_ABI``, there are a few other macros for use in less
common cases described below.
Export macros are used to annotate symbols only within their intended shared
library. This is necessary because of the way Windows handles import/export
annotations.
For example, ``LLVM_ABI`` resolves to ``__declspec(dllexport)`` only when
building source that is part of the LLVM shared library (e.g. source under
``llvm-project/llvm``). If ``LLVM_ABI`` were incorrectly used to annotate a
symbol from a different LLVM project (such as Clang) it would always resolve to
``__declspec(dllimport)`` and the symbol would not be properly exported.
How to Annotate Symbols
-----------------------
Functions
~~~~~~~~~
Exported function declarations in header files must be annotated with
``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
LLVM_ABI void exported_function(int a, int b);
Global Variables
~~~~~~~~~~~~~~~~
Exported global variables must be annotated with ``LLVM_ABI`` at their
``extern`` declarations.
.. code:: cpp
#include "llvm/Support/Compiler.h"
LLVM_ABI extern int exported_global_variable;
Classes, Structs, and Unions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Classes, structs, and unions can be annotated with ``LLVM_ABI`` at their
declaration, but this option is generally discouraged because it will
export every class member, vtable, and type information. Instead, ``LLVM_ABI``
should be applied to individual class members that require export.
In the most common case, public and protected methods without a body in the
class declaration must be annotated with ``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
class ExampleClass {
public:
// Public methods defined externally must be annotated.
LLVM_ABI int sourceDefinedPublicMethod(int a, int b);
// Methods defined in the class definition do not need annotation.
int headerDefinedPublicMethod(int a, int b) {
return a + b;
}
// Constructors and destructors must be annotated if defined externally.
ExampleClass() {}
LLVM_ABI ~ExampleClass();
// Public static methods defined externally must be annotated.
LLVM_ABI static int sourceDefinedPublicStaticMethod(int a, int b);
};
Additionally, public and protected static fields that are not initialized at
declaration must be annotated with ``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
class ExampleClass {
public:
// Public static fields defined externally must be annotated.
LLVM_ABI static int mutableStaticField;
LLVM_ABI static const int constStaticField;
// Static members initialized at declaration do not need to be annotated.
static const int initializedConstStaticField = 0;
static constexpr int initializedConstexprStaticField = 0;
};
Private methods may also require ``LLVM_ABI`` annotation. This situation occurs
when a method defined in a header calls the private method. The private method
call may be from within the class or a friend class or method.
.. code:: cpp
#include "llvm/Support/Compiler.h"
class ExampleClass {
private:
// Private methods must be annotated if referenced by a public method defined a
// header file.
LLVM_ABI int privateMethod(int a, int b);
public:
// Inlineable method defined in the class definition calls a private method
// defined externally. If the private method is not annotated for export, this
// method will fail to link.
int publicMethod(int a, int b) {
return privateMethod(a, b);
}
};
There are less common cases where you may also need to annotate an inline
function even though it is fully defined in a header. Annotating an inline
function for export does not prevent it being inlined into client code. However,
it does ensure there is a single, stable address for the function exported from
the shared library.
.. code:: cpp
#include "llvm/Support/Compiler.h"
// Annotate the function so it is exported from the library at a fixed
// address.
LLVM_ABI inline int inlineFunction(int a, int b) {
return a + b;
}
Similarly, if a stable pointer-to-member function address is required for a
method in a C++ class, it may be annotated for export.
.. code:: cpp
#include "llvm/Support/Compiler.h"
class ExampleClass {
public:
// Annotate the method so it is exported from the library at a fixed
// address.
LLVM_ABI inline int inlineMethod(int a, int b) {
return a + b;
}
};
.. note::
When an inline function is annotated for export, the header containing the
function definition **must** be included by at least one of the library's
source files or the function will never be compiled with the export
annotation.
Friend Functions
~~~~~~~~~~~~~~~~
Friend functions declared in a class, struct or union must be annotated with
``LLVM_ABI`` if the corresponding function declaration is annotated with
``LLVM_ABI``. This requirement applies even when the class containing the friend
declaration is annotated with ``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
// An exported function that has friend access to ExampleClass internals.
LLVM_ABI int friend_function(ExampleClass &obj);
class ExampleClass {
// Friend declaration of a function must be annotated the same as the actual
// function declaration.
LLVM_ABI friend int friend_function(ExampleClass &obj);
};
.. note::
Annotating the friend declaration avoids an “inconsistent dll linkage”
compiler error when building a DLL for Windows.
Virtual Table and Type Info
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Classes and structs with exported virtual methods, including child classes that
export overridden virtual methods, must also export their vtable for ELF and
Mach-O builds. This can be achieved by annotating the class rather than
individual class members.
The general rule here is to annotate at the class level if any out-of-line
method is declared ``virtual`` or ``override``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
// Annotating the class exports vtable and type information as well as all
// class members.
class LLVM_ABI ParentClass {
public:
virtual int virtualMethod(int a, int b);
virtual int anotherVirtualMethod(int a, int b);
virtual ~ParentClass();
};
class LLVM_ABI ChildClass : public ParentClass {
public:
// Inline method override does not require the class be annotated.
int virtualMethod(int a, int b) override {
return ParentClass::virtualMethod(a, b);
}
// Overriding a virtual method from the parent requires the class be
// annotated.
int pureVirtualMethod(int a, int b) override;
~ChildClass();
};
.. note::
If a class is annotated, none of its members may be annotated. If class- and
member-level annotations are combined on a class, it will fail compilation on
Windows.
Compilation Errors
++++++++++++++++++
Annotating a class with ``LLVM_ABI`` causes the compiler to fully instantiate
the class at compile time. This requires exporting every method that could be
potentially used by a client even though no existing clients may actually use
them. This can cause compilation errors that were not previously present.
The most common type of error occurs when the compiler attempts to instantiate
and export a class' implicit copy constructor and copy assignment operator. If
the class contains move-only members that cannot be copied (``std::unique_ptr``
for example), the compiler will fail to instantiate these implicit
methods.
This problem is easily addressed by explicitly deleting the class' copy
constructor and copy assignment operator:
.. code:: cpp
#include "llvm/Support/Compiler.h"
class LLVM_ABI ExportedClass {
public:
ExportedClass() = default;
// Explicitly delete the copy constructor and assignment operator.
ExportedClass(ExportedClass const&) = delete;
ExportedClass& operator=(ExportedClass const&) = delete;
};
We know this modification is harmless because any clients attempting to use
these methods already would fail to compile. For a more detailed explanation,
see `this Microsoft dev blog
<https://devblogs.microsoft.com/oldnewthing/20190927-00/?p=102932>`__.
Templates
~~~~~~~~~
Most template classes are entirely header-defined and do not need to be exported
because they will be instantiated and compiled into the client as needed. Such
template classes require no export annotations. However, there are some less
common cases where annotations are required for templates.
Specialized Template Functions
++++++++++++++++++++++++++++++
As with any other exported function, an exported specialization of a template
function not defined in a header file must have its declaration annotated with
``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
template <typename T> T templateMethod(T a, T b) {
return a + b;
}
// The explicitly specialized definition of templateMethod for int is located in
// a source file. This declaration must be annotated with LLVM_ABI to export it.
template <> LLVM_ABI int templateMethod(int a, int b);
Similarly, an exported specialization of a method in a template class must have
its declaration annotated with ``LLVM_ABI``.
.. code:: cpp
#include "llvm/Support/Compiler.h"
template <typename T> class TemplateClass {
public:
int method(int a, int b) {
return a + b;
}
};
// The explicitly specialized definition of method for int is defined in a
// source file. The declaration must be annotated with LLVM_ABI to export it.
template <> LLVM_ABI int TemplateStruct<int>::method(int a, int b);
Explicitly Instantiated Template Classes
++++++++++++++++++++++++++++++++++++++++
Explicitly instantiated template classes must be annotated with
template-specific annotations at both declaration and definition.
An extern template instantiation in a header file must be annotated with
``LLVM_TEMPLATE_ABI``. This will typically be located in a header file.
.. code:: cpp
#include "llvm/Support/Compiler.h"
template <typename T> class TemplateClass {
public:
TemplateClass(T val) : val_(val) {}
T get() const { return val_; }
private:
const T val_;
};
// Explicitly instantiate and export TempalateClass for int type.
extern template class LLVM_TEMPLATE_ABI TemplateClass<int>;
The corresponding definition of the template instantiation must be annotated
with ``LLVM_EXPORT_TEMPLATE``. This will typically be located in a source file.
.. code:: cpp
#include "TemplateClass.h"
// Explicitly instantiate and export TempalateClass for int type.
template class LLVM_EXPORT_TEMPLATE TemplateClass<int>;
|