Monday May 22, 2006
C99 inline function and the Sun C Compiler
Note, the C standard says that inline is only a suggestion to the C
compiler. The C compiler can choose not to inline anything, and
attempt to call the actual function.
The Sun C compiler does not inline C function calls unless optimizing
at -xO3 or above. And that inlining is done by the
backends. And then only if the backend's heuristics decide it is
profitable to do so. The Sun C compiler gives no way to force a
function to be inlined.
For static inline functions it is simple. Either a function
defined with the inline function specifier is inlined at a reference or
a call is made to the actual function. The compiler can choose
which to do at each reference. The Sun C compiler decides if it
is profitable to inline at -xO3 and above. When not profitable to
inline, or at an optimization of less than -xO3 a reference to the
actual function will be generated. If any reference to the actual
function is generated the function definition will be generated in the
object code. Note if the address of the function is taken, the
actual function will be generated in the object code.
Extern inline functions are more complicated. There are two types
of extern inline functions, an inline definition which never provides
an extern (global) definition of the function and an extern
inline function which always provide a global definition of the
function. To quote the C99 standard:
[#6] Any function with internal linkage can be an inline
function. For a function with external linkage, the
following restrictions apply: If a function is declared with
an inline function specifier, then it shall also be defined
in the same translation unit. If all of the file scope
declarations for a function in a translation unit include
the inline function specifier without extern, then the
definition in that translation unit is an inline definition.
An inline definition does not provide an external definition
for the function, and does not forbid an external definition
in another translation unit. An inline definition provides
an alternative to an external definition, which a translator
may use to implement any call to the function in the same
translation unit. It is unspecified whether a call to the
function uses the inline definition or the external
definition.
[#7] EXAMPLE The declaration of an inline function with
external linkage can result in either an external
definition, or a definition available for use only within
the translation unit. A file scope declaration with extern
creates an external definition. The following example shows
an entire translation unit.
inline double fahr(double t)
{
return (9.0 * t) / 5.0 + 32.0;
}
inline double cels(double t)
{
return (5.0 * (t - 32.0)) / 9.0;
}
extern double fahr(double); // creates an external definition
double convert(int is_fahr, double temp)
{
/* A translator may perform inline substitutions */
return is_fahr ? cels(temp) : fahr(temp);
}
[#8] Note that the definition of fahr is an external
definition because fahr is also declared with extern, but
the definition of cels is an inline definition. Because
cels has external linkage and is referenced, an external
definition has to appear in another translation unit (see
6.9); the inline definition and the external definition are
distinct and either may be used for the call.
So, for an inline definition, the programmer is required to
supply an extern definition of the function in another translation-unit for references to the function that are not inlined.
For an inline definition, the compiler must not
create a global definition of the function. That means any
reference to an inline definition that is not inlined must be a
reference to a global
function defined elsewhere. Put another way, the object file
produced by compiling this translation unit will not contain a global
symbol for the inline definition. And any reference to
the function that is not inlined will be to an extern
(global) symbol provided by some other object file or library at link
time.
For an extern inline function declared by a file scope declaration with
the extern storage-class-specifier (i.e. the function definition and/or
prototype), the compiler must provide a global definition of the function in the resulting object file. The
compiler can choose to inline any references to that function seen in
the translation unit where the function definition has been provided,
or the compiler can choose to call the global function.
The behavior of any program that relies on whether or not a function call is actually inlined, is undefined.
Note also an inline function with external linkage may not declare or
reference a static variable anywhere in the translation-unit.
Definition of translation-unit: A source file and all of its includes, recursively.
Like it does for static functions, the Sun C compiler decides if it is
profitable to inline a reference to an inline definition or an
extern inline function at -xO3 and above. When not profitable to
inline, or at an optimization of less than -xO3 a reference to the
global function will be generated. Likewise a reference to the
address of the function is always a reference to the global function.
The rules for C++ differ: a function which is inline anywhere must be
inline everywhere and must be defined identically in all the
translation units that use it.
The GNU C rules differ and are described in the GNU C manual, which can be found here http://gcc.gnu.org.
To obtain behavior from the Sun C compiler that is compatible with
gcc's implementation of extern inline functions for most programs, use
the -features=no%extinl flag. When this flag is specified the Sun
C compiler will treat the function as if it was declared as a static
inline function.
The one place this is not compatible will be when the address of the
function is taken. With gcc this will be an address of a global function, and with Sun's compiler the local static
definition address will be used.
thanks, it helps me a lot!
Posted by overcomeunicom on May 06, 2008 at 10:57 PM PDT #