Applications that do not require symbol preemption or position-independent code can obtain a performance benefit by taking advantage of the generic ABI visibility attributes.
Note
The visibility options are supported by both IA-32 and ItaniumŪ compilers, but currently the optimization benefits are for Itanium-based systems only.
A global symbol is a symbol that is visible outside the compilation unit in which it is declared (compilation unit is a single-source file with the associated include files). Each global symbol definition or reference in a compilation unit has a visibility attribute that controls how it may be referenced from outside the component in which it is defined. The values for visibility are defined in the table that follows.
Value |
Description |
---|---|
EXTERN |
The compiler must treat the symbol as though it is defined in another component. This means that the compiler must assume that the symbol will be overridden (preempted) by a definition of the same name in another component. (See Symbol Preemption.) If a function symbol has external visibility, the compiler knows that it must be called indirectly and can inline the indirect call stub. |
DEFAULT |
Other components can reference the symbol. Furthermore, the symbol definition may be overridden (preempted) by a definition of the same name in another component. |
PROTECTED |
Other components can reference the symbol, but it cannot be preempted by a definition of the same name in another component. |
HIDDEN |
Other components cannot directly reference the symbol. However, its address might be passed to other components indirectly; for example, as an argument to a call to a function in another component, or by having its address stored in a data item referenced by a function in another component. |
INTERNAL |
The symbol cannot be referenced outside the component where it is defined, either directly or indirectly. |
Note
Visibility applies to both references and definitions. A symbol reference's visibility attribute is an assertion that the corresponding definition will have that visibility.
Sometimes programmers need to use some of the functions or data items from a shareable object, but at the same time, they need to replace other items with definitions of their own. For example, an application may need to use the standard run-time library shareable object, libc.so, but to use its own definitions of the heap management routines malloc and free.
Note
Linux* Only: In this case it is important that calls to malloc and free within libc.so use the user's definition of the routines and not the definitions in libc.so. The user's definition should then override, or preempt, the definition within the shareable object.
This functionality of redefining the items in shareable objects is called symbol preemption. When the run-time loader loads a component, all symbols within the component that have default visibility are subject to preemption by symbols of the same name in components that are already loaded. Note that since the main program image is always loaded first, none of the symbols it defines will be preempted (redefined).
The possibility of symbol preemption inhibits many valuable compiler optimizations because symbols with default visibility are not bound to a memory address until run-time. For example, calls to a routine with default visibility cannot be inlined because the routine might be preempted if the compilation unit is linked into a shareable object. A preemptable data symbol cannot be accessed using GP-relative addressing because the name may be bound to a symbol in a different component; and the GP-relative address is not known at compile time.
Symbol preemption is a rarely used feature and has negative consequences for compiler optimization. For this reason, by default the compiler treats all global symbol definitions as non-preemptable (protected visibility). Global references to symbols defined in another compilation unit are assumed by default to be preemptable (default visibility). In those rare cases where all global definitions as well as references need to be preemptable, you can override this default.
The IntelŪ compiler has visibility attribute options that provide command-line control of the visibility attributes in addition to a source syntax to set the complete range of these attributes.
The options ensure immediate access to the feature without depending on header file modifications. The visibility options cause all global symbols to get the visibility specified by the option. There are two variety of options to specify symbol visibility explicitly.
Example |
---|
-fvisibility=keyword |
The first form specifies the default visibility for global symbols. The second form specifies the visibility for symbols that are in a file (this form overrides the first form).
This option sets the visiblity for symbols not specified in a visibility list file and that do not have VISIBILITY attribute in their declaration. If no symbol file option is specified, all symbols will get the specified attribute. Command line example:
Example |
---|
ifort -fvisibility=protected a.f |
You can set the default visibility for symbols using one of the following command line options:
Examples |
---|
-fvisibility=extern |