Allocate stacks using mmap, and mark them via the thread marker
[bpt/guile.git] / libguile / vm.c
CommitLineData
aab9d46c 1/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 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>
daccfef4 25#include <alignof.h>
17e90c5e 26#include <string.h>
e78d4bf9 27#include <stdint.h>
e3eb628d 28
5f18bc84
AW
29#ifdef HAVE_SYS_MMAN_H
30#include <sys/mman.h>
31#endif
32
1c44468d 33#include "libguile/bdw-gc.h"
e3eb628d
LC
34#include <gc/gc_mark.h>
35
560b9c25 36#include "_scm.h"
adaf86ec 37#include "control.h"
ac99cb0c 38#include "frames.h"
17e90c5e 39#include "instructions.h"
4cbc95f1 40#include "loader.h"
ac99cb0c 41#include "programs.h"
a98cef7e 42#include "vm.h"
486013d6 43#include "vm-builtins.h"
a98cef7e 44
aab9d46c
SIT
45#include "private-gc.h" /* scm_getenv_int */
46
97b18a66 47static int vm_default_engine = SCM_VM_REGULAR_ENGINE;
ea9f4f4b
AW
48
49/* Unfortunately we can't snarf these: snarfed things are only loaded up from
50 (system vm vm), which might not be loaded before an error happens. */
51static SCM sym_vm_run;
52static SCM sym_vm_error;
53static SCM sym_keyword_argument_error;
54static SCM sym_regular;
55static SCM sym_debug;
a98cef7e 56
11ea1aba
AW
57/* The VM has a number of internal assertions that shouldn't normally be
58 necessary, but might be if you think you found a bug in the VM. */
59#define VM_ENABLE_ASSERTIONS
60
53e28ed9
AW
61/* #define VM_ENABLE_PARANOID_ASSERTIONS */
62
f1046e6b
LC
63/* Size in SCM objects of the stack reserve. The reserve is used to run
64 exception handling code in case of a VM stack overflow. */
65#define VM_STACK_RESERVE_SIZE 512
66
e3eb628d 67
a98cef7e 68\f
a98cef7e
KN
69/*
70 * VM Continuation
71 */
72
6f3b0cc2
AW
73void
74scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
75{
0607ebbf 76 scm_puts_unlocked ("#<vm-continuation ", port);
6f3b0cc2 77 scm_uintprint (SCM_UNPACK (x), 16, port);
0607ebbf 78 scm_puts_unlocked (">", port);
6f3b0cc2 79}
17e90c5e 80
d8873dfe
AW
81/* In theory, a number of vm instances can be active in the call trace, and we
82 only want to reify the continuations of those in the current continuation
83 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
84 and previous values of the *the-vm* fluid within the current continuation
85 root. But we don't have access to continuation roots in the dynwind stack.
86 So, just punt for now, we just capture the continuation for the current VM.
87
88 While I'm on the topic, ideally we could avoid copying the C stack if the
89 continuation root is inside VM code, and call/cc was invoked within that same
90 call to vm_run; but that's currently not implemented.
91 */
cee1d22c 92SCM
9121d9f1 93scm_i_vm_capture_stack (SCM *stack_base, SCM *fp, SCM *sp, scm_t_uint32 *ra,
840ec334 94 scm_t_dynstack *dynstack, scm_t_uint32 flags)
a98cef7e 95{
d8873dfe
AW
96 struct scm_vm_cont *p;
97
98 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
99 p->stack_size = sp - stack_base + 1;
d8eeb67c
LC
100 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
101 "capture_vm_cont");
d8873dfe 102 p->ra = ra;
d8873dfe
AW
103 p->sp = sp;
104 p->fp = fp;
105 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
106 p->reloc = p->stack_base - stack_base;
9ede013f 107 p->dynstack = dynstack;
cee1d22c 108 p->flags = flags;
6f3b0cc2 109 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
110}
111
112static void
796e54a7 113vm_return_to_continuation (struct scm_vm *vp, SCM cont, size_t n, SCM *argv)
a98cef7e 114{
d8873dfe
AW
115 struct scm_vm_cont *cp;
116 SCM *argv_copy;
117
118 argv_copy = alloca (n * sizeof(SCM));
119 memcpy (argv_copy, argv, n * sizeof(SCM));
120
d8873dfe
AW
121 cp = SCM_VM_CONT_DATA (cont);
122
f8085163 123 if (vp->stack_size < cp->stack_size + n + 3)
29366989 124 scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
796e54a7 125 scm_list_1 (cont));
29366989 126
d8873dfe
AW
127 vp->sp = cp->sp;
128 vp->fp = cp->fp;
129 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 130
03f16599
AW
131 {
132 size_t i;
133
134 /* Push on an empty frame, as the continuation expects. */
f8085163 135 for (i = 0; i < 3; i++)
03f16599
AW
136 {
137 vp->sp++;
138 *vp->sp = SCM_BOOL_F;
139 }
140
141 /* Push the return values. */
142 for (i = 0; i < n; i++)
143 {
144 vp->sp++;
145 *vp->sp = argv_copy[i];
146 }
840ec334 147 vp->ip = cp->ra;
03f16599 148 }
d8873dfe 149}
bfffd258 150
b85cd20f 151static struct scm_vm * thread_vm (scm_i_thread *t);
bfffd258 152SCM
9ede013f 153scm_i_capture_current_stack (void)
bfffd258 154{
9ede013f 155 scm_i_thread *thread;
9ede013f
AW
156 struct scm_vm *vp;
157
158 thread = SCM_I_CURRENT_THREAD;
b85cd20f 159 vp = thread_vm (thread);
9ede013f 160
840ec334 161 return scm_i_vm_capture_stack (vp->stack_base, vp->fp, vp->sp, vp->ip,
9ede013f
AW
162 scm_dynstack_capture_all (&thread->dynstack),
163 0);
a98cef7e
KN
164}
165
59f85eed
AW
166static void vm_dispatch_apply_hook (struct scm_vm *vp) SCM_NOINLINE;
167static void vm_dispatch_push_continuation_hook (struct scm_vm *vp) SCM_NOINLINE;
168static void vm_dispatch_pop_continuation_hook (struct scm_vm *vp, SCM *old_fp) SCM_NOINLINE;
169static void vm_dispatch_next_hook (struct scm_vm *vp) SCM_NOINLINE;
170static void vm_dispatch_abort_hook (struct scm_vm *vp) SCM_NOINLINE;
171static void vm_dispatch_restore_continuation_hook (struct scm_vm *vp) SCM_NOINLINE;
c850a0ff 172
b1b942b7 173static void
59f85eed 174vm_dispatch_hook (struct scm_vm *vp, int hook_num, SCM *argv, int n)
b1b942b7 175{
7656f194 176 SCM hook;
b3567435 177 struct scm_frame c_frame;
8e4c60ff 178 scm_t_cell *frame;
893fb8d0 179 int saved_trace_level;
b1b942b7 180
7656f194 181 hook = vp->hooks[hook_num];
b1b942b7 182
7656f194
AW
183 if (SCM_LIKELY (scm_is_false (hook))
184 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
185 return;
b3567435 186
893fb8d0
AW
187 saved_trace_level = vp->trace_level;
188 vp->trace_level = 0;
b3567435
LC
189
190 /* Allocate a frame object on the stack. This is more efficient than calling
191 `scm_c_make_frame ()' to allocate on the heap, but it forces hooks to not
192 capture frame objects.
193
194 At the same time, procedures such as `frame-procedure' make sense only
195 while the stack frame represented by the frame object is visible, so it
196 seems reasonable to limit the lifetime of frame objects. */
197
5515edc5 198 c_frame.stack_holder = vp;
89b235af
AW
199 c_frame.fp_offset = vp->fp - vp->stack_base;
200 c_frame.sp_offset = vp->sp - vp->stack_base;
b3567435 201 c_frame.ip = vp->ip;
8e4c60ff
LC
202
203 /* Arrange for FRAME to be 8-byte aligned, like any other cell. */
204 frame = alloca (sizeof (*frame) + 8);
205 frame = (scm_t_cell *) ROUND_UP ((scm_t_uintptr) frame, 8UL);
206
050a40db 207 frame->word_0 = SCM_PACK (scm_tc7_frame | (SCM_VM_FRAME_KIND_VM << 8));
21041372 208 frame->word_1 = SCM_PACK_POINTER (&c_frame);
b3567435 209
c850a0ff
AW
210 if (n == 0)
211 {
212 SCM args[1];
213
214 args[0] = SCM_PACK_POINTER (frame);
215 scm_c_run_hookn (hook, args, 1);
216 }
217 else if (n == 1)
218 {
219 SCM args[2];
220
221 args[0] = SCM_PACK_POINTER (frame);
222 args[1] = argv[0];
223 scm_c_run_hookn (hook, args, 2);
224 }
225 else
226 {
227 SCM args = SCM_EOL;
228
229 while (n--)
230 args = scm_cons (argv[n], args);
231 scm_c_run_hook (hook, scm_cons (SCM_PACK_POINTER (frame), args));
232 }
b3567435 233
893fb8d0 234 vp->trace_level = saved_trace_level;
b1b942b7
AW
235}
236
ea0cd17d 237static void
59f85eed 238vm_dispatch_apply_hook (struct scm_vm *vp)
ea0cd17d 239{
59f85eed 240 return vm_dispatch_hook (vp, SCM_VM_APPLY_HOOK, NULL, 0);
ea0cd17d 241}
59f85eed 242static void vm_dispatch_push_continuation_hook (struct scm_vm *vp)
ea0cd17d 243{
59f85eed 244 return vm_dispatch_hook (vp, SCM_VM_PUSH_CONTINUATION_HOOK, NULL, 0);
ea0cd17d 245}
59f85eed 246static void vm_dispatch_pop_continuation_hook (struct scm_vm *vp, SCM *old_fp)
ea0cd17d 247{
59f85eed 248 return vm_dispatch_hook (vp, SCM_VM_POP_CONTINUATION_HOOK,
ea0cd17d
AW
249 &SCM_FRAME_LOCAL (old_fp, 1),
250 SCM_FRAME_NUM_LOCALS (old_fp, vp->sp) - 1);
251}
59f85eed 252static void vm_dispatch_next_hook (struct scm_vm *vp)
ea0cd17d 253{
59f85eed 254 return vm_dispatch_hook (vp, SCM_VM_NEXT_HOOK, NULL, 0);
ea0cd17d 255}
59f85eed 256static void vm_dispatch_abort_hook (struct scm_vm *vp)
ea0cd17d 257{
59f85eed 258 return vm_dispatch_hook (vp, SCM_VM_ABORT_CONTINUATION_HOOK,
ea0cd17d
AW
259 &SCM_FRAME_LOCAL (vp->fp, 1),
260 SCM_FRAME_NUM_LOCALS (vp->fp, vp->sp) - 1);
261}
59f85eed 262static void vm_dispatch_restore_continuation_hook (struct scm_vm *vp)
ea0cd17d 263{
59f85eed 264 return vm_dispatch_hook (vp, SCM_VM_RESTORE_CONTINUATION_HOOK, NULL, 0);
ea0cd17d
AW
265}
266
4f66bcde 267static void
b44f5451
AW
268vm_abort (struct scm_vm *vp, SCM tag,
269 size_t nstack, SCM *stack_args, SCM tail, SCM *sp,
99511cd0 270 scm_i_jmp_buf *current_registers) SCM_NORETURN;
9d381ba4
AW
271
272static void
b44f5451
AW
273vm_abort (struct scm_vm *vp, SCM tag,
274 size_t nstack, SCM *stack_args, SCM tail, SCM *sp,
99511cd0 275 scm_i_jmp_buf *current_registers)
4f66bcde 276{
eaefabee 277 size_t i;
2d026f04 278 ssize_t tail_len;
99511cd0 279 SCM *argv;
eaefabee 280
2d026f04
AW
281 tail_len = scm_ilength (tail);
282 if (tail_len < 0)
29366989
AW
283 scm_misc_error ("vm-engine", "tail values to abort should be a list",
284 scm_list_1 (tail));
285
99511cd0
AW
286 argv = alloca ((nstack + tail_len) * sizeof (SCM));
287 for (i = 0; i < nstack; i++)
288 argv[i] = stack_args[i];
289 for (; i < nstack + tail_len; i++, tail = scm_cdr (tail))
2d026f04 290 argv[i] = scm_car (tail);
eaefabee 291
99511cd0 292 /* FIXME: NULLSTACK (SCM_VM_DATA (vp)->sp - sp) */
b44f5451 293 vp->sp = sp;
99511cd0 294
b44f5451 295 scm_c_abort (vp, tag, nstack + tail_len, argv, current_registers);
cee1d22c
AW
296}
297
9d381ba4 298static void
44ece399
AW
299vm_reinstate_partial_continuation (struct scm_vm *vp, SCM cont,
300 size_t n, SCM *argv,
9d381ba4
AW
301 scm_t_dynstack *dynstack,
302 scm_i_jmp_buf *registers)
cee1d22c 303{
07801437
AW
304 struct scm_vm_cont *cp;
305 SCM *argv_copy, *base;
9ede013f 306 scm_t_ptrdiff reloc;
07801437
AW
307 size_t i;
308
309 argv_copy = alloca (n * sizeof(SCM));
310 memcpy (argv_copy, argv, n * sizeof(SCM));
311
07801437 312 cp = SCM_VM_CONT_DATA (cont);
b636cdb0 313 base = SCM_FRAME_LOCALS_ADDRESS (vp->fp);
9ede013f 314 reloc = cp->reloc + (base - cp->stack_base);
07801437 315
0fc9040f 316#define RELOC(scm_p) \
9ede013f 317 (((SCM *) (scm_p)) + reloc)
07801437
AW
318
319 if ((base - vp->stack_base) + cp->stack_size + n + 1 > vp->stack_size)
29366989
AW
320 scm_misc_error ("vm-engine",
321 "not enough space to instate partial continuation",
44ece399 322 scm_list_1 (cont));
07801437
AW
323
324 memcpy (base, cp->stack_base, cp->stack_size * sizeof (SCM));
325
326 /* now relocate frame pointers */
327 {
328 SCM *fp;
329 for (fp = RELOC (cp->fp);
330 SCM_FRAME_LOWER_ADDRESS (fp) > base;
331 fp = SCM_FRAME_DYNAMIC_LINK (fp))
332 SCM_FRAME_SET_DYNAMIC_LINK (fp, RELOC (SCM_FRAME_DYNAMIC_LINK (fp)));
333 }
334
335 vp->sp = base - 1 + cp->stack_size;
336 vp->fp = RELOC (cp->fp);
840ec334 337 vp->ip = cp->ra;
07801437 338
840ec334 339 /* Push the arguments. */
07801437
AW
340 for (i = 0; i < n; i++)
341 {
342 vp->sp++;
343 *vp->sp = argv_copy[i];
344 }
9a1c6f1f 345
9d381ba4
AW
346 /* The prompt captured a slice of the dynamic stack. Here we wind
347 those entries onto the current thread's stack. We also have to
348 relocate any prompts that we see along the way. */
349 {
350 scm_t_bits *walk;
351
352 for (walk = SCM_DYNSTACK_FIRST (cp->dynstack);
353 SCM_DYNSTACK_TAG (walk);
354 walk = SCM_DYNSTACK_NEXT (walk))
355 {
356 scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
357
358 if (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_PROMPT)
359 scm_dynstack_wind_prompt (dynstack, walk, reloc, registers);
360 else
361 scm_dynstack_wind_1 (dynstack, walk);
362 }
363 }
adbdfd6d 364#undef RELOC
4f66bcde
AW
365}
366
367\f
53bdfcf0
AW
368/*
369 * VM Error Handling
370 */
371
372static void vm_error (const char *msg, SCM arg) SCM_NORETURN;
4d497b62
AW
373static void vm_error_bad_instruction (scm_t_uint32 inst) SCM_NORETURN SCM_NOINLINE;
374static void vm_error_unbound (SCM proc, SCM sym) SCM_NORETURN SCM_NOINLINE;
375static void vm_error_unbound_fluid (SCM proc, SCM fluid) SCM_NORETURN SCM_NOINLINE;
376static void vm_error_not_a_variable (const char *func_name, SCM x) SCM_NORETURN SCM_NOINLINE;
377static void vm_error_apply_to_non_list (SCM x) SCM_NORETURN SCM_NOINLINE;
378static void vm_error_kwargs_length_not_even (SCM proc) SCM_NORETURN SCM_NOINLINE;
28d5d253
MW
379static void vm_error_kwargs_invalid_keyword (SCM proc, SCM obj) SCM_NORETURN SCM_NOINLINE;
380static void vm_error_kwargs_unrecognized_keyword (SCM proc, SCM kw) SCM_NORETURN SCM_NOINLINE;
4d497b62
AW
381static void vm_error_too_many_args (int nargs) SCM_NORETURN SCM_NOINLINE;
382static void vm_error_wrong_num_args (SCM proc) SCM_NORETURN SCM_NOINLINE;
383static void vm_error_wrong_type_apply (SCM proc) SCM_NORETURN SCM_NOINLINE;
384static void vm_error_stack_overflow (struct scm_vm *vp) SCM_NORETURN SCM_NOINLINE;
385static void vm_error_stack_underflow (void) SCM_NORETURN SCM_NOINLINE;
386static void vm_error_improper_list (SCM x) SCM_NORETURN SCM_NOINLINE;
387static void vm_error_not_a_pair (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
388static void vm_error_not_a_bytevector (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
389static void vm_error_not_a_struct (const char *subr, SCM x) SCM_NORETURN SCM_NOINLINE;
390static void vm_error_no_values (void) SCM_NORETURN SCM_NOINLINE;
391static void vm_error_not_enough_values (void) SCM_NORETURN SCM_NOINLINE;
82f4bac4 392static void vm_error_wrong_number_of_values (scm_t_uint32 expected) SCM_NORETURN SCM_NOINLINE;
4d497b62
AW
393static void vm_error_continuation_not_rewindable (SCM cont) SCM_NORETURN SCM_NOINLINE;
394static void vm_error_bad_wide_string_length (size_t len) SCM_NORETURN SCM_NOINLINE;
53bdfcf0
AW
395
396static void
397vm_error (const char *msg, SCM arg)
398{
399 scm_throw (sym_vm_error,
400 scm_list_3 (sym_vm_run, scm_from_latin1_string (msg),
401 SCM_UNBNDP (arg) ? SCM_EOL : scm_list_1 (arg)));
402 abort(); /* not reached */
403}
404
405static void
406vm_error_bad_instruction (scm_t_uint32 inst)
407{
408 vm_error ("VM: Bad instruction: ~s", scm_from_uint32 (inst));
409}
410
411static void
412vm_error_unbound (SCM proc, SCM sym)
413{
414 scm_error_scm (scm_misc_error_key, proc,
415 scm_from_latin1_string ("Unbound variable: ~s"),
416 scm_list_1 (sym), SCM_BOOL_F);
417}
418
419static void
420vm_error_unbound_fluid (SCM proc, SCM fluid)
421{
422 scm_error_scm (scm_misc_error_key, proc,
423 scm_from_latin1_string ("Unbound fluid: ~s"),
424 scm_list_1 (fluid), SCM_BOOL_F);
425}
426
427static void
428vm_error_not_a_variable (const char *func_name, SCM x)
429{
430 scm_error (scm_arg_type_key, func_name, "Not a variable: ~S",
431 scm_list_1 (x), scm_list_1 (x));
432}
433
53bdfcf0
AW
434static void
435vm_error_apply_to_non_list (SCM x)
436{
437 scm_error (scm_arg_type_key, "apply", "Apply to non-list: ~S",
438 scm_list_1 (x), scm_list_1 (x));
439}
440
441static void
442vm_error_kwargs_length_not_even (SCM proc)
443{
444 scm_error_scm (sym_keyword_argument_error, proc,
445 scm_from_latin1_string ("Odd length of keyword argument list"),
446 SCM_EOL, SCM_BOOL_F);
447}
448
449static void
4af0d97e 450vm_error_kwargs_invalid_keyword (SCM proc, SCM obj)
53bdfcf0
AW
451{
452 scm_error_scm (sym_keyword_argument_error, proc,
453 scm_from_latin1_string ("Invalid keyword"),
4af0d97e 454 SCM_EOL, scm_list_1 (obj));
53bdfcf0
AW
455}
456
457static void
4af0d97e 458vm_error_kwargs_unrecognized_keyword (SCM proc, SCM kw)
53bdfcf0
AW
459{
460 scm_error_scm (sym_keyword_argument_error, proc,
461 scm_from_latin1_string ("Unrecognized keyword"),
4af0d97e 462 SCM_EOL, scm_list_1 (kw));
53bdfcf0
AW
463}
464
465static void
466vm_error_too_many_args (int nargs)
467{
468 vm_error ("VM: Too many arguments", scm_from_int (nargs));
469}
470
471static void
472vm_error_wrong_num_args (SCM proc)
473{
474 scm_wrong_num_args (proc);
475}
476
477static void
478vm_error_wrong_type_apply (SCM proc)
479{
480 scm_error (scm_arg_type_key, NULL, "Wrong type to apply: ~S",
481 scm_list_1 (proc), scm_list_1 (proc));
482}
483
484static void
485vm_error_stack_overflow (struct scm_vm *vp)
486{
487 if (vp->stack_limit < vp->stack_base + vp->stack_size)
488 /* There are VM_STACK_RESERVE_SIZE bytes left. Make them available so
489 that `throw' below can run on this VM. */
490 vp->stack_limit = vp->stack_base + vp->stack_size;
491 else
492 /* There is no space left on the stack. FIXME: Do something more
493 sensible here! */
494 abort ();
495 vm_error ("VM: Stack overflow", SCM_UNDEFINED);
496}
497
498static void
499vm_error_stack_underflow (void)
500{
501 vm_error ("VM: Stack underflow", SCM_UNDEFINED);
502}
503
504static void
505vm_error_improper_list (SCM x)
506{
507 vm_error ("Expected a proper list, but got object with tail ~s", x);
508}
509
510static void
511vm_error_not_a_pair (const char *subr, SCM x)
512{
513 scm_wrong_type_arg_msg (subr, 1, x, "pair");
514}
515
516static void
517vm_error_not_a_bytevector (const char *subr, SCM x)
518{
519 scm_wrong_type_arg_msg (subr, 1, x, "bytevector");
520}
521
522static void
523vm_error_not_a_struct (const char *subr, SCM x)
524{
525 scm_wrong_type_arg_msg (subr, 1, x, "struct");
526}
527
528static void
529vm_error_no_values (void)
530{
531 vm_error ("Zero values returned to single-valued continuation",
532 SCM_UNDEFINED);
533}
534
535static void
536vm_error_not_enough_values (void)
537{
538 vm_error ("Too few values returned to continuation", SCM_UNDEFINED);
539}
540
82f4bac4
AW
541static void
542vm_error_wrong_number_of_values (scm_t_uint32 expected)
543{
544 vm_error ("Wrong number of values returned to continuation (expected ~a)",
545 scm_from_uint32 (expected));
546}
547
53bdfcf0
AW
548static void
549vm_error_continuation_not_rewindable (SCM cont)
550{
551 vm_error ("Unrewindable partial continuation", cont);
552}
553
554static void
555vm_error_bad_wide_string_length (size_t len)
556{
557 vm_error ("VM: Bad wide string length: ~S", scm_from_size_t (len));
558}
559
53bdfcf0
AW
560
561\f
28b119ee 562
ef6b7f71 563static SCM vm_boot_continuation;
486013d6
AW
564static SCM vm_builtin_apply;
565static SCM vm_builtin_values;
566static SCM vm_builtin_abort_to_prompt;
567static SCM vm_builtin_call_with_values;
568static SCM vm_builtin_call_with_current_continuation;
510ca126 569
ef6b7f71 570static const scm_t_uint32 vm_boot_continuation_code[] = {
095100bb 571 SCM_PACK_OP_24 (halt, 0)
510ca126
AW
572};
573
486013d6 574static const scm_t_uint32 vm_builtin_apply_code[] = {
095100bb
AW
575 SCM_PACK_OP_24 (assert_nargs_ge, 3),
576 SCM_PACK_OP_24 (tail_apply, 0), /* proc in r1, args from r2 */
510ca126
AW
577};
578
486013d6 579static const scm_t_uint32 vm_builtin_values_code[] = {
095100bb 580 SCM_PACK_OP_24 (return_values, 0) /* vals from r1 */
510ca126
AW
581};
582
486013d6 583static const scm_t_uint32 vm_builtin_abort_to_prompt_code[] = {
095100bb
AW
584 SCM_PACK_OP_24 (assert_nargs_ge, 2),
585 SCM_PACK_OP_24 (abort, 0), /* tag in r1, vals from r2 */
486013d6 586 /* FIXME: Partial continuation should capture caller regs. */
095100bb 587 SCM_PACK_OP_24 (return_values, 0) /* vals from r1 */
486013d6
AW
588};
589
590static const scm_t_uint32 vm_builtin_call_with_values_code[] = {
095100bb
AW
591 SCM_PACK_OP_24 (assert_nargs_ee, 3),
592 SCM_PACK_OP_24 (alloc_frame, 7),
593 SCM_PACK_OP_12_12 (mov, 6, 1),
594 SCM_PACK_OP_24 (call, 6), SCM_PACK_OP_ARG_8_24 (0, 1),
595 SCM_PACK_OP_12_12 (mov, 0, 2),
596 SCM_PACK_OP_24 (tail_call_shuffle, 7)
486013d6
AW
597};
598
599static const scm_t_uint32 vm_builtin_call_with_current_continuation_code[] = {
095100bb
AW
600 SCM_PACK_OP_24 (assert_nargs_ee, 2),
601 SCM_PACK_OP_24 (call_cc, 0)
486013d6
AW
602};
603
604
605static SCM
606scm_vm_builtin_ref (unsigned idx)
607{
608 switch (idx)
609 {
9f309e2c 610#define INDEX_TO_NAME(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
611 case SCM_VM_BUILTIN_##BUILTIN: return vm_builtin_##builtin;
612 FOR_EACH_VM_BUILTIN(INDEX_TO_NAME)
613#undef INDEX_TO_NAME
614 default: abort();
615 }
616}
617
9f309e2c 618SCM scm_sym_apply;
486013d6
AW
619static SCM scm_sym_values;
620static SCM scm_sym_abort_to_prompt;
621static SCM scm_sym_call_with_values;
622static SCM scm_sym_call_with_current_continuation;
623
624SCM
625scm_vm_builtin_name_to_index (SCM name)
626#define FUNC_NAME "builtin-name->index"
627{
628 SCM_VALIDATE_SYMBOL (1, name);
629
9f309e2c 630#define NAME_TO_INDEX(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
631 if (scm_is_eq (name, scm_sym_##builtin)) \
632 return scm_from_uint (SCM_VM_BUILTIN_##BUILTIN);
633 FOR_EACH_VM_BUILTIN(NAME_TO_INDEX)
634#undef NAME_TO_INDEX
635
636 return SCM_BOOL_F;
637}
638#undef FUNC_NAME
639
640SCM
641scm_vm_builtin_index_to_name (SCM index)
642#define FUNC_NAME "builtin-index->name"
643{
644 unsigned idx;
645
646 SCM_VALIDATE_UINT_COPY (1, index, idx);
647
648 switch (idx)
649 {
9f309e2c 650#define INDEX_TO_NAME(builtin, BUILTIN, req, opt, rest) \
486013d6
AW
651 case SCM_VM_BUILTIN_##BUILTIN: return scm_sym_##builtin;
652 FOR_EACH_VM_BUILTIN(INDEX_TO_NAME)
653#undef INDEX_TO_NAME
654 default: return SCM_BOOL_F;
655 }
656}
657#undef FUNC_NAME
658
659static void
660scm_init_vm_builtins (void)
661{
486013d6
AW
662 scm_c_define_gsubr ("builtin-name->index", 1, 0, 0,
663 scm_vm_builtin_name_to_index);
664 scm_c_define_gsubr ("builtin-index->name", 1, 0, 0,
665 scm_vm_builtin_index_to_name);
666}
667
668SCM
669scm_i_call_with_current_continuation (SCM proc)
670{
671 return scm_call_1 (vm_builtin_call_with_current_continuation, proc);
672}
510ca126 673
a98cef7e
KN
674\f
675/*
676 * VM
677 */
678
aab9d46c 679#define VM_MIN_STACK_SIZE (1024)
486013d6 680#define VM_DEFAULT_STACK_SIZE (256 * 1024)
aab9d46c
SIT
681static size_t vm_stack_size = VM_DEFAULT_STACK_SIZE;
682
683static void
684initialize_default_stack_size (void)
685{
686 int size = scm_getenv_int ("GUILE_STACK_SIZE", vm_stack_size);
687 if (size >= VM_MIN_STACK_SIZE)
688 vm_stack_size = size;
689}
17e90c5e 690
f42cfbf0
AW
691#define VM_NAME vm_regular_engine
692#define VM_USE_HOOKS 0
6d14383e 693#define FUNC_NAME "vm-regular-engine"
83495480 694#include "vm-engine.c"
6d14383e 695#undef FUNC_NAME
f42cfbf0
AW
696#undef VM_USE_HOOKS
697#undef VM_NAME
17e90c5e 698
f42cfbf0
AW
699#define VM_NAME vm_debug_engine
700#define VM_USE_HOOKS 1
6d14383e 701#define FUNC_NAME "vm-debug-engine"
83495480 702#include "vm-engine.c"
6d14383e 703#undef FUNC_NAME
f42cfbf0
AW
704#undef VM_USE_HOOKS
705#undef VM_NAME
17e90c5e 706
dd1c7dec
AW
707typedef SCM (*scm_t_vm_engine) (scm_i_thread *current_thread, struct scm_vm *vp,
708 scm_i_jmp_buf *registers, int resume);
73c3db66 709
f42cfbf0
AW
710static const scm_t_vm_engine vm_engines[SCM_VM_NUM_ENGINES] =
711 { vm_regular_engine, vm_debug_engine };
73c3db66 712
5f18bc84
AW
713static SCM*
714allocate_stack (size_t size)
715#define FUNC_NAME "make_vm"
716{
717 void *ret;
e3eb628d 718
5f18bc84
AW
719 if (size >= ((size_t) -1) / sizeof (SCM))
720 abort ();
721
722 size *= sizeof (SCM);
e3eb628d 723
5f18bc84
AW
724#if HAVE_SYS_MMAN_H
725 ret = mmap (NULL, size, PROT_READ | PROT_WRITE,
726 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
727 if (ret == MAP_FAILED)
728 SCM_SYSERROR;
729#else
730 ret = malloc (size);
731 if (!ret)
732 SCM_SYSERROR;
e3eb628d
LC
733#endif
734
5f18bc84
AW
735 return (SCM *) ret;
736}
737#undef FUNC_NAME
738
739static void
740free_stack (SCM *stack, size_t size)
741{
742 size *= sizeof (SCM);
743
744#if HAVE_SYS_MMAN_H
745 munmap (stack, size);
746#else
747 free (stack);
748#endif
749}
750
3506b152 751static struct scm_vm *
17e90c5e
KN
752make_vm (void)
753#define FUNC_NAME "make_vm"
a98cef7e 754{
17e90c5e 755 int i;
7f991c7d 756 struct scm_vm *vp;
747a1635 757
7f991c7d 758 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 759
aab9d46c 760 vp->stack_size= vm_stack_size;
5f18bc84 761 vp->stack_base = allocate_stack (vp->stack_size);
f1046e6b 762 vp->stack_limit = vp->stack_base + vp->stack_size - VM_STACK_RESERVE_SIZE;
3616e9e9
KN
763 vp->ip = NULL;
764 vp->sp = vp->stack_base - 1;
765 vp->fp = NULL;
ea9f4f4b 766 vp->engine = vm_default_engine;
7656f194 767 vp->trace_level = 0;
17e90c5e 768 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 769 vp->hooks[i] = SCM_BOOL_F;
3506b152
AW
770
771 return vp;
a98cef7e 772}
17e90c5e 773#undef FUNC_NAME
a98cef7e 774
e3eb628d 775/* Mark the VM stack region between its base and its current top. */
5f18bc84
AW
776struct GC_ms_entry *
777scm_i_vm_mark_stack (struct scm_vm *vp, struct GC_ms_entry *mark_stack_ptr,
778 struct GC_ms_entry *mark_stack_limit)
e3eb628d
LC
779{
780 GC_word *word;
e3eb628d 781
5f18bc84 782 for (word = (GC_word *) vp->stack_base; word <= (GC_word *) vp->sp; word++)
e3eb628d
LC
783 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
784 mark_stack_ptr, mark_stack_limit,
785 NULL);
786
787 return mark_stack_ptr;
788}
789
5f18bc84
AW
790/* Free the VM stack, as this thread is exiting. */
791void
792scm_i_vm_free_stack (struct scm_vm *vp)
793{
794 free_stack (vp->stack_base, vp->stack_size);
795 vp->stack_base = vp->stack_limit = NULL;
796 vp->stack_size = 0;
797}
e3eb628d 798
b85cd20f
AW
799static struct scm_vm *
800thread_vm (scm_i_thread *t)
55ee3607 801{
b85cd20f
AW
802 if (SCM_UNLIKELY (!t->vp))
803 t->vp = make_vm ();
804
805 return t->vp;
55ee3607
AW
806}
807
e7f9abab 808struct scm_vm *
a222cbc9 809scm_the_vm (void)
271c3d31 810{
b85cd20f
AW
811 return thread_vm (SCM_I_CURRENT_THREAD);
812}
ea9f4f4b 813
b85cd20f
AW
814SCM
815scm_call_n (SCM proc, SCM *argv, size_t nargs)
816{
817 scm_i_thread *thread;
818 struct scm_vm *vp;
bd63e5b2
AW
819 SCM *base;
820 ptrdiff_t base_frame_size;
dd1c7dec
AW
821 /* Cached variables. */
822 scm_i_jmp_buf registers; /* used for prompts */
bd63e5b2 823 size_t i;
ea9f4f4b 824
b85cd20f
AW
825 thread = SCM_I_CURRENT_THREAD;
826 vp = thread_vm (thread);
827
828 SCM_CHECK_STACK;
bd63e5b2
AW
829
830 /* Check that we have enough space: 3 words for the boot
831 continuation, 3 + nargs for the procedure application, and 3 for
832 setting up a new frame. */
833 base_frame_size = 3 + 3 + nargs + 3;
834 vp->sp += base_frame_size;
835 if (vp->sp >= vp->stack_limit)
836 vm_error_stack_overflow (vp);
837 base = vp->sp + 1 - base_frame_size;
838
839 /* Since it's possible to receive the arguments on the stack itself,
840 shuffle up the arguments first. */
841 for (i = nargs; i > 0; i--)
842 base[6 + i - 1] = argv[i - 1];
843
844 /* Push the boot continuation, which calls PROC and returns its
845 result(s). */
846 base[0] = SCM_PACK (vp->fp); /* dynamic link */
847 base[1] = SCM_PACK (vp->ip); /* ra */
848 base[2] = vm_boot_continuation;
849 vp->fp = &base[2];
850 vp->ip = (scm_t_uint32 *) vm_boot_continuation_code;
851
852 /* The pending call to PROC. */
853 base[3] = SCM_PACK (vp->fp); /* dynamic link */
854 base[4] = SCM_PACK (vp->ip); /* ra */
855 base[5] = proc;
856 vp->fp = &base[5];
857 vp->sp = &SCM_FRAME_LOCAL (vp->fp, nargs);
858
dd1c7dec
AW
859 {
860 int resume = SCM_I_SETJMP (registers);
861
862 if (SCM_UNLIKELY (resume))
863 /* Non-local return. */
864 vm_dispatch_abort_hook (vp);
865
866 return vm_engines[vp->engine](thread, vp, &registers, resume);
867 }
271c3d31 868}
499a4c07 869
a222cbc9 870/* Scheme interface */
a98cef7e 871
17e90c5e
KN
872#define VM_DEFINE_HOOK(n) \
873{ \
3d5ee0cd 874 struct scm_vm *vp; \
e7f9abab 875 vp = scm_the_vm (); \
8b22ed7a 876 if (scm_is_false (vp->hooks[n])) \
238e7a11 877 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 878 return vp->hooks[n]; \
17e90c5e
KN
879}
880
972275ee
AW
881SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 0, 0, 0,
882 (void),
17e90c5e 883 "")
c45d4d77 884#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 885{
c45d4d77 886 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
887}
888#undef FUNC_NAME
889
972275ee
AW
890SCM_DEFINE (scm_vm_push_continuation_hook, "vm-push-continuation-hook", 0, 0, 0,
891 (void),
17e90c5e 892 "")
c45d4d77 893#define FUNC_NAME s_scm_vm_push_continuation_hook
a98cef7e 894{
c45d4d77 895 VM_DEFINE_HOOK (SCM_VM_PUSH_CONTINUATION_HOOK);
a98cef7e
KN
896}
897#undef FUNC_NAME
898
972275ee
AW
899SCM_DEFINE (scm_vm_pop_continuation_hook, "vm-pop-continuation-hook", 0, 0, 0,
900 (void),
17e90c5e 901 "")
c45d4d77 902#define FUNC_NAME s_scm_vm_pop_continuation_hook
a98cef7e 903{
c45d4d77 904 VM_DEFINE_HOOK (SCM_VM_POP_CONTINUATION_HOOK);
a98cef7e
KN
905}
906#undef FUNC_NAME
907
972275ee
AW
908SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 0, 0, 0,
909 (void),
17e90c5e 910 "")
c45d4d77 911#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 912{
c45d4d77 913 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
914}
915#undef FUNC_NAME
f3120251 916
972275ee
AW
917SCM_DEFINE (scm_vm_abort_continuation_hook, "vm-abort-continuation-hook", 0, 0, 0,
918 (void),
f3120251
AW
919 "")
920#define FUNC_NAME s_scm_vm_abort_continuation_hook
921{
922 VM_DEFINE_HOOK (SCM_VM_ABORT_CONTINUATION_HOOK);
923}
924#undef FUNC_NAME
925
972275ee
AW
926SCM_DEFINE (scm_vm_restore_continuation_hook, "vm-restore-continuation-hook", 0, 0, 0,
927 (void),
f3120251
AW
928 "")
929#define FUNC_NAME s_scm_vm_restore_continuation_hook
930{
931 VM_DEFINE_HOOK (SCM_VM_RESTORE_CONTINUATION_HOOK);
932}
933#undef FUNC_NAME
a98cef7e 934
972275ee
AW
935SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 0, 0, 0,
936 (void),
17e90c5e 937 "")
7656f194 938#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 939{
e7f9abab 940 return scm_from_int (scm_the_vm ()->trace_level);
7656f194
AW
941}
942#undef FUNC_NAME
943
972275ee
AW
944SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 1, 0, 0,
945 (SCM level),
7656f194
AW
946 "")
947#define FUNC_NAME s_scm_set_vm_trace_level_x
948{
e7f9abab 949 scm_the_vm ()->trace_level = scm_to_int (level);
7656f194 950 return SCM_UNSPECIFIED;
a98cef7e
KN
951}
952#undef FUNC_NAME
953
954\f
ea9f4f4b
AW
955/*
956 * VM engines
957 */
958
959static int
960symbol_to_vm_engine (SCM engine, const char *FUNC_NAME)
961{
962 if (scm_is_eq (engine, sym_regular))
963 return SCM_VM_REGULAR_ENGINE;
964 else if (scm_is_eq (engine, sym_debug))
965 return SCM_VM_DEBUG_ENGINE;
966 else
967 SCM_MISC_ERROR ("Unknown VM engine: ~a", scm_list_1 (engine));
968}
969
970static SCM
971vm_engine_to_symbol (int engine, const char *FUNC_NAME)
972{
973 switch (engine)
974 {
975 case SCM_VM_REGULAR_ENGINE:
976 return sym_regular;
977 case SCM_VM_DEBUG_ENGINE:
978 return sym_debug;
979 default:
980 /* ? */
981 SCM_MISC_ERROR ("Unknown VM engine: ~a",
982 scm_list_1 (scm_from_int (engine)));
983 }
984}
985
972275ee
AW
986SCM_DEFINE (scm_vm_engine, "vm-engine", 0, 0, 0,
987 (void),
ea9f4f4b
AW
988 "")
989#define FUNC_NAME s_scm_vm_engine
990{
e7f9abab 991 return vm_engine_to_symbol (scm_the_vm ()->engine, FUNC_NAME);
ea9f4f4b
AW
992}
993#undef FUNC_NAME
994
995void
972275ee 996scm_c_set_vm_engine_x (int engine)
ea9f4f4b
AW
997#define FUNC_NAME "set-vm-engine!"
998{
ea9f4f4b
AW
999 if (engine < 0 || engine >= SCM_VM_NUM_ENGINES)
1000 SCM_MISC_ERROR ("Unknown VM engine: ~a",
1001 scm_list_1 (scm_from_int (engine)));
1002
e7f9abab 1003 scm_the_vm ()->engine = engine;
ea9f4f4b
AW
1004}
1005#undef FUNC_NAME
1006
972275ee
AW
1007SCM_DEFINE (scm_set_vm_engine_x, "set-vm-engine!", 1, 0, 0,
1008 (SCM engine),
ea9f4f4b
AW
1009 "")
1010#define FUNC_NAME s_scm_set_vm_engine_x
1011{
972275ee 1012 scm_c_set_vm_engine_x (symbol_to_vm_engine (engine, FUNC_NAME));
ea9f4f4b
AW
1013 return SCM_UNSPECIFIED;
1014}
1015#undef FUNC_NAME
1016
1017void
1018scm_c_set_default_vm_engine_x (int engine)
1019#define FUNC_NAME "set-default-vm-engine!"
1020{
1021 if (engine < 0 || engine >= SCM_VM_NUM_ENGINES)
1022 SCM_MISC_ERROR ("Unknown VM engine: ~a",
1023 scm_list_1 (scm_from_int (engine)));
1024
1025 vm_default_engine = engine;
1026}
1027#undef FUNC_NAME
1028
1029SCM_DEFINE (scm_set_default_vm_engine_x, "set-default-vm-engine!", 1, 0, 0,
1030 (SCM engine),
1031 "")
1032#define FUNC_NAME s_scm_set_default_vm_engine_x
1033{
1034 scm_c_set_default_vm_engine_x (symbol_to_vm_engine (engine, FUNC_NAME));
1035 return SCM_UNSPECIFIED;
1036}
1037#undef FUNC_NAME
1038
972275ee
AW
1039/* FIXME: This function makes no sense, but we keep it to make sure we
1040 have a way of switching to the debug or regular VM. */
1041SCM_DEFINE (scm_call_with_vm, "call-with-vm", 1, 0, 1,
1042 (SCM proc, SCM args),
ea9f4f4b 1043 "Apply @var{proc} to @var{args} in a dynamic extent in which\n"
972275ee 1044 "@var{vm} is the current VM.")
ea9f4f4b
AW
1045#define FUNC_NAME s_scm_call_with_vm
1046{
972275ee 1047 return scm_apply_0 (proc, args);
ea9f4f4b
AW
1048}
1049#undef FUNC_NAME
1050
1051\f
a98cef7e 1052/*
17e90c5e 1053 * Initialize
a98cef7e
KN
1054 */
1055
55ee3607
AW
1056SCM
1057scm_load_compiled_with_vm (SCM file)
07e56b27 1058{
55ee3607 1059 return scm_call_0 (scm_load_thunk_from_file (file));
07e56b27
AW
1060}
1061
67b699cc 1062
9f309e2c
AW
1063void
1064scm_init_vm_builtin_properties (void)
1065{
1066 /* FIXME: Seems hacky to do this here, but oh well :/ */
1067 scm_sym_apply = scm_from_utf8_symbol ("apply");
1068 scm_sym_values = scm_from_utf8_symbol ("values");
1069 scm_sym_abort_to_prompt = scm_from_utf8_symbol ("abort-to-prompt");
1070 scm_sym_call_with_values = scm_from_utf8_symbol ("call-with-values");
1071 scm_sym_call_with_current_continuation =
1072 scm_from_utf8_symbol ("call-with-current-continuation");
1073
1074#define INIT_BUILTIN(builtin, BUILTIN, req, opt, rest) \
1075 scm_set_procedure_property_x (vm_builtin_##builtin, scm_sym_name, \
1076 scm_sym_##builtin); \
1077 scm_set_procedure_minimum_arity_x (vm_builtin_##builtin, \
1078 SCM_I_MAKINUM (req), \
1079 SCM_I_MAKINUM (opt), \
1080 scm_from_bool (rest));
1081 FOR_EACH_VM_BUILTIN (INIT_BUILTIN);
1082#undef INIT_BUILTIN
1083}
1084
17e90c5e 1085void
07e56b27 1086scm_bootstrap_vm (void)
17e90c5e 1087{
44602b08
AW
1088 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1089 "scm_init_vm",
60ae5ca2 1090 (scm_t_extension_init_func)scm_init_vm, NULL);
486013d6
AW
1091 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1092 "scm_init_vm_builtins",
1093 (scm_t_extension_init_func)scm_init_vm_builtins,
1094 NULL);
60ae5ca2 1095
aab9d46c
SIT
1096 initialize_default_stack_size ();
1097
4a655e50
AW
1098 sym_vm_run = scm_from_latin1_symbol ("vm-run");
1099 sym_vm_error = scm_from_latin1_symbol ("vm-error");
1100 sym_keyword_argument_error = scm_from_latin1_symbol ("keyword-argument-error");
1101 sym_regular = scm_from_latin1_symbol ("regular");
1102 sym_debug = scm_from_latin1_symbol ("debug");
0404c97d 1103
ef6b7f71
AW
1104 vm_boot_continuation = scm_i_make_program (vm_boot_continuation_code);
1105 SCM_SET_CELL_WORD_0 (vm_boot_continuation,
1106 (SCM_CELL_WORD_0 (vm_boot_continuation)
73c3db66 1107 | SCM_F_PROGRAM_IS_BOOT));
9f309e2c
AW
1108
1109#define DEFINE_BUILTIN(builtin, BUILTIN, req, opt, rest) \
80797145 1110 vm_builtin_##builtin = scm_i_make_program (vm_builtin_##builtin##_code);
9f309e2c
AW
1111 FOR_EACH_VM_BUILTIN (DEFINE_BUILTIN);
1112#undef DEFINE_BUILTIN
07e56b27
AW
1113}
1114
1115void
1116scm_init_vm (void)
1117{
17e90c5e 1118#ifndef SCM_MAGIC_SNARFER
aeeff258 1119#include "libguile/vm.x"
17e90c5e 1120#endif
a98cef7e 1121}
17e90c5e
KN
1122
1123/*
1124 Local Variables:
1125 c-file-style: "gnu"
1126 End:
1127*/