1 /* Copyright (C) 2001,2008,2009,2010 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 if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x
)))
307 /* Attempt to provide the variable name in the error message. */
308 var_name
= scm_module_reverse_lookup (scm_current_module (), x
);
309 finish_args
= scm_list_1 (scm_is_true (var_name
) ? var_name
: x
);
310 goto vm_error_unbound
;
314 SCM o
= VARIABLE_REF (x
);
321 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
323 if (VARIABLE_BOUNDP (*sp
))
330 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
332 unsigned objnum
= FETCH ();
334 CHECK_OBJECT (objnum
);
335 what
= OBJECT_REF (objnum
);
337 if (!SCM_VARIABLEP (what
))
340 what
= resolve_variable (what
, scm_program_module (program
));
341 if (!VARIABLE_BOUNDP (what
))
343 finish_args
= scm_list_1 (what
);
344 goto vm_error_unbound
;
346 OBJECT_SET (objnum
, what
);
349 PUSH (VARIABLE_REF (what
));
353 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
356 unsigned int objnum
= FETCH ();
359 CHECK_OBJECT (objnum
);
360 what
= OBJECT_REF (objnum
);
362 if (!SCM_VARIABLEP (what
))
365 what
= resolve_variable (what
, scm_program_module (program
));
366 if (!VARIABLE_BOUNDP (what
))
368 finish_args
= scm_list_1 (what
);
369 goto vm_error_unbound
;
371 OBJECT_SET (objnum
, what
);
374 PUSH (VARIABLE_REF (what
));
380 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
382 LOCAL_SET (FETCH (), *sp
);
387 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
389 unsigned int i
= FETCH ();
397 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
399 VARIABLE_SET (sp
[0], sp
[-1]);
404 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
406 unsigned objnum
= FETCH ();
408 CHECK_OBJECT (objnum
);
409 what
= OBJECT_REF (objnum
);
411 if (!SCM_VARIABLEP (what
))
414 what
= resolve_variable (what
, scm_program_module (program
));
415 OBJECT_SET (objnum
, what
);
418 VARIABLE_SET (what
, *sp
);
423 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
426 unsigned int objnum
= FETCH ();
429 CHECK_OBJECT (objnum
);
430 what
= OBJECT_REF (objnum
);
432 if (!SCM_VARIABLEP (what
))
435 what
= resolve_variable (what
, scm_program_module (program
));
436 OBJECT_SET (objnum
, what
);
439 VARIABLE_SET (what
, *sp
);
449 /* offset must be at least 24 bits wide, and signed */
450 #define FETCH_OFFSET(offset) \
452 offset = FETCH () << 16; \
453 offset += FETCH () << 8; \
454 offset += FETCH (); \
455 offset -= (offset & (1<<23)) << 1; \
460 scm_t_int32 offset; \
461 FETCH_OFFSET (offset); \
465 VM_HANDLE_INTERRUPTS; \
471 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
474 FETCH_OFFSET (offset
);
477 VM_HANDLE_INTERRUPTS
;
481 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
483 BR (scm_is_true (*sp
));
486 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
488 BR (scm_is_false (*sp
));
491 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
493 sp
--; /* underflow? */
494 BR (scm_is_eq (sp
[0], sp
[1]));
497 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
499 sp
--; /* underflow? */
500 BR (!scm_is_eq (sp
[0], sp
[1]));
503 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
505 BR (scm_is_null (*sp
));
508 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
510 BR (!scm_is_null (*sp
));
518 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
524 FETCH_OFFSET (offset
);
525 if (sp
- (fp
- 1) != n
)
530 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
536 FETCH_OFFSET (offset
);
537 if (sp
- (fp
- 1) < n
)
542 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
549 FETCH_OFFSET (offset
);
550 if (sp
- (fp
- 1) > n
)
555 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
560 if (sp
- (fp
- 1) != n
)
561 goto vm_error_wrong_num_args
;
565 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
570 if (sp
- (fp
- 1) < n
)
571 goto vm_error_wrong_num_args
;
575 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
580 while (sp
- (fp
- 1) < n
)
581 PUSH (SCM_UNDEFINED
);
585 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
588 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
589 nreq
= FETCH () << 8;
591 nreq_and_opt
= FETCH () << 8;
592 nreq_and_opt
+= FETCH ();
593 ntotal
= FETCH () << 8;
596 /* look in optionals for first keyword or last positional */
597 /* starting after the last required positional arg */
599 while (/* while we have args */
601 /* and we still have positionals to fill */
602 && walk
- fp
< nreq_and_opt
603 /* and we haven't reached a keyword yet */
604 && !scm_is_keyword (*walk
))
605 /* bind this optional arg (by leaving it in place) */
607 /* now shuffle up, from walk to ntotal */
609 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
610 sp
= (fp
- 1) + ntotal
+ nshuf
;
612 for (i
= 0; i
< nshuf
; i
++)
613 sp
[-i
] = walk
[nshuf
-i
-1];
615 /* and fill optionals & keyword args with SCM_UNDEFINED */
616 while (walk
<= (fp
- 1) + ntotal
)
617 *walk
++ = SCM_UNDEFINED
;
622 /* Flags that determine whether other keywords are allowed, and whether a
623 rest argument is expected. These values must match those used by the
624 glil->assembly compiler. */
625 #define F_ALLOW_OTHER_KEYS 1
628 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
632 int kw_and_rest_flags
;
636 /* XXX: We don't actually use NKW. */
639 kw_and_rest_flags
= FETCH ();
641 if (!(kw_and_rest_flags
& F_REST
)
642 && ((sp
- (fp
- 1) - nkw
) % 2))
643 goto vm_error_kwargs_length_not_even
;
646 kw
= OBJECT_REF (idx
);
648 /* Switch NKW to be a negative index below SP. */
649 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
653 if (scm_is_keyword (sp
[nkw
]))
655 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
657 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
659 SCM si
= SCM_CDAR (walk
);
660 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
665 if (!(kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
) && !scm_is_pair (walk
))
666 goto vm_error_kwargs_unrecognized_keyword
;
670 else if (!(kw_and_rest_flags
& F_REST
))
671 goto vm_error_kwargs_invalid_keyword
;
677 #undef F_ALLOW_OTHER_KEYS
681 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
687 while (sp
- (fp
- 1) > n
)
688 /* No need to check for underflow. */
689 CONS (rest
, *sp
--, rest
);
694 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
703 while (sp
- (fp
- 1) > n
)
704 /* No need to check for underflow. */
705 CONS (rest
, *sp
--, rest
);
710 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
723 *++old_sp
= SCM_UNDEFINED
;
726 NULLSTACK (old_sp
- sp
);
731 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
733 /* NB: if you change this, see frames.c:vm-frame-num-locals */
734 /* and frames.h, vm-engine.c, etc of course */
735 PUSH ((SCM
)fp
); /* dynamic link */
741 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
746 program
= sp
[-nargs
];
748 VM_HANDLE_INTERRUPTS
;
750 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
752 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
754 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
757 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
758 && SCM_SMOB_APPLICABLE_P (program
))
761 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
765 goto vm_error_wrong_type_apply
;
770 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
771 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
772 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
773 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
774 ip
= SCM_C_OBJCODE_BASE (bp
);
775 PUSH_CONTINUATION_HOOK ();
780 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-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
;
809 #ifdef VM_ENABLE_STACK_NULLING
814 /* switch programs */
816 /* shuffle down the program and the arguments */
817 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
818 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
822 NULLSTACK (old_sp
- sp
);
824 ip
= SCM_C_OBJCODE_BASE (bp
);
831 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
839 subr
= SCM_POINTER_VALUE (pointer
);
841 VM_HANDLE_INTERRUPTS
;
853 ret
= subr (sp
[-1], sp
[0]);
856 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
859 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
862 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
865 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
868 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
871 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
874 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
877 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
883 NULLSTACK_FOR_NONLOCAL_EXIT ();
885 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
887 /* multiple values returned to continuation */
888 ret
= scm_struct_ref (ret
, SCM_INUM0
);
889 nvalues
= scm_ilength (ret
);
890 PUSH_LIST (ret
, scm_is_null
);
891 goto vm_return_values
;
900 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
907 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
909 VM_HANDLE_INTERRUPTS
;
918 ret
= subr (smob
, sp
[0]);
921 ret
= subr (smob
, sp
[-1], sp
[0]);
924 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
930 NULLSTACK_FOR_NONLOCAL_EXIT ();
932 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
934 /* multiple values returned to continuation */
935 ret
= scm_struct_ref (ret
, SCM_INUM0
);
936 nvalues
= scm_ilength (ret
);
937 PUSH_LIST (ret
, scm_is_null
);
938 goto vm_return_values
;
947 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
953 VM_HANDLE_INTERRUPTS
;
956 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
958 NULLSTACK_FOR_NONLOCAL_EXIT ();
960 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
962 /* multiple values returned to continuation */
963 ret
= scm_struct_ref (ret
, SCM_INUM0
);
964 nvalues
= scm_ilength (ret
);
965 PUSH_LIST (ret
, scm_is_null
);
966 goto vm_return_values
;
975 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
981 scm_i_check_continuation (contregs
);
982 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
983 scm_i_contregs_vm_cont (contregs
),
985 scm_i_reinstate_continuation (contregs
);
991 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
993 SCM vmcont
, intwinds
, prevwinds
;
997 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
998 { finish_args
= vmcont
;
999 goto vm_error_continuation_not_rewindable
;
1001 prevwinds
= scm_i_dynwinds ();
1002 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1005 /* Rewind prompt jmpbuffers, if any. */
1007 SCM winds
= scm_i_dynwinds ();
1008 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1009 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1014 program
= SCM_FRAME_PROGRAM (fp
);
1019 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1023 nargs
= scm_to_int (x
);
1024 /* FIXME: should truncate values? */
1028 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1032 nargs
= scm_to_int (x
);
1033 /* FIXME: should truncate values? */
1037 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1043 FETCH_OFFSET (offset
);
1047 program
= sp
[-nargs
];
1049 VM_HANDLE_INTERRUPTS
;
1051 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1053 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1055 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1058 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1059 && SCM_SMOB_APPLICABLE_P (program
))
1062 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1066 goto vm_error_wrong_type_apply
;
1070 fp
= sp
- nargs
+ 1;
1071 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1072 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1073 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1074 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1075 ip
= SCM_C_OBJCODE_BASE (bp
);
1076 PUSH_CONTINUATION_HOOK ();
1081 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1088 ASSERT (nargs
>= 2);
1090 len
= scm_ilength (ls
);
1091 if (SCM_UNLIKELY (len
< 0))
1094 goto vm_error_apply_to_non_list
;
1097 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1103 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1110 ASSERT (nargs
>= 2);
1112 len
= scm_ilength (ls
);
1113 if (SCM_UNLIKELY (len
< 0))
1116 goto vm_error_apply_to_non_list
;
1119 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1125 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1128 SCM proc
, vm_cont
, cont
;
1131 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1132 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1135 PUSH ((SCM
)fp
); /* dynamic link */
1136 PUSH (0); /* mvra */
1145 /* Otherwise, the vm continuation was reinstated, and
1146 vm_return_to_continuation pushed on one value. We know only one
1147 value was returned because we are in value context -- the
1148 previous block jumped to vm_call, not vm_mv_call, after all.
1150 So, pull our regs back down from the vp, and march on to the
1151 next instruction. */
1153 program
= SCM_FRAME_PROGRAM (fp
);
1155 RESTORE_CONTINUATION_HOOK ();
1160 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1163 SCM proc
, vm_cont
, cont
;
1166 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1168 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1169 SCM_FRAME_DYNAMIC_LINK (fp
),
1170 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1171 SCM_FRAME_RETURN_ADDRESS (fp
),
1172 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1174 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1184 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1185 does a return from the frame, either to the RA or
1188 program
= SCM_FRAME_PROGRAM (fp
);
1190 /* Unfortunately we don't know whether we are at the RA, and thus
1191 have one value without an nvalues marker, or we are at the
1192 MVRA and thus have multiple values and the nvalues
1193 marker. Instead of adding heuristics here, we will let hook
1194 client code do that. */
1195 RESTORE_CONTINUATION_HOOK ();
1200 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1203 POP_CONTINUATION_HOOK (1);
1205 VM_HANDLE_INTERRUPTS
;
1212 #ifdef VM_ENABLE_STACK_NULLING
1216 /* Restore registers */
1217 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1218 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1219 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1221 #ifdef VM_ENABLE_STACK_NULLING
1222 NULLSTACK (old_sp
- sp
);
1225 /* Set return value (sp is already pushed) */
1229 /* Restore the last program */
1230 program
= SCM_FRAME_PROGRAM (fp
);
1236 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1238 /* nvalues declared at top level, because for some reason gcc seems to think
1239 that perhaps it might be used without declaration. Fooey to that, I say. */
1242 POP_CONTINUATION_HOOK (nvalues
);
1244 VM_HANDLE_INTERRUPTS
;
1246 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1248 /* A multiply-valued continuation */
1249 SCM
*vals
= sp
- nvalues
;
1251 /* Restore registers */
1252 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1253 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1254 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1256 /* Push return values, and the number of values */
1257 for (i
= 0; i
< nvalues
; i
++)
1259 *++sp
= SCM_I_MAKINUM (nvalues
);
1261 /* Finally null the end of the stack */
1262 NULLSTACK (vals
+ nvalues
- sp
);
1264 else if (nvalues
>= 1)
1266 /* Multiple values for a single-valued continuation -- here's where I
1267 break with guile tradition and try and do something sensible. (Also,
1268 this block handles the single-valued return to an mv
1270 SCM
*vals
= sp
- nvalues
;
1271 /* Restore registers */
1272 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1273 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1274 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1276 /* Push first value */
1279 /* Finally null the end of the stack */
1280 NULLSTACK (vals
+ nvalues
- sp
);
1283 goto vm_error_no_values
;
1285 /* Restore the last program */
1286 program
= SCM_FRAME_PROGRAM (fp
);
1292 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1297 ASSERT (nvalues
>= 1);
1301 while (scm_is_pair (l
))
1307 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1308 finish_args
= scm_list_1 (l
);
1309 goto vm_error_improper_list
;
1312 goto vm_return_values
;
1315 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1319 nvalues
= scm_to_int (n
);
1320 ASSERT (nvalues
>= 0);
1321 goto vm_return_values
;
1324 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1329 nvalues
= scm_to_int (x
);
1336 if (nvalues
< nbinds
)
1337 goto vm_error_not_enough_values
;
1340 POP_LIST (nvalues
- nbinds
);
1342 DROPN (nvalues
- nbinds
);
1347 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1352 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1357 (let ((a *undef*) (b *undef*) ...)
1358 (set! a (lambda () (b ...)))
1361 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1364 LOCAL_SET (FETCH (),
1365 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1369 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1371 SCM v
= LOCAL_REF (FETCH ());
1372 ASSERT_BOUND_VARIABLE (v
);
1373 PUSH (VARIABLE_REF (v
));
1377 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1380 v
= LOCAL_REF (FETCH ());
1382 ASSERT_VARIABLE (v
);
1383 VARIABLE_SET (v
, val
);
1387 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1389 scm_t_uint8 idx
= FETCH ();
1391 CHECK_FREE_VARIABLE (idx
);
1392 PUSH (FREE_VARIABLE_REF (idx
));
1396 /* no free-set -- if a var is assigned, it should be in a box */
1398 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1401 scm_t_uint8 idx
= FETCH ();
1402 CHECK_FREE_VARIABLE (idx
);
1403 v
= FREE_VARIABLE_REF (idx
);
1404 ASSERT_BOUND_VARIABLE (v
);
1405 PUSH (VARIABLE_REF (v
));
1409 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1412 scm_t_uint8 idx
= FETCH ();
1414 CHECK_FREE_VARIABLE (idx
);
1415 v
= FREE_VARIABLE_REF (idx
);
1416 ASSERT_BOUND_VARIABLE (v
);
1417 VARIABLE_SET (v
, val
);
1421 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1430 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1431 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1432 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1434 for (n
= 0; n
< len
; n
++)
1435 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1440 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1443 /* fixme underflow */
1444 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1448 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1451 unsigned int i
= FETCH ();
1455 /* FIXME CHECK_LOCAL (i) */
1457 /* FIXME ASSERT_PROGRAM (x); */
1458 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1459 for (n
= 0; n
< len
; n
++)
1460 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1465 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1471 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1477 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1481 *sp
= scm_symbol_to_keyword (*sp
);
1485 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1489 *sp
= scm_string_to_symbol (*sp
);
1493 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1496 scm_t_uint8 escape_only_p
;
1499 escape_only_p
= FETCH ();
1500 FETCH_OFFSET (offset
);
1504 /* Push the prompt onto the dynamic stack. */
1505 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1507 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1508 if (SCM_PROMPT_SETJMP (prompt
))
1510 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1513 Note, at this point, we must assume that any variable local to
1514 vm_engine that can be assigned *has* been assigned. So we need to pull
1515 all our state back from the ip/fp/sp.
1518 program
= SCM_FRAME_PROGRAM (fp
);
1520 /* The stack contains the values returned to this prompt, along
1521 with a number-of-values marker -- like an MV return. */
1522 ABORT_CONTINUATION_HOOK ();
1526 /* Otherwise setjmp returned for the first time, so we go to execute the
1531 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1537 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1538 are actually called; the compiler should emit calls to wind and unwind for
1539 the normal dynamic-wind control flow. */
1540 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1543 goto vm_error_not_a_thunk
;
1545 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1547 finish_args
= unwind
;
1548 goto vm_error_not_a_thunk
;
1550 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1554 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1556 unsigned n
= FETCH ();
1558 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1559 goto vm_error_stack_underflow
;
1560 vm_abort (vm
, n
, vm_cookie
);
1561 /* vm_abort should not return */
1565 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1567 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1568 off of the dynamic stack. */
1569 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1573 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1575 unsigned n
= FETCH ();
1578 if (sp
- 2*n
< SCM_FRAME_UPPER_ADDRESS (fp
))
1579 goto vm_error_stack_underflow
;
1582 wf
= scm_i_make_with_fluids (n
, sp
+ 1 - 2*n
, sp
+ 1 - n
);
1583 scm_i_swap_with_fluids (wf
, dynstate
);
1584 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1588 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1591 wf
= scm_car (scm_i_dynwinds ());
1592 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1593 scm_i_swap_with_fluids (wf
, dynstate
);
1597 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1603 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
1604 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1605 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1607 /* Punt dynstate expansion and error handling to the C proc. */
1609 *sp
= scm_fluid_ref (*sp
);
1612 *sp
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1617 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1620 SCM val
, fluid
, fluids
;
1624 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (dynstate
);
1625 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1626 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1628 /* Punt dynstate expansion and error handling to the C proc. */
1630 scm_fluid_set_x (fluid
, val
);
1633 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1638 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1643 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1646 if (SCM_UNLIKELY (sp
- (fp
- 1) != (n
& 0x7)))
1647 goto vm_error_wrong_num_args
;
1653 *++old_sp
= SCM_UNDEFINED
;
1660 (defun renumber-ops ()
1661 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1664 (let ((counter -1)) (goto-char (point-min))
1665 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1667 (number-to-string (setq counter (1+ counter)))