1 /* Copyright (C) 2001,2008,2009,2010,2011,2012 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
)))
313 /* Attempt to provide the variable name in the error message. */
314 var_name
= scm_module_reverse_lookup (scm_current_module (), x
);
315 vm_error_unbound (program
, scm_is_true (var_name
) ? var_name
: x
);
319 SCM o
= VARIABLE_REF (x
);
326 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
330 VM_ASSERT (SCM_VARIABLEP (x
),
331 vm_error_not_a_variable ("variable-bound?", x
));
333 *sp
= scm_from_bool (VARIABLE_BOUNDP (x
));
337 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
339 unsigned objnum
= FETCH ();
341 CHECK_OBJECT (objnum
);
342 what
= OBJECT_REF (objnum
);
344 if (!SCM_VARIABLEP (what
))
347 resolved
= resolve_variable (what
, scm_program_module (program
));
348 VM_ASSERT (VARIABLE_BOUNDP (resolved
), vm_error_unbound (program
, what
));
350 OBJECT_SET (objnum
, what
);
353 PUSH (VARIABLE_REF (what
));
357 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
360 unsigned int objnum
= FETCH ();
363 CHECK_OBJECT (objnum
);
364 what
= OBJECT_REF (objnum
);
366 if (!SCM_VARIABLEP (what
))
369 resolved
= resolve_variable (what
, scm_program_module (program
));
370 VM_ASSERT (VARIABLE_BOUNDP (resolved
),
371 vm_error_unbound (program
, what
));
373 OBJECT_SET (objnum
, what
);
376 PUSH (VARIABLE_REF (what
));
382 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
386 LOCAL_SET (FETCH (), x
);
390 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
393 unsigned int i
= FETCH ();
401 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
403 VM_ASSERT (SCM_VARIABLEP (sp
[0]),
404 vm_error_not_a_variable ("variable-set!", sp
[0]));
405 VARIABLE_SET (sp
[0], sp
[-1]);
410 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
412 unsigned objnum
= FETCH ();
414 CHECK_OBJECT (objnum
);
415 what
= OBJECT_REF (objnum
);
417 if (!SCM_VARIABLEP (what
))
420 what
= resolve_variable (what
, scm_program_module (program
));
421 OBJECT_SET (objnum
, what
);
424 VARIABLE_SET (what
, *sp
);
429 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
432 unsigned int objnum
= FETCH ();
435 CHECK_OBJECT (objnum
);
436 what
= OBJECT_REF (objnum
);
438 if (!SCM_VARIABLEP (what
))
441 what
= resolve_variable (what
, scm_program_module (program
));
442 OBJECT_SET (objnum
, what
);
445 VARIABLE_SET (what
, *sp
);
455 /* offset must be at least 24 bits wide, and signed */
456 #define FETCH_OFFSET(offset) \
458 offset = FETCH () << 16; \
459 offset += FETCH () << 8; \
460 offset += FETCH (); \
461 offset -= (offset & (1<<23)) << 1; \
466 scm_t_int32 offset; \
467 FETCH_OFFSET (offset); \
471 VM_HANDLE_INTERRUPTS; \
475 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
478 FETCH_OFFSET (offset
);
481 VM_HANDLE_INTERRUPTS
;
485 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
489 BR (scm_is_true (x
));
492 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
496 BR (scm_is_false (x
));
499 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
503 BR (scm_is_eq (x
, y
));
506 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
510 BR (!scm_is_eq (x
, y
));
513 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
517 BR (scm_is_null (x
));
520 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
524 BR (!scm_is_null (x
));
532 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
538 FETCH_OFFSET (offset
);
539 if (sp
- (fp
- 1) != n
)
544 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
550 FETCH_OFFSET (offset
);
551 if (sp
- (fp
- 1) < n
)
556 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
563 FETCH_OFFSET (offset
);
564 if (sp
- (fp
- 1) > n
)
569 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
574 VM_ASSERT (sp
- (fp
- 1) == n
,
575 vm_error_wrong_num_args (program
));
579 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
584 VM_ASSERT (sp
- (fp
- 1) >= n
,
585 vm_error_wrong_num_args (program
));
589 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
594 while (sp
- (fp
- 1) < n
)
595 PUSH (SCM_UNDEFINED
);
599 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
602 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
603 nreq
= FETCH () << 8;
605 nreq_and_opt
= FETCH () << 8;
606 nreq_and_opt
+= FETCH ();
607 ntotal
= FETCH () << 8;
610 /* look in optionals for first keyword or last positional */
611 /* starting after the last required positional arg */
613 while (/* while we have args */
615 /* and we still have positionals to fill */
616 && walk
- fp
< nreq_and_opt
617 /* and we haven't reached a keyword yet */
618 && !scm_is_keyword (*walk
))
619 /* bind this optional arg (by leaving it in place) */
621 /* now shuffle up, from walk to ntotal */
623 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
624 sp
= (fp
- 1) + ntotal
+ nshuf
;
626 for (i
= 0; i
< nshuf
; i
++)
627 sp
[-i
] = walk
[nshuf
-i
-1];
629 /* and fill optionals & keyword args with SCM_UNDEFINED */
630 while (walk
<= (fp
- 1) + ntotal
)
631 *walk
++ = SCM_UNDEFINED
;
636 /* Flags that determine whether other keywords are allowed, and whether a
637 rest argument is expected. These values must match those used by the
638 glil->assembly compiler. */
639 #define F_ALLOW_OTHER_KEYS 1
642 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
646 int kw_and_rest_flags
;
650 /* XXX: We don't actually use NKW. */
653 kw_and_rest_flags
= FETCH ();
655 VM_ASSERT ((kw_and_rest_flags
& F_REST
)
656 || ((sp
- (fp
- 1) - nkw
) % 2) == 0,
657 vm_error_kwargs_length_not_even (program
))
660 kw
= OBJECT_REF (idx
);
662 /* Switch NKW to be a negative index below SP. */
663 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
667 if (scm_is_keyword (sp
[nkw
]))
669 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
671 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
673 SCM si
= SCM_CDAR (walk
);
674 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
679 VM_ASSERT (scm_is_pair (walk
)
680 || (kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
),
681 vm_error_kwargs_unrecognized_keyword (program
));
685 VM_ASSERT (kw_and_rest_flags
& F_REST
,
686 vm_error_kwargs_invalid_keyword (program
));
692 #undef F_ALLOW_OTHER_KEYS
696 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
702 while (sp
- (fp
- 1) > n
)
703 /* No need to check for underflow. */
704 CONS (rest
, *sp
--, rest
);
709 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
718 while (sp
- (fp
- 1) > n
)
719 /* No need to check for underflow. */
720 CONS (rest
, *sp
--, rest
);
725 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
738 *++old_sp
= SCM_UNDEFINED
;
741 NULLSTACK (old_sp
- sp
);
746 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
748 /* NB: if you change this, see frames.c:vm-frame-num-locals */
749 /* and frames.h, vm-engine.c, etc of course */
751 /* We don't initialize the dynamic link here because we don't actually
752 know that this frame will point to the current fp: it could be
753 placed elsewhere on the stack if captured in a partial
754 continuation, and invoked from some other context. */
755 PUSH (SCM_PACK (0)); /* dynamic link */
756 PUSH (SCM_PACK (0)); /* mvra */
757 PUSH (SCM_PACK (0)); /* ra */
761 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
766 program
= sp
[-nargs
];
768 VM_HANDLE_INTERRUPTS
;
770 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
772 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
774 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
777 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
778 && SCM_SMOB_APPLICABLE_P (program
))
781 prepare_smob_call (sp
, ++nargs
, program
);
787 vm_error_wrong_type_apply (program
);
798 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
799 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
800 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
801 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
802 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
803 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
806 ip
= SCM_C_OBJCODE_BASE (bp
);
807 PUSH_CONTINUATION_HOOK ();
812 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
817 program
= sp
[-nargs
];
819 VM_HANDLE_INTERRUPTS
;
821 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
823 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
825 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
828 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
829 && SCM_SMOB_APPLICABLE_P (program
))
832 prepare_smob_call (sp
, ++nargs
, program
);
838 vm_error_wrong_type_apply (program
);
844 #ifdef VM_ENABLE_STACK_NULLING
849 /* switch programs */
851 /* shuffle down the program and the arguments */
852 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
853 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
857 NULLSTACK (old_sp
- sp
);
859 ip
= SCM_C_OBJCODE_BASE (bp
);
866 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
874 subr
= SCM_POINTER_VALUE (pointer
);
876 VM_HANDLE_INTERRUPTS
;
888 ret
= subr (sp
[-1], sp
[0]);
891 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
894 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
897 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
900 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
903 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
906 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
909 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
912 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
918 NULLSTACK_FOR_NONLOCAL_EXIT ();
920 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
922 /* multiple values returned to continuation */
923 ret
= scm_struct_ref (ret
, SCM_INUM0
);
924 nvalues
= scm_ilength (ret
);
925 PUSH_LIST (ret
, scm_is_null
);
926 goto vm_return_values
;
935 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
942 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
944 VM_HANDLE_INTERRUPTS
;
953 ret
= subr (smob
, sp
[0]);
956 ret
= subr (smob
, sp
[-1], sp
[0]);
959 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
965 NULLSTACK_FOR_NONLOCAL_EXIT ();
967 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
969 /* multiple values returned to continuation */
970 ret
= scm_struct_ref (ret
, SCM_INUM0
);
971 nvalues
= scm_ilength (ret
);
972 PUSH_LIST (ret
, scm_is_null
);
973 goto vm_return_values
;
982 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
988 VM_HANDLE_INTERRUPTS
;
991 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
993 NULLSTACK_FOR_NONLOCAL_EXIT ();
995 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
997 /* multiple values returned to continuation */
998 ret
= scm_struct_ref (ret
, SCM_INUM0
);
999 nvalues
= scm_ilength (ret
);
1000 PUSH_LIST (ret
, scm_is_null
);
1001 goto vm_return_values
;
1010 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1016 scm_i_check_continuation (contregs
);
1017 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1018 scm_i_contregs_vm_cont (contregs
),
1020 scm_i_reinstate_continuation (contregs
);
1026 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1028 SCM vmcont
, intwinds
, prevwinds
;
1029 POP2 (intwinds
, vmcont
);
1031 VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont
),
1032 vm_error_continuation_not_rewindable (vmcont
));
1033 prevwinds
= scm_i_dynwinds ();
1034 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1037 /* Rewind prompt jmpbuffers, if any. */
1039 SCM winds
= scm_i_dynwinds ();
1040 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1041 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1046 program
= SCM_FRAME_PROGRAM (fp
);
1051 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1055 nargs
= scm_to_int (x
);
1056 /* FIXME: should truncate values? */
1060 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1064 nargs
= scm_to_int (x
);
1065 /* FIXME: should truncate values? */
1069 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1075 FETCH_OFFSET (offset
);
1079 program
= sp
[-nargs
];
1081 VM_HANDLE_INTERRUPTS
;
1083 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1085 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1087 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1090 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1091 && SCM_SMOB_APPLICABLE_P (program
))
1094 prepare_smob_call (sp
, ++nargs
, program
);
1100 vm_error_wrong_type_apply (program
);
1109 fp
= sp
- nargs
+ 1;
1111 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1112 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1113 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1114 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1115 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1116 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1119 ip
= SCM_C_OBJCODE_BASE (bp
);
1120 PUSH_CONTINUATION_HOOK ();
1125 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1132 ASSERT (nargs
>= 2);
1134 len
= scm_ilength (ls
);
1135 VM_ASSERT (len
>= 0,
1136 vm_error_apply_to_non_list (ls
));
1137 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1143 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1150 ASSERT (nargs
>= 2);
1152 len
= scm_ilength (ls
);
1153 VM_ASSERT (len
>= 0,
1154 vm_error_apply_to_non_list (ls
));
1155 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1161 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1164 SCM proc
, vm_cont
, cont
;
1167 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1168 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1171 PUSH (SCM_PACK (0)); /* dynamic link */
1172 PUSH (SCM_PACK (0)); /* mvra */
1173 PUSH (SCM_PACK (0)); /* ra */
1181 /* Otherwise, the vm continuation was reinstated, and
1182 vm_return_to_continuation pushed on one value. We know only one
1183 value was returned because we are in value context -- the
1184 previous block jumped to vm_call, not vm_mv_call, after all.
1186 So, pull our regs back down from the vp, and march on to the
1187 next instruction. */
1189 program
= SCM_FRAME_PROGRAM (fp
);
1191 RESTORE_CONTINUATION_HOOK ();
1196 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1199 SCM proc
, vm_cont
, cont
;
1202 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1204 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1205 SCM_FRAME_DYNAMIC_LINK (fp
),
1206 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1207 SCM_FRAME_RETURN_ADDRESS (fp
),
1208 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1210 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1220 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1221 does a return from the frame, either to the RA or
1224 program
= SCM_FRAME_PROGRAM (fp
);
1226 /* Unfortunately we don't know whether we are at the RA, and thus
1227 have one value without an nvalues marker, or we are at the
1228 MVRA and thus have multiple values and the nvalues
1229 marker. Instead of adding heuristics here, we will let hook
1230 client code do that. */
1231 RESTORE_CONTINUATION_HOOK ();
1236 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1239 POP_CONTINUATION_HOOK (1);
1241 VM_HANDLE_INTERRUPTS
;
1248 #ifdef VM_ENABLE_STACK_NULLING
1252 /* Restore registers */
1253 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1254 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1255 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1257 #ifdef VM_ENABLE_STACK_NULLING
1258 NULLSTACK (old_sp
- sp
);
1261 /* Set return value (sp is already pushed) */
1265 /* Restore the last program */
1266 program
= SCM_FRAME_PROGRAM (fp
);
1272 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1274 /* nvalues declared at top level, because for some reason gcc seems to think
1275 that perhaps it might be used without declaration. Fooey to that, I say. */
1278 POP_CONTINUATION_HOOK (nvalues
);
1280 VM_HANDLE_INTERRUPTS
;
1282 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1284 /* A multiply-valued continuation */
1285 SCM
*vals
= sp
- nvalues
;
1287 /* Restore registers */
1288 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1289 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1290 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1292 /* Push return values, and the number of values */
1293 for (i
= 0; i
< nvalues
; i
++)
1295 *++sp
= SCM_I_MAKINUM (nvalues
);
1297 /* Finally null the end of the stack */
1298 NULLSTACK (vals
+ nvalues
- sp
);
1300 else if (nvalues
>= 1)
1302 /* Multiple values for a single-valued continuation -- here's where I
1303 break with guile tradition and try and do something sensible. (Also,
1304 this block handles the single-valued return to an mv
1306 SCM
*vals
= sp
- nvalues
;
1307 /* Restore registers */
1308 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1309 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1310 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1312 /* Push first value */
1315 /* Finally null the end of the stack */
1316 NULLSTACK (vals
+ nvalues
- sp
);
1321 vm_error_no_values ();
1324 /* Restore the last program */
1325 program
= SCM_FRAME_PROGRAM (fp
);
1331 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1336 ASSERT (nvalues
>= 1);
1340 while (scm_is_pair (l
))
1346 VM_ASSERT (SCM_NULL_OR_NIL_P (l
), vm_error_improper_list (l
));
1348 goto vm_return_values
;
1351 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1355 nvalues
= scm_to_int (n
);
1356 ASSERT (nvalues
>= 0);
1357 goto vm_return_values
;
1360 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1365 nvalues
= scm_to_int (x
);
1372 VM_ASSERT (nvalues
>= nbinds
, vm_error_not_enough_values ());
1375 POP_LIST (nvalues
- nbinds
);
1377 DROPN (nvalues
- nbinds
);
1382 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1387 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1392 (let ((a *undef*) (b *undef*) ...)
1393 (set! a (lambda () (b ...)))
1396 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1399 LOCAL_SET (FETCH (),
1400 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1404 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1406 SCM v
= LOCAL_REF (FETCH ());
1407 ASSERT_BOUND_VARIABLE (v
);
1408 PUSH (VARIABLE_REF (v
));
1412 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1415 v
= LOCAL_REF (FETCH ());
1417 ASSERT_VARIABLE (v
);
1418 VARIABLE_SET (v
, val
);
1422 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1424 scm_t_uint8 idx
= FETCH ();
1426 CHECK_FREE_VARIABLE (idx
);
1427 PUSH (FREE_VARIABLE_REF (idx
));
1431 /* no free-set -- if a var is assigned, it should be in a box */
1433 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1436 scm_t_uint8 idx
= FETCH ();
1437 CHECK_FREE_VARIABLE (idx
);
1438 v
= FREE_VARIABLE_REF (idx
);
1439 ASSERT_BOUND_VARIABLE (v
);
1440 PUSH (VARIABLE_REF (v
));
1444 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1447 scm_t_uint8 idx
= FETCH ();
1449 CHECK_FREE_VARIABLE (idx
);
1450 v
= FREE_VARIABLE_REF (idx
);
1451 ASSERT_BOUND_VARIABLE (v
);
1452 VARIABLE_SET (v
, val
);
1456 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1465 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1466 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1467 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1469 for (n
= 0; n
< len
; n
++)
1470 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1475 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1478 /* fixme underflow */
1479 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1483 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1486 unsigned int i
= FETCH ();
1490 /* FIXME CHECK_LOCAL (i) */
1492 /* FIXME ASSERT_PROGRAM (x); */
1493 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1494 for (n
= 0; n
< len
; n
++)
1495 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1500 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1505 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1511 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1515 *sp
= scm_symbol_to_keyword (*sp
);
1519 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1523 *sp
= scm_string_to_symbol (*sp
);
1527 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1530 scm_t_uint8 escape_only_p
;
1533 escape_only_p
= FETCH ();
1534 FETCH_OFFSET (offset
);
1538 /* Push the prompt onto the dynamic stack. */
1539 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1541 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1542 if (SCM_PROMPT_SETJMP (prompt
))
1544 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1547 Note, at this point, we must assume that any variable local to
1548 vm_engine that can be assigned *has* been assigned. So we need to pull
1549 all our state back from the ip/fp/sp.
1552 program
= SCM_FRAME_PROGRAM (fp
);
1554 /* The stack contains the values returned to this prompt, along
1555 with a number-of-values marker -- like an MV return. */
1556 ABORT_CONTINUATION_HOOK ();
1560 /* Otherwise setjmp returned for the first time, so we go to execute the
1565 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1568 POP2 (unwind
, wind
);
1570 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1571 are actually called; the compiler should emit calls to wind and unwind for
1572 the normal dynamic-wind control flow. */
1573 VM_ASSERT (scm_to_bool (scm_thunk_p (wind
)),
1574 vm_error_not_a_thunk ("dynamic-wind", wind
));
1575 VM_ASSERT (scm_to_bool (scm_thunk_p (unwind
)),
1576 vm_error_not_a_thunk ("dynamic-wind", unwind
));
1577 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1581 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1583 unsigned n
= FETCH ();
1585 PRE_CHECK_UNDERFLOW (n
+ 2);
1586 vm_abort (vm
, n
, vm_cookie
);
1587 /* vm_abort should not return */
1591 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1593 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1594 off of the dynamic stack. */
1595 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1599 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1601 unsigned n
= FETCH ();
1607 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1610 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1611 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1615 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1618 wf
= scm_car (scm_i_dynwinds ());
1619 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1620 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1624 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1630 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1631 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1632 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1634 /* Punt dynstate expansion and error handling to the C proc. */
1636 *sp
= scm_fluid_ref (*sp
);
1640 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1641 if (scm_is_eq (val
, SCM_UNDEFINED
))
1642 val
= SCM_I_FLUID_DEFAULT (*sp
);
1643 VM_ASSERT (!scm_is_eq (val
, SCM_UNDEFINED
),
1644 vm_error_unbound_fluid (program
, *sp
));
1651 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1654 SCM val
, fluid
, fluids
;
1657 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1658 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1659 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1661 /* Punt dynstate expansion and error handling to the C proc. */
1663 scm_fluid_set_x (fluid
, val
);
1666 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1671 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1676 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1679 VM_ASSERT (sp
- (fp
- 1) == (n
& 0x7),
1680 vm_error_wrong_num_args (program
));
1686 *++old_sp
= SCM_UNDEFINED
;
1693 (defun renumber-ops ()
1694 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1697 (let ((counter -1)) (goto-char (point-min))
1698 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1700 (number-to-string (setq counter (1+ counter)))