1 /* Copyright (C) 2001,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
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.
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.
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
20 /* This file is included in vm_engine.c */
27 VM_DEFINE_INSTRUCTION (0, nop
, "nop", 0, 0, 0)
32 VM_DEFINE_INSTRUCTION (1, halt
, "halt", 0, 0, 0)
36 nvalues
= SCM_I_INUM (*sp
--);
46 ret
= scm_c_values (sp
+ 1, nvalues
);
51 #ifdef VM_ENABLE_STACK_NULLING
55 /* Restore registers */
56 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
57 /* Setting the ip here doesn't actually affect control flow, as the calling
58 code will restore its own registers, but it does help when walking the
60 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
61 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
62 NULLSTACK (old_sp
- sp
);
69 VM_DEFINE_INSTRUCTION (2, drop
, "drop", 0, 1, 0)
75 VM_DEFINE_INSTRUCTION (3, dup
, "dup", 0, 0, 1)
87 VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
89 PUSH (SCM_UNSPECIFIED
);
93 VM_DEFINE_INSTRUCTION (5, make_true
, "make-true", 0, 0, 1)
99 VM_DEFINE_INSTRUCTION (6, make_false
, "make-false", 0, 0, 1)
105 VM_DEFINE_INSTRUCTION (7, make_nil
, "make-nil", 0, 0, 1)
107 PUSH (SCM_ELISP_NIL
);
111 VM_DEFINE_INSTRUCTION (8, make_eol
, "make-eol", 0, 0, 1)
117 VM_DEFINE_INSTRUCTION (9, make_int8
, "make-int8", 1, 0, 1)
119 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
123 VM_DEFINE_INSTRUCTION (10, make_int8_0
, "make-int8:0", 0, 0, 1)
129 VM_DEFINE_INSTRUCTION (11, make_int8_1
, "make-int8:1", 0, 0, 1)
131 PUSH (SCM_I_MAKINUM (1));
135 VM_DEFINE_INSTRUCTION (12, make_int16
, "make-int16", 2, 0, 1)
139 PUSH (SCM_I_MAKINUM ((signed short) (h
<< 8) + l
));
143 VM_DEFINE_INSTRUCTION (13, make_int64
, "make-int64", 8, 0, 1)
147 v
<<= 8; v
+= FETCH ();
148 v
<<= 8; 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 PUSH (scm_from_int64 ((scm_t_int64
) v
));
158 VM_DEFINE_INSTRUCTION (14, make_uint64
, "make-uint64", 8, 0, 1)
162 v
<<= 8; v
+= FETCH ();
163 v
<<= 8; 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 PUSH (scm_from_uint64 (v
));
173 VM_DEFINE_INSTRUCTION (15, make_char8
, "make-char8", 1, 0, 1)
178 PUSH (SCM_MAKE_CHAR (v
));
179 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
180 contents of SCM_MAKE_CHAR may be evaluated more than once,
181 resulting in a double fetch. */
185 VM_DEFINE_INSTRUCTION (16, make_char32
, "make-char32", 4, 0, 1)
189 v
<<= 8; v
+= FETCH ();
190 v
<<= 8; v
+= FETCH ();
191 v
<<= 8; v
+= FETCH ();
192 PUSH (SCM_MAKE_CHAR (v
));
198 VM_DEFINE_INSTRUCTION (17, list
, "list", 2, -1, 1)
200 unsigned h
= FETCH ();
201 unsigned l
= FETCH ();
202 unsigned len
= ((h
<< 8) + l
);
207 VM_DEFINE_INSTRUCTION (18, vector
, "vector", 2, -1, 1)
209 unsigned h
= FETCH ();
210 unsigned l
= FETCH ();
211 unsigned len
= ((h
<< 8) + l
);
217 vect
= scm_make_vector (scm_from_uint (len
), SCM_BOOL_F
);
218 memcpy (SCM_I_VECTOR_WELTS(vect
), sp
, sizeof(SCM
) * len
);
230 #define OBJECT_REF(i) objects[i]
231 #define OBJECT_SET(i,o) objects[i] = o
233 #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
234 #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
236 /* For the variable operations, we _must_ obviously avoid function calls to
237 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
238 nothing more than the corresponding macros. */
239 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
240 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
241 #define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
243 #define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
247 VM_DEFINE_INSTRUCTION (19, object_ref
, "object-ref", 1, 0, 1)
249 register unsigned objnum
= FETCH ();
250 CHECK_OBJECT (objnum
);
251 PUSH (OBJECT_REF (objnum
));
255 /* FIXME: necessary? elt 255 of the vector could be a vector... */
256 VM_DEFINE_INSTRUCTION (20, long_object_ref
, "long-object-ref", 2, 0, 1)
258 unsigned int objnum
= FETCH ();
261 CHECK_OBJECT (objnum
);
262 PUSH (OBJECT_REF (objnum
));
266 VM_DEFINE_INSTRUCTION (21, local_ref
, "local-ref", 1, 0, 1)
268 PUSH (LOCAL_REF (FETCH ()));
273 VM_DEFINE_INSTRUCTION (22, long_local_ref
, "long-local-ref", 2, 0, 1)
275 unsigned int i
= FETCH ();
278 PUSH (LOCAL_REF (i
));
283 VM_DEFINE_INSTRUCTION (23, local_bound
, "local-bound?", 1, 0, 1)
285 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (FETCH ()), SCM_UNDEFINED
)));
289 VM_DEFINE_INSTRUCTION (24, long_local_bound
, "long-local-bound?", 2, 0, 1)
291 unsigned int i
= FETCH ();
294 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (i
), SCM_UNDEFINED
)));
298 VM_DEFINE_INSTRUCTION (25, variable_ref
, "variable-ref", 0, 1, 1)
302 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
303 unlike in top-variable-ref, it really isn't an internal assertion
304 that can be optimized out -- the variable could be coming directly
306 VM_ASSERT (SCM_VARIABLEP (x
),
307 vm_error_not_a_variable ("variable-ref", x
));
309 if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x
)))
314 /* Attempt to provide the variable name in the error message. */
315 var_name
= scm_module_reverse_lookup (scm_current_module (), x
);
316 vm_error_unbound (program
, scm_is_true (var_name
) ? var_name
: x
);
320 SCM o
= VARIABLE_REF (x
);
327 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
331 VM_ASSERT (SCM_VARIABLEP (x
),
332 vm_error_not_a_variable ("variable-bound?", x
));
334 *sp
= scm_from_bool (VARIABLE_BOUNDP (x
));
338 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
340 unsigned objnum
= FETCH ();
342 CHECK_OBJECT (objnum
);
343 what
= OBJECT_REF (objnum
);
345 if (!SCM_VARIABLEP (what
))
348 resolved
= resolve_variable (what
, scm_program_module (program
));
349 VM_ASSERT (VARIABLE_BOUNDP (resolved
), vm_error_unbound (program
, what
));
351 OBJECT_SET (objnum
, what
);
354 PUSH (VARIABLE_REF (what
));
358 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
361 unsigned int objnum
= FETCH ();
364 CHECK_OBJECT (objnum
);
365 what
= OBJECT_REF (objnum
);
367 if (!SCM_VARIABLEP (what
))
370 resolved
= resolve_variable (what
, scm_program_module (program
));
371 VM_ASSERT (VARIABLE_BOUNDP (resolved
),
372 vm_error_unbound (program
, what
));
374 OBJECT_SET (objnum
, what
);
377 PUSH (VARIABLE_REF (what
));
383 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
387 LOCAL_SET (FETCH (), x
);
391 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
394 unsigned int i
= FETCH ();
402 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
404 VM_ASSERT (SCM_VARIABLEP (sp
[0]),
405 vm_error_not_a_variable ("variable-set!", sp
[0]));
406 VARIABLE_SET (sp
[0], sp
[-1]);
411 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
413 unsigned objnum
= FETCH ();
415 CHECK_OBJECT (objnum
);
416 what
= OBJECT_REF (objnum
);
418 if (!SCM_VARIABLEP (what
))
421 what
= resolve_variable (what
, scm_program_module (program
));
422 OBJECT_SET (objnum
, what
);
425 VARIABLE_SET (what
, *sp
);
430 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
433 unsigned int objnum
= FETCH ();
436 CHECK_OBJECT (objnum
);
437 what
= OBJECT_REF (objnum
);
439 if (!SCM_VARIABLEP (what
))
442 what
= resolve_variable (what
, scm_program_module (program
));
443 OBJECT_SET (objnum
, what
);
446 VARIABLE_SET (what
, *sp
);
456 /* offset must be at least 24 bits wide, and signed */
457 #define FETCH_OFFSET(offset) \
459 offset = FETCH () << 16; \
460 offset += FETCH () << 8; \
461 offset += FETCH (); \
462 offset -= (offset & (1<<23)) << 1; \
467 scm_t_int32 offset; \
468 FETCH_OFFSET (offset); \
472 VM_HANDLE_INTERRUPTS; \
476 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
479 FETCH_OFFSET (offset
);
482 VM_HANDLE_INTERRUPTS
;
486 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
490 BR (scm_is_true (x
));
493 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
497 BR (scm_is_false (x
));
500 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
504 BR (scm_is_eq (x
, y
));
507 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
511 BR (!scm_is_eq (x
, y
));
514 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
518 BR (scm_is_null (x
));
521 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
525 BR (!scm_is_null (x
));
533 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
539 FETCH_OFFSET (offset
);
540 if (sp
- (fp
- 1) != n
)
545 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
551 FETCH_OFFSET (offset
);
552 if (sp
- (fp
- 1) < n
)
557 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
564 FETCH_OFFSET (offset
);
565 if (sp
- (fp
- 1) > n
)
570 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
575 VM_ASSERT (sp
- (fp
- 1) == n
,
576 vm_error_wrong_num_args (program
));
580 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
585 VM_ASSERT (sp
- (fp
- 1) >= n
,
586 vm_error_wrong_num_args (program
));
590 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
595 while (sp
- (fp
- 1) < n
)
596 PUSH (SCM_UNDEFINED
);
600 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
603 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
604 nreq
= FETCH () << 8;
606 nreq_and_opt
= FETCH () << 8;
607 nreq_and_opt
+= FETCH ();
608 ntotal
= FETCH () << 8;
611 /* look in optionals for first keyword or last positional */
612 /* starting after the last required positional arg */
614 while (/* while we have args */
616 /* and we still have positionals to fill */
617 && walk
- fp
< nreq_and_opt
618 /* and we haven't reached a keyword yet */
619 && !scm_is_keyword (*walk
))
620 /* bind this optional arg (by leaving it in place) */
622 /* now shuffle up, from walk to ntotal */
624 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
625 sp
= (fp
- 1) + ntotal
+ nshuf
;
627 for (i
= 0; i
< nshuf
; i
++)
628 sp
[-i
] = walk
[nshuf
-i
-1];
630 /* and fill optionals & keyword args with SCM_UNDEFINED */
631 while (walk
<= (fp
- 1) + ntotal
)
632 *walk
++ = SCM_UNDEFINED
;
637 /* See also bind-optionals/shuffle-or-br below. */
639 /* Flags that determine whether other keywords are allowed, and whether a
640 rest argument is expected. These values must match those used by the
641 glil->assembly compiler. */
642 #define F_ALLOW_OTHER_KEYS 1
645 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
649 int kw_and_rest_flags
;
653 /* XXX: We don't actually use NKW. */
656 kw_and_rest_flags
= FETCH ();
658 VM_ASSERT ((kw_and_rest_flags
& F_REST
)
659 || ((sp
- (fp
- 1) - nkw
) % 2) == 0,
660 vm_error_kwargs_length_not_even (program
))
663 kw
= OBJECT_REF (idx
);
665 /* Switch NKW to be a negative index below SP. */
666 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
670 if (scm_is_keyword (sp
[nkw
]))
672 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
674 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
676 SCM si
= SCM_CDAR (walk
);
677 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
682 VM_ASSERT (scm_is_pair (walk
)
683 || (kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
),
684 vm_error_kwargs_unrecognized_keyword (program
, sp
[nkw
]));
688 VM_ASSERT (kw_and_rest_flags
& F_REST
,
689 vm_error_kwargs_invalid_keyword (program
, sp
[nkw
]));
695 #undef F_ALLOW_OTHER_KEYS
699 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
705 while (sp
- (fp
- 1) > n
)
706 /* No need to check for underflow. */
707 CONS (rest
, *sp
--, rest
);
712 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
721 while (sp
- (fp
- 1) > n
)
722 /* No need to check for underflow. */
723 CONS (rest
, *sp
--, rest
);
728 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
741 *++old_sp
= SCM_UNDEFINED
;
744 NULLSTACK (old_sp
- sp
);
749 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
751 /* NB: if you change this, see frames.c:vm-frame-num-locals */
752 /* and frames.h, vm-engine.c, etc of course */
754 /* We don't initialize the dynamic link here because we don't actually
755 know that this frame will point to the current fp: it could be
756 placed elsewhere on the stack if captured in a partial
757 continuation, and invoked from some other context. */
758 PUSH (SCM_PACK (0)); /* dynamic link */
759 PUSH (SCM_PACK (0)); /* mvra */
760 PUSH (SCM_PACK (0)); /* ra */
764 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
769 VM_HANDLE_INTERRUPTS
;
776 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
777 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
778 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
779 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
780 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
781 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
784 PUSH_CONTINUATION_HOOK ();
788 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
792 ip
= SCM_C_OBJCODE_BASE (bp
);
798 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
803 VM_HANDLE_INTERRUPTS
;
807 #ifdef VM_ENABLE_STACK_NULLING
812 /* shuffle down the program and the arguments */
813 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
814 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
818 NULLSTACK (old_sp
- sp
);
823 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
827 ip
= SCM_C_OBJCODE_BASE (bp
);
833 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
841 subr
= SCM_POINTER_VALUE (pointer
);
843 VM_HANDLE_INTERRUPTS
;
855 ret
= subr (sp
[-1], sp
[0]);
858 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
861 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
864 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
867 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
870 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
873 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
876 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
879 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
885 NULLSTACK_FOR_NONLOCAL_EXIT ();
887 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
889 /* multiple values returned to continuation */
890 ret
= scm_struct_ref (ret
, SCM_INUM0
);
891 nvalues
= scm_ilength (ret
);
892 PUSH_LIST (ret
, scm_is_null
);
893 goto vm_return_values
;
902 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
909 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
911 VM_HANDLE_INTERRUPTS
;
920 ret
= subr (smob
, sp
[0]);
923 ret
= subr (smob
, sp
[-1], sp
[0]);
926 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
932 NULLSTACK_FOR_NONLOCAL_EXIT ();
934 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
936 /* multiple values returned to continuation */
937 ret
= scm_struct_ref (ret
, SCM_INUM0
);
938 nvalues
= scm_ilength (ret
);
939 PUSH_LIST (ret
, scm_is_null
);
940 goto vm_return_values
;
949 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
955 VM_HANDLE_INTERRUPTS
;
958 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
960 NULLSTACK_FOR_NONLOCAL_EXIT ();
962 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
964 /* multiple values returned to continuation */
965 ret
= scm_struct_ref (ret
, SCM_INUM0
);
966 nvalues
= scm_ilength (ret
);
967 PUSH_LIST (ret
, scm_is_null
);
968 goto vm_return_values
;
977 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
983 scm_i_check_continuation (contregs
);
984 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
985 scm_i_contregs_vm_cont (contregs
),
987 scm_i_reinstate_continuation (contregs
);
993 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
995 SCM vmcont
, intwinds
, prevwinds
;
996 POP2 (intwinds
, vmcont
);
998 VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont
),
999 vm_error_continuation_not_rewindable (vmcont
));
1000 prevwinds
= scm_i_dynwinds ();
1001 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1004 /* Rewind prompt jmpbuffers, if any. */
1006 SCM winds
= scm_i_dynwinds ();
1007 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1008 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1013 program
= SCM_FRAME_PROGRAM (fp
);
1018 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1022 nargs
= scm_to_int (x
);
1023 /* FIXME: should truncate values? */
1027 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1031 nargs
= scm_to_int (x
);
1032 /* FIXME: should truncate values? */
1036 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1043 FETCH_OFFSET (offset
);
1046 VM_HANDLE_INTERRUPTS
;
1048 fp
= sp
- nargs
+ 1;
1050 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1051 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1052 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1053 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1054 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1055 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1057 PUSH_CONTINUATION_HOOK ();
1061 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1065 ip
= SCM_C_OBJCODE_BASE (bp
);
1071 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1078 ASSERT (nargs
>= 2);
1080 len
= scm_ilength (ls
);
1081 VM_ASSERT (len
>= 0,
1082 vm_error_apply_to_non_list (ls
));
1083 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1089 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1096 ASSERT (nargs
>= 2);
1098 len
= scm_ilength (ls
);
1099 VM_ASSERT (len
>= 0,
1100 vm_error_apply_to_non_list (ls
));
1101 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1107 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1110 SCM proc
, vm_cont
, cont
;
1113 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1114 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1117 PUSH (SCM_PACK (0)); /* dynamic link */
1118 PUSH (SCM_PACK (0)); /* mvra */
1119 PUSH (SCM_PACK (0)); /* ra */
1127 /* Otherwise, the vm continuation was reinstated, and
1128 vm_return_to_continuation pushed on one value. We know only one
1129 value was returned because we are in value context -- the
1130 previous block jumped to vm_call, not vm_mv_call, after all.
1132 So, pull our regs back down from the vp, and march on to the
1133 next instruction. */
1135 program
= SCM_FRAME_PROGRAM (fp
);
1137 RESTORE_CONTINUATION_HOOK ();
1142 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1145 SCM proc
, vm_cont
, cont
;
1148 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1150 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1151 SCM_FRAME_DYNAMIC_LINK (fp
),
1152 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1153 SCM_FRAME_RETURN_ADDRESS (fp
),
1154 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1156 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1166 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1167 does a return from the frame, either to the RA or
1170 program
= SCM_FRAME_PROGRAM (fp
);
1172 /* Unfortunately we don't know whether we are at the RA, and thus
1173 have one value without an nvalues marker, or we are at the
1174 MVRA and thus have multiple values and the nvalues
1175 marker. Instead of adding heuristics here, we will let hook
1176 client code do that. */
1177 RESTORE_CONTINUATION_HOOK ();
1182 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1185 POP_CONTINUATION_HOOK (1);
1187 VM_HANDLE_INTERRUPTS
;
1194 #ifdef VM_ENABLE_STACK_NULLING
1198 /* Restore registers */
1199 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1200 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1201 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1203 #ifdef VM_ENABLE_STACK_NULLING
1204 NULLSTACK (old_sp
- sp
);
1207 /* Set return value (sp is already pushed) */
1211 /* Restore the last program */
1212 program
= SCM_FRAME_PROGRAM (fp
);
1218 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1220 /* nvalues declared at top level, because for some reason gcc seems to think
1221 that perhaps it might be used without declaration. Fooey to that, I say. */
1224 POP_CONTINUATION_HOOK (nvalues
);
1226 VM_HANDLE_INTERRUPTS
;
1228 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1230 /* A multiply-valued continuation */
1231 SCM
*vals
= sp
- nvalues
;
1233 /* Restore registers */
1234 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1235 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1236 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1238 /* Push return values, and the number of values */
1239 for (i
= 0; i
< nvalues
; i
++)
1241 *++sp
= SCM_I_MAKINUM (nvalues
);
1243 /* Finally null the end of the stack */
1244 NULLSTACK (vals
+ nvalues
- sp
);
1246 else if (nvalues
>= 1)
1248 /* Multiple values for a single-valued continuation -- here's where I
1249 break with guile tradition and try and do something sensible. (Also,
1250 this block handles the single-valued return to an mv
1252 SCM
*vals
= sp
- nvalues
;
1253 /* Restore registers */
1254 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1255 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1256 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1258 /* Push first value */
1261 /* Finally null the end of the stack */
1262 NULLSTACK (vals
+ nvalues
- sp
);
1267 vm_error_no_values ();
1270 /* Restore the last program */
1271 program
= SCM_FRAME_PROGRAM (fp
);
1277 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1282 ASSERT (nvalues
>= 1);
1286 while (scm_is_pair (l
))
1292 VM_ASSERT (SCM_NULL_OR_NIL_P (l
), vm_error_improper_list (l
));
1294 goto vm_return_values
;
1297 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1301 nvalues
= scm_to_int (n
);
1302 ASSERT (nvalues
>= 0);
1303 goto vm_return_values
;
1306 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1311 nvalues
= scm_to_int (x
);
1318 VM_ASSERT (nvalues
>= nbinds
, vm_error_not_enough_values ());
1321 POP_LIST (nvalues
- nbinds
);
1323 DROPN (nvalues
- nbinds
);
1328 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1333 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1338 (let ((a *undef*) (b *undef*) ...)
1339 (set! a (lambda () (b ...)))
1342 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1345 LOCAL_SET (FETCH (),
1346 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1350 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1352 SCM v
= LOCAL_REF (FETCH ());
1353 ASSERT_BOUND_VARIABLE (v
);
1354 PUSH (VARIABLE_REF (v
));
1358 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1361 v
= LOCAL_REF (FETCH ());
1363 ASSERT_VARIABLE (v
);
1364 VARIABLE_SET (v
, val
);
1368 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1370 scm_t_uint8 idx
= FETCH ();
1372 CHECK_FREE_VARIABLE (idx
);
1373 PUSH (FREE_VARIABLE_REF (idx
));
1377 /* no free-set -- if a var is assigned, it should be in a box */
1379 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1382 scm_t_uint8 idx
= FETCH ();
1383 CHECK_FREE_VARIABLE (idx
);
1384 v
= FREE_VARIABLE_REF (idx
);
1385 ASSERT_BOUND_VARIABLE (v
);
1386 PUSH (VARIABLE_REF (v
));
1390 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1393 scm_t_uint8 idx
= FETCH ();
1395 CHECK_FREE_VARIABLE (idx
);
1396 v
= FREE_VARIABLE_REF (idx
);
1397 ASSERT_BOUND_VARIABLE (v
);
1398 VARIABLE_SET (v
, val
);
1402 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1411 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1412 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1413 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1415 for (n
= 0; n
< len
; n
++)
1416 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1421 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1424 /* fixme underflow */
1425 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1429 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1432 unsigned int i
= FETCH ();
1436 /* FIXME CHECK_LOCAL (i) */
1438 /* FIXME ASSERT_PROGRAM (x); */
1439 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1440 for (n
= 0; n
< len
; n
++)
1441 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1446 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1451 scm_define (sym
, val
);
1455 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1459 *sp
= scm_symbol_to_keyword (*sp
);
1463 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1467 *sp
= scm_string_to_symbol (*sp
);
1471 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1474 scm_t_uint8 escape_only_p
;
1477 escape_only_p
= FETCH ();
1478 FETCH_OFFSET (offset
);
1482 /* Push the prompt onto the dynamic stack. */
1483 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1485 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1486 if (SCM_PROMPT_SETJMP (prompt
))
1488 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1491 Note, at this point, we must assume that any variable local to
1492 vm_engine that can be assigned *has* been assigned. So we need to pull
1493 all our state back from the ip/fp/sp.
1496 program
= SCM_FRAME_PROGRAM (fp
);
1498 /* The stack contains the values returned to this prompt, along
1499 with a number-of-values marker -- like an MV return. */
1500 ABORT_CONTINUATION_HOOK ();
1504 /* Otherwise setjmp returned for the first time, so we go to execute the
1509 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1512 POP2 (unwind
, wind
);
1514 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1515 are actually called; the compiler should emit calls to wind and unwind for
1516 the normal dynamic-wind control flow. */
1517 VM_ASSERT (scm_to_bool (scm_thunk_p (wind
)),
1518 vm_error_not_a_thunk ("dynamic-wind", wind
));
1519 VM_ASSERT (scm_to_bool (scm_thunk_p (unwind
)),
1520 vm_error_not_a_thunk ("dynamic-wind", unwind
));
1521 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1525 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1527 unsigned n
= FETCH ();
1529 PRE_CHECK_UNDERFLOW (n
+ 2);
1530 vm_abort (vm
, n
, vm_cookie
);
1531 /* vm_abort should not return */
1535 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1537 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1538 off of the dynamic stack. */
1539 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1543 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1545 unsigned n
= FETCH ();
1551 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1554 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1555 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1559 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1562 wf
= scm_car (scm_i_dynwinds ());
1563 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1564 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1568 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1574 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1575 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1576 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1578 /* Punt dynstate expansion and error handling to the C proc. */
1580 *sp
= scm_fluid_ref (*sp
);
1584 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1585 if (scm_is_eq (val
, SCM_UNDEFINED
))
1586 val
= SCM_I_FLUID_DEFAULT (*sp
);
1587 VM_ASSERT (!scm_is_eq (val
, SCM_UNDEFINED
),
1588 vm_error_unbound_fluid (program
, *sp
));
1595 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1598 SCM val
, fluid
, fluids
;
1601 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1602 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1603 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1605 /* Punt dynstate expansion and error handling to the C proc. */
1607 scm_fluid_set_x (fluid
, val
);
1610 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1615 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1620 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1623 VM_ASSERT (sp
- (fp
- 1) == (n
& 0x7),
1624 vm_error_wrong_num_args (program
));
1630 *++old_sp
= SCM_UNDEFINED
;
1635 /* Like bind-optionals/shuffle, but if there are too many positional
1636 arguments, jumps to the next case-lambda clause. */
1637 VM_DEFINE_INSTRUCTION (94, bind_optionals_shuffle_or_br
, "bind-optionals/shuffle-or-br", 9, -1, -1)
1640 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
1642 nreq
= FETCH () << 8;
1644 nreq_and_opt
= FETCH () << 8;
1645 nreq_and_opt
+= FETCH ();
1646 ntotal
= FETCH () << 8;
1648 FETCH_OFFSET (offset
);
1650 /* look in optionals for first keyword or last positional */
1651 /* starting after the last required positional arg */
1653 while (/* while we have args */
1655 /* and we still have positionals to fill */
1656 && walk
- fp
< nreq_and_opt
1657 /* and we haven't reached a keyword yet */
1658 && !scm_is_keyword (*walk
))
1659 /* bind this optional arg (by leaving it in place) */
1661 if (/* If we have filled all the positionals */
1662 walk
- fp
== nreq_and_opt
1663 /* and there are still more arguments */
1665 /* and the next argument is not a keyword, */
1666 && !scm_is_keyword (*walk
))
1668 /* Jump to the next case-lambda* clause. */
1673 /* Otherwise, finish as in bind-optionals/shuffle: shuffle up,
1674 from walk to ntotal */
1675 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
1676 sp
= (fp
- 1) + ntotal
+ nshuf
;
1678 for (i
= 0; i
< nshuf
; i
++)
1679 sp
[-i
] = walk
[nshuf
-i
-1];
1681 /* and fill optionals & keyword args with SCM_UNDEFINED */
1682 while (walk
<= (fp
- 1) + ntotal
)
1683 *walk
++ = SCM_UNDEFINED
;
1691 (defun renumber-ops ()
1692 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1695 (let ((counter -1)) (goto-char (point-min))
1696 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1698 (number-to-string (setq counter (1+ counter)))