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.
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 its 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.
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.
Other components can reference the symbol. Furthermore, the symbol definition may be overridden (preempted) by a definition of the same name in another component.
Other components can reference the symbol, but it cannot be preempted by a definition of the same name in another component.
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.
The symbol cannot be referenced outside the component where it is defined, either directly or indirectly.
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. 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, specify the -fpic option to override this default.
The Intel Fortran Compiler has the visibility attribute options that provide command-line control of the visibility attributes as well as 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:
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).
The file is the pathname of a file containing the list of symbols whose visibility you want to set; the symbols are separated by whitespace (spaces, tabs, or newlines).
In both options, the keyword is: extern, default, protected, hidden, and internal, see definitions above.
These two ways to explicitly set visibility are mutually exclusive: you may use the visibility attribute on the declaration, or specify the symbol name in a file, but not both.
The option -fvisibility-keyword=file specifies the same visibility attribute for a number of symbols using one of the five command line options corresponding to the keyword:
where file is the pathname of a file containing a list of the symbol names whose visibility you wish to set; the symbol names in the file are separated by either blanks, tabs, or newlines. For example, the command line option:
where file prot.txt contains symbols a, b, c, d, and e sets protected visibility for symbols a, b, c, d, and e. This has the same effect as declared attribute visibility=protected on the declaration for each of the symbols.
This option sets the visiblity for symbols not specified in a visibility list file and that do not have visibilty attribute in their declaration. If no symbol file option is specified, all symbols will get the specified attribute. Command line example:
ifort -fvisibility=protected a.f
You can set the default visibility for symbols using one of the following command line options:
The above options are listed in the order of precedence: explicitly setting the visibility to extern, by using either the attribute syntax or the command line option, overrides any setting to default, protected, hidden, or internal. Explicitly setting the visibility to default overrides any setting to protected, hidden, or internal and so on.
The visibility attribute default enables compiler to change the default symbol visibility and then set the default attribute on functions and variables that require the default setting. Since internal is a processor-specific attribute, it may not be desirable to have a general option for it.
In the combined command-line options
file prot.txt (see above) causes all global symbols except a, b, c, d, and e to have protected visibility. Those five symbols, however, will have default visibility and thus be preemptable.
Directs to treat the compilation unit as a component of a main program and not to link it as a part of a shareable object.
Since symbols defined in the main program
cannot be preempted, this enables the compiler to treat symbols declared
with default visibility as though they have protected visibility. It means
-fminshared implies -fvisibility=protected. The compiler need not generate position-independent code for the main program. It can use absolute addressing, which may reduce the size of the global offset table (GOT) and may reduce memory traffic.
Specifies full symbol preemption. Global symbol definitions as well as global symbol references get default (that is, preemptable) visibility unless explicitly specified otherwise. Generates position-independent code. Required for building shared objects on Itanium-based systems.