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)
400 LOCAL_SET (FETCH (), *sp
);
405 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
407 unsigned int i
= FETCH ();
415 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
417 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp
[0])))
419 func_name
= "variable-set!";
421 goto vm_error_not_a_variable
;
423 VARIABLE_SET (sp
[0], sp
[-1]);
428 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
430 unsigned objnum
= FETCH ();
432 CHECK_OBJECT (objnum
);
433 what
= OBJECT_REF (objnum
);
435 if (!SCM_VARIABLEP (what
))
438 what
= resolve_variable (what
, scm_program_module (program
));
439 OBJECT_SET (objnum
, what
);
442 VARIABLE_SET (what
, *sp
);
447 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
450 unsigned int objnum
= FETCH ();
453 CHECK_OBJECT (objnum
);
454 what
= OBJECT_REF (objnum
);
456 if (!SCM_VARIABLEP (what
))
459 what
= resolve_variable (what
, scm_program_module (program
));
460 OBJECT_SET (objnum
, what
);
463 VARIABLE_SET (what
, *sp
);
473 /* offset must be at least 24 bits wide, and signed */
474 #define FETCH_OFFSET(offset) \
476 offset = FETCH () << 16; \
477 offset += FETCH () << 8; \
478 offset += FETCH (); \
479 offset -= (offset & (1<<23)) << 1; \
484 scm_t_int32 offset; \
485 FETCH_OFFSET (offset); \
489 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)
507 BR (scm_is_true (*sp
));
510 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
512 BR (scm_is_false (*sp
));
515 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
517 sp
--; /* underflow? */
518 BR (scm_is_eq (sp
[0], sp
[1]));
521 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
523 sp
--; /* underflow? */
524 BR (!scm_is_eq (sp
[0], sp
[1]));
527 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
529 BR (scm_is_null (*sp
));
532 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
534 BR (!scm_is_null (*sp
));
542 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
548 FETCH_OFFSET (offset
);
549 if (sp
- (fp
- 1) != n
)
554 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
560 FETCH_OFFSET (offset
);
561 if (sp
- (fp
- 1) < n
)
566 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
573 FETCH_OFFSET (offset
);
574 if (sp
- (fp
- 1) > n
)
579 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
584 if (sp
- (fp
- 1) != n
)
585 goto vm_error_wrong_num_args
;
589 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
594 if (sp
- (fp
- 1) < n
)
595 goto vm_error_wrong_num_args
;
599 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
604 while (sp
- (fp
- 1) < n
)
605 PUSH (SCM_UNDEFINED
);
609 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
612 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
613 nreq
= FETCH () << 8;
615 nreq_and_opt
= FETCH () << 8;
616 nreq_and_opt
+= FETCH ();
617 ntotal
= FETCH () << 8;
620 /* look in optionals for first keyword or last positional */
621 /* starting after the last required positional arg */
623 while (/* while we have args */
625 /* and we still have positionals to fill */
626 && walk
- fp
< nreq_and_opt
627 /* and we haven't reached a keyword yet */
628 && !scm_is_keyword (*walk
))
629 /* bind this optional arg (by leaving it in place) */
631 /* now shuffle up, from walk to ntotal */
633 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
634 sp
= (fp
- 1) + ntotal
+ nshuf
;
636 for (i
= 0; i
< nshuf
; i
++)
637 sp
[-i
] = walk
[nshuf
-i
-1];
639 /* and fill optionals & keyword args with SCM_UNDEFINED */
640 while (walk
<= (fp
- 1) + ntotal
)
641 *walk
++ = SCM_UNDEFINED
;
646 /* Flags that determine whether other keywords are allowed, and whether a
647 rest argument is expected. These values must match those used by the
648 glil->assembly compiler. */
649 #define F_ALLOW_OTHER_KEYS 1
652 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
656 int kw_and_rest_flags
;
660 /* XXX: We don't actually use NKW. */
663 kw_and_rest_flags
= FETCH ();
665 if (!(kw_and_rest_flags
& F_REST
)
666 && ((sp
- (fp
- 1) - nkw
) % 2))
667 goto vm_error_kwargs_length_not_even
;
670 kw
= OBJECT_REF (idx
);
672 /* Switch NKW to be a negative index below SP. */
673 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
677 if (scm_is_keyword (sp
[nkw
]))
679 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
681 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
683 SCM si
= SCM_CDAR (walk
);
684 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
689 if (!(kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
) && !scm_is_pair (walk
))
690 goto vm_error_kwargs_unrecognized_keyword
;
694 else if (!(kw_and_rest_flags
& F_REST
))
695 goto vm_error_kwargs_invalid_keyword
;
701 #undef F_ALLOW_OTHER_KEYS
705 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
711 while (sp
- (fp
- 1) > n
)
712 /* No need to check for underflow. */
713 CONS (rest
, *sp
--, rest
);
718 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
727 while (sp
- (fp
- 1) > n
)
728 /* No need to check for underflow. */
729 CONS (rest
, *sp
--, rest
);
734 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
747 *++old_sp
= SCM_UNDEFINED
;
750 NULLSTACK (old_sp
- sp
);
755 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
757 /* NB: if you change this, see frames.c:vm-frame-num-locals */
758 /* and frames.h, vm-engine.c, etc of course */
760 /* We don't initialize the dynamic link here because we don't actually
761 know that this frame will point to the current fp: it could be
762 placed elsewhere on the stack if captured in a partial
763 continuation, and invoked from some other context. */
764 PUSH (0); /* dynamic link */
770 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
775 program
= sp
[-nargs
];
777 VM_HANDLE_INTERRUPTS
;
779 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
781 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
783 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
786 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
787 && SCM_SMOB_APPLICABLE_P (program
))
790 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
794 goto vm_error_wrong_type_apply
;
804 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
805 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
806 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
807 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
808 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
809 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
812 ip
= SCM_C_OBJCODE_BASE (bp
);
813 PUSH_CONTINUATION_HOOK ();
818 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
823 program
= sp
[-nargs
];
825 VM_HANDLE_INTERRUPTS
;
827 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
829 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
831 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
834 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
835 && SCM_SMOB_APPLICABLE_P (program
))
838 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
842 goto vm_error_wrong_type_apply
;
847 #ifdef VM_ENABLE_STACK_NULLING
852 /* switch programs */
854 /* shuffle down the program and the arguments */
855 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
856 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
860 NULLSTACK (old_sp
- sp
);
862 ip
= SCM_C_OBJCODE_BASE (bp
);
869 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
877 subr
= SCM_POINTER_VALUE (pointer
);
879 VM_HANDLE_INTERRUPTS
;
891 ret
= subr (sp
[-1], sp
[0]);
894 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
897 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
900 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
903 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
906 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
909 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
912 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
915 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
921 NULLSTACK_FOR_NONLOCAL_EXIT ();
923 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
925 /* multiple values returned to continuation */
926 ret
= scm_struct_ref (ret
, SCM_INUM0
);
927 nvalues
= scm_ilength (ret
);
928 PUSH_LIST (ret
, scm_is_null
);
929 goto vm_return_values
;
938 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
945 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
947 VM_HANDLE_INTERRUPTS
;
956 ret
= subr (smob
, sp
[0]);
959 ret
= subr (smob
, sp
[-1], sp
[0]);
962 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
968 NULLSTACK_FOR_NONLOCAL_EXIT ();
970 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
972 /* multiple values returned to continuation */
973 ret
= scm_struct_ref (ret
, SCM_INUM0
);
974 nvalues
= scm_ilength (ret
);
975 PUSH_LIST (ret
, scm_is_null
);
976 goto vm_return_values
;
985 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
991 VM_HANDLE_INTERRUPTS
;
994 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
996 NULLSTACK_FOR_NONLOCAL_EXIT ();
998 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
1000 /* multiple values returned to continuation */
1001 ret
= scm_struct_ref (ret
, SCM_INUM0
);
1002 nvalues
= scm_ilength (ret
);
1003 PUSH_LIST (ret
, scm_is_null
);
1004 goto vm_return_values
;
1013 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1019 scm_i_check_continuation (contregs
);
1020 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1021 scm_i_contregs_vm_cont (contregs
),
1023 scm_i_reinstate_continuation (contregs
);
1029 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1031 SCM vmcont
, intwinds
, prevwinds
;
1035 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
1036 { finish_args
= vmcont
;
1037 goto vm_error_continuation_not_rewindable
;
1039 prevwinds
= scm_i_dynwinds ();
1040 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1043 /* Rewind prompt jmpbuffers, if any. */
1045 SCM winds
= scm_i_dynwinds ();
1046 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1047 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1052 program
= SCM_FRAME_PROGRAM (fp
);
1057 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1061 nargs
= scm_to_int (x
);
1062 /* FIXME: should truncate values? */
1066 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1070 nargs
= scm_to_int (x
);
1071 /* FIXME: should truncate values? */
1075 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1081 FETCH_OFFSET (offset
);
1085 program
= sp
[-nargs
];
1087 VM_HANDLE_INTERRUPTS
;
1089 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1091 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1093 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1096 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1097 && SCM_SMOB_APPLICABLE_P (program
))
1100 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1104 goto vm_error_wrong_type_apply
;
1112 fp
= sp
- nargs
+ 1;
1114 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1115 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1116 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1117 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1118 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1119 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1122 ip
= SCM_C_OBJCODE_BASE (bp
);
1123 PUSH_CONTINUATION_HOOK ();
1128 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1135 ASSERT (nargs
>= 2);
1137 len
= scm_ilength (ls
);
1138 if (SCM_UNLIKELY (len
< 0))
1141 goto vm_error_apply_to_non_list
;
1144 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1150 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1157 ASSERT (nargs
>= 2);
1159 len
= scm_ilength (ls
);
1160 if (SCM_UNLIKELY (len
< 0))
1163 goto vm_error_apply_to_non_list
;
1166 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1172 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1175 SCM proc
, vm_cont
, cont
;
1178 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1179 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1182 PUSH (0); /* dynamic link */
1183 PUSH (0); /* mvra */
1192 /* Otherwise, the vm continuation was reinstated, and
1193 vm_return_to_continuation pushed on one value. We know only one
1194 value was returned because we are in value context -- the
1195 previous block jumped to vm_call, not vm_mv_call, after all.
1197 So, pull our regs back down from the vp, and march on to the
1198 next instruction. */
1200 program
= SCM_FRAME_PROGRAM (fp
);
1202 RESTORE_CONTINUATION_HOOK ();
1207 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1210 SCM proc
, vm_cont
, cont
;
1213 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1215 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1216 SCM_FRAME_DYNAMIC_LINK (fp
),
1217 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1218 SCM_FRAME_RETURN_ADDRESS (fp
),
1219 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1221 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1231 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1232 does a return from the frame, either to the RA or
1235 program
= SCM_FRAME_PROGRAM (fp
);
1237 /* Unfortunately we don't know whether we are at the RA, and thus
1238 have one value without an nvalues marker, or we are at the
1239 MVRA and thus have multiple values and the nvalues
1240 marker. Instead of adding heuristics here, we will let hook
1241 client code do that. */
1242 RESTORE_CONTINUATION_HOOK ();
1247 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1250 POP_CONTINUATION_HOOK (1);
1252 VM_HANDLE_INTERRUPTS
;
1259 #ifdef VM_ENABLE_STACK_NULLING
1263 /* Restore registers */
1264 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1265 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1266 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1268 #ifdef VM_ENABLE_STACK_NULLING
1269 NULLSTACK (old_sp
- sp
);
1272 /* Set return value (sp is already pushed) */
1276 /* Restore the last program */
1277 program
= SCM_FRAME_PROGRAM (fp
);
1283 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1285 /* nvalues declared at top level, because for some reason gcc seems to think
1286 that perhaps it might be used without declaration. Fooey to that, I say. */
1289 POP_CONTINUATION_HOOK (nvalues
);
1291 VM_HANDLE_INTERRUPTS
;
1293 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1295 /* A multiply-valued continuation */
1296 SCM
*vals
= sp
- nvalues
;
1298 /* Restore registers */
1299 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1300 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1301 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1303 /* Push return values, and the number of values */
1304 for (i
= 0; i
< nvalues
; i
++)
1306 *++sp
= SCM_I_MAKINUM (nvalues
);
1308 /* Finally null the end of the stack */
1309 NULLSTACK (vals
+ nvalues
- sp
);
1311 else if (nvalues
>= 1)
1313 /* Multiple values for a single-valued continuation -- here's where I
1314 break with guile tradition and try and do something sensible. (Also,
1315 this block handles the single-valued return to an mv
1317 SCM
*vals
= sp
- nvalues
;
1318 /* Restore registers */
1319 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1320 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1321 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1323 /* Push first value */
1326 /* Finally null the end of the stack */
1327 NULLSTACK (vals
+ nvalues
- sp
);
1330 goto vm_error_no_values
;
1332 /* Restore the last program */
1333 program
= SCM_FRAME_PROGRAM (fp
);
1339 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1344 ASSERT (nvalues
>= 1);
1348 while (scm_is_pair (l
))
1354 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1355 finish_args
= scm_list_1 (l
);
1356 goto vm_error_improper_list
;
1359 goto vm_return_values
;
1362 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1366 nvalues
= scm_to_int (n
);
1367 ASSERT (nvalues
>= 0);
1368 goto vm_return_values
;
1371 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1376 nvalues
= scm_to_int (x
);
1383 if (nvalues
< nbinds
)
1384 goto vm_error_not_enough_values
;
1387 POP_LIST (nvalues
- nbinds
);
1389 DROPN (nvalues
- nbinds
);
1394 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1399 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1404 (let ((a *undef*) (b *undef*) ...)
1405 (set! a (lambda () (b ...)))
1408 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1411 LOCAL_SET (FETCH (),
1412 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1416 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1418 SCM v
= LOCAL_REF (FETCH ());
1419 ASSERT_BOUND_VARIABLE (v
);
1420 PUSH (VARIABLE_REF (v
));
1424 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1427 v
= LOCAL_REF (FETCH ());
1429 ASSERT_VARIABLE (v
);
1430 VARIABLE_SET (v
, val
);
1434 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1436 scm_t_uint8 idx
= FETCH ();
1438 CHECK_FREE_VARIABLE (idx
);
1439 PUSH (FREE_VARIABLE_REF (idx
));
1443 /* no free-set -- if a var is assigned, it should be in a box */
1445 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1448 scm_t_uint8 idx
= FETCH ();
1449 CHECK_FREE_VARIABLE (idx
);
1450 v
= FREE_VARIABLE_REF (idx
);
1451 ASSERT_BOUND_VARIABLE (v
);
1452 PUSH (VARIABLE_REF (v
));
1456 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1459 scm_t_uint8 idx
= FETCH ();
1461 CHECK_FREE_VARIABLE (idx
);
1462 v
= FREE_VARIABLE_REF (idx
);
1463 ASSERT_BOUND_VARIABLE (v
);
1464 VARIABLE_SET (v
, val
);
1468 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1477 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1478 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1479 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1481 for (n
= 0; n
< len
; n
++)
1482 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1487 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1490 /* fixme underflow */
1491 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1495 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1498 unsigned int i
= FETCH ();
1502 /* FIXME CHECK_LOCAL (i) */
1504 /* FIXME ASSERT_PROGRAM (x); */
1505 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1506 for (n
= 0; n
< len
; n
++)
1507 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1512 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1518 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1524 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1528 *sp
= scm_symbol_to_keyword (*sp
);
1532 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1536 *sp
= scm_string_to_symbol (*sp
);
1540 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1543 scm_t_uint8 escape_only_p
;
1546 escape_only_p
= FETCH ();
1547 FETCH_OFFSET (offset
);
1551 /* Push the prompt onto the dynamic stack. */
1552 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1554 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1555 if (SCM_PROMPT_SETJMP (prompt
))
1557 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1560 Note, at this point, we must assume that any variable local to
1561 vm_engine that can be assigned *has* been assigned. So we need to pull
1562 all our state back from the ip/fp/sp.
1565 program
= SCM_FRAME_PROGRAM (fp
);
1567 /* The stack contains the values returned to this prompt, along
1568 with a number-of-values marker -- like an MV return. */
1569 ABORT_CONTINUATION_HOOK ();
1573 /* Otherwise setjmp returned for the first time, so we go to execute the
1578 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1584 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1585 are actually called; the compiler should emit calls to wind and unwind for
1586 the normal dynamic-wind control flow. */
1587 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1590 goto vm_error_not_a_thunk
;
1592 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1594 finish_args
= unwind
;
1595 goto vm_error_not_a_thunk
;
1597 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1601 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1603 unsigned n
= FETCH ();
1605 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1606 goto vm_error_stack_underflow
;
1607 vm_abort (vm
, n
, vm_cookie
);
1608 /* vm_abort should not return */
1612 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1614 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1615 off of the dynamic stack. */
1616 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1620 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1622 unsigned n
= FETCH ();
1628 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1631 scm_i_swap_with_fluids (wf
, dynstate
);
1632 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1636 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1639 wf
= scm_car (scm_i_dynwinds ());
1640 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1641 scm_i_swap_with_fluids (wf
, dynstate
);
1645 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1651 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
1652 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1653 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1655 /* Punt dynstate expansion and error handling to the C proc. */
1657 *sp
= scm_fluid_ref (*sp
);
1661 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1662 if (SCM_UNLIKELY (val
== SCM_UNDEFINED
))
1665 goto vm_error_unbound_fluid
;
1673 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1676 SCM val
, fluid
, fluids
;
1680 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
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)))