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)
83 VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
85 PUSH (SCM_UNSPECIFIED
);
89 VM_DEFINE_INSTRUCTION (5, make_true
, "make-true", 0, 0, 1)
95 VM_DEFINE_INSTRUCTION (6, make_false
, "make-false", 0, 0, 1)
101 VM_DEFINE_INSTRUCTION (7, make_nil
, "make-nil", 0, 0, 1)
103 PUSH (SCM_ELISP_NIL
);
107 VM_DEFINE_INSTRUCTION (8, make_eol
, "make-eol", 0, 0, 1)
113 VM_DEFINE_INSTRUCTION (9, make_int8
, "make-int8", 1, 0, 1)
115 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
119 VM_DEFINE_INSTRUCTION (10, make_int8_0
, "make-int8:0", 0, 0, 1)
125 VM_DEFINE_INSTRUCTION (11, make_int8_1
, "make-int8:1", 0, 0, 1)
127 PUSH (SCM_I_MAKINUM (1));
131 VM_DEFINE_INSTRUCTION (12, make_int16
, "make-int16", 2, 0, 1)
135 PUSH (SCM_I_MAKINUM ((signed short) (h
<< 8) + l
));
139 VM_DEFINE_INSTRUCTION (13, make_int64
, "make-int64", 8, 0, 1)
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 v
<<= 8; v
+= FETCH ();
150 PUSH (scm_from_int64 ((scm_t_int64
) v
));
154 VM_DEFINE_INSTRUCTION (14, make_uint64
, "make-uint64", 8, 0, 1)
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 v
<<= 8; v
+= FETCH ();
165 PUSH (scm_from_uint64 (v
));
169 VM_DEFINE_INSTRUCTION (15, make_char8
, "make-char8", 1, 0, 1)
174 PUSH (SCM_MAKE_CHAR (v
));
175 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
176 contents of SCM_MAKE_CHAR may be evaluated more than once,
177 resulting in a double fetch. */
181 VM_DEFINE_INSTRUCTION (16, make_char32
, "make-char32", 4, 0, 1)
185 v
<<= 8; v
+= FETCH ();
186 v
<<= 8; v
+= FETCH ();
187 v
<<= 8; v
+= FETCH ();
188 PUSH (SCM_MAKE_CHAR (v
));
194 VM_DEFINE_INSTRUCTION (17, list
, "list", 2, -1, 1)
196 unsigned h
= FETCH ();
197 unsigned l
= FETCH ();
198 unsigned len
= ((h
<< 8) + l
);
203 VM_DEFINE_INSTRUCTION (18, vector
, "vector", 2, -1, 1)
205 unsigned h
= FETCH ();
206 unsigned l
= FETCH ();
207 unsigned len
= ((h
<< 8) + l
);
213 vect
= scm_make_vector (scm_from_uint (len
), SCM_BOOL_F
);
214 memcpy (SCM_I_VECTOR_WELTS(vect
), sp
, sizeof(SCM
) * len
);
227 #define OBJECT_REF(i) objects[i]
228 #define OBJECT_SET(i,o) objects[i] = o
230 #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
231 #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
233 /* For the variable operations, we _must_ obviously avoid function calls to
234 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
235 nothing more than the corresponding macros. */
236 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
237 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
238 #define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
240 #define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
244 VM_DEFINE_INSTRUCTION (19, object_ref
, "object-ref", 1, 0, 1)
246 register unsigned objnum
= FETCH ();
247 CHECK_OBJECT (objnum
);
248 PUSH (OBJECT_REF (objnum
));
252 /* FIXME: necessary? elt 255 of the vector could be a vector... */
253 VM_DEFINE_INSTRUCTION (20, long_object_ref
, "long-object-ref", 2, 0, 1)
255 unsigned int objnum
= FETCH ();
258 CHECK_OBJECT (objnum
);
259 PUSH (OBJECT_REF (objnum
));
263 VM_DEFINE_INSTRUCTION (21, local_ref
, "local-ref", 1, 0, 1)
265 PUSH (LOCAL_REF (FETCH ()));
270 VM_DEFINE_INSTRUCTION (22, long_local_ref
, "long-local-ref", 2, 0, 1)
272 unsigned int i
= FETCH ();
275 PUSH (LOCAL_REF (i
));
280 VM_DEFINE_INSTRUCTION (23, local_bound
, "local-bound?", 1, 0, 1)
282 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (FETCH ()), SCM_UNDEFINED
)));
286 VM_DEFINE_INSTRUCTION (24, long_local_bound
, "long-local-bound?", 2, 0, 1)
288 unsigned int i
= FETCH ();
291 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (i
), SCM_UNDEFINED
)));
295 VM_DEFINE_INSTRUCTION (25, variable_ref
, "variable-ref", 0, 1, 1)
299 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
300 unlike in top-variable-ref, it really isn't an internal assertion
301 that can be optimized out -- the variable could be coming directly
303 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
305 func_name
= "variable-ref";
307 goto vm_error_not_a_variable
;
309 else 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 finish_args
= scm_is_true (var_name
) ? var_name
: x
;
316 goto vm_error_unbound
;
320 SCM o
= VARIABLE_REF (x
);
328 VM_DEFINE_INSTRUCTION (26, variable_bound
, "variable-bound?", 0, 1, 1)
332 if (SCM_UNLIKELY (!SCM_VARIABLEP (x
)))
334 func_name
= "variable-bound?";
336 goto vm_error_not_a_variable
;
339 *sp
= scm_from_bool (VARIABLE_BOUNDP (x
));
344 VM_DEFINE_INSTRUCTION (27, toplevel_ref
, "toplevel-ref", 1, 0, 1)
346 unsigned objnum
= FETCH ();
348 CHECK_OBJECT (objnum
);
349 what
= OBJECT_REF (objnum
);
351 if (!SCM_VARIABLEP (what
))
355 resolved
= resolve_variable (what
, scm_program_module (program
));
356 if (!VARIABLE_BOUNDP (resolved
))
359 goto vm_error_unbound
;
363 OBJECT_SET (objnum
, what
);
366 PUSH (VARIABLE_REF (what
));
371 VM_DEFINE_INSTRUCTION (28, long_toplevel_ref
, "long-toplevel-ref", 2, 0, 1)
374 unsigned int objnum
= FETCH ();
377 CHECK_OBJECT (objnum
);
378 what
= OBJECT_REF (objnum
);
380 if (!SCM_VARIABLEP (what
))
384 resolved
= resolve_variable (what
, scm_program_module (program
));
385 if (!VARIABLE_BOUNDP (resolved
))
388 goto vm_error_unbound
;
392 OBJECT_SET (objnum
, what
);
395 PUSH (VARIABLE_REF (what
));
402 VM_DEFINE_INSTRUCTION (29, local_set
, "local-set", 1, 1, 0)
406 LOCAL_SET (FETCH (), x
);
411 VM_DEFINE_INSTRUCTION (30, long_local_set
, "long-local-set", 2, 1, 0)
414 unsigned int i
= FETCH ();
423 VM_DEFINE_INSTRUCTION (31, variable_set
, "variable-set", 0, 2, 0)
425 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp
[0])))
427 func_name
= "variable-set!";
429 goto vm_error_not_a_variable
;
431 VARIABLE_SET (sp
[0], sp
[-1]);
436 VM_DEFINE_INSTRUCTION (32, toplevel_set
, "toplevel-set", 1, 1, 0)
438 unsigned objnum
= FETCH ();
440 CHECK_OBJECT (objnum
);
441 what
= OBJECT_REF (objnum
);
443 if (!SCM_VARIABLEP (what
))
446 what
= resolve_variable (what
, scm_program_module (program
));
447 OBJECT_SET (objnum
, what
);
450 VARIABLE_SET (what
, *sp
);
456 VM_DEFINE_INSTRUCTION (33, long_toplevel_set
, "long-toplevel-set", 2, 1, 0)
459 unsigned int objnum
= FETCH ();
462 CHECK_OBJECT (objnum
);
463 what
= OBJECT_REF (objnum
);
465 if (!SCM_VARIABLEP (what
))
468 what
= resolve_variable (what
, scm_program_module (program
));
469 OBJECT_SET (objnum
, what
);
472 VARIABLE_SET (what
, *sp
);
483 /* offset must be at least 24 bits wide, and signed */
484 #define FETCH_OFFSET(offset) \
486 offset = FETCH () << 16; \
487 offset += FETCH () << 8; \
488 offset += FETCH (); \
489 offset -= (offset & (1<<23)) << 1; \
494 scm_t_int32 offset; \
495 FETCH_OFFSET (offset); \
499 VM_HANDLE_INTERRUPTS; \
502 VM_DEFINE_INSTRUCTION (34, br
, "br", 3, 0, 0)
505 FETCH_OFFSET (offset
);
508 VM_HANDLE_INTERRUPTS
;
512 VM_DEFINE_INSTRUCTION (35, br_if
, "br-if", 3, 0, 0)
516 BR (scm_is_true (x
));
521 VM_DEFINE_INSTRUCTION (36, br_if_not
, "br-if-not", 3, 0, 0)
525 BR (scm_is_false (x
));
530 VM_DEFINE_INSTRUCTION (37, br_if_eq
, "br-if-eq", 3, 0, 0)
534 BR (scm_is_eq (x
, y
));
540 VM_DEFINE_INSTRUCTION (38, br_if_not_eq
, "br-if-not-eq", 3, 0, 0)
544 BR (!scm_is_eq (x
, y
));
550 VM_DEFINE_INSTRUCTION (39, br_if_null
, "br-if-null", 3, 0, 0)
554 BR (scm_is_null (x
));
559 VM_DEFINE_INSTRUCTION (40, br_if_not_null
, "br-if-not-null", 3, 0, 0)
563 BR (!scm_is_null (x
));
573 VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne
, "br-if-nargs-ne", 5, 0, 0)
579 FETCH_OFFSET (offset
);
580 if (sp
- (fp
- 1) != n
)
585 VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt
, "br-if-nargs-lt", 5, 0, 0)
591 FETCH_OFFSET (offset
);
592 if (sp
- (fp
- 1) < n
)
597 VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt
, "br-if-nargs-gt", 5, 0, 0)
604 FETCH_OFFSET (offset
);
605 if (sp
- (fp
- 1) > n
)
610 VM_DEFINE_INSTRUCTION (44, assert_nargs_ee
, "assert-nargs-ee", 2, 0, 0)
615 if (sp
- (fp
- 1) != n
)
616 goto vm_error_wrong_num_args
;
620 VM_DEFINE_INSTRUCTION (45, assert_nargs_ge
, "assert-nargs-ge", 2, 0, 0)
625 if (sp
- (fp
- 1) < n
)
626 goto vm_error_wrong_num_args
;
630 VM_DEFINE_INSTRUCTION (46, bind_optionals
, "bind-optionals", 2, -1, -1)
635 while (sp
- (fp
- 1) < n
)
636 PUSH (SCM_UNDEFINED
);
640 VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle
, "bind-optionals/shuffle", 6, -1, -1)
643 scm_t_ptrdiff nreq
, nreq_and_opt
, ntotal
;
644 nreq
= FETCH () << 8;
646 nreq_and_opt
= FETCH () << 8;
647 nreq_and_opt
+= FETCH ();
648 ntotal
= FETCH () << 8;
651 /* look in optionals for first keyword or last positional */
652 /* starting after the last required positional arg */
654 while (/* while we have args */
656 /* and we still have positionals to fill */
657 && walk
- fp
< nreq_and_opt
658 /* and we haven't reached a keyword yet */
659 && !scm_is_keyword (*walk
))
660 /* bind this optional arg (by leaving it in place) */
662 /* now shuffle up, from walk to ntotal */
664 scm_t_ptrdiff nshuf
= sp
- walk
+ 1, i
;
665 sp
= (fp
- 1) + ntotal
+ nshuf
;
667 for (i
= 0; i
< nshuf
; i
++)
668 sp
[-i
] = walk
[nshuf
-i
-1];
670 /* and fill optionals & keyword args with SCM_UNDEFINED */
671 while (walk
<= (fp
- 1) + ntotal
)
672 *walk
++ = SCM_UNDEFINED
;
677 /* Flags that determine whether other keywords are allowed, and whether a
678 rest argument is expected. These values must match those used by the
679 glil->assembly compiler. */
680 #define F_ALLOW_OTHER_KEYS 1
683 VM_DEFINE_INSTRUCTION (48, bind_kwargs
, "bind-kwargs", 5, 0, 0)
687 int kw_and_rest_flags
;
691 /* XXX: We don't actually use NKW. */
694 kw_and_rest_flags
= FETCH ();
696 if (!(kw_and_rest_flags
& F_REST
)
697 && ((sp
- (fp
- 1) - nkw
) % 2))
698 goto vm_error_kwargs_length_not_even
;
701 kw
= OBJECT_REF (idx
);
703 /* Switch NKW to be a negative index below SP. */
704 for (nkw
= -(sp
- (fp
- 1) - nkw
) + 1; nkw
< 0; nkw
++)
708 if (scm_is_keyword (sp
[nkw
]))
710 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
712 if (scm_is_eq (SCM_CAAR (walk
), sp
[nkw
]))
714 SCM si
= SCM_CDAR (walk
);
715 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_long (si
),
720 if (!(kw_and_rest_flags
& F_ALLOW_OTHER_KEYS
) && !scm_is_pair (walk
))
721 goto vm_error_kwargs_unrecognized_keyword
;
725 else if (!(kw_and_rest_flags
& F_REST
))
726 goto vm_error_kwargs_invalid_keyword
;
734 #undef F_ALLOW_OTHER_KEYS
738 VM_DEFINE_INSTRUCTION (49, push_rest
, "push-rest", 2, -1, -1)
744 while (sp
- (fp
- 1) > n
)
745 /* No need to check for underflow. */
746 CONS (rest
, *sp
--, rest
);
752 VM_DEFINE_INSTRUCTION (50, bind_rest
, "bind-rest", 4, -1, -1)
761 while (sp
- (fp
- 1) > n
)
762 /* No need to check for underflow. */
763 CONS (rest
, *sp
--, rest
);
769 VM_DEFINE_INSTRUCTION (51, reserve_locals
, "reserve-locals", 2, -1, -1)
782 *++old_sp
= SCM_UNDEFINED
;
785 NULLSTACK (old_sp
- sp
);
790 VM_DEFINE_INSTRUCTION (52, new_frame
, "new-frame", 0, 0, 3)
792 /* NB: if you change this, see frames.c:vm-frame-num-locals */
793 /* and frames.h, vm-engine.c, etc of course */
795 /* We don't initialize the dynamic link here because we don't actually
796 know that this frame will point to the current fp: it could be
797 placed elsewhere on the stack if captured in a partial
798 continuation, and invoked from some other context. */
799 PUSH (SCM_PACK (0)); /* dynamic link */
800 PUSH (SCM_PACK (0)); /* mvra */
801 PUSH (SCM_PACK (0)); /* ra */
805 VM_DEFINE_INSTRUCTION (53, call
, "call", 1, -1, 1)
810 program
= sp
[-nargs
];
812 VM_HANDLE_INTERRUPTS
;
814 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
816 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
818 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
821 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
822 && SCM_SMOB_APPLICABLE_P (program
))
825 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
829 goto vm_error_wrong_type_apply
;
839 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
840 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
841 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
842 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
843 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
844 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, 0);
847 ip
= SCM_C_OBJCODE_BASE (bp
);
848 PUSH_CONTINUATION_HOOK ();
853 VM_DEFINE_INSTRUCTION (54, tail_call
, "tail-call", 1, -1, 1)
858 program
= sp
[-nargs
];
860 VM_HANDLE_INTERRUPTS
;
862 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
864 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
866 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
869 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
870 && SCM_SMOB_APPLICABLE_P (program
))
873 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
877 goto vm_error_wrong_type_apply
;
882 #ifdef VM_ENABLE_STACK_NULLING
887 /* switch programs */
889 /* shuffle down the program and the arguments */
890 for (i
= -1, sp
= sp
- nargs
+ 1; i
< nargs
; i
++)
891 SCM_FRAME_STACK_ADDRESS (fp
)[i
] = sp
[i
];
895 NULLSTACK (old_sp
- sp
);
897 ip
= SCM_C_OBJCODE_BASE (bp
);
904 VM_DEFINE_INSTRUCTION (55, subr_call
, "subr-call", 1, -1, -1)
912 subr
= SCM_POINTER_VALUE (pointer
);
914 VM_HANDLE_INTERRUPTS
;
926 ret
= subr (sp
[-1], sp
[0]);
929 ret
= subr (sp
[-2], sp
[-1], sp
[0]);
932 ret
= subr (sp
[-3], sp
[-2], sp
[-1], sp
[0]);
935 ret
= subr (sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
938 ret
= subr (sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
941 ret
= subr (sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
944 ret
= subr (sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
947 ret
= subr (sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
950 ret
= subr (sp
[-9], sp
[-8], sp
[-7], sp
[-6], sp
[-5], sp
[-4], sp
[-3], sp
[-2], sp
[-1], sp
[0]);
957 NULLSTACK_FOR_NONLOCAL_EXIT ();
959 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
961 /* multiple values returned to continuation */
962 ret
= scm_struct_ref (ret
, SCM_INUM0
);
963 nvalues
= scm_ilength (ret
);
964 PUSH_LIST (ret
, scm_is_null
);
966 goto vm_return_values
;
976 VM_DEFINE_INSTRUCTION (56, smob_call
, "smob-call", 1, -1, -1)
983 subr
= SCM_SMOB_DESCRIPTOR (smob
).apply
;
985 VM_HANDLE_INTERRUPTS
;
994 ret
= subr (smob
, sp
[0]);
997 ret
= subr (smob
, sp
[-1], sp
[0]);
1000 ret
= subr (smob
, sp
[-2], sp
[-1], sp
[0]);
1007 NULLSTACK_FOR_NONLOCAL_EXIT ();
1009 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
1011 /* multiple values returned to continuation */
1012 ret
= scm_struct_ref (ret
, SCM_INUM0
);
1013 nvalues
= scm_ilength (ret
);
1014 PUSH_LIST (ret
, scm_is_null
);
1016 goto vm_return_values
;
1026 VM_DEFINE_INSTRUCTION (57, foreign_call
, "foreign-call", 1, -1, -1)
1032 VM_HANDLE_INTERRUPTS
;
1035 ret
= scm_i_foreign_call (foreign
, sp
- nargs
+ 1);
1038 NULLSTACK_FOR_NONLOCAL_EXIT ();
1040 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
1042 /* multiple values returned to continuation */
1043 ret
= scm_struct_ref (ret
, SCM_INUM0
);
1044 nvalues
= scm_ilength (ret
);
1045 PUSH_LIST (ret
, scm_is_null
);
1047 goto vm_return_values
;
1057 VM_DEFINE_INSTRUCTION (58, continuation_call
, "continuation-call", 0, -1, 0)
1063 scm_i_check_continuation (contregs
);
1064 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
1065 scm_i_contregs_vm_cont (contregs
),
1067 scm_i_reinstate_continuation (contregs
);
1069 /* no DEAD, no NEXT */
1073 VM_DEFINE_INSTRUCTION (59, partial_cont_call
, "partial-cont-call", 0, -1, 0)
1075 SCM vmcont
, intwinds
, prevwinds
;
1076 POP2 (intwinds
, vmcont
);
1078 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont
)))
1080 finish_args
= vmcont
;
1081 goto vm_error_continuation_not_rewindable
;
1083 prevwinds
= scm_i_dynwinds ();
1084 vm_reinstate_partial_continuation (vm
, vmcont
, intwinds
, sp
+ 1 - fp
, fp
,
1089 /* Rewind prompt jmpbuffers, if any. */
1091 SCM winds
= scm_i_dynwinds ();
1092 for (; !scm_is_eq (winds
, prevwinds
); winds
= scm_cdr (winds
))
1093 if (SCM_PROMPT_P (scm_car (winds
)) && SCM_PROMPT_SETJMP (scm_car (winds
)))
1100 program
= SCM_FRAME_PROGRAM (fp
);
1105 VM_DEFINE_INSTRUCTION (60, tail_call_nargs
, "tail-call/nargs", 0, 0, 1)
1109 nargs
= scm_to_int (x
);
1111 /* FIXME: should truncate values? */
1115 VM_DEFINE_INSTRUCTION (61, call_nargs
, "call/nargs", 0, 0, 1)
1119 nargs
= scm_to_int (x
);
1121 /* FIXME: should truncate values? */
1125 VM_DEFINE_INSTRUCTION (62, mv_call
, "mv-call", 4, -1, 1)
1131 FETCH_OFFSET (offset
);
1135 program
= sp
[-nargs
];
1137 VM_HANDLE_INTERRUPTS
;
1139 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program
)))
1141 if (SCM_STRUCTP (program
) && SCM_STRUCT_APPLICABLE_P (program
))
1143 sp
[-nargs
] = SCM_STRUCT_PROCEDURE (program
);
1146 else if (SCM_NIMP (program
) && SCM_TYP7 (program
) == scm_tc7_smob
1147 && SCM_SMOB_APPLICABLE_P (program
))
1150 sp
[-nargs
] = scm_i_smob_apply_trampoline (program
);
1154 goto vm_error_wrong_type_apply
;
1162 fp
= sp
- nargs
+ 1;
1164 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp
) == 0);
1165 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp
) == 0);
1166 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp
) == 0);
1167 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
1168 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
);
1169 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp
, mvra
);
1172 ip
= SCM_C_OBJCODE_BASE (bp
);
1173 PUSH_CONTINUATION_HOOK ();
1178 VM_DEFINE_INSTRUCTION (63, apply
, "apply", 1, -1, 1)
1185 ASSERT (nargs
>= 2);
1187 len
= scm_ilength (ls
);
1188 if (SCM_UNLIKELY (len
< 0))
1191 goto vm_error_apply_to_non_list
;
1194 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1201 VM_DEFINE_INSTRUCTION (64, tail_apply
, "tail-apply", 1, -1, 1)
1208 ASSERT (nargs
>= 2);
1210 len
= scm_ilength (ls
);
1211 if (SCM_UNLIKELY (len
< 0))
1214 goto vm_error_apply_to_non_list
;
1217 PUSH_LIST (ls
, SCM_NULL_OR_NIL_P
);
1224 VM_DEFINE_INSTRUCTION (65, call_cc
, "call/cc", 0, 1, 1)
1227 SCM proc
, vm_cont
, cont
;
1230 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
, fp
, sp
, ip
, NULL
, 0);
1231 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1235 PUSH (SCM_PACK (0)); /* dynamic link */
1236 PUSH (SCM_PACK (0)); /* mvra */
1237 PUSH (SCM_PACK (0)); /* ra */
1247 /* Otherwise, the vm continuation was reinstated, and
1248 vm_return_to_continuation pushed on one value. We know only one
1249 value was returned because we are in value context -- the
1250 previous block jumped to vm_call, not vm_mv_call, after all.
1252 So, pull our regs back down from the vp, and march on to the
1253 next instruction. */
1257 program
= SCM_FRAME_PROGRAM (fp
);
1259 RESTORE_CONTINUATION_HOOK ();
1264 VM_DEFINE_INSTRUCTION (66, tail_call_cc
, "tail-call/cc", 0, 1, 1)
1267 SCM proc
, vm_cont
, cont
;
1270 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1272 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
1273 SCM_FRAME_DYNAMIC_LINK (fp
),
1274 SCM_FRAME_LOWER_ADDRESS (fp
) - 1,
1275 SCM_FRAME_RETURN_ADDRESS (fp
),
1276 SCM_FRAME_MV_RETURN_ADDRESS (fp
),
1278 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1293 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
1294 does a return from the frame, either to the RA or
1297 program
= SCM_FRAME_PROGRAM (fp
);
1299 /* Unfortunately we don't know whether we are at the RA, and thus
1300 have one value without an nvalues marker, or we are at the
1301 MVRA and thus have multiple values and the nvalues
1302 marker. Instead of adding heuristics here, we will let hook
1303 client code do that. */
1304 RESTORE_CONTINUATION_HOOK ();
1309 VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
1312 POP_CONTINUATION_HOOK (1);
1314 VM_HANDLE_INTERRUPTS
;
1321 #ifdef VM_ENABLE_STACK_NULLING
1325 /* Restore registers */
1326 sp
= SCM_FRAME_LOWER_ADDRESS (fp
);
1327 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1328 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1330 #ifdef VM_ENABLE_STACK_NULLING
1331 NULLSTACK (old_sp
- sp
);
1334 /* Set return value (sp is already pushed) */
1340 /* Restore the last program */
1341 program
= SCM_FRAME_PROGRAM (fp
);
1347 VM_DEFINE_INSTRUCTION (68, return_values
, "return/values", 1, -1, -1)
1349 /* nvalues declared at top level, because for some reason gcc seems to think
1350 that perhaps it might be used without declaration. Fooey to that, I say. */
1353 POP_CONTINUATION_HOOK (nvalues
);
1355 VM_HANDLE_INTERRUPTS
;
1357 if (nvalues
!= 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp
))
1359 /* A multiply-valued continuation */
1360 SCM
*vals
= sp
- nvalues
;
1362 /* Restore registers */
1363 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1364 ip
= SCM_FRAME_MV_RETURN_ADDRESS (fp
);
1365 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1367 /* Push return values, and the number of values */
1368 for (i
= 0; i
< nvalues
; i
++)
1370 *++sp
= SCM_I_MAKINUM (nvalues
);
1372 /* Finally null the end of the stack */
1373 NULLSTACK (vals
+ nvalues
- sp
);
1375 else if (nvalues
>= 1)
1377 /* Multiple values for a single-valued continuation -- here's where I
1378 break with guile tradition and try and do something sensible. (Also,
1379 this block handles the single-valued return to an mv
1381 SCM
*vals
= sp
- nvalues
;
1382 /* Restore registers */
1383 sp
= SCM_FRAME_LOWER_ADDRESS (fp
) - 1;
1384 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
1385 fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
1387 /* Push first value */
1390 /* Finally null the end of the stack */
1391 NULLSTACK (vals
+ nvalues
- sp
);
1394 goto vm_error_no_values
;
1396 /* Restore the last program */
1397 program
= SCM_FRAME_PROGRAM (fp
);
1403 VM_DEFINE_INSTRUCTION (69, return_values_star
, "return/values*", 1, -1, -1)
1408 ASSERT (nvalues
>= 1);
1412 while (scm_is_pair (l
))
1418 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l
))) {
1419 finish_args
= scm_list_1 (l
);
1420 goto vm_error_improper_list
;
1424 goto vm_return_values
;
1427 VM_DEFINE_INSTRUCTION (70, return_nvalues
, "return/nvalues", 0, 1, -1)
1431 nvalues
= scm_to_int (n
);
1433 ASSERT (nvalues
>= 0);
1434 goto vm_return_values
;
1437 VM_DEFINE_INSTRUCTION (71, truncate_values
, "truncate-values", 2, -1, -1)
1442 nvalues
= scm_to_int (x
);
1450 if (nvalues
< nbinds
)
1451 goto vm_error_not_enough_values
;
1454 POP_LIST (nvalues
- nbinds
);
1456 DROPN (nvalues
- nbinds
);
1461 VM_DEFINE_INSTRUCTION (72, box
, "box", 1, 1, 0)
1466 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable
, SCM_UNPACK (val
)));
1472 (let ((a *undef*) (b *undef*) ...)
1473 (set! a (lambda () (b ...)))
1476 VM_DEFINE_INSTRUCTION (73, empty_box
, "empty-box", 1, 0, 0)
1479 LOCAL_SET (FETCH (),
1480 scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1484 VM_DEFINE_INSTRUCTION (74, local_boxed_ref
, "local-boxed-ref", 1, 0, 1)
1486 SCM v
= LOCAL_REF (FETCH ());
1487 ASSERT_BOUND_VARIABLE (v
);
1488 PUSH (VARIABLE_REF (v
));
1493 VM_DEFINE_INSTRUCTION (75, local_boxed_set
, "local-boxed-set", 1, 1, 0)
1496 v
= LOCAL_REF (FETCH ());
1498 ASSERT_VARIABLE (v
);
1499 VARIABLE_SET (v
, val
);
1505 VM_DEFINE_INSTRUCTION (76, free_ref
, "free-ref", 1, 0, 1)
1507 scm_t_uint8 idx
= FETCH ();
1509 CHECK_FREE_VARIABLE (idx
);
1510 PUSH (FREE_VARIABLE_REF (idx
));
1514 /* no free-set -- if a var is assigned, it should be in a box */
1516 VM_DEFINE_INSTRUCTION (77, free_boxed_ref
, "free-boxed-ref", 1, 0, 1)
1519 scm_t_uint8 idx
= FETCH ();
1520 CHECK_FREE_VARIABLE (idx
);
1521 v
= FREE_VARIABLE_REF (idx
);
1522 ASSERT_BOUND_VARIABLE (v
);
1523 PUSH (VARIABLE_REF (v
));
1528 VM_DEFINE_INSTRUCTION (78, free_boxed_set
, "free-boxed-set", 1, 1, 0)
1531 scm_t_uint8 idx
= FETCH ();
1533 CHECK_FREE_VARIABLE (idx
);
1534 v
= FREE_VARIABLE_REF (idx
);
1535 ASSERT_BOUND_VARIABLE (v
);
1536 VARIABLE_SET (v
, val
);
1542 VM_DEFINE_INSTRUCTION (79, make_closure
, "make-closure", 2, -1, 1)
1551 closure
= scm_words (scm_tc7_program
| (len
<<16), len
+ 3);
1552 SCM_SET_CELL_OBJECT_1 (closure
, SCM_PROGRAM_OBJCODE (sp
[-len
]));
1553 SCM_SET_CELL_OBJECT_2 (closure
, SCM_PROGRAM_OBJTABLE (sp
[-len
]));
1555 for (n
= 0; n
< len
; n
++)
1556 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, sp
[-len
+ 1 + n
]);
1562 VM_DEFINE_INSTRUCTION (80, make_variable
, "make-variable", 0, 0, 1)
1565 /* fixme underflow */
1566 PUSH (scm_cell (scm_tc7_variable
, SCM_UNPACK (SCM_UNDEFINED
)));
1570 VM_DEFINE_INSTRUCTION (81, fix_closure
, "fix-closure", 2, -1, 0)
1573 unsigned int i
= FETCH ();
1577 /* FIXME CHECK_LOCAL (i) */
1579 /* FIXME ASSERT_PROGRAM (x); */
1580 len
= SCM_PROGRAM_NUM_FREE_VARIABLES (x
);
1581 for (n
= 0; n
< len
; n
++)
1582 SCM_PROGRAM_FREE_VARIABLE_SET (x
, n
, sp
[-len
+ 1 + n
]);
1588 VM_DEFINE_INSTRUCTION (82, define
, "define", 0, 0, 2)
1593 VARIABLE_SET (scm_sym2var (sym
, scm_current_module_lookup_closure (),
1601 VM_DEFINE_INSTRUCTION (83, make_keyword
, "make-keyword", 0, 1, 1)
1605 *sp
= scm_symbol_to_keyword (*sp
);
1609 VM_DEFINE_INSTRUCTION (84, make_symbol
, "make-symbol", 0, 1, 1)
1613 *sp
= scm_string_to_symbol (*sp
);
1617 VM_DEFINE_INSTRUCTION (85, prompt
, "prompt", 4, 2, 0)
1620 scm_t_uint8 escape_only_p
;
1623 escape_only_p
= FETCH ();
1624 FETCH_OFFSET (offset
);
1628 /* Push the prompt onto the dynamic stack. */
1629 prompt
= scm_c_make_prompt (k
, fp
, sp
, ip
+ offset
, escape_only_p
, vm_cookie
,
1631 scm_i_set_dynwinds (scm_cons (prompt
, SCM_PROMPT_DYNWINDS (prompt
)));
1632 if (SCM_PROMPT_SETJMP (prompt
))
1634 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
1637 Note, at this point, we must assume that any variable local to
1638 vm_engine that can be assigned *has* been assigned. So we need to pull
1639 all our state back from the ip/fp/sp.
1644 program
= SCM_FRAME_PROGRAM (fp
);
1646 /* The stack contains the values returned to this prompt, along
1647 with a number-of-values marker -- like an MV return. */
1648 ABORT_CONTINUATION_HOOK ();
1655 /* Otherwise setjmp returned for the first time, so we go to execute the
1660 VM_DEFINE_INSTRUCTION (86, wind
, "wind", 0, 2, 0)
1663 POP2 (unwind
, wind
);
1665 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1666 are actually called; the compiler should emit calls to wind and unwind for
1667 the normal dynamic-wind control flow. */
1668 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind
))))
1671 goto vm_error_not_a_thunk
;
1673 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind
))))
1675 finish_args
= unwind
;
1676 goto vm_error_not_a_thunk
;
1678 scm_i_set_dynwinds (scm_cons (scm_cons (wind
, unwind
), scm_i_dynwinds ()));
1684 VM_DEFINE_INSTRUCTION (87, abort
, "abort", 1, -1, -1)
1686 unsigned n
= FETCH ();
1688 if (sp
- n
- 2 <= SCM_FRAME_UPPER_ADDRESS (fp
))
1689 goto vm_error_stack_underflow
;
1690 vm_abort (vm
, n
, vm_cookie
);
1691 /* vm_abort should not return */
1695 VM_DEFINE_INSTRUCTION (88, unwind
, "unwind", 0, 0, 0)
1697 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1698 off of the dynamic stack. */
1699 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1703 VM_DEFINE_INSTRUCTION (89, wind_fluids
, "wind-fluids", 1, -1, 0)
1705 unsigned n
= FETCH ();
1711 wf
= scm_i_make_with_fluids (n
, sp
+ 1, sp
+ 1 + n
);
1714 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1715 scm_i_set_dynwinds (scm_cons (wf
, scm_i_dynwinds ()));
1720 VM_DEFINE_INSTRUCTION (90, unwind_fluids
, "unwind-fluids", 0, 0, 0)
1723 wf
= scm_car (scm_i_dynwinds ());
1724 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1725 scm_i_swap_with_fluids (wf
, current_thread
->dynamic_state
);
1730 VM_DEFINE_INSTRUCTION (91, fluid_ref
, "fluid-ref", 0, 1, 1)
1736 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1737 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp
))
1738 || ((num
= SCM_I_FLUID_NUM (*sp
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1740 /* Punt dynstate expansion and error handling to the C proc. */
1743 *sp
= scm_fluid_ref (*sp
);
1747 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
1749 if (scm_is_eq (val
, SCM_UNDEFINED
))
1750 val
= SCM_I_FLUID_DEFAULT (*sp
);
1751 if (SCM_UNLIKELY (scm_is_eq (val
, SCM_UNDEFINED
)))
1754 goto vm_error_unbound_fluid
;
1762 VM_DEFINE_INSTRUCTION (92, fluid_set
, "fluid-set", 0, 2, 0)
1765 SCM val
, fluid
, fluids
;
1768 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
1769 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
1770 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
1772 /* Punt dynstate expansion and error handling to the C proc. */
1774 scm_fluid_set_x (fluid
, val
);
1777 SCM_SIMPLE_VECTOR_SET (fluids
, num
, val
);
1784 VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals
, "assert-nargs-ee/locals", 1, 0, 0)
1789 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1792 if (SCM_UNLIKELY (sp
- (fp
- 1) != (n
& 0x7)))
1793 goto vm_error_wrong_num_args
;
1799 *++old_sp
= SCM_UNDEFINED
;
1806 (defun renumber-ops ()
1807 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1810 (let ((counter -1)) (goto-char (point-min))
1811 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1813 (number-to-string (setq counter (1+ counter)))