1 /* Copyright (C) 2001,2008,2009,2010,2011 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)
34 nvalues
= SCM_I_INUM (*sp
--);
43 finish_args
= scm_values (finish_args
);
47 #ifdef VM_ENABLE_STACK_NULLING
51 /* Restore registers */
52 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
53 /* Setting the ip here doesn't actually affect control flow, as the calling
54 code will restore its own registers, but it does help when walking the
56 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
57 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
58 NULLSTACK (old_sp
- sp
);
64 VM_DEFINE_INSTRUCTION (2, drop
, "drop", 0, 1, 0)
70 VM_DEFINE_INSTRUCTION (3, dup
, "dup", 0, 0, 1)
82 VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
84 PUSH (SCM_UNSPECIFIED
);
88 VM_DEFINE_INSTRUCTION (5, make_true
, "make-true", 0, 0, 1)
94 VM_DEFINE_INSTRUCTION (6, make_false
, "make-false", 0, 0, 1)
100 VM_DEFINE_INSTRUCTION (7, make_nil
, "make-nil", 0, 0, 1)
102 PUSH (SCM_ELISP_NIL
);
106 VM_DEFINE_INSTRUCTION (8, make_eol
, "make-eol", 0, 0, 1)
112 VM_DEFINE_INSTRUCTION (9, make_int8
, "make-int8", 1, 0, 1)
114 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
118 VM_DEFINE_INSTRUCTION (10, make_int8_0
, "make-int8:0", 0, 0, 1)
124 VM_DEFINE_INSTRUCTION (11, make_int8_1
, "make-int8:1", 0, 0, 1)
126 PUSH (SCM_I_MAKINUM (1));
130 VM_DEFINE_INSTRUCTION (12, make_int16
, "make-int16", 2, 0, 1)
134 PUSH (SCM_I_MAKINUM ((signed short) (h
<< 8) + l
));
138 VM_DEFINE_INSTRUCTION (13, make_int64
, "make-int64", 8, 0, 1)
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 v
<<= 8; v
+= FETCH ();
148 v
<<= 8; v
+= FETCH ();
149 PUSH (scm_from_int64 ((scm_t_int64
) v
));
153 VM_DEFINE_INSTRUCTION (14, make_uint64
, "make-uint64", 8, 0, 1)
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 v
<<= 8; v
+= FETCH ();
163 v
<<= 8; v
+= FETCH ();
164 PUSH (scm_from_uint64 (v
));
168 VM_DEFINE_INSTRUCTION (15, make_char8
, "make-char8", 1, 0, 1)
173 PUSH (SCM_MAKE_CHAR (v
));
174 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
175 contents of SCM_MAKE_CHAR may be evaluated more than once,
176 resulting in a double fetch. */
180 VM_DEFINE_INSTRUCTION (16, make_char32
, "make-char32", 4, 0, 1)
184 v
<<= 8; v
+= FETCH ();
185 v
<<= 8; v
+= FETCH ();
186 v
<<= 8; v
+= FETCH ();
187 PUSH (SCM_MAKE_CHAR (v
));
193 VM_DEFINE_INSTRUCTION (17, list
, "list", 2, -1, 1)
195 unsigned h
= FETCH ();
196 unsigned l
= FETCH ();
197 unsigned len
= ((h
<< 8) + l
);
202 VM_DEFINE_INSTRUCTION (18, vector
, "vector", 2, -1, 1)
204 unsigned h
= FETCH ();
205 unsigned l
= FETCH ();
206 unsigned len
= ((h
<< 8) + l
);
212 vect
= scm_make_vector (scm_from_uint (len
), SCM_BOOL_F
);
213 memcpy (SCM_I_VECTOR_WELTS(vect
), sp
, sizeof(SCM
) * len
);
225 #define OBJECT_REF(i) objects[i]
226 #define OBJECT_SET(i,o) objects[i] = o
228 #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
229 #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
231 /* For the variable operations, we _must_ obviously avoid function calls to
232 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
233 nothing more than the corresponding macros. */
234 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
235 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
236 #define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
238 #define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
242 VM_DEFINE_INSTRUCTION (19, object_ref
, "object-ref", 1, 0, 1)
244 register unsigned objnum
= FETCH ();
245 CHECK_OBJECT (objnum
);
246 PUSH (OBJECT_REF (objnum
));
250 /* FIXME: necessary? elt 255 of the vector could be a vector... */
251 VM_DEFINE_INSTRUCTION (20, long_object_ref
, "long-object-ref", 2, 0, 1)
253 unsigned int objnum
= FETCH ();
256 CHECK_OBJECT (objnum
);
257 PUSH (OBJECT_REF (objnum
));
261 VM_DEFINE_INSTRUCTION (21, local_ref
, "local-ref", 1, 0, 1)
263 PUSH (LOCAL_REF (FETCH ()));
268 VM_DEFINE_INSTRUCTION (22, long_local_ref
, "long-local-ref", 2, 0, 1)
270 unsigned int i
= FETCH ();
273 PUSH (LOCAL_REF (i
));
278 VM_DEFINE_INSTRUCTION (23, local_bound
, "local-bound?", 1, 0, 1)
280 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (FETCH ()), SCM_UNDEFINED
)));
284 VM_DEFINE_INSTRUCTION (24, long_local_bound
, "long-local-bound?", 2, 0, 1)
286 unsigned int i
= FETCH ();
289 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (i
), SCM_UNDEFINED
)));
293 VM_DEFINE_INSTRUCTION (25, variable_ref
, "variable-ref", 0, 1, 1)
297 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
298 unlike in top-variable-ref, it really isn't an internal assertion
299 that can be optimized out -- the variable could be coming directly
301 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
303 func_name
= "variable-ref";
305 goto vm_error_not_a_variable
;
307 else if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x
)))
311 /* Attempt to provide the variable name in the error message. */
312 var_name
= scm_module_reverse_lookup (scm_current_module (), x
);
313 finish_args
= scm_is_true (var_name
) ? var_name
: x
;
314 goto vm_error_unbound
;
318 SCM o
= VARIABLE_REF (x
);
325 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
329 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
331 func_name
= "variable-bound?";
333 goto vm_error_not_a_variable
;
336 *sp
= scm_from_bool (VARIABLE_BOUNDP (x
));
340 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
342 unsigned objnum
= FETCH ();
344 CHECK_OBJECT (objnum
);
345 what
= OBJECT_REF (objnum
);
347 if (!SCM_VARIABLEP (what
))
350 resolved
= resolve_variable (what
, scm_program_module (program
));
351 if (!VARIABLE_BOUNDP (resolved
))
354 goto vm_error_unbound
;
357 OBJECT_SET (objnum
, what
);
360 PUSH (VARIABLE_REF (what
));
364 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
367 unsigned int objnum
= FETCH ();
370 CHECK_OBJECT (objnum
);
371 what
= OBJECT_REF (objnum
);
373 if (!SCM_VARIABLEP (what
))
376 resolved
= resolve_variable (what
, scm_program_module (program
));
377 if (!VARIABLE_BOUNDP (resolved
))
380 goto vm_error_unbound
;
383 OBJECT_SET (objnum
, what
);
386 PUSH (VARIABLE_REF (what
));
392 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
396 LOCAL_SET (FETCH (), x
);
400 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
403 unsigned int i
= FETCH ();
411 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
413 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp
[0])))
415 func_name
= "variable-set!";
417 goto vm_error_not_a_variable
;
419 VARIABLE_SET (sp
[0], sp
[-1]);
424 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
426 unsigned objnum
= FETCH ();
428 CHECK_OBJECT (objnum
);
429 what
= OBJECT_REF (objnum
);
431 if (!SCM_VARIABLEP (what
))
434 what
= resolve_variable (what
, scm_program_module (program
));
435 OBJECT_SET (objnum
, what
);
438 VARIABLE_SET (what
, *sp
);
443 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
446 unsigned int objnum
= FETCH ();
449 CHECK_OBJECT (objnum
);
450 what
= OBJECT_REF (objnum
);
452 if (!SCM_VARIABLEP (what
))
455 what
= resolve_variable (what
, scm_program_module (program
));
456 OBJECT_SET (objnum
, what
);
459 VARIABLE_SET (what
, *sp
);
469 /* offset must be at least 24 bits wide, and signed */
470 #define FETCH_OFFSET(offset) \
472 offset = FETCH () << 16; \
473 offset += FETCH () << 8; \
474 offset += FETCH (); \
475 offset -= (offset & (1<<23)) << 1; \
480 scm_t_int32 offset; \
481 FETCH_OFFSET (offset); \
485 VM_HANDLE_INTERRUPTS; \
489 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
492 FETCH_OFFSET (offset
);
495 VM_HANDLE_INTERRUPTS
;
499 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
503 BR (scm_is_true (x
));
506 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
510 BR (scm_is_false (x
));
513 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
517 BR (scm_is_eq (x
, y
));
520 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
524 BR (!scm_is_eq (x
, y
));
527 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
531 BR (scm_is_null (x
));
534 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
538 BR (!scm_is_null (x
));
546 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
552 FETCH_OFFSET (offset
);
553 if (sp
- (fp
- 1) != n
)
558 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
564 FETCH_OFFSET (offset
);
565 if (sp
- (fp
- 1) < n
)
570 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
577 FETCH_OFFSET (offset
);
578 if (sp
- (fp
- 1) > n
)
583 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
588 if (sp
- (fp
- 1) != n
)
589 goto vm_error_wrong_num_args
;
593 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
598 if (sp
- (fp
- 1) < n
)
599 goto vm_error_wrong_num_args
;
603 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
608 while (sp
- (fp
- 1) < n
)
609 PUSH (SCM_UNDEFINED
);
613 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
616 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
617 nreq
= FETCH () << 8;
619 nreq_and_opt
= FETCH () << 8;
620 nreq_and_opt
+= FETCH ();
621 ntotal
= FETCH () << 8;
624 /* look in optionals for first keyword or last positional */
625 /* starting after the last required positional arg */
627 while (/* while we have args */
629 /* and we still have positionals to fill */
630 && walk
- fp
< nreq_and_opt
631 /* and we haven't reached a keyword yet */
632 && !scm_is_keyword (*walk
))
633 /* bind this optional arg (by leaving it in place) */
635 /* now shuffle up, from walk to ntotal */
637 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
638 sp
= (fp
- 1) + ntotal
+ nshuf
;
640 for (i
= 0; i
< nshuf
; i
++)
641 sp
[-i
] = walk
[nshuf
-i
-1];
643 /* and fill optionals & keyword args with SCM_UNDEFINED */
644 while (walk
<= (fp
- 1) + ntotal
)
645 *walk
++ = SCM_UNDEFINED
;
650 /* Flags that determine whether other keywords are allowed, and whether a
651 rest argument is expected. These values must match those used by the
652 glil->assembly compiler. */
653 #define F_ALLOW_OTHER_KEYS 1
656 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
660 int kw_and_rest_flags
;
664 /* XXX: We don't actually use NKW. */
667 kw_and_rest_flags
= FETCH ();
669 if (!(kw_and_rest_flags
& F_REST
)
670 && ((sp
- (fp
- 1) - nkw
) % 2))
671 goto vm_error_kwargs_length_not_even
;
674 kw
= OBJECT_REF (idx
);
676 /* Switch NKW to be a negative index below SP. */
677 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
681 if (scm_is_keyword (sp
[nkw
]))
683 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
685 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
687 SCM si
= SCM_CDAR (walk
);
688 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
693 if (!(kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
) && !scm_is_pair (walk
))
694 goto vm_error_kwargs_unrecognized_keyword
;
698 else if (!(kw_and_rest_flags
& F_REST
))
699 goto vm_error_kwargs_invalid_keyword
;
705 #undef F_ALLOW_OTHER_KEYS
709 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
715 while (sp
- (fp
- 1) > n
)
716 /* No need to check for underflow. */
717 CONS (rest
, *sp
--, rest
);
722 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
731 while (sp
- (fp
- 1) > n
)
732 /* No need to check for underflow. */
733 CONS (rest
, *sp
--, rest
);
738 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
751 *++old_sp
= SCM_UNDEFINED
;
754 NULLSTACK (old_sp
- sp
);
759 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
761 /* NB: if you change this, see frames.c:vm-frame-num-locals */
762 /* and frames.h, vm-engine.c, etc of course */
764 /* We don't initialize the dynamic link here because we don't actually
765 know that this frame will point to the current fp: it could be
766 placed elsewhere on the stack if captured in a partial
767 continuation, and invoked from some other context. */
768 PUSH (SCM_PACK (0)); /* dynamic link */
769 PUSH (SCM_PACK (0)); /* mvra */
770 PUSH (SCM_PACK (0)); /* ra */
774 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
779 program
= sp
[-nargs
];
781 VM_HANDLE_INTERRUPTS
;
783 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
785 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
787 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
790 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
791 && SCM_SMOB_APPLICABLE_P (program
))
794 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
798 goto vm_error_wrong_type_apply
;
808 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
809 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
810 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
811 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
812 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
813 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
816 ip
= SCM_C_OBJCODE_BASE (bp
);
817 PUSH_CONTINUATION_HOOK ();
822 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
827 program
= sp
[-nargs
];
829 VM_HANDLE_INTERRUPTS
;
831 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
833 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
835 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
838 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
839 && SCM_SMOB_APPLICABLE_P (program
))
842 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
846 goto vm_error_wrong_type_apply
;
851 #ifdef VM_ENABLE_STACK_NULLING
856 /* switch programs */
858 /* shuffle down the program and the arguments */
859 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
860 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
864 NULLSTACK (old_sp
- sp
);
866 ip
= SCM_C_OBJCODE_BASE (bp
);
873 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
881 subr
= SCM_POINTER_VALUE (pointer
);
883 VM_HANDLE_INTERRUPTS
;
895 ret
= subr (sp
[-1], sp
[0]);
898 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
901 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
904 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
907 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
910 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
913 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
916 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
919 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
925 NULLSTACK_FOR_NONLOCAL_EXIT ();
927 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
929 /* multiple values returned to continuation */
930 ret
= scm_struct_ref (ret
, SCM_INUM0
);
931 nvalues
= scm_ilength (ret
);
932 PUSH_LIST (ret
, scm_is_null
);
933 goto vm_return_values
;
942 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
949 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
951 VM_HANDLE_INTERRUPTS
;
960 ret
= subr (smob
, sp
[0]);
963 ret
= subr (smob
, sp
[-1], sp
[0]);
966 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
972 NULLSTACK_FOR_NONLOCAL_EXIT ();
974 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
976 /* multiple values returned to continuation */
977 ret
= scm_struct_ref (ret
, SCM_INUM0
);
978 nvalues
= scm_ilength (ret
);
979 PUSH_LIST (ret
, scm_is_null
);
980 goto vm_return_values
;
989 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
995 VM_HANDLE_INTERRUPTS
;
998 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
1000 NULLSTACK_FOR_NONLOCAL_EXIT ();
1002 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
1004 /* multiple values returned to continuation */
1005 ret
= scm_struct_ref (ret
, SCM_INUM0
);
1006 nvalues
= scm_ilength (ret
);
1007 PUSH_LIST (ret
, scm_is_null
);
1008 goto vm_return_values
;
1017 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1023 scm_i_check_continuation (contregs
);
1024 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1025 scm_i_contregs_vm_cont (contregs
),
1027 scm_i_reinstate_continuation (contregs
);
1033 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1035 SCM vmcont
, intwinds
, prevwinds
;
1036 POP2 (intwinds
, vmcont
);
1038 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
1039 { finish_args
= vmcont
;
1040 goto vm_error_continuation_not_rewindable
;
1042 prevwinds
= scm_i_dynwinds ();
1043 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1046 /* Rewind prompt jmpbuffers, if any. */
1048 SCM winds
= scm_i_dynwinds ();
1049 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1050 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1055 program
= SCM_FRAME_PROGRAM (fp
);
1060 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1064 nargs
= scm_to_int (x
);
1065 /* FIXME: should truncate values? */
1069 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1073 nargs
= scm_to_int (x
);
1074 /* FIXME: should truncate values? */
1078 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1084 FETCH_OFFSET (offset
);
1088 program
= sp
[-nargs
];
1090 VM_HANDLE_INTERRUPTS
;
1092 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1094 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1096 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1099 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1100 && SCM_SMOB_APPLICABLE_P (program
))
1103 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1107 goto vm_error_wrong_type_apply
;
1115 fp
= sp
- nargs
+ 1;
1117 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1118 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1119 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1120 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1121 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1122 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1125 ip
= SCM_C_OBJCODE_BASE (bp
);
1126 PUSH_CONTINUATION_HOOK ();
1131 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1138 ASSERT (nargs
>= 2);
1140 len
= scm_ilength (ls
);
1141 if (SCM_UNLIKELY (len
< 0))
1144 goto vm_error_apply_to_non_list
;
1147 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1153 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1160 ASSERT (nargs
>= 2);
1162 len
= scm_ilength (ls
);
1163 if (SCM_UNLIKELY (len
< 0))
1166 goto vm_error_apply_to_non_list
;
1169 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1175 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1178 SCM proc
, vm_cont
, cont
;
1181 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1182 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1185 PUSH (SCM_PACK (0)); /* dynamic link */
1186 PUSH (SCM_PACK (0)); /* mvra */
1187 PUSH (SCM_PACK (0)); /* ra */
1195 /* Otherwise, the vm continuation was reinstated, and
1196 vm_return_to_continuation pushed on one value. We know only one
1197 value was returned because we are in value context -- the
1198 previous block jumped to vm_call, not vm_mv_call, after all.
1200 So, pull our regs back down from the vp, and march on to the
1201 next instruction. */
1203 program
= SCM_FRAME_PROGRAM (fp
);
1205 RESTORE_CONTINUATION_HOOK ();
1210 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1213 SCM proc
, vm_cont
, cont
;
1216 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1218 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1219 SCM_FRAME_DYNAMIC_LINK (fp
),
1220 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1221 SCM_FRAME_RETURN_ADDRESS (fp
),
1222 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1224 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1234 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1235 does a return from the frame, either to the RA or
1238 program
= SCM_FRAME_PROGRAM (fp
);
1240 /* Unfortunately we don't know whether we are at the RA, and thus
1241 have one value without an nvalues marker, or we are at the
1242 MVRA and thus have multiple values and the nvalues
1243 marker. Instead of adding heuristics here, we will let hook
1244 client code do that. */
1245 RESTORE_CONTINUATION_HOOK ();
1250 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1253 POP_CONTINUATION_HOOK (1);
1255 VM_HANDLE_INTERRUPTS
;
1262 #ifdef VM_ENABLE_STACK_NULLING
1266 /* Restore registers */
1267 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1268 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1269 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1271 #ifdef VM_ENABLE_STACK_NULLING
1272 NULLSTACK (old_sp
- sp
);
1275 /* Set return value (sp is already pushed) */
1279 /* Restore the last program */
1280 program
= SCM_FRAME_PROGRAM (fp
);
1286 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1288 /* nvalues declared at top level, because for some reason gcc seems to think
1289 that perhaps it might be used without declaration. Fooey to that, I say. */
1292 POP_CONTINUATION_HOOK (nvalues
);
1294 VM_HANDLE_INTERRUPTS
;
1296 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1298 /* A multiply-valued continuation */
1299 SCM
*vals
= sp
- nvalues
;
1301 /* Restore registers */
1302 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1303 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1304 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1306 /* Push return values, and the number of values */
1307 for (i
= 0; i
< nvalues
; i
++)
1309 *++sp
= SCM_I_MAKINUM (nvalues
);
1311 /* Finally null the end of the stack */
1312 NULLSTACK (vals
+ nvalues
- sp
);
1314 else if (nvalues
>= 1)
1316 /* Multiple values for a single-valued continuation -- here's where I
1317 break with guile tradition and try and do something sensible. (Also,
1318 this block handles the single-valued return to an mv
1320 SCM
*vals
= sp
- nvalues
;
1321 /* Restore registers */
1322 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1323 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1324 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1326 /* Push first value */
1329 /* Finally null the end of the stack */
1330 NULLSTACK (vals
+ nvalues
- sp
);
1333 goto vm_error_no_values
;
1335 /* Restore the last program */
1336 program
= SCM_FRAME_PROGRAM (fp
);
1342 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1347 ASSERT (nvalues
>= 1);
1351 while (scm_is_pair (l
))
1357 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1358 finish_args
= scm_list_1 (l
);
1359 goto vm_error_improper_list
;
1362 goto vm_return_values
;
1365 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1369 nvalues
= scm_to_int (n
);
1370 ASSERT (nvalues
>= 0);
1371 goto vm_return_values
;
1374 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1379 nvalues
= scm_to_int (x
);
1386 if (nvalues
< nbinds
)
1387 goto vm_error_not_enough_values
;
1390 POP_LIST (nvalues
- nbinds
);
1392 DROPN (nvalues
- nbinds
);
1397 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1402 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1407 (let ((a *undef*) (b *undef*) ...)
1408 (set! a (lambda () (b ...)))
1411 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1414 LOCAL_SET (FETCH (),
1415 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1419 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1421 SCM v
= LOCAL_REF (FETCH ());
1422 ASSERT_BOUND_VARIABLE (v
);
1423 PUSH (VARIABLE_REF (v
));
1427 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1430 v
= LOCAL_REF (FETCH ());
1432 ASSERT_VARIABLE (v
);
1433 VARIABLE_SET (v
, val
);
1437 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1439 scm_t_uint8 idx
= FETCH ();
1441 CHECK_FREE_VARIABLE (idx
);
1442 PUSH (FREE_VARIABLE_REF (idx
));
1446 /* no free-set -- if a var is assigned, it should be in a box */
1448 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1451 scm_t_uint8 idx
= FETCH ();
1452 CHECK_FREE_VARIABLE (idx
);
1453 v
= FREE_VARIABLE_REF (idx
);
1454 ASSERT_BOUND_VARIABLE (v
);
1455 PUSH (VARIABLE_REF (v
));
1459 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1462 scm_t_uint8 idx
= FETCH ();
1464 CHECK_FREE_VARIABLE (idx
);
1465 v
= FREE_VARIABLE_REF (idx
);
1466 ASSERT_BOUND_VARIABLE (v
);
1467 VARIABLE_SET (v
, val
);
1471 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1480 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1481 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1482 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1484 for (n
= 0; n
< len
; n
++)
1485 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1490 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1493 /* fixme underflow */
1494 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1498 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1501 unsigned int i
= FETCH ();
1505 /* FIXME CHECK_LOCAL (i) */
1507 /* FIXME ASSERT_PROGRAM (x); */
1508 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1509 for (n
= 0; n
< len
; n
++)
1510 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1515 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1520 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1526 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1530 *sp
= scm_symbol_to_keyword (*sp
);
1534 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1538 *sp
= scm_string_to_symbol (*sp
);
1542 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1545 scm_t_uint8 escape_only_p
;
1548 escape_only_p
= FETCH ();
1549 FETCH_OFFSET (offset
);
1553 /* Push the prompt onto the dynamic stack. */
1554 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1556 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1557 if (SCM_PROMPT_SETJMP (prompt
))
1559 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1562 Note, at this point, we must assume that any variable local to
1563 vm_engine that can be assigned *has* been assigned. So we need to pull
1564 all our state back from the ip/fp/sp.
1567 program
= SCM_FRAME_PROGRAM (fp
);
1569 /* The stack contains the values returned to this prompt, along
1570 with a number-of-values marker -- like an MV return. */
1571 ABORT_CONTINUATION_HOOK ();
1575 /* Otherwise setjmp returned for the first time, so we go to execute the
1580 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1583 POP2 (unwind
, wind
);
1585 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1586 are actually called; the compiler should emit calls to wind and unwind for
1587 the normal dynamic-wind control flow. */
1588 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1591 goto vm_error_not_a_thunk
;
1593 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1595 finish_args
= unwind
;
1596 goto vm_error_not_a_thunk
;
1598 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1602 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1604 unsigned n
= FETCH ();
1606 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1607 goto vm_error_stack_underflow
;
1608 vm_abort (vm
, n
, vm_cookie
);
1609 /* vm_abort should not return */
1613 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1615 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1616 off of the dynamic stack. */
1617 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1621 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1623 unsigned n
= FETCH ();
1629 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1632 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1633 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1637 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1640 wf
= scm_car (scm_i_dynwinds ());
1641 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1642 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1646 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1652 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1653 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1654 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1656 /* Punt dynstate expansion and error handling to the C proc. */
1658 *sp
= scm_fluid_ref (*sp
);
1662 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1663 if (SCM_UNLIKELY (scm_is_eq (val
, SCM_UNDEFINED
)))
1666 goto vm_error_unbound_fluid
;
1674 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1677 SCM val
, fluid
, fluids
;
1680 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1681 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1682 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1684 /* Punt dynstate expansion and error handling to the C proc. */
1686 scm_fluid_set_x (fluid
, val
);
1689 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1694 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1699 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1702 if (SCM_UNLIKELY (sp
- (fp
- 1) != (n
& 0x7)))
1703 goto vm_error_wrong_num_args
;
1709 *++old_sp
= SCM_UNDEFINED
;
1716 (defun renumber-ops ()
1717 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1720 (let ((counter -1)) (goto-char (point-min))
1721 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1723 (number-to-string (setq counter (1+ counter)))