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 for any calls to that function, the compiler may use the inline definition or call a global function by that name defined elsewhere.  When we say the compiler may use the inline definition, that does not necessarily mean the compiler actually inlines the code. The compiler might also create a local function for the inline definition and call that local function.  For other references, i.e. taking the address of the inline function definition, the compiler should create references to a global function defined elsewhere.

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.  Implementation note: The global function created by the compiler is placed in a comdat sections. You can have multiple global symbols in comdat and the linker only chooses one.  This is compatible with C++ use of comdat.  Without the inline keyword an extern function definition is not placed in comdat and a the linker will complain if there are duplicate global symbols with the same name.

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.

gcc

The GNU C rules differ and are described in the GNU C manual, which can be found here http://gcc.gnu.org.

  • A function defined with inline and without either extern or static keywords, will always cause a global function to be emitted.  gcc may inline references to the function within the object code for the translation-unit in which it appears.  And references to the function from other translation-units in the program will be satisfied by linking with this object code.
  • For a function defined with "extern inline" a global function is never emitted.  References to the function are either inlined or are made to a global function that must be defined somewhere else.
  • A function defined with "static inline" acts the same as C99.

Sun C compiler gcc compatibility for inline functions

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.

Comments:

thanks, it helps me a lot!

Posted by overcomeunicom on May 06, 2008 at 03:57 PM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Douglas is a principal software engineer working as the C compiler project lead and the Oracle Solaris Studio technical lead.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
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
   
       
Today