steps on the way to have the callee check the number of arguments
[bpt/guile.git] / libguile / vm-i-system.c
1 /* Copyright (C) 2001,2008,2009 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 vp->time += scm_c_get_internal_run_time () - start_time;
35 HALT_HOOK ();
36 nvalues = SCM_I_INUM (*sp--);
37 NULLSTACK (1);
38 if (nvalues == 1)
39 POP (finish_args);
40 else
41 {
42 POP_LIST (nvalues);
43 POP (finish_args);
44 SYNC_REGISTER ();
45 finish_args = scm_values (finish_args);
46 }
47
48 {
49 ASSERT (sp == stack_base);
50 ASSERT (stack_base == SCM_FRAME_UPPER_ADDRESS (fp) - 1);
51
52 /* Restore registers */
53 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
54 ip = NULL;
55 fp = SCM_FRAME_DYNAMIC_LINK (fp);
56 NULLSTACK (stack_base - sp);
57 }
58
59 goto vm_done;
60 }
61
62 VM_DEFINE_INSTRUCTION (2, break, "break", 0, 0, 0)
63 {
64 BREAK_HOOK ();
65 NEXT;
66 }
67
68 VM_DEFINE_INSTRUCTION (3, drop, "drop", 0, 1, 0)
69 {
70 DROP ();
71 NEXT;
72 }
73
74 VM_DEFINE_INSTRUCTION (4, dup, "dup", 0, 0, 1)
75 {
76 SCM x = *sp;
77 PUSH (x);
78 NEXT;
79 }
80
81 \f
82 /*
83 * Object creation
84 */
85
86 VM_DEFINE_INSTRUCTION (5, void, "void", 0, 0, 1)
87 {
88 PUSH (SCM_UNSPECIFIED);
89 NEXT;
90 }
91
92 VM_DEFINE_INSTRUCTION (6, make_true, "make-true", 0, 0, 1)
93 {
94 PUSH (SCM_BOOL_T);
95 NEXT;
96 }
97
98 VM_DEFINE_INSTRUCTION (7, make_false, "make-false", 0, 0, 1)
99 {
100 PUSH (SCM_BOOL_F);
101 NEXT;
102 }
103
104 VM_DEFINE_INSTRUCTION (8, make_eol, "make-eol", 0, 0, 1)
105 {
106 PUSH (SCM_EOL);
107 NEXT;
108 }
109
110 VM_DEFINE_INSTRUCTION (9, make_int8, "make-int8", 1, 0, 1)
111 {
112 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
113 NEXT;
114 }
115
116 VM_DEFINE_INSTRUCTION (10, make_int8_0, "make-int8:0", 0, 0, 1)
117 {
118 PUSH (SCM_INUM0);
119 NEXT;
120 }
121
122 VM_DEFINE_INSTRUCTION (11, make_int8_1, "make-int8:1", 0, 0, 1)
123 {
124 PUSH (SCM_I_MAKINUM (1));
125 NEXT;
126 }
127
128 VM_DEFINE_INSTRUCTION (12, make_int16, "make-int16", 2, 0, 1)
129 {
130 int h = FETCH ();
131 int l = FETCH ();
132 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
133 NEXT;
134 }
135
136 VM_DEFINE_INSTRUCTION (13, make_int64, "make-int64", 8, 0, 1)
137 {
138 scm_t_uint64 v = 0;
139 v += FETCH ();
140 v <<= 8; v += FETCH ();
141 v <<= 8; v += FETCH ();
142 v <<= 8; v += FETCH ();
143 v <<= 8; v += FETCH ();
144 v <<= 8; v += FETCH ();
145 v <<= 8; v += FETCH ();
146 v <<= 8; v += FETCH ();
147 PUSH (scm_from_int64 ((scm_t_int64) v));
148 NEXT;
149 }
150
151 VM_DEFINE_INSTRUCTION (14, make_uint64, "make-uint64", 8, 0, 1)
152 {
153 scm_t_uint64 v = 0;
154 v += FETCH ();
155 v <<= 8; v += FETCH ();
156 v <<= 8; v += FETCH ();
157 v <<= 8; v += FETCH ();
158 v <<= 8; v += FETCH ();
159 v <<= 8; v += FETCH ();
160 v <<= 8; v += FETCH ();
161 v <<= 8; v += FETCH ();
162 PUSH (scm_from_uint64 (v));
163 NEXT;
164 }
165
166 VM_DEFINE_INSTRUCTION (15, make_char8, "make-char8", 1, 0, 1)
167 {
168 scm_t_uint8 v = 0;
169 v = FETCH ();
170
171 PUSH (SCM_MAKE_CHAR (v));
172 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
173 contents of SCM_MAKE_CHAR may be evaluated more than once,
174 resulting in a double fetch. */
175 NEXT;
176 }
177
178 VM_DEFINE_INSTRUCTION (16, make_char32, "make-char32", 4, 0, 1)
179 {
180 scm_t_wchar v = 0;
181 v += FETCH ();
182 v <<= 8; v += FETCH ();
183 v <<= 8; v += FETCH ();
184 v <<= 8; v += FETCH ();
185 PUSH (SCM_MAKE_CHAR (v));
186 NEXT;
187 }
188
189
190
191 VM_DEFINE_INSTRUCTION (17, list, "list", 2, -1, 1)
192 {
193 unsigned h = FETCH ();
194 unsigned l = FETCH ();
195 unsigned len = ((h << 8) + l);
196 POP_LIST (len);
197 NEXT;
198 }
199
200 VM_DEFINE_INSTRUCTION (18, vector, "vector", 2, -1, 1)
201 {
202 unsigned h = FETCH ();
203 unsigned l = FETCH ();
204 unsigned len = ((h << 8) + l);
205 SCM vect;
206
207 SYNC_REGISTER ();
208 sp++; sp -= len;
209 CHECK_UNDERFLOW ();
210 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
211 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
212 NULLSTACK (len);
213 *sp = vect;
214
215 NEXT;
216 }
217
218 \f
219 /*
220 * Variable access
221 */
222
223 #define OBJECT_REF(i) objects[i]
224 #define OBJECT_SET(i,o) objects[i] = o
225
226 #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
227 #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
228
229 /* For the variable operations, we _must_ obviously avoid function calls to
230 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
231 nothing more than the corresponding macros. */
232 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
233 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
234 #define VARIABLE_BOUNDP(v) (VARIABLE_REF (v) != SCM_UNDEFINED)
235
236 #define FREE_VARIABLE_REF(i) free_vars[i]
237
238 /* ref */
239
240 VM_DEFINE_INSTRUCTION (19, object_ref, "object-ref", 1, 0, 1)
241 {
242 register unsigned objnum = FETCH ();
243 CHECK_OBJECT (objnum);
244 PUSH (OBJECT_REF (objnum));
245 NEXT;
246 }
247
248 /* FIXME: necessary? elt 255 of the vector could be a vector... */
249 VM_DEFINE_INSTRUCTION (20, long_object_ref, "long-object-ref", 2, 0, 1)
250 {
251 unsigned int objnum = FETCH ();
252 objnum <<= 8;
253 objnum += FETCH ();
254 CHECK_OBJECT (objnum);
255 PUSH (OBJECT_REF (objnum));
256 NEXT;
257 }
258
259 VM_DEFINE_INSTRUCTION (21, local_ref, "local-ref", 1, 0, 1)
260 {
261 PUSH (LOCAL_REF (FETCH ()));
262 ASSERT_BOUND (*sp);
263 NEXT;
264 }
265
266 VM_DEFINE_INSTRUCTION (22, long_local_ref, "long-local-ref", 2, 0, 1)
267 {
268 unsigned int i = FETCH ();
269 i <<= 8;
270 i += FETCH ();
271 PUSH (LOCAL_REF (i));
272 ASSERT_BOUND (*sp);
273 NEXT;
274 }
275
276 VM_DEFINE_INSTRUCTION (23, variable_ref, "variable-ref", 0, 0, 1)
277 {
278 SCM x = *sp;
279
280 if (!VARIABLE_BOUNDP (x))
281 {
282 finish_args = scm_list_1 (x);
283 /* Was: finish_args = SCM_LIST1 (SCM_CAR (x)); */
284 goto vm_error_unbound;
285 }
286 else
287 {
288 SCM o = VARIABLE_REF (x);
289 *sp = o;
290 }
291
292 NEXT;
293 }
294
295 VM_DEFINE_INSTRUCTION (24, toplevel_ref, "toplevel-ref", 1, 0, 1)
296 {
297 unsigned objnum = FETCH ();
298 SCM what;
299 CHECK_OBJECT (objnum);
300 what = OBJECT_REF (objnum);
301
302 if (!SCM_VARIABLEP (what))
303 {
304 SYNC_REGISTER ();
305 what = resolve_variable (what, scm_program_module (program));
306 if (!VARIABLE_BOUNDP (what))
307 {
308 finish_args = scm_list_1 (what);
309 goto vm_error_unbound;
310 }
311 OBJECT_SET (objnum, what);
312 }
313
314 PUSH (VARIABLE_REF (what));
315 NEXT;
316 }
317
318 VM_DEFINE_INSTRUCTION (25, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
319 {
320 SCM what;
321 unsigned int objnum = FETCH ();
322 objnum <<= 8;
323 objnum += FETCH ();
324 CHECK_OBJECT (objnum);
325 what = OBJECT_REF (objnum);
326
327 if (!SCM_VARIABLEP (what))
328 {
329 SYNC_REGISTER ();
330 what = resolve_variable (what, scm_program_module (program));
331 if (!VARIABLE_BOUNDP (what))
332 {
333 finish_args = scm_list_1 (what);
334 goto vm_error_unbound;
335 }
336 OBJECT_SET (objnum, what);
337 }
338
339 PUSH (VARIABLE_REF (what));
340 NEXT;
341 }
342
343 /* set */
344
345 VM_DEFINE_INSTRUCTION (26, local_set, "local-set", 1, 1, 0)
346 {
347 LOCAL_SET (FETCH (), *sp);
348 DROP ();
349 NEXT;
350 }
351
352 VM_DEFINE_INSTRUCTION (27, long_local_set, "long-local-set", 2, 1, 0)
353 {
354 unsigned int i = FETCH ();
355 i <<= 8;
356 i += FETCH ();
357 LOCAL_SET (i, *sp);
358 DROP ();
359 NEXT;
360 }
361
362 VM_DEFINE_INSTRUCTION (28, variable_set, "variable-set", 0, 1, 0)
363 {
364 VARIABLE_SET (sp[0], sp[-1]);
365 DROPN (2);
366 NEXT;
367 }
368
369 VM_DEFINE_INSTRUCTION (29, toplevel_set, "toplevel-set", 1, 1, 0)
370 {
371 unsigned objnum = FETCH ();
372 SCM what;
373 CHECK_OBJECT (objnum);
374 what = OBJECT_REF (objnum);
375
376 if (!SCM_VARIABLEP (what))
377 {
378 SYNC_BEFORE_GC ();
379 what = resolve_variable (what, scm_program_module (program));
380 OBJECT_SET (objnum, what);
381 }
382
383 VARIABLE_SET (what, *sp);
384 DROP ();
385 NEXT;
386 }
387
388 VM_DEFINE_INSTRUCTION (30, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
389 {
390 SCM what;
391 unsigned int objnum = FETCH ();
392 objnum <<= 8;
393 objnum += FETCH ();
394 CHECK_OBJECT (objnum);
395 what = OBJECT_REF (objnum);
396
397 if (!SCM_VARIABLEP (what))
398 {
399 SYNC_BEFORE_GC ();
400 what = resolve_variable (what, scm_program_module (program));
401 OBJECT_SET (objnum, what);
402 }
403
404 VARIABLE_SET (what, *sp);
405 DROP ();
406 NEXT;
407 }
408
409 \f
410 /*
411 * branch and jump
412 */
413
414 /* offset must be at least 24 bits wide, and signed */
415 #define FETCH_OFFSET(offset) \
416 { \
417 offset = FETCH () << 16; \
418 offset += FETCH () << 8; \
419 offset += FETCH (); \
420 offset -= (offset & (1<<23)) << 1; \
421 }
422
423 #define BR(p) \
424 { \
425 scm_t_int32 offset; \
426 FETCH_OFFSET (offset); \
427 if (p) \
428 ip += offset; \
429 NULLSTACK (1); \
430 DROP (); \
431 NEXT; \
432 }
433
434 VM_DEFINE_INSTRUCTION (31, br, "br", 3, 0, 0)
435 {
436 scm_t_int32 offset;
437 FETCH_OFFSET (offset);
438 ip += offset;
439 NEXT;
440 }
441
442 VM_DEFINE_INSTRUCTION (32, br_if, "br-if", 3, 0, 0)
443 {
444 BR (!SCM_FALSEP (*sp));
445 }
446
447 VM_DEFINE_INSTRUCTION (33, br_if_not, "br-if-not", 3, 0, 0)
448 {
449 BR (SCM_FALSEP (*sp));
450 }
451
452 VM_DEFINE_INSTRUCTION (34, br_if_eq, "br-if-eq", 3, 0, 0)
453 {
454 sp--; /* underflow? */
455 BR (SCM_EQ_P (sp[0], sp[1]));
456 }
457
458 VM_DEFINE_INSTRUCTION (35, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
459 {
460 sp--; /* underflow? */
461 BR (!SCM_EQ_P (sp[0], sp[1]));
462 }
463
464 VM_DEFINE_INSTRUCTION (36, br_if_null, "br-if-null", 3, 0, 0)
465 {
466 BR (SCM_NULLP (*sp));
467 }
468
469 VM_DEFINE_INSTRUCTION (37, br_if_not_null, "br-if-not-null", 3, 0, 0)
470 {
471 BR (!SCM_NULLP (*sp));
472 }
473
474 \f
475 /*
476 * Subprogram call
477 */
478
479 VM_DEFINE_INSTRUCTION (38, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
480 {
481 scm_t_ptrdiff n;
482 n = FETCH () << 8;
483 n += FETCH ();
484 #if 0
485 if (sp - fp != n)
486 goto vm_error_wrong_num_args;
487 #endif
488 NEXT;
489 }
490
491 VM_DEFINE_INSTRUCTION (39, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
492 {
493 scm_t_ptrdiff n;
494 n = FETCH () << 8;
495 n += FETCH ();
496 #if 0
497 if (sp - fp < n)
498 goto vm_error_wrong_num_args;
499 #endif
500 NEXT;
501 }
502
503 VM_DEFINE_INSTRUCTION (40, push_rest_list, "push-rest-list", 2, -1, -1)
504 {
505 scm_t_ptrdiff n;
506 n = FETCH () << 8;
507 n += FETCH ();
508 #if 0
509 SCM rest = SCM_EOL;
510 while (sp - fp >= n)
511 /* No need to check for underflow. */
512 CONS (rest, *sp--, rest);
513 PUSH (rest);
514 #endif
515 NEXT;
516 }
517
518 VM_DEFINE_INSTRUCTION (41, new_frame, "new-frame", 0, 0, 3)
519 {
520 PUSH ((SCM)fp); /* dynamic link */
521 PUSH (0); /* mvra */
522 PUSH (0); /* ra */
523 NEXT;
524 }
525
526 VM_DEFINE_INSTRUCTION (42, call, "call", 1, -1, 1)
527 {
528 SCM x;
529 nargs = FETCH ();
530
531 vm_call:
532 x = sp[-nargs];
533
534 SYNC_REGISTER ();
535 SCM_TICK; /* allow interrupt here */
536
537 /*
538 * Subprogram call
539 */
540 if (SCM_PROGRAM_P (x))
541 {
542 program = x;
543 CACHE_PROGRAM ();
544 INIT_ARGS ();
545 fp = sp - bp->nargs + 1;
546 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
547 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
548 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
549 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
550 INIT_FRAME ();
551 ENTER_HOOK ();
552 APPLY_HOOK ();
553 NEXT;
554 }
555 /*
556 * Other interpreted or compiled call
557 */
558 if (!SCM_FALSEP (scm_procedure_p (x)))
559 {
560 SCM args;
561 /* At this point, the stack contains the frame, the procedure and each one
562 of its arguments. */
563 POP_LIST (nargs);
564 POP (args);
565 DROP (); /* drop the procedure */
566 DROP_FRAME ();
567
568 SYNC_REGISTER ();
569 PUSH (scm_apply (x, args, SCM_EOL));
570 NULLSTACK_FOR_NONLOCAL_EXIT ();
571 if (SCM_UNLIKELY (SCM_VALUESP (*sp)))
572 {
573 /* truncate values */
574 SCM values;
575 POP (values);
576 values = scm_struct_ref (values, SCM_INUM0);
577 if (scm_is_null (values))
578 goto vm_error_not_enough_values;
579 PUSH (SCM_CAR (values));
580 }
581 NEXT;
582 }
583
584 program = x;
585 goto vm_error_wrong_type_apply;
586 }
587
588 VM_DEFINE_INSTRUCTION (43, goto_args, "goto/args", 1, -1, 1)
589 {
590 register SCM x;
591 nargs = FETCH ();
592 vm_goto_args:
593 x = sp[-nargs];
594
595 SYNC_REGISTER ();
596 SCM_TICK; /* allow interrupt here */
597
598 /*
599 * Tail call
600 */
601 if (SCM_PROGRAM_P (x))
602 {
603 int i;
604 #ifdef VM_ENABLE_STACK_NULLING
605 SCM *old_sp;
606 #endif
607
608 EXIT_HOOK ();
609
610 /* switch programs */
611 program = x;
612 CACHE_PROGRAM ();
613 INIT_ARGS ();
614
615 #ifdef VM_ENABLE_STACK_NULLING
616 old_sp = sp;
617 CHECK_STACK_LEAK ();
618 #endif
619
620 /* delay shuffling the new program+args down so that if INIT_ARGS had to
621 cons up a rest arg, going into GC, the stack still made sense */
622 for (i = -1, sp = sp - bp->nargs + 1; i < bp->nargs; i++)
623 fp[i] = sp[i];
624 sp = fp + i - 1;
625
626 NULLSTACK (old_sp - sp);
627
628 INIT_FRAME ();
629
630 ENTER_HOOK ();
631 APPLY_HOOK ();
632 NEXT;
633 }
634
635 /*
636 * Other interpreted or compiled call
637 */
638 if (!SCM_FALSEP (scm_procedure_p (x)))
639 {
640 SCM args;
641 POP_LIST (nargs);
642 POP (args);
643
644 SYNC_REGISTER ();
645 *sp = scm_apply (x, args, SCM_EOL);
646 NULLSTACK_FOR_NONLOCAL_EXIT ();
647
648 if (SCM_UNLIKELY (SCM_VALUESP (*sp)))
649 {
650 /* multiple values returned to continuation */
651 SCM values;
652 POP (values);
653 values = scm_struct_ref (values, SCM_INUM0);
654 nvalues = scm_ilength (values);
655 PUSH_LIST (values, SCM_NULLP);
656 goto vm_return_values;
657 }
658 else
659 goto vm_return;
660 }
661
662 program = x;
663
664 goto vm_error_wrong_type_apply;
665 }
666
667 VM_DEFINE_INSTRUCTION (44, goto_nargs, "goto/nargs", 0, 0, 1)
668 {
669 SCM x;
670 POP (x);
671 nargs = scm_to_int (x);
672 /* FIXME: should truncate values? */
673 goto vm_goto_args;
674 }
675
676 VM_DEFINE_INSTRUCTION (45, call_nargs, "call/nargs", 0, 0, 1)
677 {
678 SCM x;
679 POP (x);
680 nargs = scm_to_int (x);
681 /* FIXME: should truncate values? */
682 goto vm_call;
683 }
684
685 VM_DEFINE_INSTRUCTION (46, mv_call, "mv-call", 4, -1, 1)
686 {
687 SCM x;
688 scm_t_int32 offset;
689 scm_t_uint8 *mvra;
690
691 nargs = FETCH ();
692 FETCH_OFFSET (offset);
693 mvra = ip + offset;
694
695 x = sp[-nargs];
696
697 /*
698 * Subprogram call
699 */
700 if (SCM_PROGRAM_P (x))
701 {
702 program = x;
703 CACHE_PROGRAM ();
704 INIT_ARGS ();
705 fp = sp - bp->nargs + 1;
706 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
707 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
708 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
709 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
710 INIT_FRAME ();
711 ENTER_HOOK ();
712 APPLY_HOOK ();
713 NEXT;
714 }
715 /*
716 * Other interpreted or compiled call
717 */
718 if (!SCM_FALSEP (scm_procedure_p (x)))
719 {
720 SCM args;
721 /* At this point, the stack contains the procedure and each one of its
722 arguments. */
723 POP_LIST (nargs);
724 POP (args);
725 DROP (); /* drop the procedure */
726 DROP_FRAME ();
727
728 SYNC_REGISTER ();
729 PUSH (scm_apply (x, args, SCM_EOL));
730 NULLSTACK_FOR_NONLOCAL_EXIT ();
731 if (SCM_VALUESP (*sp))
732 {
733 SCM values, len;
734 POP (values);
735 values = scm_struct_ref (values, SCM_INUM0);
736 len = scm_length (values);
737 PUSH_LIST (values, SCM_NULLP);
738 PUSH (len);
739 ip = mvra;
740 }
741 NEXT;
742 }
743
744 program = x;
745 goto vm_error_wrong_type_apply;
746 }
747
748 VM_DEFINE_INSTRUCTION (47, apply, "apply", 1, -1, 1)
749 {
750 int len;
751 SCM ls;
752 POP (ls);
753
754 nargs = FETCH ();
755 ASSERT (nargs >= 2);
756
757 len = scm_ilength (ls);
758 if (len < 0)
759 goto vm_error_wrong_type_arg;
760
761 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
762
763 nargs += len - 2;
764 goto vm_call;
765 }
766
767 VM_DEFINE_INSTRUCTION (48, goto_apply, "goto/apply", 1, -1, 1)
768 {
769 int len;
770 SCM ls;
771 POP (ls);
772
773 nargs = FETCH ();
774 ASSERT (nargs >= 2);
775
776 len = scm_ilength (ls);
777 if (len < 0)
778 goto vm_error_wrong_type_arg;
779
780 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
781
782 nargs += len - 2;
783 goto vm_goto_args;
784 }
785
786 VM_DEFINE_INSTRUCTION (49, call_cc, "call/cc", 0, 1, 1)
787 {
788 int first;
789 SCM proc, cont;
790 POP (proc);
791 SYNC_ALL ();
792 cont = scm_make_continuation (&first);
793 if (first)
794 {
795 PUSH ((SCM)fp); /* dynamic link */
796 PUSH (0); /* mvra */
797 PUSH (0); /* ra */
798 PUSH (proc);
799 PUSH (cont);
800 nargs = 1;
801 goto vm_call;
802 }
803 ASSERT (sp == vp->sp);
804 ASSERT (fp == vp->fp);
805 else if (SCM_VALUESP (cont))
806 {
807 /* multiple values returned to continuation */
808 SCM values;
809 values = scm_struct_ref (cont, SCM_INUM0);
810 if (SCM_NULLP (values))
811 goto vm_error_no_values;
812 /* non-tail context does not accept multiple values? */
813 PUSH (SCM_CAR (values));
814 NEXT;
815 }
816 else
817 {
818 PUSH (cont);
819 NEXT;
820 }
821 }
822
823 VM_DEFINE_INSTRUCTION (50, goto_cc, "goto/cc", 0, 1, 1)
824 {
825 int first;
826 SCM proc, cont;
827 POP (proc);
828 SYNC_ALL ();
829 cont = scm_make_continuation (&first);
830 ASSERT (sp == vp->sp);
831 ASSERT (fp == vp->fp);
832 if (first)
833 {
834 PUSH (proc);
835 PUSH (cont);
836 nargs = 1;
837 goto vm_goto_args;
838 }
839 else if (SCM_VALUESP (cont))
840 {
841 /* multiple values returned to continuation */
842 SCM values;
843 values = scm_struct_ref (cont, SCM_INUM0);
844 nvalues = scm_ilength (values);
845 PUSH_LIST (values, SCM_NULLP);
846 goto vm_return_values;
847 }
848 else
849 {
850 PUSH (cont);
851 goto vm_return;
852 }
853 }
854
855 VM_DEFINE_INSTRUCTION (51, return, "return", 0, 1, 1)
856 {
857 vm_return:
858 EXIT_HOOK ();
859 RETURN_HOOK ();
860 SYNC_REGISTER ();
861 SCM_TICK; /* allow interrupt here */
862 {
863 SCM ret;
864
865 POP (ret);
866 ASSERT (sp == stack_base);
867 ASSERT (stack_base == SCM_FRAME_UPPER_ADDRESS (fp) - 1);
868
869 /* Restore registers */
870 sp = SCM_FRAME_LOWER_ADDRESS (fp);
871 ip = SCM_FRAME_RETURN_ADDRESS (fp);
872 fp = SCM_FRAME_DYNAMIC_LINK (fp);
873 {
874 #ifdef VM_ENABLE_STACK_NULLING
875 int nullcount = stack_base - sp;
876 #endif
877 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
878 NULLSTACK (nullcount);
879 }
880
881 /* Set return value (sp is already pushed) */
882 *sp = ret;
883 }
884
885 /* Restore the last program */
886 program = SCM_FRAME_PROGRAM (fp);
887 CACHE_PROGRAM ();
888 CHECK_IP ();
889 NEXT;
890 }
891
892 VM_DEFINE_INSTRUCTION (52, return_values, "return/values", 1, -1, -1)
893 {
894 /* nvalues declared at top level, because for some reason gcc seems to think
895 that perhaps it might be used without declaration. Fooey to that, I say. */
896 nvalues = FETCH ();
897 vm_return_values:
898 EXIT_HOOK ();
899 RETURN_HOOK ();
900
901 ASSERT (stack_base == SCM_FRAME_UPPER_ADDRESS (fp) - 1);
902
903 /* data[1] is the mv return address */
904 if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
905 {
906 int i;
907 /* Restore registers */
908 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
909 ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
910 fp = SCM_FRAME_DYNAMIC_LINK (fp);
911
912 /* Push return values, and the number of values */
913 for (i = 0; i < nvalues; i++)
914 *++sp = stack_base[1+i];
915 *++sp = SCM_I_MAKINUM (nvalues);
916
917 /* Finally set new stack_base */
918 NULLSTACK (stack_base - sp + nvalues + 1);
919 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
920 }
921 else if (nvalues >= 1)
922 {
923 /* Multiple values for a single-valued continuation -- here's where I
924 break with guile tradition and try and do something sensible. (Also,
925 this block handles the single-valued return to an mv
926 continuation.) */
927 /* Restore registers */
928 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
929 ip = SCM_FRAME_RETURN_ADDRESS (fp);
930 fp = SCM_FRAME_DYNAMIC_LINK (fp);
931
932 /* Push first value */
933 *++sp = stack_base[1];
934
935 /* Finally set new stack_base */
936 NULLSTACK (stack_base - sp + nvalues + 1);
937 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
938 }
939 else
940 goto vm_error_no_values;
941
942 /* Restore the last program */
943 program = SCM_FRAME_PROGRAM (fp);
944 CACHE_PROGRAM ();
945 CHECK_IP ();
946 NEXT;
947 }
948
949 VM_DEFINE_INSTRUCTION (53, return_values_star, "return/values*", 1, -1, -1)
950 {
951 SCM l;
952
953 nvalues = FETCH ();
954 ASSERT (nvalues >= 1);
955
956 nvalues--;
957 POP (l);
958 while (SCM_CONSP (l))
959 {
960 PUSH (SCM_CAR (l));
961 l = SCM_CDR (l);
962 nvalues++;
963 }
964 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
965 finish_args = scm_list_1 (l);
966 goto vm_error_improper_list;
967 }
968
969 goto vm_return_values;
970 }
971
972 VM_DEFINE_INSTRUCTION (54, truncate_values, "truncate-values", 2, -1, -1)
973 {
974 SCM x;
975 int nbinds, rest;
976 POP (x);
977 nvalues = scm_to_int (x);
978 nbinds = FETCH ();
979 rest = FETCH ();
980
981 if (rest)
982 nbinds--;
983
984 if (nvalues < nbinds)
985 goto vm_error_not_enough_values;
986
987 if (rest)
988 POP_LIST (nvalues - nbinds);
989 else
990 DROPN (nvalues - nbinds);
991
992 NEXT;
993 }
994
995 VM_DEFINE_INSTRUCTION (55, box, "box", 1, 1, 0)
996 {
997 SCM val;
998 POP (val);
999 SYNC_BEFORE_GC ();
1000 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
1001 NEXT;
1002 }
1003
1004 /* for letrec:
1005 (let ((a *undef*) (b *undef*) ...)
1006 (set! a (lambda () (b ...)))
1007 ...)
1008 */
1009 VM_DEFINE_INSTRUCTION (56, empty_box, "empty-box", 1, 0, 0)
1010 {
1011 SYNC_BEFORE_GC ();
1012 LOCAL_SET (FETCH (),
1013 scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1014 NEXT;
1015 }
1016
1017 VM_DEFINE_INSTRUCTION (57, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
1018 {
1019 SCM v = LOCAL_REF (FETCH ());
1020 ASSERT_BOUND_VARIABLE (v);
1021 PUSH (VARIABLE_REF (v));
1022 NEXT;
1023 }
1024
1025 VM_DEFINE_INSTRUCTION (58, local_boxed_set, "local-boxed-set", 1, 1, 0)
1026 {
1027 SCM v, val;
1028 v = LOCAL_REF (FETCH ());
1029 POP (val);
1030 ASSERT_VARIABLE (v);
1031 VARIABLE_SET (v, val);
1032 NEXT;
1033 }
1034
1035 VM_DEFINE_INSTRUCTION (59, free_ref, "free-ref", 1, 0, 1)
1036 {
1037 scm_t_uint8 idx = FETCH ();
1038
1039 CHECK_FREE_VARIABLE (idx);
1040 PUSH (FREE_VARIABLE_REF (idx));
1041 NEXT;
1042 }
1043
1044 /* no free-set -- if a var is assigned, it should be in a box */
1045
1046 VM_DEFINE_INSTRUCTION (60, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
1047 {
1048 SCM v;
1049 scm_t_uint8 idx = FETCH ();
1050 CHECK_FREE_VARIABLE (idx);
1051 v = FREE_VARIABLE_REF (idx);
1052 ASSERT_BOUND_VARIABLE (v);
1053 PUSH (VARIABLE_REF (v));
1054 NEXT;
1055 }
1056
1057 VM_DEFINE_INSTRUCTION (61, free_boxed_set, "free-boxed-set", 1, 1, 0)
1058 {
1059 SCM v, val;
1060 scm_t_uint8 idx = FETCH ();
1061 POP (val);
1062 CHECK_FREE_VARIABLE (idx);
1063 v = FREE_VARIABLE_REF (idx);
1064 ASSERT_BOUND_VARIABLE (v);
1065 VARIABLE_SET (v, val);
1066 NEXT;
1067 }
1068
1069 VM_DEFINE_INSTRUCTION (62, make_closure, "make-closure", 0, 2, 1)
1070 {
1071 SCM vect;
1072 POP (vect);
1073 SYNC_BEFORE_GC ();
1074 /* fixme underflow */
1075 *sp = scm_double_cell (scm_tc7_program, (scm_t_bits)SCM_PROGRAM_OBJCODE (*sp),
1076 (scm_t_bits)SCM_PROGRAM_OBJTABLE (*sp), (scm_t_bits)vect);
1077 NEXT;
1078 }
1079
1080 VM_DEFINE_INSTRUCTION (63, make_variable, "make-variable", 0, 0, 1)
1081 {
1082 SYNC_BEFORE_GC ();
1083 /* fixme underflow */
1084 PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1085 NEXT;
1086 }
1087
1088 VM_DEFINE_INSTRUCTION (64, fix_closure, "fix-closure", 2, 0, 1)
1089 {
1090 SCM x, vect;
1091 unsigned int i = FETCH ();
1092 i <<= 8;
1093 i += FETCH ();
1094 POP (vect);
1095 /* FIXME CHECK_LOCAL (i) */
1096 x = LOCAL_REF (i);
1097 /* FIXME ASSERT_PROGRAM (x); */
1098 SCM_SET_CELL_WORD_3 (x, vect);
1099 NEXT;
1100 }
1101
1102 VM_DEFINE_INSTRUCTION (65, define, "define", 0, 0, 2)
1103 {
1104 SCM sym, val;
1105 POP (sym);
1106 POP (val);
1107 SYNC_REGISTER ();
1108 VARIABLE_SET (scm_sym2var (sym, scm_current_module_lookup_closure (),
1109 SCM_BOOL_T),
1110 val);
1111 NEXT;
1112 }
1113
1114 VM_DEFINE_INSTRUCTION (66, make_keyword, "make-keyword", 0, 1, 1)
1115 {
1116 CHECK_UNDERFLOW ();
1117 SYNC_REGISTER ();
1118 *sp = scm_symbol_to_keyword (*sp);
1119 NEXT;
1120 }
1121
1122 VM_DEFINE_INSTRUCTION (67, make_symbol, "make-symbol", 0, 1, 1)
1123 {
1124 CHECK_UNDERFLOW ();
1125 SYNC_REGISTER ();
1126 *sp = scm_string_to_symbol (*sp);
1127 NEXT;
1128 }
1129
1130
1131 /*
1132 (defun renumber-ops ()
1133 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1134 (interactive "")
1135 (save-excursion
1136 (let ((counter -1)) (goto-char (point-min))
1137 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1138 (replace-match
1139 (number-to-string (setq counter (1+ counter)))
1140 t t nil 1)))))
1141 */
1142 /*
1143 Local Variables:
1144 c-file-style: "gnu"
1145 End:
1146 */