add a test for ffi and pointers
[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"
ac99cb0c 31#include "frames.h"
17e90c5e 32#include "instructions.h"
8f5cfc81 33#include "objcodes.h"
ac99cb0c 34#include "programs.h"
fb10a008 35#include "lang.h" /* NULL_OR_NIL_P */
a98cef7e
KN
36#include "vm.h"
37
a98cef7e
KN
38/* I sometimes use this for debugging. */
39#define vm_puts(OBJ) \
40{ \
22bcbe8c
AW
41 scm_display (OBJ, scm_current_error_port ()); \
42 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
43}
44
11ea1aba
AW
45/* The VM has a number of internal assertions that shouldn't normally be
46 necessary, but might be if you think you found a bug in the VM. */
47#define VM_ENABLE_ASSERTIONS
48
49/* We can add a mode that ensures that all stack items above the stack pointer
50 are NULL. This is useful for checking the internal consistency of the VM's
51 assumptions and its operators, but isn't necessary for normal operation. It
616167fc 52 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 53/* NB! If you enable this, search for NULLING in throw.c */
616167fc 54/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 55
53e28ed9
AW
56/* #define VM_ENABLE_PARANOID_ASSERTIONS */
57
11ea1aba
AW
58#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
59#define VM_ENABLE_ASSERTIONS
60#endif
61
e3eb628d
LC
62/* When defined, arrange so that the GC doesn't scan the VM stack beyond its
63 current SP. This should help avoid excess data retention. See
64 http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/3001
65 for a discussion. */
66#define VM_ENABLE_PRECISE_STACK_GC_SCAN
67
68
a98cef7e 69\f
a98cef7e
KN
70/*
71 * VM Continuation
72 */
73
6f3b0cc2
AW
74void
75scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
76{
77 scm_puts ("#<vm-continuation ", port);
78 scm_uintprint (SCM_UNPACK (x), 16, port);
79 scm_puts (">", port);
80}
17e90c5e 81
a98cef7e 82static SCM
3d5ee0cd 83capture_vm_cont (struct scm_vm *vp)
a98cef7e 84{
bfffd258
AW
85 struct scm_vm_cont *p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
86 p->stack_size = vp->sp - vp->stack_base + 1;
d8eeb67c
LC
87 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
88 "capture_vm_cont");
11ea1aba 89#ifdef VM_ENABLE_STACK_NULLING
66db076a
AW
90 if (vp->sp >= vp->stack_base)
91 if (!vp->sp[0] || vp->sp[1])
92 abort ();
11ea1aba
AW
93 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
94#endif
3d5ee0cd 95 p->ip = vp->ip;
7aa6f86b
AW
96 p->sp = vp->sp;
97 p->fp = vp->fp;
bfffd258 98 memcpy (p->stack_base, vp->stack_base, p->stack_size * sizeof (SCM));
11ea1aba 99 p->reloc = p->stack_base - vp->stack_base;
6f3b0cc2 100 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
101}
102
103static void
3d5ee0cd 104reinstate_vm_cont (struct scm_vm *vp, SCM cont)
a98cef7e 105{
bfffd258 106 struct scm_vm_cont *p = SCM_VM_CONT_DATA (cont);
3d5ee0cd 107 if (vp->stack_size < p->stack_size)
a98cef7e 108 {
17e90c5e 109 /* puts ("FIXME: Need to expand"); */
a98cef7e
KN
110 abort ();
111 }
11ea1aba
AW
112#ifdef VM_ENABLE_STACK_NULLING
113 {
7aa6f86b 114 scm_t_ptrdiff nzero = (vp->sp - p->sp);
11ea1aba 115 if (nzero > 0)
66db076a
AW
116 memset (vp->stack_base + p->stack_size, 0, nzero * sizeof (SCM));
117 /* actually nzero should always be negative, because vm_reset_stack will
118 unwind the stack to some point *below* this continuation */
11ea1aba
AW
119 }
120#endif
3d5ee0cd 121 vp->ip = p->ip;
7aa6f86b
AW
122 vp->sp = p->sp;
123 vp->fp = p->fp;
bfffd258
AW
124 memcpy (vp->stack_base, p->stack_base, p->stack_size * sizeof (SCM));
125}
126
127/* In theory, a number of vm instances can be active in the call trace, and we
128 only want to reify the continuations of those in the current continuation
129 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
130 and previous values of the *the-vm* fluid within the current continuation
131 root. But we don't have access to continuation roots in the dynwind stack.
132 So, just punt for now -- take the current value of *the-vm*.
133
134 While I'm on the topic, ideally we could avoid copying the C stack if the
135 continuation root is inside VM code, and call/cc was invoked within that same
136 call to vm_run; but that's currently not implemented.
137 */
138SCM
139scm_vm_capture_continuations (void)
140{
141 SCM vm = scm_the_vm ();
142 return scm_acons (vm, capture_vm_cont (SCM_VM_DATA (vm)), SCM_EOL);
143}
144
145void
146scm_vm_reinstate_continuations (SCM conts)
147{
148 for (; conts != SCM_EOL; conts = SCM_CDR (conts))
149 reinstate_vm_cont (SCM_VM_DATA (SCM_CAAR (conts)), SCM_CDAR (conts));
a98cef7e
KN
150}
151
b1b942b7 152static void
7656f194 153vm_dispatch_hook (SCM vm, int hook_num)
b1b942b7 154{
7656f194
AW
155 struct scm_vm *vp;
156 SCM hook;
157 SCM frame;
b1b942b7 158
7656f194
AW
159 vp = SCM_VM_DATA (vm);
160 hook = vp->hooks[hook_num];
b1b942b7 161
7656f194
AW
162 if (SCM_LIKELY (scm_is_false (hook))
163 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
164 return;
165
166 vp->trace_level--;
167 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
168 scm_c_run_hookn (hook, &frame, 1);
169 vp->trace_level++;
b1b942b7
AW
170}
171
17e90c5e
KN
172\f
173/*
174 * VM Internal functions
175 */
176
f6a8e791
AW
177SCM_SYMBOL (sym_vm_run, "vm-run");
178SCM_SYMBOL (sym_vm_error, "vm-error");
179SCM_SYMBOL (sym_keyword_argument_error, "keyword-argument-error");
180SCM_SYMBOL (sym_debug, "debug");
17e90c5e 181
6f3b0cc2
AW
182void
183scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
184{
185 scm_puts ("#<vm ", port);
186 scm_uintprint (SCM_UNPACK (x), 16, port);
187 scm_puts (">", port);
188}
189
2fda0242 190static SCM
d2d7acd5 191really_make_boot_program (long nargs)
2fda0242 192{
5bd047ce 193 SCM u8vec;
97fcf583
AW
194 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
195 scm_op_make_int8_1, scm_op_halt };
28b119ee 196 struct scm_objcode *bp;
3b9e095b 197 SCM ret;
5bd047ce 198
53e28ed9 199 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 200 abort ();
28b119ee
AW
201 text[1] = (scm_t_uint8)nargs;
202
d7e7a02a 203 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 204 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
205 bp->len = sizeof(text);
206 bp->metalen = 0;
28b119ee 207
7055591c
AW
208 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
209 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 210 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 211 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 212 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 213
3b9e095b 214 return ret;
2fda0242 215}
d2d7acd5
AW
216#define NUM_BOOT_PROGS 8
217static SCM
218vm_make_boot_program (long nargs)
219{
220 static SCM programs[NUM_BOOT_PROGS] = { 0, };
221
222 if (SCM_UNLIKELY (!programs[0]))
223 {
224 int i;
225 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 226 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
227 }
228
229 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
230 return programs[nargs];
231 else
232 return really_make_boot_program (nargs);
233}
2fda0242 234
a98cef7e
KN
235\f
236/*
237 * VM
238 */
239
b7393ea1
AW
240static SCM
241resolve_variable (SCM what, SCM program_module)
242{
9bd48cb1 243 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
244 {
245 if (SCM_LIKELY (scm_module_system_booted_p
246 && scm_is_true (program_module)))
247 /* might longjmp */
248 return scm_module_lookup (program_module, what);
249 else
250 {
251 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
252 if (scm_is_false (v))
253 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
254 else
255 return v;
256 }
257 }
258 else
259 {
260 SCM mod;
261 /* compilation of @ or @@
262 `what' is a three-element list: (MODNAME SYM INTERFACE?)
263 INTERFACE? is #t if we compiled @ or #f if we compiled @@
264 */
265 mod = scm_resolve_module (SCM_CAR (what));
266 if (scm_is_true (SCM_CADDR (what)))
267 mod = scm_module_public_interface (mod);
5c8cefe5 268 if (scm_is_false (mod))
b7393ea1
AW
269 scm_misc_error (NULL, "no such module: ~S",
270 scm_list_1 (SCM_CAR (what)));
271 /* might longjmp */
272 return scm_module_lookup (mod, SCM_CADR (what));
273 }
274}
275
51e9ba2f 276#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 277
17e90c5e 278#define VM_NAME vm_regular_engine
6d14383e
AW
279#define FUNC_NAME "vm-regular-engine"
280#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 281#include "vm-engine.c"
17e90c5e 282#undef VM_NAME
6d14383e 283#undef FUNC_NAME
17e90c5e 284#undef VM_ENGINE
17e90c5e
KN
285
286#define VM_NAME vm_debug_engine
6d14383e
AW
287#define FUNC_NAME "vm-debug-engine"
288#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 289#include "vm-engine.c"
17e90c5e 290#undef VM_NAME
6d14383e 291#undef FUNC_NAME
17e90c5e
KN
292#undef VM_ENGINE
293
6d14383e
AW
294static const scm_t_vm_engine vm_engines[] =
295 { vm_regular_engine, vm_debug_engine };
296
e3eb628d
LC
297#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
298
299/* The GC "kind" for the VM stack. */
300static int vm_stack_gc_kind;
301
302#endif
303
a98cef7e 304static SCM
17e90c5e
KN
305make_vm (void)
306#define FUNC_NAME "make_vm"
a98cef7e 307{
17e90c5e 308 int i;
7f991c7d 309 struct scm_vm *vp;
747a1635 310
7f991c7d 311 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 312
3d5ee0cd 313 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
314
315#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
316 vp->stack_base = (SCM *)
317 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
318
319 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
320 top is. */
321 *vp->stack_base = PTR2SCM (vp);
322 vp->stack_base++;
323 vp->stack_size--;
324#else
d8eeb67c
LC
325 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
326 "stack-base");
e3eb628d
LC
327#endif
328
2bbe1533
AW
329#ifdef VM_ENABLE_STACK_NULLING
330 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
331#endif
75d315e1 332 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
333 vp->ip = NULL;
334 vp->sp = vp->stack_base - 1;
335 vp->fp = NULL;
6d14383e 336 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 337 vp->options = SCM_EOL;
7656f194 338 vp->trace_level = 0;
17e90c5e 339 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 340 vp->hooks[i] = SCM_BOOL_F;
6f3b0cc2 341 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 342}
17e90c5e 343#undef FUNC_NAME
a98cef7e 344
e3eb628d
LC
345#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
346
347/* Mark the VM stack region between its base and its current top. */
348static struct GC_ms_entry *
349vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
350 struct GC_ms_entry *mark_stack_limit, GC_word env)
351{
352 GC_word *word;
353 const struct scm_vm *vm;
354
355 /* The first word of the VM stack should contain a pointer to the
356 corresponding VM. */
357 vm = * ((struct scm_vm **) addr);
358
8071c490
LC
359 if (vm == NULL
360 || (SCM *) addr != vm->stack_base - 1
78747ac6 361 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
362 /* ADDR must be a pointer to a free-list element, which we must ignore
363 (see warning in <gc/gc_mark.h>). */
364 return mark_stack_ptr;
365
e3eb628d
LC
366 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
367 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
368 mark_stack_ptr, mark_stack_limit,
369 NULL);
370
371 return mark_stack_ptr;
372}
373
374#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
375
376
6d14383e 377SCM
4abef68f 378scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 379{
4abef68f 380 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 381 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
382}
383
6f3b0cc2
AW
384SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
385 (SCM vm, SCM program, SCM args),
386 "")
387#define FUNC_NAME s_scm_vm_apply
a98cef7e 388{
6d14383e
AW
389 SCM *argv;
390 int i, nargs;
391
392 SCM_VALIDATE_VM (1, vm);
67e2d80a 393 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
394
395 nargs = scm_ilength (args);
396 if (SCM_UNLIKELY (nargs < 0))
397 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
398
399 argv = alloca(nargs * sizeof(SCM));
400 for (i = 0; i < nargs; i++)
401 {
402 argv[i] = SCM_CAR (args);
403 args = SCM_CDR (args);
404 }
405
4abef68f 406 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 407}
17e90c5e 408#undef FUNC_NAME
a98cef7e 409
14aa25e4
AW
410SCM
411scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
412{
413 return scm_c_vm_run (vm, thunk, NULL, 0);
414}
415
a98cef7e
KN
416/* Scheme interface */
417
418SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
419 (void),
420 "")
a98cef7e
KN
421#define FUNC_NAME s_scm_vm_version
422{
d3518113 423 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
424}
425#undef FUNC_NAME
426
499a4c07 427SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 428 (void),
499a4c07
KN
429 "")
430#define FUNC_NAME s_scm_the_vm
431{
2bbe1533 432 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 433
8b22ed7a 434 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 435 t->vm = make_vm ();
f63ea2ce 436
2bbe1533 437 return t->vm;
499a4c07
KN
438}
439#undef FUNC_NAME
440
441
a98cef7e
KN
442SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
443 (SCM obj),
17e90c5e 444 "")
a98cef7e
KN
445#define FUNC_NAME s_scm_vm_p
446{
9bd48cb1 447 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
448}
449#undef FUNC_NAME
450
451SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
452 (void),
453 "")
454#define FUNC_NAME s_scm_make_vm,
a98cef7e 455{
17e90c5e 456 return make_vm ();
a98cef7e
KN
457}
458#undef FUNC_NAME
459
17e90c5e 460SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 461 (SCM vm),
17e90c5e
KN
462 "")
463#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
464{
465 SCM_VALIDATE_VM (1, vm);
f41cb00c 466 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
467}
468#undef FUNC_NAME
469
470SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
471 (SCM vm),
17e90c5e 472 "")
a98cef7e
KN
473#define FUNC_NAME s_scm_vm_sp
474{
475 SCM_VALIDATE_VM (1, vm);
f41cb00c 476 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
477}
478#undef FUNC_NAME
479
480SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
481 (SCM vm),
17e90c5e 482 "")
a98cef7e
KN
483#define FUNC_NAME s_scm_vm_fp
484{
485 SCM_VALIDATE_VM (1, vm);
f41cb00c 486 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
487}
488#undef FUNC_NAME
489
17e90c5e
KN
490#define VM_DEFINE_HOOK(n) \
491{ \
3d5ee0cd 492 struct scm_vm *vp; \
17e90c5e 493 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 494 vp = SCM_VM_DATA (vm); \
8b22ed7a 495 if (scm_is_false (vp->hooks[n])) \
238e7a11 496 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 497 return vp->hooks[n]; \
17e90c5e
KN
498}
499
500SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 501 (SCM vm),
17e90c5e
KN
502 "")
503#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 504{
17e90c5e 505 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
506}
507#undef FUNC_NAME
508
17e90c5e
KN
509SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
510 (SCM vm),
511 "")
512#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 513{
17e90c5e 514 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
515}
516#undef FUNC_NAME
517
17e90c5e 518SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 519 (SCM vm),
17e90c5e
KN
520 "")
521#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 522{
17e90c5e 523 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
524}
525#undef FUNC_NAME
526
7a0d0cee
KN
527SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
528 (SCM vm),
529 "")
530#define FUNC_NAME s_scm_vm_break_hook
531{
532 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
533}
534#undef FUNC_NAME
535
17e90c5e
KN
536SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
537 (SCM vm),
538 "")
539#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 540{
17e90c5e 541 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
542}
543#undef FUNC_NAME
544
17e90c5e
KN
545SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
546 (SCM vm),
547 "")
548#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 549{
17e90c5e 550 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
551}
552#undef FUNC_NAME
553
17e90c5e 554SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 555 (SCM vm),
17e90c5e
KN
556 "")
557#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 558{
17e90c5e 559 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
560}
561#undef FUNC_NAME
562
17e90c5e 563SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 564 (SCM vm),
17e90c5e
KN
565 "")
566#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 567{
17e90c5e 568 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
569}
570#undef FUNC_NAME
571
17e90c5e
KN
572SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
573 (SCM vm, SCM key),
574 "")
575#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
576{
577 SCM_VALIDATE_VM (1, vm);
17e90c5e 578 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
579}
580#undef FUNC_NAME
581
17e90c5e
KN
582SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
583 (SCM vm, SCM key, SCM val),
584 "")
585#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
586{
587 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
588 SCM_VM_DATA (vm)->options
589 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
590 return SCM_UNSPECIFIED;
a98cef7e
KN
591}
592#undef FUNC_NAME
593
7656f194 594SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
595 (SCM vm),
596 "")
7656f194 597#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 598{
a98cef7e 599 SCM_VALIDATE_VM (1, vm);
7656f194
AW
600 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
601}
602#undef FUNC_NAME
603
604SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
605 (SCM vm, SCM level),
606 "")
607#define FUNC_NAME s_scm_set_vm_trace_level_x
608{
609 SCM_VALIDATE_VM (1, vm);
610 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
611 return SCM_UNSPECIFIED;
a98cef7e
KN
612}
613#undef FUNC_NAME
614
615\f
616/*
17e90c5e 617 * Initialize
a98cef7e
KN
618 */
619
07e56b27
AW
620SCM scm_load_compiled_with_vm (SCM file)
621{
53e28ed9 622 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 623 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 624
4abef68f 625 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
626}
627
17e90c5e 628void
07e56b27 629scm_bootstrap_vm (void)
17e90c5e 630{
60ae5ca2
AW
631 scm_c_register_extension ("libguile", "scm_init_vm",
632 (scm_t_extension_init_func)scm_init_vm, NULL);
633
e3eb628d
LC
634#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
635 vm_stack_gc_kind =
636 GC_new_kind (GC_new_free_list (),
637 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
638 0, 1);
639
640#endif
07e56b27
AW
641}
642
643void
644scm_init_vm (void)
645{
17e90c5e 646#ifndef SCM_MAGIC_SNARFER
aeeff258 647#include "libguile/vm.x"
17e90c5e 648#endif
a98cef7e 649}
17e90c5e
KN
650
651/*
652 Local Variables:
653 c-file-style: "gnu"
654 End:
655*/