fix some missed references when calling C functions
[bpt/guile.git] / libguile / vm-engine.h
CommitLineData
8f5cfc81 1/* Copyright (C) 2001 Free Software Foundation, Inc.
a98cef7e
KN
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42/* This file is included in vm_engine.c */
43
44/*
3d5ee0cd 45 * Options
a98cef7e
KN
46 */
47
ac02b386
KN
48#define VM_USE_HOOKS 1 /* Various hooks */
49#define VM_USE_CLOCK 1 /* Bogoclock */
50#define VM_CHECK_EXTERNAL 1 /* Check external link */
0b5f0e49 51#define VM_CHECK_OBJECT 1 /* Check object table */
a98cef7e
KN
52
53\f
54/*
17e90c5e 55 * Registers
a98cef7e
KN
56 */
57
17e90c5e 58/* Register optimization. [ stolen from librep/src/lispmach.h,v 1.3 ]
9df03fd0 59
17e90c5e
KN
60 Some compilers underestimate the use of the local variables representing
61 the abstract machine registers, and don't put them in hardware registers,
62 which slows down the interpreter considerably.
63 For GCC, I have hand-assigned hardware registers for several architectures.
64*/
9df03fd0 65
17e90c5e
KN
66#ifdef __GNUC__
67#ifdef __mips__
68#define IP_REG asm("$16")
69#define SP_REG asm("$17")
70#define FP_REG asm("$18")
71#endif
72#ifdef __sparc__
73#define IP_REG asm("%l0")
74#define SP_REG asm("%l1")
75#define FP_REG asm("%l2")
76#endif
77#ifdef __alpha__
78#ifdef __CRAY__
79#define IP_REG asm("r9")
80#define SP_REG asm("r10")
81#define FP_REG asm("r11")
9df03fd0 82#else
17e90c5e
KN
83#define IP_REG asm("$9")
84#define SP_REG asm("$10")
85#define FP_REG asm("$11")
86#endif
87#endif
88#ifdef __i386__
89#define IP_REG asm("%esi")
90#define SP_REG asm("%edi")
91#define FP_REG
92#endif
93#if defined(PPC) || defined(_POWER) || defined(_IBMR2)
94#define IP_REG asm("26")
95#define SP_REG asm("27")
96#define FP_REG asm("28")
97#endif
98#ifdef __hppa__
99#define IP_REG asm("%r18")
100#define SP_REG asm("%r17")
101#define FP_REG asm("%r16")
102#endif
103#ifdef __mc68000__
104#define IP_REG asm("a5")
105#define SP_REG asm("a4")
106#define FP_REG
107#endif
108#ifdef __arm__
109#define IP_REG asm("r9")
110#define SP_REG asm("r8")
111#define FP_REG asm("r7")
112#endif
9df03fd0
KN
113#endif
114
17d1b4bf
AW
115#ifndef IP_REG
116#define IP_REG
117#endif
118#ifndef SP_REG
119#define SP_REG
120#endif
121#ifndef FP_REG
122#define FP_REG
123#endif
124
9df03fd0 125\f
a98cef7e 126/*
3d5ee0cd 127 * Cache/Sync
a98cef7e
KN
128 */
129
3d5ee0cd 130#define CACHE_REGISTER() \
17e90c5e 131{ \
3d5ee0cd
KN
132 ip = vp->ip; \
133 sp = vp->sp; \
134 fp = vp->fp; \
f13c269b 135 stack_base = fp ? SCM_FRAME_UPPER_ADDRESS (fp) - 1 : vp->stack_base; \
17e90c5e 136}
a98cef7e 137
3d5ee0cd 138#define SYNC_REGISTER() \
a98cef7e 139{ \
3d5ee0cd
KN
140 vp->ip = ip; \
141 vp->sp = sp; \
142 vp->fp = fp; \
a98cef7e
KN
143}
144
7e4760e4
AW
145#ifdef IP_PARANOIA
146#define CHECK_IP() \
147 do { if (ip < bp->base || ip - bp->base > bp->size) abort (); } while (0)
148#else
149#define CHECK_IP()
150#endif
151
238e7a11
LC
152/* Get a local copy of the program's "object table" (i.e. the vector of
153 external bindings that are referenced by the program), initialized by
154 `load-program'. */
a52b2d3d
LC
155/* XXX: We could instead use the "simple vector macros", thus not having to
156 call `scm_vector_writable_elements ()' and the likes. */
157#define CACHE_PROGRAM() \
158{ \
159 ssize_t _vincr; \
160 \
e677365c
AW
161 if (bp != SCM_PROGRAM_DATA (program)) { \
162 bp = SCM_PROGRAM_DATA (program); \
163 /* Was: objects = SCM_VELTS (bp->objs); */ \
a52b2d3d 164 \
e677365c
AW
165 if (objects) \
166 scm_array_handle_release (&objects_handle); \
a52b2d3d 167 \
e677365c
AW
168 objects = scm_vector_writable_elements (bp->objs, &objects_handle, \
169 &object_count, &_vincr); \
170 } \
41f248a8
KN
171}
172
3d5ee0cd
KN
173#define SYNC_BEFORE_GC() \
174{ \
175 SYNC_REGISTER (); \
17e90c5e 176}
a98cef7e 177
17e90c5e 178#define SYNC_ALL() \
a98cef7e 179{ \
3d5ee0cd 180 SYNC_REGISTER (); \
a98cef7e
KN
181}
182
a98cef7e 183\f
ac02b386
KN
184/*
185 * Error check
186 */
187
188#undef CHECK_EXTERNAL
189#if VM_CHECK_EXTERNAL
190#define CHECK_EXTERNAL(e) \
191 do { if (!SCM_CONSP (e)) goto vm_error_external; } while (0)
192#else
193#define CHECK_EXTERNAL(e)
194#endif
195
0b5f0e49
LC
196/* Accesses to a program's object table. */
197#if VM_CHECK_OBJECT
198#define CHECK_OBJECT(_num) \
199 do { if ((_num) >= object_count) goto vm_error_object; } while (0)
200#else
201#define CHECK_OBJECT(_num)
202#endif
203
ac02b386 204\f
3d5ee0cd
KN
205/*
206 * Hooks
207 */
208
209#undef RUN_HOOK
210#if VM_USE_HOOKS
211#define RUN_HOOK(h) \
212{ \
ac02b386 213 if (!SCM_FALSEP (vp->hooks[h])) \
3d5ee0cd 214 { \
af988bbf
KN
215 SYNC_REGISTER (); \
216 vm_heapify_frames (vm); \
ac02b386 217 scm_c_run_hook (vp->hooks[h], hook_args); \
af988bbf 218 CACHE_REGISTER (); \
3d5ee0cd
KN
219 } \
220}
221#else
222#define RUN_HOOK(h)
223#endif
224
ac02b386
KN
225#define BOOT_HOOK() RUN_HOOK (SCM_VM_BOOT_HOOK)
226#define HALT_HOOK() RUN_HOOK (SCM_VM_HALT_HOOK)
227#define NEXT_HOOK() RUN_HOOK (SCM_VM_NEXT_HOOK)
7a0d0cee 228#define BREAK_HOOK() RUN_HOOK (SCM_VM_BREAK_HOOK)
ac02b386
KN
229#define ENTER_HOOK() RUN_HOOK (SCM_VM_ENTER_HOOK)
230#define APPLY_HOOK() RUN_HOOK (SCM_VM_APPLY_HOOK)
231#define EXIT_HOOK() RUN_HOOK (SCM_VM_EXIT_HOOK)
232#define RETURN_HOOK() RUN_HOOK (SCM_VM_RETURN_HOOK)
3d5ee0cd
KN
233
234\f
a98cef7e
KN
235/*
236 * Stack operation
237 */
238
17e90c5e 239#define CHECK_OVERFLOW() \
3616e9e9 240 if (sp > stack_limit) \
17e90c5e
KN
241 goto vm_error_stack_overflow
242
7e4760e4
AW
243#define CHECK_UNDERFLOW() \
244 if (sp < stack_base) \
245 goto vm_error_stack_underflow;
a98cef7e 246
3616e9e9 247#define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0)
659b4611
AW
248#define DROP() do { sp--; CHECK_UNDERFLOW (); } while (0)
249#define DROPN(_n) do { sp -= (_n); CHECK_UNDERFLOW (); } while (0)
17e90c5e
KN
250#define POP(x) do { x = *sp; DROP (); } while (0)
251
2d80426a
LC
252/* A fast CONS. This has to be fast since its used, for instance, by
253 POP_LIST when fetching a function's argument list. Note: `scm_cell' is an
254 inlined function in Guile 1.7. Unfortunately, it calls
255 `scm_gc_for_newcell ()' which is _not_ inlined and allocated cells on the
256 heap. XXX */
257#define CONS(x,y,z) \
258{ \
259 SYNC_BEFORE_GC (); \
260 x = scm_cell (SCM_UNPACK (y), SCM_UNPACK (z)); \
a98cef7e
KN
261}
262
f41cb00c
LC
263/* Pop the N objects on top of the stack and push a list that contains
264 them. */
17e90c5e 265#define POP_LIST(n) \
f41cb00c
LC
266do \
267{ \
17e90c5e
KN
268 int i; \
269 SCM l = SCM_EOL; \
3616e9e9
KN
270 sp -= n; \
271 for (i = n; i; i--) \
17e90c5e 272 CONS (l, sp[i], l); \
3616e9e9 273 PUSH (l); \
17e90c5e
KN
274} while (0)
275
135b32ee
LC
276\f
277/* Below is a (slightly broken) experiment to avoid calling `scm_cell' and to
278 allocate cells on the stack. This is a significant improvement for
279 programs which call a lot of procedures, since the procedure call
280 mechanism uses POP_LIST which normally uses `scm_cons'.
281
282 What it does is that it creates a list whose cells are allocated on the
283 VM's stack instead of being allocated on the heap via `scm_cell'. This is
284 much faster. However, if the callee does something like:
285
286 (lambda (. args)
287 (set! the-args args))
288
289 then terrible things may happen since the list of arguments may be
290 overwritten later on. */
291
292
293/* Awful hack that aligns PTR so that it can be considered as a non-immediate
294 value by Guile. */
295#define ALIGN_AS_NON_IMMEDIATE(_ptr) \
296{ \
297 if ((scm_t_bits)(_ptr) & 6) \
298 { \
299 size_t _incr; \
300 \
301 _incr = (scm_t_bits)(_ptr) & 6; \
302 _incr = (~_incr) & 7; \
303 (_ptr) += _incr; \
304 } \
305}
306
307#define POP_LIST_ON_STACK(n) \
308do \
309{ \
310 int i; \
311 if (n == 0) \
312 { \
313 sp -= n; \
314 PUSH (SCM_EOL); \
315 } \
316 else \
317 { \
318 SCM *list_head, *list; \
319 \
320 list_head = sp + 1; \
321 ALIGN_AS_NON_IMMEDIATE (list_head); \
322 list = list_head; \
323 \
324 sp -= n; \
325 for (i = 1; i <= n; i++) \
326 { \
327 /* The cell's car and cdr. */ \
328 *(list) = sp[i]; \
329 *(list + 1) = PTR2SCM (list + 2); \
330 list += 2; \
331 } \
332 \
333 /* The last pair's cdr is '(). */ \
334 list--; \
335 *list = SCM_EOL; \
336 /* Push the SCM object that points */ \
337 /* to the first cell. */ \
338 PUSH (PTR2SCM (list_head)); \
339 } \
340} \
341while (0)
342
343/* end of the experiment */
344
345\f
cb4cca12
KN
346#define POP_LIST_MARK() \
347do { \
348 SCM o; \
349 SCM l = SCM_EOL; \
350 POP (o); \
351 while (!SCM_UNBNDP (o)) \
352 { \
353 CONS (l, o, l); \
354 POP (o); \
355 } \
356 PUSH (l); \
357} while (0)
358
a98cef7e
KN
359\f
360/*
17e90c5e 361 * Instruction operation
a98cef7e
KN
362 */
363
17e90c5e 364#define FETCH() (*ip++)
17e90c5e
KN
365#define FETCH_LENGTH(len) do { ip = vm_fetch_length (ip, &len); } while (0)
366
367#undef CLOCK
368#if VM_USE_CLOCK
3d5ee0cd 369#define CLOCK(n) vp->clock += n
a98cef7e 370#else
17e90c5e 371#define CLOCK(n)
a98cef7e
KN
372#endif
373
17e90c5e
KN
374#undef NEXT_JUMP
375#ifdef HAVE_LABELS_AS_VALUES
376#define NEXT_JUMP() goto *jump_table[FETCH ()]
377#else
378#define NEXT_JUMP() goto vm_start
379#endif
380
381#define NEXT \
382{ \
383 CLOCK (1); \
17e90c5e
KN
384 NEXT_HOOK (); \
385 NEXT_JUMP (); \
a98cef7e
KN
386}
387
388\f
389/*
ac02b386 390 * Stack frame
17e90c5e
KN
391 */
392
17e90c5e
KN
393#define INIT_ARGS() \
394{ \
395 if (bp->nrest) \
396 { \
5315b862 397 int n = nargs - (bp->nargs - 1); \
17e90c5e
KN
398 if (n < 0) \
399 goto vm_error_wrong_num_args; \
400 POP_LIST (n); \
401 } \
402 else \
403 { \
404 if (nargs != bp->nargs) \
405 goto vm_error_wrong_num_args; \
406 } \
407}
408
ac99cb0c 409/* See frames.h for the layout of stack frames */
2cdb8cdc
AW
410/* When this is called, bp points to the new program data,
411 and the arguments are already on the stack */
3616e9e9
KN
412#define NEW_FRAME() \
413{ \
24aa2715 414 int i; \
2cdb8cdc
AW
415 SCM *dl, *data; \
416 scm_byte_t *ra = ip; \
24aa2715 417 \
2cdb8cdc
AW
418 /* Save old registers */ \
419 ra = ip; \
420 dl = fp; \
421 \
422 /* New registers */ \
423 fp = sp - bp->nargs + 1; \
424 data = SCM_FRAME_DATA_ADDRESS (fp); \
da320011 425 sp = data + 4; \
3616e9e9 426 CHECK_OVERFLOW (); \
2cdb8cdc
AW
427 stack_base = sp; \
428 ip = bp->base; \
24aa2715
KN
429 \
430 /* Init local variables */ \
2cdb8cdc
AW
431 for (i=bp->nlocs; i; i--) \
432 data[-i] = SCM_UNDEFINED; \
24aa2715
KN
433 \
434 /* Create external variables */ \
435 external = bp->external; \
436 for (i = 0; i < bp->nexts; i++) \
437 CONS (external, SCM_UNDEFINED, external); \
ac02b386
KN
438 \
439 /* Set frame data */ \
da320011
AW
440 data[4] = (SCM)ra; \
441 data[3] = 0x0; \
2cdb8cdc
AW
442 data[2] = (SCM)dl; \
443 data[1] = SCM_BOOL_F; \
444 data[0] = external; \
3616e9e9
KN
445}
446
af988bbf
KN
447#define CACHE_EXTERNAL() external = fp[bp->nargs + bp->nlocs]
448
17e90c5e
KN
449/*
450 Local Variables:
451 c-file-style: "gnu"
452 End:
453*/