connect a few more wires to promptenstein
[bpt/guile.git] / libguile / vm-i-system.c
1 /* Copyright (C) 2001,2008,2009,2010 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
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.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
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
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19
20 /* This file is included in vm_engine.c */
21
22 \f
23 /*
24 * Basic operations
25 */
26
27 VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
28 {
29 NEXT;
30 }
31
32 VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
33 {
34 HALT_HOOK ();
35 nvalues = SCM_I_INUM (*sp--);
36 NULLSTACK (1);
37 if (nvalues == 1)
38 POP (finish_args);
39 else
40 {
41 POP_LIST (nvalues);
42 POP (finish_args);
43 SYNC_REGISTER ();
44 finish_args = scm_values (finish_args);
45 }
46
47 {
48 #ifdef VM_ENABLE_STACK_NULLING
49 SCM *old_sp = sp;
50 #endif
51
52 /* Restore registers */
53 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
54 /* Setting the ip here doesn't actually affect control flow, as the calling
55 code will restore its own registers, but it does help when walking the
56 stack */
57 ip = SCM_FRAME_RETURN_ADDRESS (fp);
58 fp = SCM_FRAME_DYNAMIC_LINK (fp);
59 NULLSTACK (old_sp - sp);
60 }
61
62 goto vm_done;
63 }
64
65 VM_DEFINE_INSTRUCTION (2, break, "break", 0, 0, 0)
66 {
67 BREAK_HOOK ();
68 NEXT;
69 }
70
71 VM_DEFINE_INSTRUCTION (3, drop, "drop", 0, 1, 0)
72 {
73 DROP ();
74 NEXT;
75 }
76
77 VM_DEFINE_INSTRUCTION (4, dup, "dup", 0, 0, 1)
78 {
79 SCM x = *sp;
80 PUSH (x);
81 NEXT;
82 }
83
84 \f
85 /*
86 * Object creation
87 */
88
89 VM_DEFINE_INSTRUCTION (5, void, "void", 0, 0, 1)
90 {
91 PUSH (SCM_UNSPECIFIED);
92 NEXT;
93 }
94
95 VM_DEFINE_INSTRUCTION (6, make_true, "make-true", 0, 0, 1)
96 {
97 PUSH (SCM_BOOL_T);
98 NEXT;
99 }
100
101 VM_DEFINE_INSTRUCTION (7, make_false, "make-false", 0, 0, 1)
102 {
103 PUSH (SCM_BOOL_F);
104 NEXT;
105 }
106
107 VM_DEFINE_INSTRUCTION (8, make_nil, "make-nil", 0, 0, 1)
108 {
109 PUSH (SCM_ELISP_NIL);
110 NEXT;
111 }
112
113 VM_DEFINE_INSTRUCTION (9, make_eol, "make-eol", 0, 0, 1)
114 {
115 PUSH (SCM_EOL);
116 NEXT;
117 }
118
119 VM_DEFINE_INSTRUCTION (10, make_int8, "make-int8", 1, 0, 1)
120 {
121 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
122 NEXT;
123 }
124
125 VM_DEFINE_INSTRUCTION (11, make_int8_0, "make-int8:0", 0, 0, 1)
126 {
127 PUSH (SCM_INUM0);
128 NEXT;
129 }
130
131 VM_DEFINE_INSTRUCTION (12, make_int8_1, "make-int8:1", 0, 0, 1)
132 {
133 PUSH (SCM_I_MAKINUM (1));
134 NEXT;
135 }
136
137 VM_DEFINE_INSTRUCTION (13, make_int16, "make-int16", 2, 0, 1)
138 {
139 int h = FETCH ();
140 int l = FETCH ();
141 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
142 NEXT;
143 }
144
145 VM_DEFINE_INSTRUCTION (14, make_int64, "make-int64", 8, 0, 1)
146 {
147 scm_t_uint64 v = 0;
148 v += FETCH ();
149 v <<= 8; v += FETCH ();
150 v <<= 8; v += FETCH ();
151 v <<= 8; v += FETCH ();
152 v <<= 8; v += FETCH ();
153 v <<= 8; v += FETCH ();
154 v <<= 8; v += FETCH ();
155 v <<= 8; v += FETCH ();
156 PUSH (scm_from_int64 ((scm_t_int64) v));
157 NEXT;
158 }
159
160 VM_DEFINE_INSTRUCTION (15, make_uint64, "make-uint64", 8, 0, 1)
161 {
162 scm_t_uint64 v = 0;
163 v += FETCH ();
164 v <<= 8; v += FETCH ();
165 v <<= 8; v += FETCH ();
166 v <<= 8; v += FETCH ();
167 v <<= 8; v += FETCH ();
168 v <<= 8; v += FETCH ();
169 v <<= 8; v += FETCH ();
170 v <<= 8; v += FETCH ();
171 PUSH (scm_from_uint64 (v));
172 NEXT;
173 }
174
175 VM_DEFINE_INSTRUCTION (16, make_char8, "make-char8", 1, 0, 1)
176 {
177 scm_t_uint8 v = 0;
178 v = FETCH ();
179
180 PUSH (SCM_MAKE_CHAR (v));
181 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
182 contents of SCM_MAKE_CHAR may be evaluated more than once,
183 resulting in a double fetch. */
184 NEXT;
185 }
186
187 VM_DEFINE_INSTRUCTION (17, make_char32, "make-char32", 4, 0, 1)
188 {
189 scm_t_wchar v = 0;
190 v += FETCH ();
191 v <<= 8; v += FETCH ();
192 v <<= 8; v += FETCH ();
193 v <<= 8; v += FETCH ();
194 PUSH (SCM_MAKE_CHAR (v));
195 NEXT;
196 }
197
198
199
200 VM_DEFINE_INSTRUCTION (18, list, "list", 2, -1, 1)
201 {
202 unsigned h = FETCH ();
203 unsigned l = FETCH ();
204 unsigned len = ((h << 8) + l);
205 POP_LIST (len);
206 NEXT;
207 }
208
209 VM_DEFINE_INSTRUCTION (19, vector, "vector", 2, -1, 1)
210 {
211 unsigned h = FETCH ();
212 unsigned l = FETCH ();
213 unsigned len = ((h << 8) + l);
214 SCM vect;
215
216 SYNC_REGISTER ();
217 sp++; sp -= len;
218 CHECK_UNDERFLOW ();
219 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
220 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
221 NULLSTACK (len);
222 *sp = vect;
223
224 NEXT;
225 }
226
227 \f
228 /*
229 * Variable access
230 */
231
232 #define OBJECT_REF(i) objects[i]
233 #define OBJECT_SET(i,o) objects[i] = o
234
235 #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
236 #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
237
238 /* For the variable operations, we _must_ obviously avoid function calls to
239 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
240 nothing more than the corresponding macros. */
241 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
242 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
243 #define VARIABLE_BOUNDP(v) (VARIABLE_REF (v) != SCM_UNDEFINED)
244
245 #define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
246
247 /* ref */
248
249 VM_DEFINE_INSTRUCTION (20, object_ref, "object-ref", 1, 0, 1)
250 {
251 register unsigned objnum = FETCH ();
252 CHECK_OBJECT (objnum);
253 PUSH (OBJECT_REF (objnum));
254 NEXT;
255 }
256
257 /* FIXME: necessary? elt 255 of the vector could be a vector... */
258 VM_DEFINE_INSTRUCTION (21, long_object_ref, "long-object-ref", 2, 0, 1)
259 {
260 unsigned int objnum = FETCH ();
261 objnum <<= 8;
262 objnum += FETCH ();
263 CHECK_OBJECT (objnum);
264 PUSH (OBJECT_REF (objnum));
265 NEXT;
266 }
267
268 VM_DEFINE_INSTRUCTION (22, local_ref, "local-ref", 1, 0, 1)
269 {
270 PUSH (LOCAL_REF (FETCH ()));
271 ASSERT_BOUND (*sp);
272 NEXT;
273 }
274
275 VM_DEFINE_INSTRUCTION (23, long_local_ref, "long-local-ref", 2, 0, 1)
276 {
277 unsigned int i = FETCH ();
278 i <<= 8;
279 i += FETCH ();
280 PUSH (LOCAL_REF (i));
281 ASSERT_BOUND (*sp);
282 NEXT;
283 }
284
285 VM_DEFINE_INSTRUCTION (24, local_bound, "local-bound?", 1, 0, 1)
286 {
287 if (LOCAL_REF (FETCH ()) == SCM_UNDEFINED)
288 PUSH (SCM_BOOL_F);
289 else
290 PUSH (SCM_BOOL_T);
291 NEXT;
292 }
293
294 VM_DEFINE_INSTRUCTION (25, long_local_bound, "long-local-bound?", 2, 0, 1)
295 {
296 unsigned int i = FETCH ();
297 i <<= 8;
298 i += FETCH ();
299 if (LOCAL_REF (i) == SCM_UNDEFINED)
300 PUSH (SCM_BOOL_F);
301 else
302 PUSH (SCM_BOOL_T);
303 NEXT;
304 }
305
306 VM_DEFINE_INSTRUCTION (26, variable_ref, "variable-ref", 0, 1, 1)
307 {
308 SCM x = *sp;
309
310 if (!VARIABLE_BOUNDP (x))
311 {
312 finish_args = scm_list_1 (x);
313 /* Was: finish_args = SCM_LIST1 (SCM_CAR (x)); */
314 goto vm_error_unbound;
315 }
316 else
317 {
318 SCM o = VARIABLE_REF (x);
319 *sp = o;
320 }
321
322 NEXT;
323 }
324
325 VM_DEFINE_INSTRUCTION (27, variable_bound, "variable-bound?", 0, 1, 1)
326 {
327 if (VARIABLE_BOUNDP (*sp))
328 *sp = SCM_BOOL_T;
329 else
330 *sp = SCM_BOOL_F;
331 NEXT;
332 }
333
334 VM_DEFINE_INSTRUCTION (28, toplevel_ref, "toplevel-ref", 1, 0, 1)
335 {
336 unsigned objnum = FETCH ();
337 SCM what;
338 CHECK_OBJECT (objnum);
339 what = OBJECT_REF (objnum);
340
341 if (!SCM_VARIABLEP (what))
342 {
343 SYNC_REGISTER ();
344 what = resolve_variable (what, scm_program_module (program));
345 if (!VARIABLE_BOUNDP (what))
346 {
347 finish_args = scm_list_1 (what);
348 goto vm_error_unbound;
349 }
350 OBJECT_SET (objnum, what);
351 }
352
353 PUSH (VARIABLE_REF (what));
354 NEXT;
355 }
356
357 VM_DEFINE_INSTRUCTION (29, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
358 {
359 SCM what;
360 unsigned int objnum = FETCH ();
361 objnum <<= 8;
362 objnum += FETCH ();
363 CHECK_OBJECT (objnum);
364 what = OBJECT_REF (objnum);
365
366 if (!SCM_VARIABLEP (what))
367 {
368 SYNC_REGISTER ();
369 what = resolve_variable (what, scm_program_module (program));
370 if (!VARIABLE_BOUNDP (what))
371 {
372 finish_args = scm_list_1 (what);
373 goto vm_error_unbound;
374 }
375 OBJECT_SET (objnum, what);
376 }
377
378 PUSH (VARIABLE_REF (what));
379 NEXT;
380 }
381
382 /* set */
383
384 VM_DEFINE_INSTRUCTION (30, local_set, "local-set", 1, 1, 0)
385 {
386 LOCAL_SET (FETCH (), *sp);
387 DROP ();
388 NEXT;
389 }
390
391 VM_DEFINE_INSTRUCTION (31, long_local_set, "long-local-set", 2, 1, 0)
392 {
393 unsigned int i = FETCH ();
394 i <<= 8;
395 i += FETCH ();
396 LOCAL_SET (i, *sp);
397 DROP ();
398 NEXT;
399 }
400
401 VM_DEFINE_INSTRUCTION (32, variable_set, "variable-set", 0, 2, 0)
402 {
403 VARIABLE_SET (sp[0], sp[-1]);
404 DROPN (2);
405 NEXT;
406 }
407
408 VM_DEFINE_INSTRUCTION (33, toplevel_set, "toplevel-set", 1, 1, 0)
409 {
410 unsigned objnum = FETCH ();
411 SCM what;
412 CHECK_OBJECT (objnum);
413 what = OBJECT_REF (objnum);
414
415 if (!SCM_VARIABLEP (what))
416 {
417 SYNC_BEFORE_GC ();
418 what = resolve_variable (what, scm_program_module (program));
419 OBJECT_SET (objnum, what);
420 }
421
422 VARIABLE_SET (what, *sp);
423 DROP ();
424 NEXT;
425 }
426
427 VM_DEFINE_INSTRUCTION (34, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
428 {
429 SCM what;
430 unsigned int objnum = FETCH ();
431 objnum <<= 8;
432 objnum += FETCH ();
433 CHECK_OBJECT (objnum);
434 what = OBJECT_REF (objnum);
435
436 if (!SCM_VARIABLEP (what))
437 {
438 SYNC_BEFORE_GC ();
439 what = resolve_variable (what, scm_program_module (program));
440 OBJECT_SET (objnum, what);
441 }
442
443 VARIABLE_SET (what, *sp);
444 DROP ();
445 NEXT;
446 }
447
448 \f
449 /*
450 * branch and jump
451 */
452
453 /* offset must be at least 24 bits wide, and signed */
454 #define FETCH_OFFSET(offset) \
455 { \
456 offset = FETCH () << 16; \
457 offset += FETCH () << 8; \
458 offset += FETCH (); \
459 offset -= (offset & (1<<23)) << 1; \
460 }
461
462 #define BR(p) \
463 { \
464 scm_t_int32 offset; \
465 FETCH_OFFSET (offset); \
466 if (p) \
467 ip += offset; \
468 if (offset < 0) \
469 VM_HANDLE_INTERRUPTS; \
470 NULLSTACK (1); \
471 DROP (); \
472 NEXT; \
473 }
474
475 VM_DEFINE_INSTRUCTION (35, br, "br", 3, 0, 0)
476 {
477 scm_t_int32 offset;
478 FETCH_OFFSET (offset);
479 ip += offset;
480 if (offset < 0)
481 VM_HANDLE_INTERRUPTS;
482 NEXT;
483 }
484
485 VM_DEFINE_INSTRUCTION (36, br_if, "br-if", 3, 0, 0)
486 {
487 BR (scm_is_true_and_not_nil (*sp));
488 }
489
490 VM_DEFINE_INSTRUCTION (37, br_if_not, "br-if-not", 3, 0, 0)
491 {
492 BR (scm_is_false_or_nil (*sp));
493 }
494
495 VM_DEFINE_INSTRUCTION (38, br_if_eq, "br-if-eq", 3, 0, 0)
496 {
497 sp--; /* underflow? */
498 BR (scm_is_eq (sp[0], sp[1]));
499 }
500
501 VM_DEFINE_INSTRUCTION (39, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
502 {
503 sp--; /* underflow? */
504 BR (!scm_is_eq (sp[0], sp[1]));
505 }
506
507 VM_DEFINE_INSTRUCTION (40, br_if_null, "br-if-null", 3, 0, 0)
508 {
509 BR (scm_is_null_or_nil (*sp));
510 }
511
512 VM_DEFINE_INSTRUCTION (41, br_if_not_null, "br-if-not-null", 3, 0, 0)
513 {
514 BR (!scm_is_null_or_nil (*sp));
515 }
516
517 \f
518 /*
519 * Subprogram call
520 */
521
522 VM_DEFINE_INSTRUCTION (42, br_if_nargs_ne, "br-if-nargs-ne", 5, 0, 0)
523 {
524 scm_t_ptrdiff n;
525 scm_t_int32 offset;
526 n = FETCH () << 8;
527 n += FETCH ();
528 FETCH_OFFSET (offset);
529 if (sp - (fp - 1) != n)
530 ip += offset;
531 NEXT;
532 }
533
534 VM_DEFINE_INSTRUCTION (43, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
535 {
536 scm_t_ptrdiff n;
537 scm_t_int32 offset;
538 n = FETCH () << 8;
539 n += FETCH ();
540 FETCH_OFFSET (offset);
541 if (sp - (fp - 1) < n)
542 ip += offset;
543 NEXT;
544 }
545
546 VM_DEFINE_INSTRUCTION (44, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
547 {
548 scm_t_ptrdiff n;
549 scm_t_int32 offset;
550
551 n = FETCH () << 8;
552 n += FETCH ();
553 FETCH_OFFSET (offset);
554 if (sp - (fp - 1) > n)
555 ip += offset;
556 NEXT;
557 }
558
559 VM_DEFINE_INSTRUCTION (45, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
560 {
561 scm_t_ptrdiff n;
562 n = FETCH () << 8;
563 n += FETCH ();
564 if (sp - (fp - 1) != n)
565 goto vm_error_wrong_num_args;
566 NEXT;
567 }
568
569 VM_DEFINE_INSTRUCTION (46, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
570 {
571 scm_t_ptrdiff n;
572 n = FETCH () << 8;
573 n += FETCH ();
574 if (sp - (fp - 1) < n)
575 goto vm_error_wrong_num_args;
576 NEXT;
577 }
578
579 VM_DEFINE_INSTRUCTION (47, bind_optionals, "bind-optionals", 2, -1, -1)
580 {
581 scm_t_ptrdiff n;
582 n = FETCH () << 8;
583 n += FETCH ();
584 while (sp - (fp - 1) < n)
585 PUSH (SCM_UNDEFINED);
586 NEXT;
587 }
588
589 VM_DEFINE_INSTRUCTION (48, bind_optionals_shuffle, "bind-optionals/shuffle", 6, -1, -1)
590 {
591 SCM *walk;
592 scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
593 nreq = FETCH () << 8;
594 nreq += FETCH ();
595 nreq_and_opt = FETCH () << 8;
596 nreq_and_opt += FETCH ();
597 ntotal = FETCH () << 8;
598 ntotal += FETCH ();
599
600 /* look in optionals for first keyword or last positional */
601 /* starting after the last required positional arg */
602 walk = fp + nreq;
603 while (/* while we have args */
604 walk <= sp
605 /* and we still have positionals to fill */
606 && walk - fp < nreq_and_opt
607 /* and we haven't reached a keyword yet */
608 && !scm_is_keyword (*walk))
609 /* bind this optional arg (by leaving it in place) */
610 walk++;
611 /* now shuffle up, from walk to ntotal */
612 {
613 scm_t_ptrdiff nshuf = sp - walk + 1, i;
614 sp = (fp - 1) + ntotal + nshuf;
615 CHECK_OVERFLOW ();
616 for (i = 0; i < nshuf; i++)
617 sp[-i] = walk[nshuf-i-1];
618 }
619 /* and fill optionals & keyword args with SCM_UNDEFINED */
620 while (walk <= (fp - 1) + ntotal)
621 *walk++ = SCM_UNDEFINED;
622
623 NEXT;
624 }
625
626 /* Flags that determine whether other keywords are allowed, and whether a
627 rest argument is expected. These values must match those used by the
628 glil->assembly compiler. */
629 #define F_ALLOW_OTHER_KEYS 1
630 #define F_REST 2
631
632 VM_DEFINE_INSTRUCTION (49, bind_kwargs, "bind-kwargs", 5, 0, 0)
633 {
634 scm_t_uint16 idx;
635 scm_t_ptrdiff nkw;
636 int kw_and_rest_flags;
637 SCM kw;
638 idx = FETCH () << 8;
639 idx += FETCH ();
640 /* XXX: We don't actually use NKW. */
641 nkw = FETCH () << 8;
642 nkw += FETCH ();
643 kw_and_rest_flags = FETCH ();
644
645 if (!(kw_and_rest_flags & F_REST)
646 && ((sp - (fp - 1) - nkw) % 2))
647 goto vm_error_kwargs_length_not_even;
648
649 CHECK_OBJECT (idx);
650 kw = OBJECT_REF (idx);
651
652 /* Switch NKW to be a negative index below SP. */
653 for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
654 {
655 SCM walk;
656
657 if (scm_is_keyword (sp[nkw]))
658 {
659 for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
660 {
661 if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
662 {
663 SCM si = SCM_CDAR (walk);
664 LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
665 sp[nkw + 1]);
666 break;
667 }
668 }
669 if (!(kw_and_rest_flags & F_ALLOW_OTHER_KEYS) && !scm_is_pair (walk))
670 goto vm_error_kwargs_unrecognized_keyword;
671
672 nkw++;
673 }
674 else if (!(kw_and_rest_flags & F_REST))
675 goto vm_error_kwargs_invalid_keyword;
676 }
677
678 NEXT;
679 }
680
681 #undef F_ALLOW_OTHER_KEYS
682 #undef F_REST
683
684
685 VM_DEFINE_INSTRUCTION (50, push_rest, "push-rest", 2, -1, -1)
686 {
687 scm_t_ptrdiff n;
688 SCM rest = SCM_EOL;
689 n = FETCH () << 8;
690 n += FETCH ();
691 while (sp - (fp - 1) > n)
692 /* No need to check for underflow. */
693 CONS (rest, *sp--, rest);
694 PUSH (rest);
695 NEXT;
696 }
697
698 VM_DEFINE_INSTRUCTION (51, bind_rest, "bind-rest", 4, -1, -1)
699 {
700 scm_t_ptrdiff n;
701 scm_t_uint32 i;
702 SCM rest = SCM_EOL;
703 n = FETCH () << 8;
704 n += FETCH ();
705 i = FETCH () << 8;
706 i += FETCH ();
707 while (sp - (fp - 1) > n)
708 /* No need to check for underflow. */
709 CONS (rest, *sp--, rest);
710 LOCAL_SET (i, rest);
711 NEXT;
712 }
713
714 VM_DEFINE_INSTRUCTION (52, reserve_locals, "reserve-locals", 2, -1, -1)
715 {
716 SCM *old_sp;
717 scm_t_int32 n;
718 n = FETCH () << 8;
719 n += FETCH ();
720 old_sp = sp;
721 sp = (fp - 1) + n;
722
723 if (old_sp < sp)
724 {
725 CHECK_OVERFLOW ();
726 while (old_sp < sp)
727 *++old_sp = SCM_UNDEFINED;
728 }
729 else
730 NULLSTACK (old_sp - sp);
731
732 NEXT;
733 }
734
735 VM_DEFINE_INSTRUCTION (53, new_frame, "new-frame", 0, 0, 3)
736 {
737 /* NB: if you change this, see frames.c:vm-frame-num-locals */
738 /* and frames.h, vm-engine.c, etc of course */
739 PUSH ((SCM)fp); /* dynamic link */
740 PUSH (0); /* mvra */
741 PUSH (0); /* ra */
742 NEXT;
743 }
744
745 VM_DEFINE_INSTRUCTION (54, call, "call", 1, -1, 1)
746 {
747 nargs = FETCH ();
748
749 vm_call:
750 program = sp[-nargs];
751
752 VM_HANDLE_INTERRUPTS;
753
754 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
755 {
756 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
757 {
758 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
759 goto vm_call;
760 }
761 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
762 && SCM_SMOB_APPLICABLE_P (program))
763 {
764 SYNC_REGISTER ();
765 sp[-nargs] = scm_i_smob_apply_trampoline (program);
766 goto vm_call;
767 }
768 else
769 goto vm_error_wrong_type_apply;
770 }
771
772 CACHE_PROGRAM ();
773 fp = sp - nargs + 1;
774 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
775 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
776 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
777 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
778 ip = SCM_C_OBJCODE_BASE (bp);
779 ENTER_HOOK ();
780 APPLY_HOOK ();
781 NEXT;
782 }
783
784 VM_DEFINE_INSTRUCTION (55, tail_call, "tail-call", 1, -1, 1)
785 {
786 nargs = FETCH ();
787
788 vm_tail_call:
789 program = sp[-nargs];
790
791 VM_HANDLE_INTERRUPTS;
792
793 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
794 {
795 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
796 {
797 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
798 goto vm_tail_call;
799 }
800 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
801 && SCM_SMOB_APPLICABLE_P (program))
802 {
803 SYNC_REGISTER ();
804 sp[-nargs] = scm_i_smob_apply_trampoline (program);
805 goto vm_tail_call;
806 }
807 else
808 goto vm_error_wrong_type_apply;
809 }
810 else
811 {
812 int i;
813 #ifdef VM_ENABLE_STACK_NULLING
814 SCM *old_sp = sp;
815 CHECK_STACK_LEAK ();
816 #endif
817
818 EXIT_HOOK ();
819
820 /* switch programs */
821 CACHE_PROGRAM ();
822 /* shuffle down the program and the arguments */
823 for (i = -1, sp = sp - nargs + 1; i < nargs; i++)
824 SCM_FRAME_STACK_ADDRESS (fp)[i] = sp[i];
825
826 sp = fp + i - 1;
827
828 NULLSTACK (old_sp - sp);
829
830 ip = SCM_C_OBJCODE_BASE (bp);
831
832 ENTER_HOOK ();
833 APPLY_HOOK ();
834 NEXT;
835 }
836 }
837
838 VM_DEFINE_INSTRUCTION (56, subr_call, "subr-call", 1, -1, -1)
839 {
840 SCM foreign, ret;
841 SCM (*subr)();
842 nargs = FETCH ();
843 POP (foreign);
844
845 subr = SCM_FOREIGN_POINTER (foreign, void);
846
847 VM_HANDLE_INTERRUPTS;
848 SYNC_REGISTER ();
849
850 switch (nargs)
851 {
852 case 0:
853 ret = subr ();
854 break;
855 case 1:
856 ret = subr (sp[0]);
857 break;
858 case 2:
859 ret = subr (sp[-1], sp[0]);
860 break;
861 case 3:
862 ret = subr (sp[-2], sp[-1], sp[0]);
863 break;
864 case 4:
865 ret = subr (sp[-3], sp[-2], sp[-1], sp[0]);
866 break;
867 case 5:
868 ret = subr (sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
869 break;
870 case 6:
871 ret = subr (sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
872 break;
873 case 7:
874 ret = subr (sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
875 break;
876 case 8:
877 ret = subr (sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
878 break;
879 case 9:
880 ret = subr (sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
881 break;
882 case 10:
883 ret = subr (sp[-9], sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
884 break;
885 default:
886 abort ();
887 }
888
889 NULLSTACK_FOR_NONLOCAL_EXIT ();
890
891 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
892 {
893 /* multiple values returned to continuation */
894 ret = scm_struct_ref (ret, SCM_INUM0);
895 nvalues = scm_ilength (ret);
896 PUSH_LIST (ret, scm_is_null);
897 goto vm_return_values;
898 }
899 else
900 {
901 PUSH (ret);
902 goto vm_return;
903 }
904 }
905
906 VM_DEFINE_INSTRUCTION (57, smob_call, "smob-call", 1, -1, -1)
907 {
908 SCM smob, ret;
909 SCM (*subr)();
910 nargs = FETCH ();
911 POP (smob);
912
913 subr = SCM_SMOB_DESCRIPTOR (smob).apply;
914
915 VM_HANDLE_INTERRUPTS;
916 SYNC_REGISTER ();
917
918 switch (nargs)
919 {
920 case 0:
921 ret = subr (smob);
922 break;
923 case 1:
924 ret = subr (smob, sp[0]);
925 break;
926 case 2:
927 ret = subr (smob, sp[-1], sp[0]);
928 break;
929 case 3:
930 ret = subr (smob, sp[-2], sp[-1], sp[0]);
931 break;
932 default:
933 abort ();
934 }
935
936 NULLSTACK_FOR_NONLOCAL_EXIT ();
937
938 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
939 {
940 /* multiple values returned to continuation */
941 ret = scm_struct_ref (ret, SCM_INUM0);
942 nvalues = scm_ilength (ret);
943 PUSH_LIST (ret, scm_is_null);
944 goto vm_return_values;
945 }
946 else
947 {
948 PUSH (ret);
949 goto vm_return;
950 }
951 }
952
953 VM_DEFINE_INSTRUCTION (58, foreign_call, "foreign-call", 1, -1, -1)
954 {
955 SCM foreign, ret;
956 nargs = FETCH ();
957 POP (foreign);
958
959 VM_HANDLE_INTERRUPTS;
960 SYNC_REGISTER ();
961
962 ret = scm_i_foreign_call (foreign, sp - nargs + 1);
963
964 NULLSTACK_FOR_NONLOCAL_EXIT ();
965
966 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
967 {
968 /* multiple values returned to continuation */
969 ret = scm_struct_ref (ret, SCM_INUM0);
970 nvalues = scm_ilength (ret);
971 PUSH_LIST (ret, scm_is_null);
972 goto vm_return_values;
973 }
974 else
975 {
976 PUSH (ret);
977 goto vm_return;
978 }
979 }
980
981 VM_DEFINE_INSTRUCTION (59, tail_call_nargs, "tail-call/nargs", 0, 0, 1)
982 {
983 SCM x;
984 POP (x);
985 nargs = scm_to_int (x);
986 /* FIXME: should truncate values? */
987 goto vm_tail_call;
988 }
989
990 VM_DEFINE_INSTRUCTION (60, call_nargs, "call/nargs", 0, 0, 1)
991 {
992 SCM x;
993 POP (x);
994 nargs = scm_to_int (x);
995 /* FIXME: should truncate values? */
996 goto vm_call;
997 }
998
999 VM_DEFINE_INSTRUCTION (61, mv_call, "mv-call", 4, -1, 1)
1000 {
1001 scm_t_int32 offset;
1002 scm_t_uint8 *mvra;
1003
1004 nargs = FETCH ();
1005 FETCH_OFFSET (offset);
1006 mvra = ip + offset;
1007
1008 vm_mv_call:
1009 program = sp[-nargs];
1010
1011 VM_HANDLE_INTERRUPTS;
1012
1013 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
1014 {
1015 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
1016 {
1017 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
1018 goto vm_mv_call;
1019 }
1020 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
1021 && SCM_SMOB_APPLICABLE_P (program))
1022 {
1023 SYNC_REGISTER ();
1024 sp[-nargs] = scm_i_smob_apply_trampoline (program);
1025 goto vm_mv_call;
1026 }
1027 else
1028 goto vm_error_wrong_type_apply;
1029 }
1030
1031 CACHE_PROGRAM ();
1032 fp = sp - nargs + 1;
1033 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
1034 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
1035 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
1036 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
1037 ip = SCM_C_OBJCODE_BASE (bp);
1038 ENTER_HOOK ();
1039 APPLY_HOOK ();
1040 NEXT;
1041 }
1042
1043 VM_DEFINE_INSTRUCTION (62, apply, "apply", 1, -1, 1)
1044 {
1045 int len;
1046 SCM ls;
1047 POP (ls);
1048
1049 nargs = FETCH ();
1050 ASSERT (nargs >= 2);
1051
1052 len = scm_ilength (ls);
1053 if (len < 0)
1054 goto vm_error_wrong_type_arg;
1055
1056 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
1057
1058 nargs += len - 2;
1059 goto vm_call;
1060 }
1061
1062 VM_DEFINE_INSTRUCTION (63, tail_apply, "tail-apply", 1, -1, 1)
1063 {
1064 int len;
1065 SCM ls;
1066 POP (ls);
1067
1068 nargs = FETCH ();
1069 ASSERT (nargs >= 2);
1070
1071 len = scm_ilength (ls);
1072 if (len < 0)
1073 goto vm_error_wrong_type_arg;
1074
1075 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
1076
1077 nargs += len - 2;
1078 goto vm_tail_call;
1079 }
1080
1081 VM_DEFINE_INSTRUCTION (64, call_cc, "call/cc", 0, 1, 1)
1082 {
1083 int first;
1084 SCM proc, cont;
1085 POP (proc);
1086 SYNC_ALL ();
1087 cont = scm_make_continuation (&first);
1088 if (first)
1089 {
1090 PUSH ((SCM)fp); /* dynamic link */
1091 PUSH (0); /* mvra */
1092 PUSH (0); /* ra */
1093 PUSH (proc);
1094 PUSH (cont);
1095 nargs = 1;
1096 goto vm_call;
1097 }
1098 ASSERT (sp == vp->sp);
1099 ASSERT (fp == vp->fp);
1100 else if (SCM_VALUESP (cont))
1101 {
1102 /* multiple values returned to continuation */
1103 SCM values;
1104 values = scm_struct_ref (cont, SCM_INUM0);
1105 if (scm_is_null (values))
1106 goto vm_error_no_values;
1107 /* non-tail context does not accept multiple values? */
1108 PUSH (SCM_CAR (values));
1109 NEXT;
1110 }
1111 else
1112 {
1113 PUSH (cont);
1114 NEXT;
1115 }
1116 }
1117
1118 VM_DEFINE_INSTRUCTION (65, tail_call_cc, "tail-call/cc", 0, 1, 1)
1119 {
1120 int first;
1121 SCM proc, cont;
1122 POP (proc);
1123 SYNC_ALL ();
1124 cont = scm_make_continuation (&first);
1125 ASSERT (sp == vp->sp);
1126 ASSERT (fp == vp->fp);
1127 if (first)
1128 {
1129 PUSH (proc);
1130 PUSH (cont);
1131 nargs = 1;
1132 goto vm_tail_call;
1133 }
1134 else if (SCM_VALUESP (cont))
1135 {
1136 /* multiple values returned to continuation */
1137 SCM values;
1138 values = scm_struct_ref (cont, SCM_INUM0);
1139 nvalues = scm_ilength (values);
1140 PUSH_LIST (values, scm_is_null);
1141 goto vm_return_values;
1142 }
1143 else
1144 {
1145 PUSH (cont);
1146 goto vm_return;
1147 }
1148 }
1149
1150 VM_DEFINE_INSTRUCTION (66, return, "return", 0, 1, 1)
1151 {
1152 vm_return:
1153 EXIT_HOOK ();
1154 RETURN_HOOK (1);
1155
1156 VM_HANDLE_INTERRUPTS;
1157
1158 {
1159 SCM ret;
1160
1161 POP (ret);
1162
1163 #ifdef VM_ENABLE_STACK_NULLING
1164 SCM *old_sp = sp;
1165 #endif
1166
1167 /* Restore registers */
1168 sp = SCM_FRAME_LOWER_ADDRESS (fp);
1169 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1170 fp = SCM_FRAME_DYNAMIC_LINK (fp);
1171
1172 #ifdef VM_ENABLE_STACK_NULLING
1173 NULLSTACK (old_sp - sp);
1174 #endif
1175
1176 /* Set return value (sp is already pushed) */
1177 *sp = ret;
1178 }
1179
1180 /* Restore the last program */
1181 program = SCM_FRAME_PROGRAM (fp);
1182 CACHE_PROGRAM ();
1183 CHECK_IP ();
1184 NEXT;
1185 }
1186
1187 VM_DEFINE_INSTRUCTION (67, return_values, "return/values", 1, -1, -1)
1188 {
1189 /* nvalues declared at top level, because for some reason gcc seems to think
1190 that perhaps it might be used without declaration. Fooey to that, I say. */
1191 nvalues = FETCH ();
1192 vm_return_values:
1193 EXIT_HOOK ();
1194 RETURN_HOOK (nvalues);
1195
1196 VM_HANDLE_INTERRUPTS;
1197
1198 if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
1199 {
1200 /* A multiply-valued continuation */
1201 SCM *vals = sp - nvalues;
1202 int i;
1203 /* Restore registers */
1204 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
1205 ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
1206 fp = SCM_FRAME_DYNAMIC_LINK (fp);
1207
1208 /* Push return values, and the number of values */
1209 for (i = 0; i < nvalues; i++)
1210 *++sp = vals[i+1];
1211 *++sp = SCM_I_MAKINUM (nvalues);
1212
1213 /* Finally null the end of the stack */
1214 NULLSTACK (vals + nvalues - sp);
1215 }
1216 else if (nvalues >= 1)
1217 {
1218 /* Multiple values for a single-valued continuation -- here's where I
1219 break with guile tradition and try and do something sensible. (Also,
1220 this block handles the single-valued return to an mv
1221 continuation.) */
1222 SCM *vals = sp - nvalues;
1223 /* Restore registers */
1224 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
1225 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1226 fp = SCM_FRAME_DYNAMIC_LINK (fp);
1227
1228 /* Push first value */
1229 *++sp = vals[1];
1230
1231 /* Finally null the end of the stack */
1232 NULLSTACK (vals + nvalues - sp);
1233 }
1234 else
1235 goto vm_error_no_values;
1236
1237 /* Restore the last program */
1238 program = SCM_FRAME_PROGRAM (fp);
1239 CACHE_PROGRAM ();
1240 CHECK_IP ();
1241 NEXT;
1242 }
1243
1244 VM_DEFINE_INSTRUCTION (68, return_values_star, "return/values*", 1, -1, -1)
1245 {
1246 SCM l;
1247
1248 nvalues = FETCH ();
1249 ASSERT (nvalues >= 1);
1250
1251 nvalues--;
1252 POP (l);
1253 while (scm_is_pair (l))
1254 {
1255 PUSH (SCM_CAR (l));
1256 l = SCM_CDR (l);
1257 nvalues++;
1258 }
1259 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
1260 finish_args = scm_list_1 (l);
1261 goto vm_error_improper_list;
1262 }
1263
1264 goto vm_return_values;
1265 }
1266
1267 VM_DEFINE_INSTRUCTION (88, return_nvalues, "return/nvalues", 0, 1, -1)
1268 {
1269 SCM n;
1270 POP (n);
1271 nvalues = scm_to_int (n);
1272 ASSERT (nvalues >= 0);
1273 goto vm_return_values;
1274 }
1275
1276 VM_DEFINE_INSTRUCTION (69, truncate_values, "truncate-values", 2, -1, -1)
1277 {
1278 SCM x;
1279 int nbinds, rest;
1280 POP (x);
1281 nvalues = scm_to_int (x);
1282 nbinds = FETCH ();
1283 rest = FETCH ();
1284
1285 if (rest)
1286 nbinds--;
1287
1288 if (nvalues < nbinds)
1289 goto vm_error_not_enough_values;
1290
1291 if (rest)
1292 POP_LIST (nvalues - nbinds);
1293 else
1294 DROPN (nvalues - nbinds);
1295
1296 NEXT;
1297 }
1298
1299 VM_DEFINE_INSTRUCTION (70, box, "box", 1, 1, 0)
1300 {
1301 SCM val;
1302 POP (val);
1303 SYNC_BEFORE_GC ();
1304 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
1305 NEXT;
1306 }
1307
1308 /* for letrec:
1309 (let ((a *undef*) (b *undef*) ...)
1310 (set! a (lambda () (b ...)))
1311 ...)
1312 */
1313 VM_DEFINE_INSTRUCTION (71, empty_box, "empty-box", 1, 0, 0)
1314 {
1315 SYNC_BEFORE_GC ();
1316 LOCAL_SET (FETCH (),
1317 scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1318 NEXT;
1319 }
1320
1321 VM_DEFINE_INSTRUCTION (72, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
1322 {
1323 SCM v = LOCAL_REF (FETCH ());
1324 ASSERT_BOUND_VARIABLE (v);
1325 PUSH (VARIABLE_REF (v));
1326 NEXT;
1327 }
1328
1329 VM_DEFINE_INSTRUCTION (73, local_boxed_set, "local-boxed-set", 1, 1, 0)
1330 {
1331 SCM v, val;
1332 v = LOCAL_REF (FETCH ());
1333 POP (val);
1334 ASSERT_VARIABLE (v);
1335 VARIABLE_SET (v, val);
1336 NEXT;
1337 }
1338
1339 VM_DEFINE_INSTRUCTION (74, free_ref, "free-ref", 1, 0, 1)
1340 {
1341 scm_t_uint8 idx = FETCH ();
1342
1343 CHECK_FREE_VARIABLE (idx);
1344 PUSH (FREE_VARIABLE_REF (idx));
1345 NEXT;
1346 }
1347
1348 /* no free-set -- if a var is assigned, it should be in a box */
1349
1350 VM_DEFINE_INSTRUCTION (75, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
1351 {
1352 SCM v;
1353 scm_t_uint8 idx = FETCH ();
1354 CHECK_FREE_VARIABLE (idx);
1355 v = FREE_VARIABLE_REF (idx);
1356 ASSERT_BOUND_VARIABLE (v);
1357 PUSH (VARIABLE_REF (v));
1358 NEXT;
1359 }
1360
1361 VM_DEFINE_INSTRUCTION (76, free_boxed_set, "free-boxed-set", 1, 1, 0)
1362 {
1363 SCM v, val;
1364 scm_t_uint8 idx = FETCH ();
1365 POP (val);
1366 CHECK_FREE_VARIABLE (idx);
1367 v = FREE_VARIABLE_REF (idx);
1368 ASSERT_BOUND_VARIABLE (v);
1369 VARIABLE_SET (v, val);
1370 NEXT;
1371 }
1372
1373 VM_DEFINE_INSTRUCTION (77, make_closure, "make-closure", 2, -1, 1)
1374 {
1375 size_t n, len;
1376 SCM closure;
1377
1378 len = FETCH ();
1379 len <<= 8;
1380 len += FETCH ();
1381 SYNC_BEFORE_GC ();
1382 closure = scm_words (scm_tc7_program | (len<<16), len + 3);
1383 SCM_SET_CELL_OBJECT_1 (closure, SCM_PROGRAM_OBJCODE (sp[-len]));
1384 SCM_SET_CELL_OBJECT_2 (closure, SCM_PROGRAM_OBJTABLE (sp[-len]));
1385 sp[-len] = closure;
1386 for (n = 0; n < len; n++)
1387 SCM_PROGRAM_FREE_VARIABLE_SET (closure, n, sp[-len + 1 + n]);
1388 DROPN (len);
1389 NEXT;
1390 }
1391
1392 VM_DEFINE_INSTRUCTION (78, make_variable, "make-variable", 0, 0, 1)
1393 {
1394 SYNC_BEFORE_GC ();
1395 /* fixme underflow */
1396 PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1397 NEXT;
1398 }
1399
1400 VM_DEFINE_INSTRUCTION (79, fix_closure, "fix-closure", 2, -1, 0)
1401 {
1402 SCM x;
1403 unsigned int i = FETCH ();
1404 size_t n, len;
1405 i <<= 8;
1406 i += FETCH ();
1407 /* FIXME CHECK_LOCAL (i) */
1408 x = LOCAL_REF (i);
1409 /* FIXME ASSERT_PROGRAM (x); */
1410 len = SCM_PROGRAM_NUM_FREE_VARIABLES (x);
1411 for (n = 0; n < len; n++)
1412 SCM_PROGRAM_FREE_VARIABLE_SET (x, n, sp[-len + 1 + n]);
1413 DROPN (len);
1414 NEXT;
1415 }
1416
1417 VM_DEFINE_INSTRUCTION (80, define, "define", 0, 0, 2)
1418 {
1419 SCM sym, val;
1420 POP (sym);
1421 POP (val);
1422 SYNC_REGISTER ();
1423 VARIABLE_SET (scm_sym2var (sym, scm_current_module_lookup_closure (),
1424 SCM_BOOL_T),
1425 val);
1426 NEXT;
1427 }
1428
1429 VM_DEFINE_INSTRUCTION (81, make_keyword, "make-keyword", 0, 1, 1)
1430 {
1431 CHECK_UNDERFLOW ();
1432 SYNC_REGISTER ();
1433 *sp = scm_symbol_to_keyword (*sp);
1434 NEXT;
1435 }
1436
1437 VM_DEFINE_INSTRUCTION (82, make_symbol, "make-symbol", 0, 1, 1)
1438 {
1439 CHECK_UNDERFLOW ();
1440 SYNC_REGISTER ();
1441 *sp = scm_string_to_symbol (*sp);
1442 NEXT;
1443 }
1444
1445 VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 5, 3, 0)
1446 {
1447 scm_t_int32 offset;
1448 scm_t_uint8 inline_handler_p, escape_only_p;
1449 SCM k, handler, pre_unwind, prompt;
1450
1451 inline_handler_p = FETCH ();
1452 escape_only_p = FETCH ();
1453 FETCH_OFFSET (offset);
1454 POP (pre_unwind);
1455 POP (handler);
1456 POP (k);
1457
1458 SYNC_REGISTER ();
1459 /* Push the prompt onto the dynamic stack. The setjmp itself has to be local
1460 to this procedure. */
1461 /* FIXME: do more error checking */
1462 prompt = scm_c_make_prompt (vm, k, handler, pre_unwind,
1463 inline_handler_p, escape_only_p);
1464 scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
1465 if (SCM_PROMPT_SETJMP (prompt))
1466 {
1467 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1468 to the handler or post-handler label. (The meaning of the label differs
1469 depending on whether the prompt's handler is rendered inline or not.)
1470 */
1471 CACHE_REGISTER (); /* Really we only need SP. FP and IP should be
1472 unmodified. */
1473 ip += offset;
1474 NEXT;
1475 }
1476
1477 /* Otherwise setjmp returned for the first time, so we go to execute the
1478 prompt's body. */
1479 NEXT;
1480 }
1481
1482 VM_DEFINE_INSTRUCTION (85, wind, "wind", 0, 2, 0)
1483 {
1484 SCM wind, unwind;
1485 POP (unwind);
1486 POP (wind);
1487 SYNC_REGISTER ();
1488 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1489 are actually called; the compiler should emit calls to wind and unwind for
1490 the normal dynamic-wind control flow. */
1491 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind))))
1492 {
1493 finish_args = wind;
1494 goto vm_error_not_a_thunk;
1495 }
1496 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind))))
1497 {
1498 finish_args = unwind;
1499 goto vm_error_not_a_thunk;
1500 }
1501 scm_i_set_dynwinds (scm_cons (scm_cons (wind, unwind), scm_i_dynwinds ()));
1502 NEXT;
1503 }
1504
1505 VM_DEFINE_INSTRUCTION (86, throw, "throw", 1, -1, -1)
1506 {
1507 unsigned n = FETCH ();
1508 SCM k;
1509 SCM args;
1510 POP_LIST (n);
1511 POP (args);
1512 POP (k);
1513 SYNC_REGISTER ();
1514 vm_throw (vm, k, args);
1515 /* vm_throw should not return */
1516 abort ();
1517 }
1518
1519 VM_DEFINE_INSTRUCTION (87, unwind, "unwind", 0, 0, 0)
1520 {
1521 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1522 off of the dynamic stack. */
1523 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1524 NEXT;
1525 }
1526
1527
1528
1529 /*
1530 (defun renumber-ops ()
1531 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1532 (interactive "")
1533 (save-excursion
1534 (let ((counter -1)) (goto-char (point-min))
1535 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1536 (replace-match
1537 (number-to-string (setq counter (1+ counter)))
1538 t t nil 1)))))
1539 (renumber-ops)
1540 */
1541 /*
1542 Local Variables:
1543 c-file-style: "gnu"
1544 End:
1545 */