simplify inline function infrastructure
[bpt/guile.git] / libguile / inline.h
CommitLineData
16ea9620
MV
1/* classes: h_files */
2
3#ifndef SCM_INLINE_H
4#define SCM_INLINE_H
5
452c5ad9
LC
6/* Copyright (C) 2001, 2002, 2003, 2004, 2006, 2008, 2009, 2010,
7 * 2011 Free Software Foundation, Inc.
16ea9620 8 *
73be1d9e 9 * This library is free software; you can redistribute it and/or
53befeb7
NJ
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
16ea9620 13 *
53befeb7
NJ
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
16ea9620 18 *
73be1d9e
MV
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
53befeb7
NJ
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
73be1d9e 23 */
16ea9620
MV
24
25/* This file is for inline functions. On platforms that don't support
4cf77f09
AW
26 inlining functions, they are turned into ordinary functions. On
27 platforms that do support inline functions, the definitions are still
28 compiled into the library, once, in inline.c. */
16ea9620 29
1e71eafb 30#include <stdio.h>
f5c2af4b
LC
31#include <string.h>
32
33#include "libguile/__scm.h"
1e71eafb 34
16ea9620
MV
35#include "libguile/pairs.h"
36#include "libguile/gc.h"
9bc4701c 37#include "libguile/threads.h"
2a610be5 38#include "libguile/array-handle.h"
f5c2af4b 39#include "libguile/ports.h"
2a610be5 40#include "libguile/numbers.h"
f5c2af4b 41#include "libguile/error.h"
16ea9620 42
c8a1bdc4 43
4cf77f09
AW
44SCM_INLINE SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
45SCM_INLINE SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
c8a1bdc4 46 scm_t_bits ccr, scm_t_bits cdr);
4cf77f09 47SCM_INLINE SCM scm_words (scm_t_bits car, scm_t_uint16 n_words);
16ea9620 48
4cf77f09
AW
49SCM_INLINE SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
50SCM_INLINE void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM val);
60e7529a 51
4cf77f09
AW
52SCM_INLINE int scm_is_pair (SCM x);
53SCM_INLINE int scm_is_string (SCM x);
f5c2af4b 54
4cf77f09
AW
55SCM_INLINE int scm_get_byte_or_eof (SCM port);
56SCM_INLINE int scm_peek_byte_or_eof (SCM port);
57SCM_INLINE void scm_putc (char c, SCM port);
58SCM_INLINE void scm_puts (const char *str_data, SCM port);
3f520967 59
60e7529a 60
4cf77f09 61#if SCM_CAN_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
60e7529a
RB
62/* either inlining, or being included from inline.c. We use (and
63 repeat) this long #if test here and below so that we don't have to
64 introduce any extraneous symbols into the public namespace. We
65 only need SCM_C_INLINE to be seen publically . */
c8a1bdc4 66
4cf77f09 67SCM_INLINE_IMPLEMENTATION SCM
228a24ef 68scm_cell (scm_t_bits car, scm_t_bits cdr)
16ea9620 69{
4cf77f09 70 SCM cell = PTR2SCM (SCM_GC_MALLOC (sizeof (scm_t_cell)));
c8a1bdc4 71
c812243b
LC
72 /* Initialize the type slot last so that the cell is ignored by the GC
73 until it is completely initialized. This is only relevant when the GC
74 can actually run during this code, which it can't since the GC only runs
75 when all other threads are stopped. */
26224b3f 76 SCM_GC_SET_CELL_WORD (cell, 1, cdr);
c812243b 77 SCM_GC_SET_CELL_WORD (cell, 0, car);
16ea9620 78
26224b3f 79 return cell;
16ea9620
MV
80}
81
4cf77f09 82SCM_INLINE_IMPLEMENTATION SCM
228a24ef
DH
83scm_double_cell (scm_t_bits car, scm_t_bits cbr,
84 scm_t_bits ccr, scm_t_bits cdr)
16ea9620 85{
5e1e20c8 86 SCM z;
c8a1bdc4 87
4cf77f09 88 z = PTR2SCM (SCM_GC_MALLOC (2 * sizeof (scm_t_cell)));
16ea9620
MV
89 /* Initialize the type slot last so that the cell is ignored by the
90 GC until it is completely initialized. This is only relevant
b2a339f6
MV
91 when the GC can actually run during this code, which it can't
92 since the GC only runs when all other threads are stopped.
16ea9620 93 */
1fc8902f
DH
94 SCM_GC_SET_CELL_WORD (z, 1, cbr);
95 SCM_GC_SET_CELL_WORD (z, 2, ccr);
96 SCM_GC_SET_CELL_WORD (z, 3, cdr);
97 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 98
3553e1d1
GH
99 /* When this function is inlined, it's possible that the last
100 SCM_GC_SET_CELL_WORD above will be adjacent to a following
101 initialization of z. E.g., it occurred in scm_make_real. GCC
102 from around version 3 (e.g., certainly 3.2) began taking
103 advantage of strict C aliasing rules which say that it's OK to
104 interchange the initialization above and the one below when the
105 pointer types appear to differ sufficiently. We don't want that,
106 of course. GCC allows this behaviour to be disabled with the
107 -fno-strict-aliasing option, but would also need to be supplied
108 by Guile users. Instead, the following statements prevent the
109 reordering.
110 */
111#ifdef __GNUC__
e809758a
AW
112 __asm__ volatile ("" : : : "memory");
113#else
114 /* portable version, just in case any other compiler does the same
115 thing. */
116 scm_remember_upto_here_1 (z);
117#endif
118
119 return z;
120}
121
4cf77f09 122SCM_INLINE_IMPLEMENTATION SCM
e809758a
AW
123scm_words (scm_t_bits car, scm_t_uint16 n_words)
124{
125 SCM z;
126
4cf77f09 127 z = PTR2SCM (SCM_GC_MALLOC (sizeof (scm_t_bits) * n_words));
e809758a
AW
128 SCM_GC_SET_CELL_WORD (z, 0, car);
129
130 /* FIXME: is the following concern even relevant with BDW-GC? */
131
132 /* When this function is inlined, it's possible that the last
133 SCM_GC_SET_CELL_WORD above will be adjacent to a following
134 initialization of z. E.g., it occurred in scm_make_real. GCC
135 from around version 3 (e.g., certainly 3.2) began taking
136 advantage of strict C aliasing rules which say that it's OK to
137 interchange the initialization above and the one below when the
138 pointer types appear to differ sufficiently. We don't want that,
139 of course. GCC allows this behaviour to be disabled with the
140 -fno-strict-aliasing option, but would also need to be supplied
141 by Guile users. Instead, the following statements prevent the
142 reordering.
143 */
144#ifdef __GNUC__
cb975c21 145 __asm__ volatile ("" : : : "memory");
3553e1d1
GH
146#else
147 /* portable version, just in case any other compiler does the same
148 thing. */
149 scm_remember_upto_here_1 (z);
c8a1bdc4 150#endif
6253f3f1 151
c8a1bdc4
HWN
152 return z;
153}
6253f3f1 154
4cf77f09 155SCM_INLINE_IMPLEMENTATION SCM
9598a406
MV
156scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
157{
6d7c4402 158 if (SCM_UNLIKELY (p < 0 && ((size_t)-p) > h->base))
2a610be5
AW
159 /* catch overflow */
160 scm_out_of_range (NULL, scm_from_ssize_t (p));
161 /* perhaps should catch overflow here too */
162 return h->impl->vref (h, h->base + p);
9598a406 163}
eab1b259 164
4cf77f09 165SCM_INLINE_IMPLEMENTATION void
9598a406
MV
166scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
167{
3245c0fb 168 if (SCM_UNLIKELY (p < 0 && ((size_t)-p) > h->base))
2a610be5
AW
169 /* catch overflow */
170 scm_out_of_range (NULL, scm_from_ssize_t (p));
171 /* perhaps should catch overflow here too */
172 h->impl->vset (h, h->base + p, v);
9598a406 173}
eab1b259 174
4cf77f09 175SCM_INLINE_IMPLEMENTATION int
d5ad4aa6
MV
176scm_is_pair (SCM x)
177{
23f2b9a3
KR
178 /* The following "workaround_for_gcc_295" avoids bad code generated by
179 i386 gcc 2.95.4 (the Debian packaged 2.95.4-24 at least).
180
181 Under the default -O2 the inlined SCM_I_CONSP test gets "optimized" so
182 the fetch of the tag word from x is done before confirming it's a
183 non-immediate (SCM_NIMP). Needless to say that bombs badly if x is a
184 immediate. This was seen to afflict scm_srfi1_split_at and something
185 deep in the bowels of ceval(). In both cases segvs resulted from
186 deferencing a random immediate value. srfi-1.test exposes the problem
187 through a short list, the immediate being SCM_EOL in that case.
188 Something in syntax.test exposed the ceval() problem.
189
190 Just "volatile SCM workaround_for_gcc_295 = lst" is enough to avoid the
191 problem, without even using that variable. The "w=w" is just to
192 prevent a warning about it being unused.
193 */
194#if defined (__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 95
195 volatile SCM workaround_for_gcc_295 = x;
196 workaround_for_gcc_295 = workaround_for_gcc_295;
197#endif
198
d5ad4aa6
MV
199 return SCM_I_CONSP (x);
200}
201
4cf77f09 202SCM_INLINE_IMPLEMENTATION int
183f7849
LC
203scm_is_string (SCM x)
204{
205 return SCM_NIMP (x) && (SCM_TYP7 (x) == scm_tc7_string);
206}
f5c2af4b
LC
207
208/* Port I/O. */
209
4cf77f09 210SCM_INLINE_IMPLEMENTATION int
889975e5 211scm_get_byte_or_eof (SCM port)
f5c2af4b
LC
212{
213 int c;
214 scm_t_port *pt = SCM_PTAB_ENTRY (port);
215
216 if (pt->rw_active == SCM_PORT_WRITE)
217 /* may be marginally faster than calling scm_flush. */
218 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
219
220 if (pt->rw_random)
221 pt->rw_active = SCM_PORT_READ;
222
223 if (pt->read_pos >= pt->read_end)
224 {
452c5ad9 225 if (SCM_UNLIKELY (scm_fill_input (port) == EOF))
f5c2af4b
LC
226 return EOF;
227 }
228
229 c = *(pt->read_pos++);
230
f5c2af4b
LC
231 return c;
232}
233
452c5ad9 234/* Like `scm_get_byte_or_eof' but does not change PORT's `read_pos'. */
4cf77f09 235SCM_INLINE_IMPLEMENTATION int
452c5ad9
LC
236scm_peek_byte_or_eof (SCM port)
237{
238 int c;
239 scm_t_port *pt = SCM_PTAB_ENTRY (port);
240
241 if (pt->rw_active == SCM_PORT_WRITE)
242 /* may be marginally faster than calling scm_flush. */
243 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
244
245 if (pt->rw_random)
246 pt->rw_active = SCM_PORT_READ;
247
248 if (pt->read_pos >= pt->read_end)
249 {
250 if (SCM_UNLIKELY (scm_fill_input (port) == EOF))
251 return EOF;
252 }
253
254 c = *pt->read_pos;
255
256 return c;
257}
258
4cf77f09 259SCM_INLINE_IMPLEMENTATION void
f5c2af4b
LC
260scm_putc (char c, SCM port)
261{
262 SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
263 scm_lfwrite (&c, 1, port);
264}
265
4cf77f09 266SCM_INLINE_IMPLEMENTATION void
f5c2af4b
LC
267scm_puts (const char *s, SCM port)
268{
269 SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
270 scm_lfwrite (s, strlen (s), port);
271}
272
273
16ea9620 274#endif
16ea9620 275#endif