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
));
528 VM_DEFINE_INSTRUCTION (41, br_if_nil
, "br-if-nil", 3, 0, 0)
532 BR (scm_is_lisp_false (x
));
535 VM_DEFINE_INSTRUCTION (42, br_if_not_nil
, "br-if-not-nil", 3, 0, 0)
539 BR (!scm_is_lisp_false (x
));
549 VM_DEFINE_INSTRUCTION (43, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
555 FETCH_OFFSET (offset
);
556 if (sp
- (fp
- 1) != n
)
561 VM_DEFINE_INSTRUCTION (44, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
567 FETCH_OFFSET (offset
);
568 if (sp
- (fp
- 1) < n
)
573 VM_DEFINE_INSTRUCTION (45, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
580 FETCH_OFFSET (offset
);
581 if (sp
- (fp
- 1) > n
)
586 VM_DEFINE_INSTRUCTION (46, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
591 VM_ASSERT (sp
- (fp
- 1) == n
,
592 vm_error_wrong_num_args (program
));
596 VM_DEFINE_INSTRUCTION (47, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
601 VM_ASSERT (sp
- (fp
- 1) >= n
,
602 vm_error_wrong_num_args (program
));
606 VM_DEFINE_INSTRUCTION (48, bind_optionals
, "bind-optionals", 2, -1, -1)
611 while (sp
- (fp
- 1) < n
)
612 PUSH (SCM_UNDEFINED
);
616 VM_DEFINE_INSTRUCTION (49, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
619 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
620 nreq
= FETCH () << 8;
622 nreq_and_opt
= FETCH () << 8;
623 nreq_and_opt
+= FETCH ();
624 ntotal
= FETCH () << 8;
627 /* look in optionals for first keyword or last positional */
628 /* starting after the last required positional arg */
630 while (/* while we have args */
632 /* and we still have positionals to fill */
633 && walk
- fp
< nreq_and_opt
634 /* and we haven't reached a keyword yet */
635 && !scm_is_keyword (*walk
))
636 /* bind this optional arg (by leaving it in place) */
638 /* now shuffle up, from walk to ntotal */
640 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
641 sp
= (fp
- 1) + ntotal
+ nshuf
;
643 for (i
= 0; i
< nshuf
; i
++)
644 sp
[-i
] = walk
[nshuf
-i
-1];
646 /* and fill optionals & keyword args with SCM_UNDEFINED */
647 while (walk
<= (fp
- 1) + ntotal
)
648 *walk
++ = SCM_UNDEFINED
;
653 /* See also bind-optionals/shuffle-or-br below. */
655 /* Flags that determine whether other keywords are allowed, and whether a
656 rest argument is expected. These values must match those used by the
657 glil->assembly compiler. */
658 #define F_ALLOW_OTHER_KEYS 1
661 VM_DEFINE_INSTRUCTION (50, bind_kwargs
, "bind-kwargs", 5, 0, 0)
665 int kw_and_rest_flags
;
669 /* XXX: We don't actually use NKW. */
672 kw_and_rest_flags
= FETCH ();
674 VM_ASSERT ((kw_and_rest_flags
& F_REST
)
675 || ((sp
- (fp
- 1) - nkw
) % 2) == 0,
676 vm_error_kwargs_length_not_even (program
))
679 kw
= OBJECT_REF (idx
);
681 /* Switch NKW to be a negative index below SP. */
682 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
686 if (scm_is_keyword (sp
[nkw
]))
688 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
690 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
692 SCM si
= SCM_CDAR (walk
);
693 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
698 VM_ASSERT (scm_is_pair (walk
)
699 || (kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
),
700 vm_error_kwargs_unrecognized_keyword (program
));
704 VM_ASSERT (kw_and_rest_flags
& F_REST
,
705 vm_error_kwargs_invalid_keyword (program
));
711 #undef F_ALLOW_OTHER_KEYS
715 VM_DEFINE_INSTRUCTION (51, push_rest
, "push-rest", 2, -1, -1)
722 while (sp
- (fp
- 1) > n
)
723 /* No need to check for underflow. */
724 rest
= scm_cons (*sp
--, rest
);
729 VM_DEFINE_INSTRUCTION (52, bind_rest
, "bind-rest", 4, -1, -1)
739 while (sp
- (fp
- 1) > n
)
740 /* No need to check for underflow. */
741 rest
= scm_cons (*sp
--, rest
);
746 VM_DEFINE_INSTRUCTION (53, reserve_locals
, "reserve-locals", 2, -1, -1)
759 *++old_sp
= SCM_UNDEFINED
;
762 NULLSTACK (old_sp
- sp
);
767 VM_DEFINE_INSTRUCTION (54, new_frame
, "new-frame", 0, 0, 3)
769 /* NB: if you change this, see frames.c:vm-frame-num-locals */
770 /* and frames.h, vm-engine.c, etc of course */
772 /* We don't initialize the dynamic link here because we don't actually
773 know that this frame will point to the current fp: it could be
774 placed elsewhere on the stack if captured in a partial
775 continuation, and invoked from some other context. */
776 PUSH (SCM_PACK (0)); /* dynamic link */
777 PUSH (SCM_PACK (0)); /* mvra */
778 PUSH (SCM_PACK (0)); /* ra */
782 VM_DEFINE_INSTRUCTION (55, call
, "call", 1, -1, 1)
787 VM_HANDLE_INTERRUPTS
;
794 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
795 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
796 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
797 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
798 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
799 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
802 PUSH_CONTINUATION_HOOK ();
806 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
810 ip
= SCM_C_OBJCODE_BASE (bp
);
816 VM_DEFINE_INSTRUCTION (56, tail_call
, "tail-call", 1, -1, 1)
821 VM_HANDLE_INTERRUPTS
;
825 #ifdef VM_ENABLE_STACK_NULLING
830 /* shuffle down the program and the arguments */
831 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
832 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
836 NULLSTACK (old_sp
- sp
);
841 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
845 ip
= SCM_C_OBJCODE_BASE (bp
);
851 VM_DEFINE_INSTRUCTION (57, subr_call
, "subr-call", 1, -1, -1)
859 subr
= SCM_POINTER_VALUE (pointer
);
861 VM_HANDLE_INTERRUPTS
;
873 ret
= subr (sp
[-1], sp
[0]);
876 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
879 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
882 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
885 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
888 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
891 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
894 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
897 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
903 NULLSTACK_FOR_NONLOCAL_EXIT ();
905 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
907 /* multiple values returned to continuation */
908 ret
= scm_struct_ref (ret
, SCM_INUM0
);
909 nvalues
= scm_ilength (ret
);
910 PUSH_LIST (ret
, scm_is_null
);
911 goto vm_return_values
;
920 /* Instruction 58 used to be smob-call. */
922 VM_DEFINE_INSTRUCTION (59, foreign_call
, "foreign-call", 1, -1, -1)
928 VM_HANDLE_INTERRUPTS
;
931 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
933 NULLSTACK_FOR_NONLOCAL_EXIT ();
935 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
937 /* multiple values returned to continuation */
938 ret
= scm_struct_ref (ret
, SCM_INUM0
);
939 nvalues
= scm_ilength (ret
);
940 PUSH_LIST (ret
, scm_is_null
);
941 goto vm_return_values
;
950 VM_DEFINE_INSTRUCTION (60, continuation_call
, "continuation-call", 0, -1, 0)
956 scm_i_check_continuation (contregs
);
957 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
958 scm_i_contregs_vm_cont (contregs
),
960 scm_i_reinstate_continuation (contregs
);
966 VM_DEFINE_INSTRUCTION (61, partial_cont_call
, "partial-cont-call", 0, -1, 0)
971 VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont
),
972 vm_error_continuation_not_rewindable (vmcont
));
973 vm_reinstate_partial_continuation (vm
, vmcont
, sp
+ 1 - fp
, fp
,
974 ¤t_thread
->dynstack
,
978 program
= SCM_FRAME_PROGRAM (fp
);
983 VM_DEFINE_INSTRUCTION (62, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
987 nargs
= scm_to_int (x
);
988 /* FIXME: should truncate values? */
992 VM_DEFINE_INSTRUCTION (63, call_nargs
, "call/nargs", 0, 0, 1)
996 nargs
= scm_to_int (x
);
997 /* FIXME: should truncate values? */
1001 VM_DEFINE_INSTRUCTION (64, mv_call
, "mv-call", 4, -1, 1)
1008 FETCH_OFFSET (offset
);
1011 VM_HANDLE_INTERRUPTS
;
1013 fp
= sp
- nargs
+ 1;
1015 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1016 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1017 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1018 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1019 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1020 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1022 PUSH_CONTINUATION_HOOK ();
1026 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1030 ip
= SCM_C_OBJCODE_BASE (bp
);
1036 VM_DEFINE_INSTRUCTION (65, apply
, "apply", 1, -1, 1)
1043 ASSERT (nargs
>= 2);
1045 len
= scm_ilength (ls
);
1046 VM_ASSERT (len
>= 0,
1047 vm_error_apply_to_non_list (ls
));
1048 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1054 VM_DEFINE_INSTRUCTION (66, tail_apply
, "tail-apply", 1, -1, 1)
1061 ASSERT (nargs
>= 2);
1063 len
= scm_ilength (ls
);
1064 VM_ASSERT (len
>= 0,
1065 vm_error_apply_to_non_list (ls
));
1066 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1072 VM_DEFINE_INSTRUCTION (67, call_cc
, "call/cc", 0, 1, 1)
1075 SCM proc
, vm_cont
, cont
;
1076 scm_t_dynstack
*dynstack
;
1079 dynstack
= scm_dynstack_capture_all (¤t_thread
->dynstack
);
1080 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
,
1082 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1085 PUSH (SCM_PACK (0)); /* dynamic link */
1086 PUSH (SCM_PACK (0)); /* mvra */
1087 PUSH (SCM_PACK (0)); /* ra */
1095 /* Otherwise, the vm continuation was reinstated, and
1096 vm_return_to_continuation pushed on one value. We know only one
1097 value was returned because we are in value context -- the
1098 previous block jumped to vm_call, not vm_mv_call, after all.
1100 So, pull our regs back down from the vp, and march on to the
1101 next instruction. */
1103 program
= SCM_FRAME_PROGRAM (fp
);
1105 RESTORE_CONTINUATION_HOOK ();
1110 VM_DEFINE_INSTRUCTION (68, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1113 SCM proc
, vm_cont
, cont
;
1114 scm_t_dynstack
*dynstack
;
1117 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1119 dynstack
= scm_dynstack_capture_all (¤t_thread
->dynstack
);
1120 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1121 SCM_FRAME_DYNAMIC_LINK (fp
),
1122 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1123 SCM_FRAME_RETURN_ADDRESS (fp
),
1124 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1127 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1137 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1138 does a return from the frame, either to the RA or
1141 program
= SCM_FRAME_PROGRAM (fp
);
1143 /* Unfortunately we don't know whether we are at the RA, and thus
1144 have one value without an nvalues marker, or we are at the
1145 MVRA and thus have multiple values and the nvalues
1146 marker. Instead of adding heuristics here, we will let hook
1147 client code do that. */
1148 RESTORE_CONTINUATION_HOOK ();
1153 VM_DEFINE_INSTRUCTION (69, return, "return", 0, 1, 1)
1156 POP_CONTINUATION_HOOK (sp
, 1);
1158 VM_HANDLE_INTERRUPTS
;
1165 #ifdef VM_ENABLE_STACK_NULLING
1169 /* Restore registers */
1170 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1171 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1172 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1174 #ifdef VM_ENABLE_STACK_NULLING
1175 NULLSTACK (old_sp
- sp
);
1178 /* Set return value (sp is already pushed) */
1182 /* Restore the last program */
1183 program
= SCM_FRAME_PROGRAM (fp
);
1189 VM_DEFINE_INSTRUCTION (70, return_values
, "return/values", 1, -1, -1)
1191 /* nvalues declared at top level, because for some reason gcc seems to think
1192 that perhaps it might be used without declaration. Fooey to that, I say. */
1195 POP_CONTINUATION_HOOK (sp
+ 1 - nvalues
, nvalues
);
1197 VM_HANDLE_INTERRUPTS
;
1199 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1201 /* A multiply-valued continuation */
1202 SCM
*vals
= sp
- nvalues
;
1204 /* Restore registers */
1205 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1206 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1207 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1209 /* Push return values, and the number of values */
1210 for (i
= 0; i
< nvalues
; i
++)
1212 *++sp
= SCM_I_MAKINUM (nvalues
);
1214 /* Finally null the end of the stack */
1215 NULLSTACK (vals
+ nvalues
- sp
);
1217 else if (nvalues
>= 1)
1219 /* Multiple values for a single-valued continuation -- here's where I
1220 break with guile tradition and try and do something sensible. (Also,
1221 this block handles the single-valued return to an mv
1223 SCM
*vals
= sp
- nvalues
;
1224 /* Restore registers */
1225 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1226 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1227 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1229 /* Push first value */
1232 /* Finally null the end of the stack */
1233 NULLSTACK (vals
+ nvalues
- sp
);
1238 vm_error_no_values ();
1241 /* Restore the last program */
1242 program
= SCM_FRAME_PROGRAM (fp
);
1248 VM_DEFINE_INSTRUCTION (71, return_values_star
, "return/values*", 1, -1, -1)
1253 ASSERT (nvalues
>= 1);
1257 while (scm_is_pair (l
))
1263 VM_ASSERT (SCM_NULL_OR_NIL_P (l
), vm_error_improper_list (l
));
1265 goto vm_return_values
;
1268 VM_DEFINE_INSTRUCTION (72, return_nvalues
, "return/nvalues", 0, 1, -1)
1272 nvalues
= scm_to_int (n
);
1273 ASSERT (nvalues
>= 0);
1274 goto vm_return_values
;
1277 VM_DEFINE_INSTRUCTION (73, truncate_values
, "truncate-values", 2, -1, -1)
1282 nvalues
= scm_to_int (x
);
1289 VM_ASSERT (nvalues
>= nbinds
, vm_error_not_enough_values ());
1292 POP_LIST (nvalues
- nbinds
);
1294 DROPN (nvalues
- nbinds
);
1299 VM_DEFINE_INSTRUCTION (74, box
, "box", 1, 1, 0)
1304 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1309 (let ((a *undef*) (b *undef*) ...)
1310 (set! a (lambda () (b ...)))
1313 VM_DEFINE_INSTRUCTION (75, empty_box
, "empty-box", 1, 0, 0)
1316 LOCAL_SET (FETCH (),
1317 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1321 VM_DEFINE_INSTRUCTION (76, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1323 SCM v
= LOCAL_REF (FETCH ());
1324 ASSERT_BOUND_VARIABLE (v
);
1325 PUSH (VARIABLE_REF (v
));
1329 VM_DEFINE_INSTRUCTION (77, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1332 v
= LOCAL_REF (FETCH ());
1334 ASSERT_VARIABLE (v
);
1335 VARIABLE_SET (v
, val
);
1339 VM_DEFINE_INSTRUCTION (78, free_ref
, "free-ref", 1, 0, 1)
1341 scm_t_uint8 idx
= FETCH ();
1343 CHECK_FREE_VARIABLE (idx
);
1344 PUSH (FREE_VARIABLE_REF (idx
));
1348 /* no free-set -- if a var is assigned, it should be in a box */
1350 VM_DEFINE_INSTRUCTION (79, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
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
));
1361 VM_DEFINE_INSTRUCTION (80, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1364 scm_t_uint8 idx
= FETCH ();
1366 CHECK_FREE_VARIABLE (idx
);
1367 v
= FREE_VARIABLE_REF (idx
);
1368 ASSERT_BOUND_VARIABLE (v
);
1369 VARIABLE_SET (v
, val
);
1373 VM_DEFINE_INSTRUCTION (81, make_closure
, "make-closure", 2, -1, 1)
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
]));
1386 for (n
= 0; n
< len
; n
++)
1387 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1392 VM_DEFINE_INSTRUCTION (82, make_variable
, "make-variable", 0, 0, 1)
1395 /* fixme underflow */
1396 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1400 VM_DEFINE_INSTRUCTION (83, fix_closure
, "fix-closure", 2, -1, 0)
1403 unsigned int i
= FETCH ();
1407 /* FIXME CHECK_LOCAL (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
]);
1417 VM_DEFINE_INSTRUCTION (84, define
, "define", 0, 0, 2)
1422 scm_define (sym
, val
);
1426 VM_DEFINE_INSTRUCTION (85, make_keyword
, "make-keyword", 0, 1, 1)
1430 *sp
= scm_symbol_to_keyword (*sp
);
1434 VM_DEFINE_INSTRUCTION (86, make_symbol
, "make-symbol", 0, 1, 1)
1438 *sp
= scm_string_to_symbol (*sp
);
1442 VM_DEFINE_INSTRUCTION (87, prompt
, "prompt", 4, 2, 0)
1445 scm_t_uint8 escape_only_p
;
1447 scm_t_dynstack_prompt_flags flags
;
1449 escape_only_p
= FETCH ();
1450 FETCH_OFFSET (offset
);
1454 /* Push the prompt onto the dynamic stack. */
1455 flags
= escape_only_p
? SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
: 0;
1456 scm_dynstack_push_prompt (¤t_thread
->dynstack
, flags
, k
,
1457 fp
, sp
, ip
+ offset
, ®isters
);
1461 VM_DEFINE_INSTRUCTION (88, wind
, "wind", 0, 2, 0)
1464 POP2 (unwind
, wind
);
1466 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1467 are actually called; the compiler should emit calls to wind and unwind for
1468 the normal dynamic-wind control flow. Also note that the compiler
1469 should have inserted checks that they wind and unwind procs are
1470 thunks, if it could not prove that to be the case. */
1471 scm_dynstack_push_dynwind (¤t_thread
->dynstack
, wind
, unwind
);
1475 VM_DEFINE_INSTRUCTION (89, abort
, "abort", 1, -1, -1)
1477 unsigned n
= FETCH ();
1479 PRE_CHECK_UNDERFLOW (n
+ 2);
1480 vm_abort (vm
, n
, ®isters
);
1481 /* vm_abort should not return */
1485 VM_DEFINE_INSTRUCTION (90, unwind
, "unwind", 0, 0, 0)
1487 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1488 off of the dynamic stack. */
1489 scm_dynstack_pop (¤t_thread
->dynstack
);
1493 VM_DEFINE_INSTRUCTION (91, push_fluid
, "push-fluid", 0, 2, 0)
1498 scm_dynstack_push_fluids (¤t_thread
->dynstack
, 1, &fluid
, &val
,
1499 current_thread
->dynamic_state
);
1503 VM_DEFINE_INSTRUCTION (92, pop_fluid
, "pop-fluid", 0, 0, 0)
1505 /* This function must not allocate. */
1506 scm_dynstack_unwind_fluids (¤t_thread
->dynstack
,
1507 current_thread
->dynamic_state
);
1511 VM_DEFINE_INSTRUCTION (93, fluid_ref
, "fluid-ref", 0, 1, 1)
1517 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1518 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1519 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1521 /* Punt dynstate expansion and error handling to the C proc. */
1523 *sp
= scm_fluid_ref (*sp
);
1527 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1528 if (scm_is_eq (val
, SCM_UNDEFINED
))
1529 val
= SCM_I_FLUID_DEFAULT (*sp
);
1530 VM_ASSERT (!scm_is_eq (val
, SCM_UNDEFINED
),
1531 vm_error_unbound_fluid (program
, *sp
));
1538 VM_DEFINE_INSTRUCTION (94, fluid_set
, "fluid-set", 0, 2, 0)
1541 SCM val
, fluid
, fluids
;
1544 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1545 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1546 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1548 /* Punt dynstate expansion and error handling to the C proc. */
1550 scm_fluid_set_x (fluid
, val
);
1553 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1558 VM_DEFINE_INSTRUCTION (95, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1563 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1566 VM_ASSERT (sp
- (fp
- 1) == (n
& 0x7),
1567 vm_error_wrong_num_args (program
));
1573 *++old_sp
= SCM_UNDEFINED
;
1578 /* Like bind-optionals/shuffle, but if there are too many positional
1579 arguments, jumps to the next case-lambda clause. */
1580 VM_DEFINE_INSTRUCTION (96, bind_optionals_shuffle_or_br
, "bind-optionals/shuffle-or-br", 9, -1, -1)
1583 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
1585 nreq
= FETCH () << 8;
1587 nreq_and_opt
= FETCH () << 8;
1588 nreq_and_opt
+= FETCH ();
1589 ntotal
= FETCH () << 8;
1591 FETCH_OFFSET (offset
);
1593 /* look in optionals for first keyword or last positional */
1594 /* starting after the last required positional arg */
1596 while (/* while we have args */
1598 /* and we still have positionals to fill */
1599 && walk
- fp
< nreq_and_opt
1600 /* and we haven't reached a keyword yet */
1601 && !scm_is_keyword (*walk
))
1602 /* bind this optional arg (by leaving it in place) */
1604 if (/* If we have filled all the positionals */
1605 walk
- fp
== nreq_and_opt
1606 /* and there are still more arguments */
1608 /* and the next argument is not a keyword, */
1609 && !scm_is_keyword (*walk
))
1611 /* Jump to the next case-lambda* clause. */
1616 /* Otherwise, finish as in bind-optionals/shuffle: shuffle up,
1617 from walk to ntotal */
1618 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
1619 sp
= (fp
- 1) + ntotal
+ nshuf
;
1621 for (i
= 0; i
< nshuf
; i
++)
1622 sp
[-i
] = walk
[nshuf
-i
-1];
1624 /* and fill optionals & keyword args with SCM_UNDEFINED */
1625 while (walk
<= (fp
- 1) + ntotal
)
1626 *walk
++ = SCM_UNDEFINED
;
1634 (defun renumber-ops ()
1635 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1638 (let ((counter -1)) (goto-char (point-min))
1639 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1641 (number-to-string (setq counter (1+ counter)))