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) (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 if (LOCAL_REF (FETCH ()) == SCM_UNDEFINED
)
287 VM_DEFINE_INSTRUCTION (24, long_local_bound
, "long-local-bound?", 2, 0, 1)
289 unsigned int i
= FETCH ();
292 if (LOCAL_REF (i
) == SCM_UNDEFINED
)
299 VM_DEFINE_INSTRUCTION (25, variable_ref
, "variable-ref", 0, 1, 1)
303 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
304 unlike in top-variable-ref, it really isn't an internal assertion
305 that can be optimized out -- the variable could be coming directly
307 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
309 func_name
= "variable-ref";
311 goto vm_error_not_a_variable
;
313 else if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x
)))
317 /* Attempt to provide the variable name in the error message. */
318 var_name
= scm_module_reverse_lookup (scm_current_module (), x
);
319 finish_args
= scm_is_true (var_name
) ? var_name
: x
;
320 goto vm_error_unbound
;
324 SCM o
= VARIABLE_REF (x
);
331 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
335 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
337 func_name
= "variable-bound?";
339 goto vm_error_not_a_variable
;
342 *sp
= scm_from_bool (VARIABLE_BOUNDP (x
));
346 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
348 unsigned objnum
= FETCH ();
350 CHECK_OBJECT (objnum
);
351 what
= OBJECT_REF (objnum
);
353 if (!SCM_VARIABLEP (what
))
356 resolved
= resolve_variable (what
, scm_program_module (program
));
357 if (!VARIABLE_BOUNDP (resolved
))
360 goto vm_error_unbound
;
363 OBJECT_SET (objnum
, what
);
366 PUSH (VARIABLE_REF (what
));
370 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
373 unsigned int objnum
= FETCH ();
376 CHECK_OBJECT (objnum
);
377 what
= OBJECT_REF (objnum
);
379 if (!SCM_VARIABLEP (what
))
382 resolved
= resolve_variable (what
, scm_program_module (program
));
383 if (!VARIABLE_BOUNDP (resolved
))
386 goto vm_error_unbound
;
389 OBJECT_SET (objnum
, what
);
392 PUSH (VARIABLE_REF (what
));
398 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
402 LOCAL_SET (FETCH (), x
);
406 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
409 unsigned int i
= FETCH ();
417 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
419 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp
[0])))
421 func_name
= "variable-set!";
423 goto vm_error_not_a_variable
;
425 VARIABLE_SET (sp
[0], sp
[-1]);
430 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
432 unsigned objnum
= FETCH ();
434 CHECK_OBJECT (objnum
);
435 what
= OBJECT_REF (objnum
);
437 if (!SCM_VARIABLEP (what
))
440 what
= resolve_variable (what
, scm_program_module (program
));
441 OBJECT_SET (objnum
, what
);
444 VARIABLE_SET (what
, *sp
);
449 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
452 unsigned int objnum
= FETCH ();
455 CHECK_OBJECT (objnum
);
456 what
= OBJECT_REF (objnum
);
458 if (!SCM_VARIABLEP (what
))
461 what
= resolve_variable (what
, scm_program_module (program
));
462 OBJECT_SET (objnum
, what
);
465 VARIABLE_SET (what
, *sp
);
475 /* offset must be at least 24 bits wide, and signed */
476 #define FETCH_OFFSET(offset) \
478 offset = FETCH () << 16; \
479 offset += FETCH () << 8; \
480 offset += FETCH (); \
481 offset -= (offset & (1<<23)) << 1; \
486 scm_t_int32 offset; \
487 FETCH_OFFSET (offset); \
491 VM_HANDLE_INTERRUPTS; \
495 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
498 FETCH_OFFSET (offset
);
501 VM_HANDLE_INTERRUPTS
;
505 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
509 BR (scm_is_true (x
));
512 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
516 BR (scm_is_false (x
));
519 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
523 BR (scm_is_eq (x
, y
));
526 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
530 BR (!scm_is_eq (x
, y
));
533 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
537 BR (scm_is_null (x
));
540 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
544 BR (!scm_is_null (x
));
552 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
558 FETCH_OFFSET (offset
);
559 if (sp
- (fp
- 1) != n
)
564 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
570 FETCH_OFFSET (offset
);
571 if (sp
- (fp
- 1) < n
)
576 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
583 FETCH_OFFSET (offset
);
584 if (sp
- (fp
- 1) > n
)
589 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
594 if (sp
- (fp
- 1) != n
)
595 goto vm_error_wrong_num_args
;
599 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
604 if (sp
- (fp
- 1) < n
)
605 goto vm_error_wrong_num_args
;
609 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
614 while (sp
- (fp
- 1) < n
)
615 PUSH (SCM_UNDEFINED
);
619 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
622 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
623 nreq
= FETCH () << 8;
625 nreq_and_opt
= FETCH () << 8;
626 nreq_and_opt
+= FETCH ();
627 ntotal
= FETCH () << 8;
630 /* look in optionals for first keyword or last positional */
631 /* starting after the last required positional arg */
633 while (/* while we have args */
635 /* and we still have positionals to fill */
636 && walk
- fp
< nreq_and_opt
637 /* and we haven't reached a keyword yet */
638 && !scm_is_keyword (*walk
))
639 /* bind this optional arg (by leaving it in place) */
641 /* now shuffle up, from walk to ntotal */
643 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
644 sp
= (fp
- 1) + ntotal
+ nshuf
;
646 for (i
= 0; i
< nshuf
; i
++)
647 sp
[-i
] = walk
[nshuf
-i
-1];
649 /* and fill optionals & keyword args with SCM_UNDEFINED */
650 while (walk
<= (fp
- 1) + ntotal
)
651 *walk
++ = SCM_UNDEFINED
;
656 /* Flags that determine whether other keywords are allowed, and whether a
657 rest argument is expected. These values must match those used by the
658 glil->assembly compiler. */
659 #define F_ALLOW_OTHER_KEYS 1
662 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
666 int kw_and_rest_flags
;
670 /* XXX: We don't actually use NKW. */
673 kw_and_rest_flags
= FETCH ();
675 if (!(kw_and_rest_flags
& F_REST
)
676 && ((sp
- (fp
- 1) - nkw
) % 2))
677 goto vm_error_kwargs_length_not_even
;
680 kw
= OBJECT_REF (idx
);
682 /* Switch NKW to be a negative index below SP. */
683 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
687 if (scm_is_keyword (sp
[nkw
]))
689 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
691 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
693 SCM si
= SCM_CDAR (walk
);
694 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
699 if (!(kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
) && !scm_is_pair (walk
))
700 goto vm_error_kwargs_unrecognized_keyword
;
704 else if (!(kw_and_rest_flags
& F_REST
))
705 goto vm_error_kwargs_invalid_keyword
;
711 #undef F_ALLOW_OTHER_KEYS
715 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
721 while (sp
- (fp
- 1) > n
)
722 /* No need to check for underflow. */
723 CONS (rest
, *sp
--, rest
);
728 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
737 while (sp
- (fp
- 1) > n
)
738 /* No need to check for underflow. */
739 CONS (rest
, *sp
--, rest
);
744 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
757 *++old_sp
= SCM_UNDEFINED
;
760 NULLSTACK (old_sp
- sp
);
765 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
767 /* NB: if you change this, see frames.c:vm-frame-num-locals */
768 /* and frames.h, vm-engine.c, etc of course */
770 /* We don't initialize the dynamic link here because we don't actually
771 know that this frame will point to the current fp: it could be
772 placed elsewhere on the stack if captured in a partial
773 continuation, and invoked from some other context. */
774 PUSH (0); /* dynamic link */
780 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
785 program
= sp
[-nargs
];
787 VM_HANDLE_INTERRUPTS
;
789 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
791 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
793 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
796 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
797 && SCM_SMOB_APPLICABLE_P (program
))
800 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
804 goto vm_error_wrong_type_apply
;
814 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
815 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
816 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
817 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
818 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
819 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
822 ip
= SCM_C_OBJCODE_BASE (bp
);
823 PUSH_CONTINUATION_HOOK ();
828 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
833 program
= sp
[-nargs
];
835 VM_HANDLE_INTERRUPTS
;
837 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
839 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
841 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
844 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
845 && SCM_SMOB_APPLICABLE_P (program
))
848 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
852 goto vm_error_wrong_type_apply
;
857 #ifdef VM_ENABLE_STACK_NULLING
862 /* switch programs */
864 /* shuffle down the program and the arguments */
865 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
866 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
870 NULLSTACK (old_sp
- sp
);
872 ip
= SCM_C_OBJCODE_BASE (bp
);
879 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
887 subr
= SCM_POINTER_VALUE (pointer
);
889 VM_HANDLE_INTERRUPTS
;
901 ret
= subr (sp
[-1], sp
[0]);
904 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
907 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
910 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
913 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
916 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
919 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
922 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
925 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
931 NULLSTACK_FOR_NONLOCAL_EXIT ();
933 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
935 /* multiple values returned to continuation */
936 ret
= scm_struct_ref (ret
, SCM_INUM0
);
937 nvalues
= scm_ilength (ret
);
938 PUSH_LIST (ret
, scm_is_null
);
939 goto vm_return_values
;
948 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
955 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
957 VM_HANDLE_INTERRUPTS
;
966 ret
= subr (smob
, sp
[0]);
969 ret
= subr (smob
, sp
[-1], sp
[0]);
972 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
978 NULLSTACK_FOR_NONLOCAL_EXIT ();
980 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
982 /* multiple values returned to continuation */
983 ret
= scm_struct_ref (ret
, SCM_INUM0
);
984 nvalues
= scm_ilength (ret
);
985 PUSH_LIST (ret
, scm_is_null
);
986 goto vm_return_values
;
995 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
1001 VM_HANDLE_INTERRUPTS
;
1004 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
1006 NULLSTACK_FOR_NONLOCAL_EXIT ();
1008 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
1010 /* multiple values returned to continuation */
1011 ret
= scm_struct_ref (ret
, SCM_INUM0
);
1012 nvalues
= scm_ilength (ret
);
1013 PUSH_LIST (ret
, scm_is_null
);
1014 goto vm_return_values
;
1023 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1029 scm_i_check_continuation (contregs
);
1030 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1031 scm_i_contregs_vm_cont (contregs
),
1033 scm_i_reinstate_continuation (contregs
);
1039 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1041 SCM vmcont
, intwinds
, prevwinds
;
1042 POP2 (intwinds
, vmcont
);
1044 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
1045 { finish_args
= vmcont
;
1046 goto vm_error_continuation_not_rewindable
;
1048 prevwinds
= scm_i_dynwinds ();
1049 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1052 /* Rewind prompt jmpbuffers, if any. */
1054 SCM winds
= scm_i_dynwinds ();
1055 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1056 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1061 program
= SCM_FRAME_PROGRAM (fp
);
1066 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1070 nargs
= scm_to_int (x
);
1071 /* FIXME: should truncate values? */
1075 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1079 nargs
= scm_to_int (x
);
1080 /* FIXME: should truncate values? */
1084 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1090 FETCH_OFFSET (offset
);
1094 program
= sp
[-nargs
];
1096 VM_HANDLE_INTERRUPTS
;
1098 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1100 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1102 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1105 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1106 && SCM_SMOB_APPLICABLE_P (program
))
1109 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1113 goto vm_error_wrong_type_apply
;
1121 fp
= sp
- nargs
+ 1;
1123 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1124 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1125 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1126 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1127 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1128 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1131 ip
= SCM_C_OBJCODE_BASE (bp
);
1132 PUSH_CONTINUATION_HOOK ();
1137 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1144 ASSERT (nargs
>= 2);
1146 len
= scm_ilength (ls
);
1147 if (SCM_UNLIKELY (len
< 0))
1150 goto vm_error_apply_to_non_list
;
1153 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1159 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1166 ASSERT (nargs
>= 2);
1168 len
= scm_ilength (ls
);
1169 if (SCM_UNLIKELY (len
< 0))
1172 goto vm_error_apply_to_non_list
;
1175 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1181 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1184 SCM proc
, vm_cont
, cont
;
1187 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1188 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1191 PUSH (0); /* dynamic link */
1192 PUSH (0); /* mvra */
1201 /* Otherwise, the vm continuation was reinstated, and
1202 vm_return_to_continuation pushed on one value. We know only one
1203 value was returned because we are in value context -- the
1204 previous block jumped to vm_call, not vm_mv_call, after all.
1206 So, pull our regs back down from the vp, and march on to the
1207 next instruction. */
1209 program
= SCM_FRAME_PROGRAM (fp
);
1211 RESTORE_CONTINUATION_HOOK ();
1216 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1219 SCM proc
, vm_cont
, cont
;
1222 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1224 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1225 SCM_FRAME_DYNAMIC_LINK (fp
),
1226 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1227 SCM_FRAME_RETURN_ADDRESS (fp
),
1228 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1230 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1240 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1241 does a return from the frame, either to the RA or
1244 program
= SCM_FRAME_PROGRAM (fp
);
1246 /* Unfortunately we don't know whether we are at the RA, and thus
1247 have one value without an nvalues marker, or we are at the
1248 MVRA and thus have multiple values and the nvalues
1249 marker. Instead of adding heuristics here, we will let hook
1250 client code do that. */
1251 RESTORE_CONTINUATION_HOOK ();
1256 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1259 POP_CONTINUATION_HOOK (1);
1261 VM_HANDLE_INTERRUPTS
;
1268 #ifdef VM_ENABLE_STACK_NULLING
1272 /* Restore registers */
1273 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1274 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1275 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1277 #ifdef VM_ENABLE_STACK_NULLING
1278 NULLSTACK (old_sp
- sp
);
1281 /* Set return value (sp is already pushed) */
1285 /* Restore the last program */
1286 program
= SCM_FRAME_PROGRAM (fp
);
1292 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1294 /* nvalues declared at top level, because for some reason gcc seems to think
1295 that perhaps it might be used without declaration. Fooey to that, I say. */
1298 POP_CONTINUATION_HOOK (nvalues
);
1300 VM_HANDLE_INTERRUPTS
;
1302 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1304 /* A multiply-valued continuation */
1305 SCM
*vals
= sp
- nvalues
;
1307 /* Restore registers */
1308 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1309 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1310 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1312 /* Push return values, and the number of values */
1313 for (i
= 0; i
< nvalues
; i
++)
1315 *++sp
= SCM_I_MAKINUM (nvalues
);
1317 /* Finally null the end of the stack */
1318 NULLSTACK (vals
+ nvalues
- sp
);
1320 else if (nvalues
>= 1)
1322 /* Multiple values for a single-valued continuation -- here's where I
1323 break with guile tradition and try and do something sensible. (Also,
1324 this block handles the single-valued return to an mv
1326 SCM
*vals
= sp
- nvalues
;
1327 /* Restore registers */
1328 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1329 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1330 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1332 /* Push first value */
1335 /* Finally null the end of the stack */
1336 NULLSTACK (vals
+ nvalues
- sp
);
1339 goto vm_error_no_values
;
1341 /* Restore the last program */
1342 program
= SCM_FRAME_PROGRAM (fp
);
1348 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1353 ASSERT (nvalues
>= 1);
1357 while (scm_is_pair (l
))
1363 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1364 finish_args
= scm_list_1 (l
);
1365 goto vm_error_improper_list
;
1368 goto vm_return_values
;
1371 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1375 nvalues
= scm_to_int (n
);
1376 ASSERT (nvalues
>= 0);
1377 goto vm_return_values
;
1380 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1385 nvalues
= scm_to_int (x
);
1392 if (nvalues
< nbinds
)
1393 goto vm_error_not_enough_values
;
1396 POP_LIST (nvalues
- nbinds
);
1398 DROPN (nvalues
- nbinds
);
1403 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1408 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1413 (let ((a *undef*) (b *undef*) ...)
1414 (set! a (lambda () (b ...)))
1417 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1420 LOCAL_SET (FETCH (),
1421 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1425 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1427 SCM v
= LOCAL_REF (FETCH ());
1428 ASSERT_BOUND_VARIABLE (v
);
1429 PUSH (VARIABLE_REF (v
));
1433 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1436 v
= LOCAL_REF (FETCH ());
1438 ASSERT_VARIABLE (v
);
1439 VARIABLE_SET (v
, val
);
1443 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1445 scm_t_uint8 idx
= FETCH ();
1447 CHECK_FREE_VARIABLE (idx
);
1448 PUSH (FREE_VARIABLE_REF (idx
));
1452 /* no free-set -- if a var is assigned, it should be in a box */
1454 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1457 scm_t_uint8 idx
= FETCH ();
1458 CHECK_FREE_VARIABLE (idx
);
1459 v
= FREE_VARIABLE_REF (idx
);
1460 ASSERT_BOUND_VARIABLE (v
);
1461 PUSH (VARIABLE_REF (v
));
1465 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1468 scm_t_uint8 idx
= FETCH ();
1470 CHECK_FREE_VARIABLE (idx
);
1471 v
= FREE_VARIABLE_REF (idx
);
1472 ASSERT_BOUND_VARIABLE (v
);
1473 VARIABLE_SET (v
, val
);
1477 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1486 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1487 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1488 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1490 for (n
= 0; n
< len
; n
++)
1491 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1496 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1499 /* fixme underflow */
1500 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1504 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1507 unsigned int i
= FETCH ();
1511 /* FIXME CHECK_LOCAL (i) */
1513 /* FIXME ASSERT_PROGRAM (x); */
1514 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1515 for (n
= 0; n
< len
; n
++)
1516 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1521 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1526 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1532 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1536 *sp
= scm_symbol_to_keyword (*sp
);
1540 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1544 *sp
= scm_string_to_symbol (*sp
);
1548 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1551 scm_t_uint8 escape_only_p
;
1554 escape_only_p
= FETCH ();
1555 FETCH_OFFSET (offset
);
1559 /* Push the prompt onto the dynamic stack. */
1560 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1562 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1563 if (SCM_PROMPT_SETJMP (prompt
))
1565 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1568 Note, at this point, we must assume that any variable local to
1569 vm_engine that can be assigned *has* been assigned. So we need to pull
1570 all our state back from the ip/fp/sp.
1573 program
= SCM_FRAME_PROGRAM (fp
);
1575 /* The stack contains the values returned to this prompt, along
1576 with a number-of-values marker -- like an MV return. */
1577 ABORT_CONTINUATION_HOOK ();
1581 /* Otherwise setjmp returned for the first time, so we go to execute the
1586 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1589 POP2 (unwind
, wind
);
1591 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1592 are actually called; the compiler should emit calls to wind and unwind for
1593 the normal dynamic-wind control flow. */
1594 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1597 goto vm_error_not_a_thunk
;
1599 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1601 finish_args
= unwind
;
1602 goto vm_error_not_a_thunk
;
1604 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1608 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1610 unsigned n
= FETCH ();
1612 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1613 goto vm_error_stack_underflow
;
1614 vm_abort (vm
, n
, vm_cookie
);
1615 /* vm_abort should not return */
1619 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1621 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1622 off of the dynamic stack. */
1623 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1627 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1629 unsigned n
= FETCH ();
1635 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1638 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1639 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1643 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1646 wf
= scm_car (scm_i_dynwinds ());
1647 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1648 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1652 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1658 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1659 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1660 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1662 /* Punt dynstate expansion and error handling to the C proc. */
1664 *sp
= scm_fluid_ref (*sp
);
1668 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1669 if (SCM_UNLIKELY (val
== SCM_UNDEFINED
))
1672 goto vm_error_unbound_fluid
;
1680 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1683 SCM val
, fluid
, fluids
;
1686 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1687 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1688 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1690 /* Punt dynstate expansion and error handling to the C proc. */
1692 scm_fluid_set_x (fluid
, val
);
1695 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1700 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1705 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1708 if (SCM_UNLIKELY (sp
- (fp
- 1) != (n
& 0x7)))
1709 goto vm_error_wrong_num_args
;
1715 *++old_sp
= SCM_UNDEFINED
;
1722 (defun renumber-ops ()
1723 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1726 (let ((counter -1)) (goto-char (point-min))
1727 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1729 (number-to-string (setq counter (1+ counter)))