version.h has SCM_EFFECTIVE_VERSION; effective-version uses that
[bpt/guile.git] / libguile / vm.c
CommitLineData
a6029b97 1/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
a98cef7e 2 *
560b9c25 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
560b9c25
AW
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
560b9c25
AW
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
560b9c25 17 */
a98cef7e 18
13c47753
AW
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
da8b4747 23#include <stdlib.h>
6d14383e 24#include <alloca.h>
17e90c5e 25#include <string.h>
e3eb628d 26
1c44468d 27#include "libguile/bdw-gc.h"
e3eb628d
LC
28#include <gc/gc_mark.h>
29
560b9c25 30#include "_scm.h"
adaf86ec 31#include "control.h"
ac99cb0c 32#include "frames.h"
17e90c5e 33#include "instructions.h"
8f5cfc81 34#include "objcodes.h"
ac99cb0c 35#include "programs.h"
fb10a008 36#include "lang.h" /* NULL_OR_NIL_P */
a98cef7e
KN
37#include "vm.h"
38
a98cef7e
KN
39/* I sometimes use this for debugging. */
40#define vm_puts(OBJ) \
41{ \
22bcbe8c
AW
42 scm_display (OBJ, scm_current_error_port ()); \
43 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
44}
45
11ea1aba
AW
46/* The VM has a number of internal assertions that shouldn't normally be
47 necessary, but might be if you think you found a bug in the VM. */
48#define VM_ENABLE_ASSERTIONS
49
50/* We can add a mode that ensures that all stack items above the stack pointer
51 are NULL. This is useful for checking the internal consistency of the VM's
52 assumptions and its operators, but isn't necessary for normal operation. It
616167fc 53 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 54/* NB! If you enable this, search for NULLING in throw.c */
616167fc 55/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 56
53e28ed9
AW
57/* #define VM_ENABLE_PARANOID_ASSERTIONS */
58
11ea1aba
AW
59#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
60#define VM_ENABLE_ASSERTIONS
61#endif
62
e3eb628d
LC
63/* When defined, arrange so that the GC doesn't scan the VM stack beyond its
64 current SP. This should help avoid excess data retention. See
65 http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/3001
66 for a discussion. */
67#define VM_ENABLE_PRECISE_STACK_GC_SCAN
68
69
a98cef7e 70\f
a98cef7e
KN
71/*
72 * VM Continuation
73 */
74
6f3b0cc2
AW
75void
76scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
77{
78 scm_puts ("#<vm-continuation ", port);
79 scm_uintprint (SCM_UNPACK (x), 16, port);
80 scm_puts (">", port);
81}
17e90c5e 82
d8873dfe
AW
83/* In theory, a number of vm instances can be active in the call trace, and we
84 only want to reify the continuations of those in the current continuation
85 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
86 and previous values of the *the-vm* fluid within the current continuation
87 root. But we don't have access to continuation roots in the dynwind stack.
88 So, just punt for now, we just capture the continuation for the current VM.
89
90 While I'm on the topic, ideally we could avoid copying the C stack if the
91 continuation root is inside VM code, and call/cc was invoked within that same
92 call to vm_run; but that's currently not implemented.
93 */
cee1d22c
AW
94SCM
95scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint8 *ra,
96 scm_t_uint8 *mvra, scm_t_uint32 flags)
a98cef7e 97{
d8873dfe
AW
98 struct scm_vm_cont *p;
99
100 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
101 p->stack_size = sp - stack_base + 1;
d8eeb67c
LC
102 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
103 "capture_vm_cont");
d8873dfe
AW
104#if defined(VM_ENABLE_STACK_NULLING) && 0
105 /* Tail continuations leave their frame on the stack for subsequent
106 application, but don't capture the frame -- so there are some elements on
107 the stack then, and this check doesn't work, so disable it for now. */
108 if (sp >= vp->stack_base)
66db076a
AW
109 if (!vp->sp[0] || vp->sp[1])
110 abort ();
11ea1aba
AW
111 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
112#endif
d8873dfe
AW
113 p->ra = ra;
114 p->mvra = mvra;
115 p->sp = sp;
116 p->fp = fp;
117 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
118 p->reloc = p->stack_base - stack_base;
cee1d22c 119 p->flags = flags;
6f3b0cc2 120 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
121}
122
123static void
d8873dfe 124vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
a98cef7e 125{
d8873dfe
AW
126 struct scm_vm *vp;
127 struct scm_vm_cont *cp;
128 SCM *argv_copy;
129
130 argv_copy = alloca (n * sizeof(SCM));
131 memcpy (argv_copy, argv, n * sizeof(SCM));
132
133 vp = SCM_VM_DATA (vm);
134 cp = SCM_VM_CONT_DATA (cont);
135
136 if (n == 0 && !cp->mvra)
137 scm_misc_error (NULL, "Too few values returned to continuation",
138 SCM_EOL);
139
140 if (vp->stack_size < cp->stack_size + n + 1)
29366989
AW
141 scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
142 scm_list_2 (vm, cont));
143
11ea1aba
AW
144#ifdef VM_ENABLE_STACK_NULLING
145 {
d8873dfe 146 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
11ea1aba 147 if (nzero > 0)
d8873dfe 148 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
66db076a
AW
149 /* actually nzero should always be negative, because vm_reset_stack will
150 unwind the stack to some point *below* this continuation */
11ea1aba
AW
151 }
152#endif
d8873dfe
AW
153 vp->sp = cp->sp;
154 vp->fp = cp->fp;
155 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 156
d8873dfe
AW
157 if (n == 1 || !cp->mvra)
158 {
159 vp->ip = cp->ra;
160 vp->sp++;
161 *vp->sp = argv_copy[0];
162 }
163 else
164 {
165 size_t i;
166 for (i = 0; i < n; i++)
167 {
168 vp->sp++;
169 *vp->sp = argv_copy[i];
170 }
171 vp->sp++;
172 *vp->sp = scm_from_size_t (n);
173 vp->ip = cp->mvra;
174 }
175}
bfffd258 176
bfffd258 177SCM
269479e3 178scm_i_vm_capture_continuation (SCM vm)
bfffd258 179{
d8873dfe 180 struct scm_vm *vp = SCM_VM_DATA (vm);
cee1d22c 181 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL, 0);
a98cef7e
KN
182}
183
b1b942b7 184static void
7656f194 185vm_dispatch_hook (SCM vm, int hook_num)
b1b942b7 186{
7656f194
AW
187 struct scm_vm *vp;
188 SCM hook;
189 SCM frame;
b1b942b7 190
7656f194
AW
191 vp = SCM_VM_DATA (vm);
192 hook = vp->hooks[hook_num];
b1b942b7 193
7656f194
AW
194 if (SCM_LIKELY (scm_is_false (hook))
195 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
196 return;
197
198 vp->trace_level--;
199 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
200 scm_c_run_hookn (hook, &frame, 1);
201 vp->trace_level++;
b1b942b7
AW
202}
203
cee1d22c 204static void vm_abort (SCM vm, size_t n, scm_t_int64 cookie) SCM_NORETURN;
4f66bcde 205static void
cee1d22c 206vm_abort (SCM vm, size_t n, scm_t_int64 vm_cookie)
4f66bcde 207{
eaefabee 208 size_t i;
2d026f04
AW
209 ssize_t tail_len;
210 SCM tag, tail, *argv;
eaefabee 211
2d026f04
AW
212 /* FIXME: VM_ENABLE_STACK_NULLING */
213 tail = *(SCM_VM_DATA (vm)->sp--);
214 /* NULLSTACK (1) */
215 tail_len = scm_ilength (tail);
216 if (tail_len < 0)
29366989
AW
217 scm_misc_error ("vm-engine", "tail values to abort should be a list",
218 scm_list_1 (tail));
219
eaefabee 220 tag = SCM_VM_DATA (vm)->sp[-n];
2d026f04 221 argv = alloca ((n + tail_len) * sizeof (SCM));
eaefabee
AW
222 for (i = 0; i < n; i++)
223 argv[i] = SCM_VM_DATA (vm)->sp[-(n-1-i)];
2d026f04
AW
224 for (; i < n + tail_len; i++, tail = scm_cdr (tail))
225 argv[i] = scm_car (tail);
226 /* NULLSTACK (n + 1) */
eaefabee
AW
227 SCM_VM_DATA (vm)->sp -= n + 1;
228
cee1d22c
AW
229 scm_c_abort (vm, tag, n + tail_len, argv, vm_cookie);
230}
231
232static void
07801437 233vm_reinstate_partial_continuation (SCM vm, SCM cont, SCM intwinds,
adbdfd6d 234 size_t n, SCM *argv, scm_t_int64 vm_cookie)
cee1d22c 235{
07801437
AW
236 struct scm_vm *vp;
237 struct scm_vm_cont *cp;
238 SCM *argv_copy, *base;
239 size_t i;
240
241 argv_copy = alloca (n * sizeof(SCM));
242 memcpy (argv_copy, argv, n * sizeof(SCM));
243
244 vp = SCM_VM_DATA (vm);
245 cp = SCM_VM_CONT_DATA (cont);
246 base = SCM_FRAME_UPPER_ADDRESS (vp->fp) + 1;
247
248#define RELOC(scm_p) (scm_p + cp->reloc + (base - cp->stack_base))
249
250 if ((base - vp->stack_base) + cp->stack_size + n + 1 > vp->stack_size)
29366989
AW
251 scm_misc_error ("vm-engine",
252 "not enough space to instate partial continuation",
253 scm_list_2 (vm, cont));
07801437
AW
254
255 memcpy (base, cp->stack_base, cp->stack_size * sizeof (SCM));
256
257 /* now relocate frame pointers */
258 {
259 SCM *fp;
260 for (fp = RELOC (cp->fp);
261 SCM_FRAME_LOWER_ADDRESS (fp) > base;
262 fp = SCM_FRAME_DYNAMIC_LINK (fp))
263 SCM_FRAME_SET_DYNAMIC_LINK (fp, RELOC (SCM_FRAME_DYNAMIC_LINK (fp)));
264 }
265
266 vp->sp = base - 1 + cp->stack_size;
267 vp->fp = RELOC (cp->fp);
268 vp->ip = cp->mvra;
269
07801437
AW
270 /* now push args. ip is in a MV context. */
271 for (i = 0; i < n; i++)
272 {
273 vp->sp++;
274 *vp->sp = argv_copy[i];
275 }
276 vp->sp++;
277 *vp->sp = scm_from_size_t (n);
9a1c6f1f 278
adbdfd6d
AW
279 /* Finally, rewind the dynamic state.
280
281 We have to treat prompts specially, because we could be rewinding the
282 dynamic state from a different thread, or just a different position on the
283 C and/or VM stack -- so we need to reset the jump buffers so that an abort
284 comes back here, with appropriately adjusted sp and fp registers. */
9a1c6f1f
AW
285 {
286 long delta = 0;
287 SCM newwinds = scm_i_dynwinds ();
288 for (; scm_is_pair (intwinds); intwinds = scm_cdr (intwinds), delta--)
adbdfd6d
AW
289 {
290 SCM x = scm_car (intwinds);
291 if (SCM_PROMPT_P (x))
292 /* the jmpbuf will be reset by our caller */
293 x = scm_c_make_prompt (SCM_PROMPT_TAG (x),
294 RELOC (SCM_PROMPT_REGISTERS (x)->fp),
295 RELOC (SCM_PROMPT_REGISTERS (x)->sp),
296 SCM_PROMPT_REGISTERS (x)->ip,
297 SCM_PROMPT_ESCAPE_P (x),
298 vm_cookie,
299 newwinds);
300 newwinds = scm_cons (x, newwinds);
301 }
9a1c6f1f
AW
302 scm_dowinds (newwinds, delta);
303 }
adbdfd6d 304#undef RELOC
4f66bcde
AW
305}
306
307\f
17e90c5e
KN
308/*
309 * VM Internal functions
310 */
311
0404c97d
AW
312/* Unfortunately we can't snarf these: snarfed things are only loaded up from
313 (system vm vm), which might not be loaded before an error happens. */
314static SCM sym_vm_run, sym_vm_error, sym_keyword_argument_error, sym_debug;
17e90c5e 315
6f3b0cc2
AW
316void
317scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
318{
319 scm_puts ("#<vm ", port);
320 scm_uintprint (SCM_UNPACK (x), 16, port);
321 scm_puts (">", port);
322}
323
2fda0242 324static SCM
d2d7acd5 325really_make_boot_program (long nargs)
2fda0242 326{
5bd047ce 327 SCM u8vec;
97fcf583
AW
328 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
329 scm_op_make_int8_1, scm_op_halt };
28b119ee 330 struct scm_objcode *bp;
3b9e095b 331 SCM ret;
5bd047ce 332
53e28ed9 333 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
29366989
AW
334 scm_misc_error ("vm-engine", "too many args when making boot procedure",
335 scm_list_1 (scm_from_long (nargs)));
336
28b119ee
AW
337 text[1] = (scm_t_uint8)nargs;
338
d7e7a02a 339 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 340 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
341 bp->len = sizeof(text);
342 bp->metalen = 0;
28b119ee 343
7055591c
AW
344 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
345 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 346 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 347 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 348 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 349
3b9e095b 350 return ret;
2fda0242 351}
d2d7acd5
AW
352#define NUM_BOOT_PROGS 8
353static SCM
354vm_make_boot_program (long nargs)
355{
356 static SCM programs[NUM_BOOT_PROGS] = { 0, };
357
358 if (SCM_UNLIKELY (!programs[0]))
359 {
360 int i;
361 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 362 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
363 }
364
365 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
366 return programs[nargs];
367 else
368 return really_make_boot_program (nargs);
369}
2fda0242 370
a98cef7e
KN
371\f
372/*
373 * VM
374 */
375
b7393ea1
AW
376static SCM
377resolve_variable (SCM what, SCM program_module)
378{
9bd48cb1 379 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
380 {
381 if (SCM_LIKELY (scm_module_system_booted_p
382 && scm_is_true (program_module)))
383 /* might longjmp */
384 return scm_module_lookup (program_module, what);
385 else
386 {
387 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
388 if (scm_is_false (v))
389 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
390 else
391 return v;
392 }
393 }
394 else
395 {
396 SCM mod;
397 /* compilation of @ or @@
398 `what' is a three-element list: (MODNAME SYM INTERFACE?)
399 INTERFACE? is #t if we compiled @ or #f if we compiled @@
400 */
401 mod = scm_resolve_module (SCM_CAR (what));
402 if (scm_is_true (SCM_CADDR (what)))
403 mod = scm_module_public_interface (mod);
5c8cefe5 404 if (scm_is_false (mod))
b7393ea1
AW
405 scm_misc_error (NULL, "no such module: ~S",
406 scm_list_1 (SCM_CAR (what)));
407 /* might longjmp */
408 return scm_module_lookup (mod, SCM_CADR (what));
409 }
410}
411
51e9ba2f 412#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 413
17e90c5e 414#define VM_NAME vm_regular_engine
6d14383e
AW
415#define FUNC_NAME "vm-regular-engine"
416#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 417#include "vm-engine.c"
17e90c5e 418#undef VM_NAME
6d14383e 419#undef FUNC_NAME
17e90c5e 420#undef VM_ENGINE
17e90c5e
KN
421
422#define VM_NAME vm_debug_engine
6d14383e
AW
423#define FUNC_NAME "vm-debug-engine"
424#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 425#include "vm-engine.c"
17e90c5e 426#undef VM_NAME
6d14383e 427#undef FUNC_NAME
17e90c5e
KN
428#undef VM_ENGINE
429
6d14383e
AW
430static const scm_t_vm_engine vm_engines[] =
431 { vm_regular_engine, vm_debug_engine };
432
e3eb628d
LC
433#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
434
435/* The GC "kind" for the VM stack. */
436static int vm_stack_gc_kind;
437
438#endif
439
a98cef7e 440static SCM
17e90c5e
KN
441make_vm (void)
442#define FUNC_NAME "make_vm"
a98cef7e 443{
17e90c5e 444 int i;
7f991c7d 445 struct scm_vm *vp;
747a1635 446
7f991c7d 447 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 448
3d5ee0cd 449 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
450
451#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
452 vp->stack_base = (SCM *)
453 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
454
455 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
456 top is. */
457 *vp->stack_base = PTR2SCM (vp);
458 vp->stack_base++;
459 vp->stack_size--;
460#else
d8eeb67c
LC
461 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
462 "stack-base");
e3eb628d
LC
463#endif
464
2bbe1533
AW
465#ifdef VM_ENABLE_STACK_NULLING
466 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
467#endif
75d315e1 468 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
469 vp->ip = NULL;
470 vp->sp = vp->stack_base - 1;
471 vp->fp = NULL;
6d14383e 472 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 473 vp->options = SCM_EOL;
7656f194 474 vp->trace_level = 0;
17e90c5e 475 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 476 vp->hooks[i] = SCM_BOOL_F;
2d026f04 477 vp->cookie = 0;
6f3b0cc2 478 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 479}
17e90c5e 480#undef FUNC_NAME
a98cef7e 481
e3eb628d
LC
482#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
483
484/* Mark the VM stack region between its base and its current top. */
485static struct GC_ms_entry *
486vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
487 struct GC_ms_entry *mark_stack_limit, GC_word env)
488{
489 GC_word *word;
490 const struct scm_vm *vm;
491
492 /* The first word of the VM stack should contain a pointer to the
493 corresponding VM. */
494 vm = * ((struct scm_vm **) addr);
495
8071c490
LC
496 if (vm == NULL
497 || (SCM *) addr != vm->stack_base - 1
78747ac6 498 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
499 /* ADDR must be a pointer to a free-list element, which we must ignore
500 (see warning in <gc/gc_mark.h>). */
501 return mark_stack_ptr;
502
e3eb628d
LC
503 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
504 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
505 mark_stack_ptr, mark_stack_limit,
506 NULL);
507
508 return mark_stack_ptr;
509}
510
511#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
512
513
6d14383e 514SCM
4abef68f 515scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 516{
4abef68f 517 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 518 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
519}
520
6f3b0cc2
AW
521SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
522 (SCM vm, SCM program, SCM args),
523 "")
524#define FUNC_NAME s_scm_vm_apply
a98cef7e 525{
6d14383e
AW
526 SCM *argv;
527 int i, nargs;
528
529 SCM_VALIDATE_VM (1, vm);
67e2d80a 530 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
531
532 nargs = scm_ilength (args);
533 if (SCM_UNLIKELY (nargs < 0))
534 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
535
536 argv = alloca(nargs * sizeof(SCM));
537 for (i = 0; i < nargs; i++)
538 {
539 argv[i] = SCM_CAR (args);
540 args = SCM_CDR (args);
541 }
542
4abef68f 543 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 544}
17e90c5e 545#undef FUNC_NAME
a98cef7e
KN
546
547/* Scheme interface */
548
549SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
550 (void),
551 "")
a98cef7e
KN
552#define FUNC_NAME s_scm_vm_version
553{
d3518113 554 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
555}
556#undef FUNC_NAME
557
499a4c07 558SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 559 (void),
499a4c07
KN
560 "")
561#define FUNC_NAME s_scm_the_vm
562{
2bbe1533 563 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 564
8b22ed7a 565 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 566 t->vm = make_vm ();
f63ea2ce 567
2bbe1533 568 return t->vm;
499a4c07
KN
569}
570#undef FUNC_NAME
571
572
a98cef7e
KN
573SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
574 (SCM obj),
17e90c5e 575 "")
a98cef7e
KN
576#define FUNC_NAME s_scm_vm_p
577{
9bd48cb1 578 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
579}
580#undef FUNC_NAME
581
582SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
583 (void),
584 "")
585#define FUNC_NAME s_scm_make_vm,
a98cef7e 586{
17e90c5e 587 return make_vm ();
a98cef7e
KN
588}
589#undef FUNC_NAME
590
17e90c5e 591SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 592 (SCM vm),
17e90c5e
KN
593 "")
594#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
595{
596 SCM_VALIDATE_VM (1, vm);
f41cb00c 597 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
598}
599#undef FUNC_NAME
600
601SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
602 (SCM vm),
17e90c5e 603 "")
a98cef7e
KN
604#define FUNC_NAME s_scm_vm_sp
605{
606 SCM_VALIDATE_VM (1, vm);
f41cb00c 607 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
608}
609#undef FUNC_NAME
610
611SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
612 (SCM vm),
17e90c5e 613 "")
a98cef7e
KN
614#define FUNC_NAME s_scm_vm_fp
615{
616 SCM_VALIDATE_VM (1, vm);
f41cb00c 617 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
618}
619#undef FUNC_NAME
620
17e90c5e
KN
621#define VM_DEFINE_HOOK(n) \
622{ \
3d5ee0cd 623 struct scm_vm *vp; \
17e90c5e 624 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 625 vp = SCM_VM_DATA (vm); \
8b22ed7a 626 if (scm_is_false (vp->hooks[n])) \
238e7a11 627 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 628 return vp->hooks[n]; \
17e90c5e
KN
629}
630
631SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 632 (SCM vm),
17e90c5e
KN
633 "")
634#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 635{
17e90c5e 636 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
637}
638#undef FUNC_NAME
639
17e90c5e
KN
640SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
641 (SCM vm),
642 "")
643#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 644{
17e90c5e 645 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
646}
647#undef FUNC_NAME
648
17e90c5e 649SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 650 (SCM vm),
17e90c5e
KN
651 "")
652#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 653{
17e90c5e 654 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
655}
656#undef FUNC_NAME
657
7a0d0cee
KN
658SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
659 (SCM vm),
660 "")
661#define FUNC_NAME s_scm_vm_break_hook
662{
663 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
664}
665#undef FUNC_NAME
666
17e90c5e
KN
667SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
668 (SCM vm),
669 "")
670#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 671{
17e90c5e 672 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
673}
674#undef FUNC_NAME
675
17e90c5e
KN
676SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
677 (SCM vm),
678 "")
679#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 680{
17e90c5e 681 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
682}
683#undef FUNC_NAME
684
17e90c5e 685SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 686 (SCM vm),
17e90c5e
KN
687 "")
688#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 689{
17e90c5e 690 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
691}
692#undef FUNC_NAME
693
17e90c5e 694SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 695 (SCM vm),
17e90c5e
KN
696 "")
697#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 698{
17e90c5e 699 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
700}
701#undef FUNC_NAME
702
17e90c5e
KN
703SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
704 (SCM vm, SCM key),
705 "")
706#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
707{
708 SCM_VALIDATE_VM (1, vm);
17e90c5e 709 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
710}
711#undef FUNC_NAME
712
17e90c5e
KN
713SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
714 (SCM vm, SCM key, SCM val),
715 "")
716#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
717{
718 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
719 SCM_VM_DATA (vm)->options
720 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
721 return SCM_UNSPECIFIED;
a98cef7e
KN
722}
723#undef FUNC_NAME
724
7656f194 725SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
726 (SCM vm),
727 "")
7656f194 728#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 729{
a98cef7e 730 SCM_VALIDATE_VM (1, vm);
7656f194
AW
731 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
732}
733#undef FUNC_NAME
734
735SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
736 (SCM vm, SCM level),
737 "")
738#define FUNC_NAME s_scm_set_vm_trace_level_x
739{
740 SCM_VALIDATE_VM (1, vm);
741 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
742 return SCM_UNSPECIFIED;
a98cef7e
KN
743}
744#undef FUNC_NAME
745
746\f
747/*
17e90c5e 748 * Initialize
a98cef7e
KN
749 */
750
07e56b27
AW
751SCM scm_load_compiled_with_vm (SCM file)
752{
53e28ed9 753 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 754 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 755
4abef68f 756 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
757}
758
17e90c5e 759void
07e56b27 760scm_bootstrap_vm (void)
17e90c5e 761{
60ae5ca2
AW
762 scm_c_register_extension ("libguile", "scm_init_vm",
763 (scm_t_extension_init_func)scm_init_vm, NULL);
764
35ac7852
AW
765 sym_vm_run = scm_from_locale_symbol ("vm-run");
766 sym_vm_error = scm_from_locale_symbol ("vm-error");
767 sym_keyword_argument_error = scm_from_locale_symbol ("keyword-argument-error");
768 sym_debug = scm_from_locale_symbol ("debug");
0404c97d 769
e3eb628d
LC
770#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
771 vm_stack_gc_kind =
772 GC_new_kind (GC_new_free_list (),
773 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
774 0, 1);
775
776#endif
07e56b27
AW
777}
778
779void
780scm_init_vm (void)
781{
17e90c5e 782#ifndef SCM_MAGIC_SNARFER
aeeff258 783#include "libguile/vm.x"
17e90c5e 784#endif
a98cef7e 785}
17e90c5e
KN
786
787/*
788 Local Variables:
789 c-file-style: "gnu"
790 End:
791*/