summaryrefslogtreecommitdiff
path: root/docs/port/inline.txt
blob: 73962713e142371a0b752b4e322dc07c39e3259b (plain)
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
                             Inline Functions In C

Introduction

   GNU C (and some other compilers) had inline functions long before
   standard C introduced them (in the 1999 standard); this page summarizes
   the rules they use, and makes some suggestions as to how to actually
   use inline functions.

   The point of making a function "inline" is to hint to the compiler that
   it is worth making some form of extra effort to call the function
   faster than it would otherwise - generally by substituting the code of
   the function into its caller. As well as eliminating the need for a
   call and return sequence, it might allow the compiler to perform
   certain optimizations between the bodies of both functions.

   Sometimes it is necessary for the compiler to emit a stand-alone copy
   of the object code for a function even though it is an inline function
   - for instance if it is necessary to take the address of the function,
   or if it can't be inlined in some particular context, or (perhaps) if
   optimization has been turned off. (And of course, if you use a compiler
   that doesn't understand "inline", you'll need a stand-alone copy of the
   object code so that all the calls actually work at all.)

   There are various ways to define inline functions; any given kind of
   definition might definitely emit stand-alone object code, definitely
   not emit stand-alone object code, or only emit stand-alone object code
   if it is known to be needed. Sometimes this can lead to duplication of
   object code, which is a potential problem for following reasons:
    1. It wastes space.
    2. It can cause pointers to what is apparently the same function to
       compare not equal to one another.
    3. It might reduce the effectiveness of the instruction cache.
       (Although inlining might do that in other ways too.)

   If any of these are a problem for you then you will want to use a
   strategy that avoids duplication. These are discussed below.

GNU C inline rules

   The GNU C rules are described in the GNU C manual, which is included
   with the compiler. This is freely available if you follow links from
   e.g. [1]http://gcc.gnu.org.
     * A function defined with "inline" on its own. Stand-alone object
       code is always emitted. You can only write one definition like this
       in your entire program. If you want to use it from other
       translation units to the one where it is defined, you put a
       declaration in a header file; but it would not be inlined in those
       translation units.
       This is of rather limited use: if you only want to use the function
       from one translation unit then "static inline" below makes more
       sense, if not the you probably want some form that allows the
       function to be inlined in more than one translation unit.
       However it does have the advantage that by defining away the
       "inline" keyword, the program reduces to a portable program with
       the same meaning (provided no other non-portable constructions are
       used).
     * A function defined with "extern inline". Stand-alone object code is
       never emitted. You can have multiple such definitions and your
       program will still work. However, you should add a non-inline
       definition somewhere too, in case the function is not inlined
       everywhere.
       This provides sensible semantics (you can avoid duplicate copies of
       the functions' object code) but is a bit inconvenient to use.
       One approach to using this would be to put the definitions in a
       header file, surrounded by a #if that expands to true either when
       using GNU C, or when the header has been included from the file
       that is contain the emitted definitions (whether or not using GNU
       C). In the latter case the "extern" is omitted (for instance
       writing "EXTERN" and #define-ing that to either "extern" or
       nothing). The "#else" branch would contain just declarations of the
       functions, for non-GNU compilers.
     * A function defined with "static inline". Stand-alone object code
       may be emitted if required. You can have multiple definitions in
       your program, in different translation units, and it will still
       work. Just dropping the "inline" reduces the program to a portable
       one (again, all other things being equal).
       This is probably useful primarily for small functions that you
       might otherwise use macros for. If the function isn't always
       inlined then you get duplicate copies of the object code, with the
       problems described above.
       A sensible approach would be to put the "static inline" functions
       in either a header file if they are to be widely used or just in
       the source files that use them if they are only ever used from one
       file.

C99 inline rules

   The specification for "inline" is section 6.7.4 of the C99 standard
   (ISO/IEC 9899:1999). This isn't freely available, but you can buy a PDF
   of it from [2]ISO relatively cheaply.
     * A function where all the declarations (including the definition)
       mention "inline" and never "extern". There must be a definition in
       the same translation unit. No stand-alone object code is emitted.
       You can (must?) have a separate (not inline) definition in another
       translation unit, and the compiler might choose either that or the
       inline definition.
       Such functions may not contain modifiable static variables, and may
       not refer to static variables or functions elsewhere in the source
       file where they are declared.
     * A function where at least one declaration mentions "inline", but
       where some declaration doesn't mention "inline" or does mention
       "extern". There must be a definition in the same translation unit.
       Stand-alone object code is emitted (just like a normal function)
       and can be called from other translation units in your program.
       The same constraint about statics above applies here, too.
     * A function defined "static inline". A local definition may be
       emitted if required. You can have multiple definitions in your
       program, in different translation units, and it will still work.
       This is the same as the GNU C rules.

   main is not allowed to be an inline function.

   (If you think I've misinterpreted these rules, please let me know!)

   (C++ is stricter: a function which is inline anywhere must be inline
   everywhere and must be defined identically in all the translation units
   that use it.)

   Recent versions of GNU C have a -std=c99 option, but this doesn't
   enable C99 inline rules yet. The manual recommends sticking to "static
   inline", that being the portable subset, and promises C99 semantics in
   a future release. (But it's been three years since I wrote that, and
   the situation does not appear to have changed yet.)

Strategies for using inline functions

   These rules suggest several possible models for using inline functions
   in more or less portable ways.
    1. A simple portable model. Use "static inline" (either in a common
       header file or just in one file). If the compiler needs to emit a
       definition (e.g. to take its address, or because it doesn't want to
       inline some call) then you waste a bit of space; if you take the
       address of the function in two translation units then the result
       won't compare equal.
       For instance, in a header file:
static inline int max(int a, int b) {
  return a > b ? a : b;
}
       You can support legacy compilers (i.e. anything without "inline")
       via -Dinline="", although this wastes space.
    2. A GNU C model. Use "extern inline" in a common header and provide a
       definition in a .c file somewhere, perhaps using macros to ensure
       that the same code is used in each case. For instance, in the
       header file:
#ifndef INLINE
# define INLINE extern inline
#endif
INLINE int max(int a, int b) {
  return a > b ? a : b;
}

       ...and in exactly one source file:
#define INLINE
#include "header.h"
       Supporting legacy compilers is awkward unless you don't mind
       wasting space and having multiple addresses for the same function;
       you need to restrict the definitions to a in single translation
       unit (with INLINE defined to the empty string) and add some
       external declarations in the header file.
    3. A C99 model. Use "inline" in a common header, and provide
       definitions in a .c file somewhere, via "extern" declarations. For
       instance, in the header file:
inline int max(int a, int b) {
  return a > b ? a : b;
}
       ...and in exactly one source file:
#include "header.h"
extern int max(int a, int b);
       To support legacy compilers, you have to swap the whole thing
       around so that the declarations are visible in the common header
       and the definitions are restricted to a single translation unit,
       with inline defined away.
    4. A complicated portable mode. Use macros to choose either "extern
       inline" for GNU C, "inline" for C99, or neither for a definition.
       For instance, in the header:
#ifndef INLINE
# if __GNUC__
#  define INLINE extern inline
# else
#  define INLINE inline
# endif
#endif
INLINE int max(int a, int b) {
  return a > b ? a : b;
}

       ...and in exactly one source file:
#define INLINE
#include "header.h"
       Supporting legacy compilers has the same issues as the GNU C model.
       (This model won't work properly when GNU C gains C99 inline support
       - instead it'll be necessary to determine which version of the
       compiler is in use and whether it is a C99 mode.)

   Please report any errors.
     __________________________________________________________________

   [3]RJK | [4]Contents

References

   1. http://gcc.gnu.org/
   2. http://www.iso.ch/
   3. http://www.greenend.org.uk/rjk/
   4. http://www.greenend.org.uk/rjk/contents.html