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 */
759 PUSH ((SCM
)fp
); /* dynamic link */
765 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
770 program
= sp
[-nargs
];
772 VM_HANDLE_INTERRUPTS
;
774 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
776 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
778 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
781 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
782 && SCM_SMOB_APPLICABLE_P (program
))
785 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
789 goto vm_error_wrong_type_apply
;
794 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
795 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
796 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
797 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
798 ip
= SCM_C_OBJCODE_BASE (bp
);
799 PUSH_CONTINUATION_HOOK ();
804 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
809 program
= sp
[-nargs
];
811 VM_HANDLE_INTERRUPTS
;
813 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
815 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
817 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
820 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
821 && SCM_SMOB_APPLICABLE_P (program
))
824 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
828 goto vm_error_wrong_type_apply
;
833 #ifdef VM_ENABLE_STACK_NULLING
838 /* switch programs */
840 /* shuffle down the program and the arguments */
841 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
842 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
846 NULLSTACK (old_sp
- sp
);
848 ip
= SCM_C_OBJCODE_BASE (bp
);
855 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
863 subr
= SCM_POINTER_VALUE (pointer
);
865 VM_HANDLE_INTERRUPTS
;
877 ret
= subr (sp
[-1], sp
[0]);
880 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
883 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
886 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
889 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
892 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
895 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
898 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
901 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
907 NULLSTACK_FOR_NONLOCAL_EXIT ();
909 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
911 /* multiple values returned to continuation */
912 ret
= scm_struct_ref (ret
, SCM_INUM0
);
913 nvalues
= scm_ilength (ret
);
914 PUSH_LIST (ret
, scm_is_null
);
915 goto vm_return_values
;
924 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
931 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
933 VM_HANDLE_INTERRUPTS
;
942 ret
= subr (smob
, sp
[0]);
945 ret
= subr (smob
, sp
[-1], sp
[0]);
948 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
954 NULLSTACK_FOR_NONLOCAL_EXIT ();
956 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
958 /* multiple values returned to continuation */
959 ret
= scm_struct_ref (ret
, SCM_INUM0
);
960 nvalues
= scm_ilength (ret
);
961 PUSH_LIST (ret
, scm_is_null
);
962 goto vm_return_values
;
971 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
977 VM_HANDLE_INTERRUPTS
;
980 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
982 NULLSTACK_FOR_NONLOCAL_EXIT ();
984 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
986 /* multiple values returned to continuation */
987 ret
= scm_struct_ref (ret
, SCM_INUM0
);
988 nvalues
= scm_ilength (ret
);
989 PUSH_LIST (ret
, scm_is_null
);
990 goto vm_return_values
;
999 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1005 scm_i_check_continuation (contregs
);
1006 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1007 scm_i_contregs_vm_cont (contregs
),
1009 scm_i_reinstate_continuation (contregs
);
1015 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1017 SCM vmcont
, intwinds
, prevwinds
;
1021 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
1022 { finish_args
= vmcont
;
1023 goto vm_error_continuation_not_rewindable
;
1025 prevwinds
= scm_i_dynwinds ();
1026 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1029 /* Rewind prompt jmpbuffers, if any. */
1031 SCM winds
= scm_i_dynwinds ();
1032 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1033 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1038 program
= SCM_FRAME_PROGRAM (fp
);
1043 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1047 nargs
= scm_to_int (x
);
1048 /* FIXME: should truncate values? */
1052 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1056 nargs
= scm_to_int (x
);
1057 /* FIXME: should truncate values? */
1061 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1067 FETCH_OFFSET (offset
);
1071 program
= sp
[-nargs
];
1073 VM_HANDLE_INTERRUPTS
;
1075 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1077 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1079 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1082 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1083 && SCM_SMOB_APPLICABLE_P (program
))
1086 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1090 goto vm_error_wrong_type_apply
;
1094 fp
= sp
- nargs
+ 1;
1095 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1096 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1097 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1098 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1099 ip
= SCM_C_OBJCODE_BASE (bp
);
1100 PUSH_CONTINUATION_HOOK ();
1105 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1112 ASSERT (nargs
>= 2);
1114 len
= scm_ilength (ls
);
1115 if (SCM_UNLIKELY (len
< 0))
1118 goto vm_error_apply_to_non_list
;
1121 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1127 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1134 ASSERT (nargs
>= 2);
1136 len
= scm_ilength (ls
);
1137 if (SCM_UNLIKELY (len
< 0))
1140 goto vm_error_apply_to_non_list
;
1143 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1149 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1152 SCM proc
, vm_cont
, cont
;
1155 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1156 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1159 PUSH ((SCM
)fp
); /* dynamic link */
1160 PUSH (0); /* mvra */
1169 /* Otherwise, the vm continuation was reinstated, and
1170 vm_return_to_continuation pushed on one value. We know only one
1171 value was returned because we are in value context -- the
1172 previous block jumped to vm_call, not vm_mv_call, after all.
1174 So, pull our regs back down from the vp, and march on to the
1175 next instruction. */
1177 program
= SCM_FRAME_PROGRAM (fp
);
1179 RESTORE_CONTINUATION_HOOK ();
1184 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1187 SCM proc
, vm_cont
, cont
;
1190 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1192 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1193 SCM_FRAME_DYNAMIC_LINK (fp
),
1194 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1195 SCM_FRAME_RETURN_ADDRESS (fp
),
1196 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1198 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1208 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1209 does a return from the frame, either to the RA or
1212 program
= SCM_FRAME_PROGRAM (fp
);
1214 /* Unfortunately we don't know whether we are at the RA, and thus
1215 have one value without an nvalues marker, or we are at the
1216 MVRA and thus have multiple values and the nvalues
1217 marker. Instead of adding heuristics here, we will let hook
1218 client code do that. */
1219 RESTORE_CONTINUATION_HOOK ();
1224 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1227 POP_CONTINUATION_HOOK (1);
1229 VM_HANDLE_INTERRUPTS
;
1236 #ifdef VM_ENABLE_STACK_NULLING
1240 /* Restore registers */
1241 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1242 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1243 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1245 #ifdef VM_ENABLE_STACK_NULLING
1246 NULLSTACK (old_sp
- sp
);
1249 /* Set return value (sp is already pushed) */
1253 /* Restore the last program */
1254 program
= SCM_FRAME_PROGRAM (fp
);
1260 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1262 /* nvalues declared at top level, because for some reason gcc seems to think
1263 that perhaps it might be used without declaration. Fooey to that, I say. */
1266 POP_CONTINUATION_HOOK (nvalues
);
1268 VM_HANDLE_INTERRUPTS
;
1270 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1272 /* A multiply-valued continuation */
1273 SCM
*vals
= sp
- nvalues
;
1275 /* Restore registers */
1276 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1277 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1278 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1280 /* Push return values, and the number of values */
1281 for (i
= 0; i
< nvalues
; i
++)
1283 *++sp
= SCM_I_MAKINUM (nvalues
);
1285 /* Finally null the end of the stack */
1286 NULLSTACK (vals
+ nvalues
- sp
);
1288 else if (nvalues
>= 1)
1290 /* Multiple values for a single-valued continuation -- here's where I
1291 break with guile tradition and try and do something sensible. (Also,
1292 this block handles the single-valued return to an mv
1294 SCM
*vals
= sp
- nvalues
;
1295 /* Restore registers */
1296 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1297 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1298 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1300 /* Push first value */
1303 /* Finally null the end of the stack */
1304 NULLSTACK (vals
+ nvalues
- sp
);
1307 goto vm_error_no_values
;
1309 /* Restore the last program */
1310 program
= SCM_FRAME_PROGRAM (fp
);
1316 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1321 ASSERT (nvalues
>= 1);
1325 while (scm_is_pair (l
))
1331 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1332 finish_args
= scm_list_1 (l
);
1333 goto vm_error_improper_list
;
1336 goto vm_return_values
;
1339 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1343 nvalues
= scm_to_int (n
);
1344 ASSERT (nvalues
>= 0);
1345 goto vm_return_values
;
1348 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1353 nvalues
= scm_to_int (x
);
1360 if (nvalues
< nbinds
)
1361 goto vm_error_not_enough_values
;
1364 POP_LIST (nvalues
- nbinds
);
1366 DROPN (nvalues
- nbinds
);
1371 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1376 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1381 (let ((a *undef*) (b *undef*) ...)
1382 (set! a (lambda () (b ...)))
1385 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1388 LOCAL_SET (FETCH (),
1389 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1393 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1395 SCM v
= LOCAL_REF (FETCH ());
1396 ASSERT_BOUND_VARIABLE (v
);
1397 PUSH (VARIABLE_REF (v
));
1401 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1404 v
= LOCAL_REF (FETCH ());
1406 ASSERT_VARIABLE (v
);
1407 VARIABLE_SET (v
, val
);
1411 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1413 scm_t_uint8 idx
= FETCH ();
1415 CHECK_FREE_VARIABLE (idx
);
1416 PUSH (FREE_VARIABLE_REF (idx
));
1420 /* no free-set -- if a var is assigned, it should be in a box */
1422 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1425 scm_t_uint8 idx
= FETCH ();
1426 CHECK_FREE_VARIABLE (idx
);
1427 v
= FREE_VARIABLE_REF (idx
);
1428 ASSERT_BOUND_VARIABLE (v
);
1429 PUSH (VARIABLE_REF (v
));
1433 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1436 scm_t_uint8 idx
= FETCH ();
1438 CHECK_FREE_VARIABLE (idx
);
1439 v
= FREE_VARIABLE_REF (idx
);
1440 ASSERT_BOUND_VARIABLE (v
);
1441 VARIABLE_SET (v
, val
);
1445 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1454 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1455 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1456 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1458 for (n
= 0; n
< len
; n
++)
1459 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1464 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1467 /* fixme underflow */
1468 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1472 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1475 unsigned int i
= FETCH ();
1479 /* FIXME CHECK_LOCAL (i) */
1481 /* FIXME ASSERT_PROGRAM (x); */
1482 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1483 for (n
= 0; n
< len
; n
++)
1484 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1489 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1495 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1501 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1505 *sp
= scm_symbol_to_keyword (*sp
);
1509 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1513 *sp
= scm_string_to_symbol (*sp
);
1517 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1520 scm_t_uint8 escape_only_p
;
1523 escape_only_p
= FETCH ();
1524 FETCH_OFFSET (offset
);
1528 /* Push the prompt onto the dynamic stack. */
1529 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1531 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1532 if (SCM_PROMPT_SETJMP (prompt
))
1534 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1537 Note, at this point, we must assume that any variable local to
1538 vm_engine that can be assigned *has* been assigned. So we need to pull
1539 all our state back from the ip/fp/sp.
1542 program
= SCM_FRAME_PROGRAM (fp
);
1544 /* The stack contains the values returned to this prompt, along
1545 with a number-of-values marker -- like an MV return. */
1546 ABORT_CONTINUATION_HOOK ();
1550 /* Otherwise setjmp returned for the first time, so we go to execute the
1555 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1561 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1562 are actually called; the compiler should emit calls to wind and unwind for
1563 the normal dynamic-wind control flow. */
1564 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1567 goto vm_error_not_a_thunk
;
1569 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1571 finish_args
= unwind
;
1572 goto vm_error_not_a_thunk
;
1574 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1578 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1580 unsigned n
= FETCH ();
1582 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1583 goto vm_error_stack_underflow
;
1584 vm_abort (vm
, n
, vm_cookie
);
1585 /* vm_abort should not return */
1589 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1591 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1592 off of the dynamic stack. */
1593 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1597 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1599 unsigned n
= FETCH ();
1605 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1608 scm_i_swap_with_fluids (wf
, dynstate
);
1609 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1613 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1616 wf
= scm_car (scm_i_dynwinds ());
1617 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1618 scm_i_swap_with_fluids (wf
, dynstate
);
1622 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1628 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
1629 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1630 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1632 /* Punt dynstate expansion and error handling to the C proc. */
1634 *sp
= scm_fluid_ref (*sp
);
1638 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1639 if (SCM_UNLIKELY (val
== SCM_UNDEFINED
))
1642 goto vm_error_unbound_fluid
;
1650 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1653 SCM val
, fluid
, fluids
;
1657 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
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 if (SCM_UNLIKELY (sp
- (fp
- 1) != (n
& 0x7)))
1680 goto vm_error_wrong_num_args
;
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)))