Update Gnulib to v0.0-6827-g39c3009; use the `dirfd' module.
[bpt/guile.git] / libguile / vm-i-system.c
CommitLineData
dce0252b 1/* Copyright (C) 2001,2008,2009,2010,2011 Free Software Foundation, Inc.
a98cef7e 2 *
53e28ed9 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
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.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
53e28ed9
AW
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
53e28ed9
AW
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
53e28ed9
AW
17 */
18
a98cef7e
KN
19
20/* This file is included in vm_engine.c */
21
a98cef7e
KN
22\f
23/*
24 * Basic operations
25 */
26
53e28ed9 27VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
a98cef7e
KN
28{
29 NEXT;
30}
31
53e28ed9 32VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
a98cef7e 33{
a222b0fa 34 nvalues = SCM_I_INUM (*sp--);
11ea1aba 35 NULLSTACK (1);
a222b0fa 36 if (nvalues == 1)
e06e857c 37 POP (finish_args);
a222b0fa
AW
38 else
39 {
40 POP_LIST (nvalues);
e06e857c 41 POP (finish_args);
877ffa3f 42 SYNC_REGISTER ();
e06e857c 43 finish_args = scm_values (finish_args);
a222b0fa
AW
44 }
45
1dc8f851 46 {
6c6a4439
AW
47#ifdef VM_ENABLE_STACK_NULLING
48 SCM *old_sp = sp;
49#endif
1dc8f851
AW
50
51 /* Restore registers */
52 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
6c6a4439
AW
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
55 stack */
56 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1dc8f851 57 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 58 NULLSTACK (old_sp - sp);
1dc8f851 59 }
e06e857c
AW
60
61 goto vm_done;
a98cef7e
KN
62}
63
cf45ff03 64VM_DEFINE_INSTRUCTION (2, drop, "drop", 0, 1, 0)
a98cef7e 65{
17e90c5e 66 DROP ();
a98cef7e
KN
67 NEXT;
68}
69
cf45ff03 70VM_DEFINE_INSTRUCTION (3, dup, "dup", 0, 0, 1)
26403690 71{
f349065e
KN
72 SCM x = *sp;
73 PUSH (x);
26403690
KN
74 NEXT;
75}
76
17e90c5e
KN
77\f
78/*
79 * Object creation
80 */
a98cef7e 81
cf45ff03 82VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
a98cef7e 83{
17e90c5e 84 PUSH (SCM_UNSPECIFIED);
a98cef7e
KN
85 NEXT;
86}
87
cf45ff03 88VM_DEFINE_INSTRUCTION (5, make_true, "make-true", 0, 0, 1)
a98cef7e 89{
17e90c5e 90 PUSH (SCM_BOOL_T);
a98cef7e
KN
91 NEXT;
92}
93
cf45ff03 94VM_DEFINE_INSTRUCTION (6, make_false, "make-false", 0, 0, 1)
a98cef7e 95{
17e90c5e 96 PUSH (SCM_BOOL_F);
a98cef7e
KN
97 NEXT;
98}
99
cf45ff03 100VM_DEFINE_INSTRUCTION (7, make_nil, "make-nil", 0, 0, 1)
4530432e
DK
101{
102 PUSH (SCM_ELISP_NIL);
103 NEXT;
104}
105
cf45ff03 106VM_DEFINE_INSTRUCTION (8, make_eol, "make-eol", 0, 0, 1)
a98cef7e 107{
17e90c5e 108 PUSH (SCM_EOL);
a98cef7e
KN
109 NEXT;
110}
111
cf45ff03 112VM_DEFINE_INSTRUCTION (9, make_int8, "make-int8", 1, 0, 1)
a98cef7e 113{
2d80426a 114 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
a98cef7e
KN
115 NEXT;
116}
117
cf45ff03 118VM_DEFINE_INSTRUCTION (10, make_int8_0, "make-int8:0", 0, 0, 1)
a98cef7e 119{
238e7a11 120 PUSH (SCM_INUM0);
a98cef7e
KN
121 NEXT;
122}
123
cf45ff03 124VM_DEFINE_INSTRUCTION (11, make_int8_1, "make-int8:1", 0, 0, 1)
a98cef7e 125{
238e7a11 126 PUSH (SCM_I_MAKINUM (1));
a98cef7e
KN
127 NEXT;
128}
129
cf45ff03 130VM_DEFINE_INSTRUCTION (12, make_int16, "make-int16", 2, 0, 1)
a98cef7e 131{
ea9b4b29
KN
132 int h = FETCH ();
133 int l = FETCH ();
2d80426a 134 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
a98cef7e
KN
135 NEXT;
136}
137
cf45ff03 138VM_DEFINE_INSTRUCTION (13, make_int64, "make-int64", 8, 0, 1)
586cfdec
AW
139{
140 scm_t_uint64 v = 0;
141 v += FETCH ();
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));
150 NEXT;
151}
152
cf45ff03 153VM_DEFINE_INSTRUCTION (14, make_uint64, "make-uint64", 8, 0, 1)
586cfdec
AW
154{
155 scm_t_uint64 v = 0;
156 v += FETCH ();
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));
165 NEXT;
166}
167
cf45ff03 168VM_DEFINE_INSTRUCTION (15, make_char8, "make-char8", 1, 0, 1)
a98cef7e 169{
4c402b88
MG
170 scm_t_uint8 v = 0;
171 v = FETCH ();
172
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. */
a98cef7e
KN
177 NEXT;
178}
179
cf45ff03 180VM_DEFINE_INSTRUCTION (16, make_char32, "make-char32", 4, 0, 1)
904a78f1
MG
181{
182 scm_t_wchar v = 0;
183 v += FETCH ();
184 v <<= 8; v += FETCH ();
185 v <<= 8; v += FETCH ();
186 v <<= 8; v += FETCH ();
187 PUSH (SCM_MAKE_CHAR (v));
188 NEXT;
189}
190
191
192
cf45ff03 193VM_DEFINE_INSTRUCTION (17, list, "list", 2, -1, 1)
cb4cca12 194{
23b587b0
LC
195 unsigned h = FETCH ();
196 unsigned l = FETCH ();
197 unsigned len = ((h << 8) + l);
198 POP_LIST (len);
cb4cca12
KN
199 NEXT;
200}
201
cf45ff03 202VM_DEFINE_INSTRUCTION (18, vector, "vector", 2, -1, 1)
cb4cca12 203{
23b587b0
LC
204 unsigned h = FETCH ();
205 unsigned l = FETCH ();
206 unsigned len = ((h << 8) + l);
5338b62b
AW
207 SCM vect;
208
877ffa3f 209 SYNC_REGISTER ();
5338b62b
AW
210 sp++; sp -= len;
211 CHECK_UNDERFLOW ();
212 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
213 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
214 NULLSTACK (len);
215 *sp = vect;
216
cb4cca12
KN
217 NEXT;
218}
219
a98cef7e
KN
220\f
221/*
17e90c5e 222 * Variable access
a98cef7e
KN
223 */
224
17e90c5e
KN
225#define OBJECT_REF(i) objects[i]
226#define OBJECT_SET(i,o) objects[i] = o
a98cef7e 227
af988bbf
KN
228#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
229#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
a98cef7e 230
2d80426a
LC
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)
d223c3fc 236#define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
a98cef7e 237
6f16379e 238#define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
8d90b356 239
17e90c5e 240/* ref */
a98cef7e 241
cf45ff03 242VM_DEFINE_INSTRUCTION (19, object_ref, "object-ref", 1, 0, 1)
a98cef7e 243{
a52b2d3d 244 register unsigned objnum = FETCH ();
0b5f0e49
LC
245 CHECK_OBJECT (objnum);
246 PUSH (OBJECT_REF (objnum));
17e90c5e 247 NEXT;
a98cef7e
KN
248}
249
a5cfddd5 250/* FIXME: necessary? elt 255 of the vector could be a vector... */
cf45ff03 251VM_DEFINE_INSTRUCTION (20, long_object_ref, "long-object-ref", 2, 0, 1)
a5cfddd5
AW
252{
253 unsigned int objnum = FETCH ();
254 objnum <<= 8;
255 objnum += FETCH ();
256 CHECK_OBJECT (objnum);
257 PUSH (OBJECT_REF (objnum));
258 NEXT;
259}
260
cf45ff03 261VM_DEFINE_INSTRUCTION (21, local_ref, "local-ref", 1, 0, 1)
a98cef7e 262{
17e90c5e 263 PUSH (LOCAL_REF (FETCH ()));
a1a482e0 264 ASSERT_BOUND (*sp);
17e90c5e 265 NEXT;
a98cef7e
KN
266}
267
cf45ff03 268VM_DEFINE_INSTRUCTION (22, long_local_ref, "long-local-ref", 2, 0, 1)
a98cef7e 269{
80545853
AW
270 unsigned int i = FETCH ();
271 i <<= 8;
272 i += FETCH ();
28b119ee 273 PUSH (LOCAL_REF (i));
a1a482e0 274 ASSERT_BOUND (*sp);
a98cef7e
KN
275 NEXT;
276}
277
cf45ff03 278VM_DEFINE_INSTRUCTION (23, local_bound, "local-bound?", 1, 0, 1)
3092a14d 279{
d223c3fc 280 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (FETCH ()), SCM_UNDEFINED)));
3092a14d
AW
281 NEXT;
282}
283
cf45ff03 284VM_DEFINE_INSTRUCTION (24, long_local_bound, "long-local-bound?", 2, 0, 1)
3092a14d
AW
285{
286 unsigned int i = FETCH ();
287 i <<= 8;
288 i += FETCH ();
d223c3fc 289 PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (i), SCM_UNDEFINED)));
3092a14d
AW
290 NEXT;
291}
292
cf45ff03 293VM_DEFINE_INSTRUCTION (25, variable_ref, "variable-ref", 0, 1, 1)
a98cef7e 294{
17e90c5e 295 SCM x = *sp;
238e7a11 296
dce0252b
AW
297 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
298 unlike in top-variable-ref, it really isn't an internal assertion
299 that can be optimized out -- the variable could be coming directly
300 from the user. */
301 if (SCM_UNLIKELY (!SCM_VARIABLEP (x)))
302 {
303 func_name = "variable-ref";
304 finish_args = x;
305 goto vm_error_not_a_variable;
306 }
307 else if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x)))
17e90c5e 308 {
1af77230
LC
309 SCM var_name;
310
311 /* Attempt to provide the variable name in the error message. */
312 var_name = scm_module_reverse_lookup (scm_current_module (), x);
d1079217 313 finish_args = scm_is_true (var_name) ? var_name : x;
17e90c5e
KN
314 goto vm_error_unbound;
315 }
238e7a11
LC
316 else
317 {
2d80426a 318 SCM o = VARIABLE_REF (x);
238e7a11
LC
319 *sp = o;
320 }
321
a98cef7e
KN
322 NEXT;
323}
324
cf45ff03 325VM_DEFINE_INSTRUCTION (26, variable_bound, "variable-bound?", 0, 1, 1)
3092a14d 326{
dce0252b
AW
327 SCM x = *sp;
328
329 if (SCM_UNLIKELY (!SCM_VARIABLEP (x)))
330 {
331 func_name = "variable-bound?";
332 finish_args = x;
333 goto vm_error_not_a_variable;
334 }
3092a14d 335 else
dce0252b 336 *sp = scm_from_bool (VARIABLE_BOUNDP (x));
3092a14d
AW
337 NEXT;
338}
339
cf45ff03 340VM_DEFINE_INSTRUCTION (27, toplevel_ref, "toplevel-ref", 1, 0, 1)
9cc649b8 341{
6297d229 342 unsigned objnum = FETCH ();
45dc6b34 343 SCM what, resolved;
9cc649b8 344 CHECK_OBJECT (objnum);
fd358575 345 what = OBJECT_REF (objnum);
9cc649b8 346
45dc6b34 347 if (!SCM_VARIABLEP (what))
9cc649b8 348 {
d0168f3d 349 SYNC_REGISTER ();
45dc6b34
MG
350 resolved = resolve_variable (what, scm_program_module (program));
351 if (!VARIABLE_BOUNDP (resolved))
9cc649b8 352 {
d1079217 353 finish_args = what;
9cc649b8
AW
354 goto vm_error_unbound;
355 }
45dc6b34 356 what = resolved;
fd358575 357 OBJECT_SET (objnum, what);
9cc649b8
AW
358 }
359
fd358575 360 PUSH (VARIABLE_REF (what));
9cc649b8
AW
361 NEXT;
362}
363
cf45ff03 364VM_DEFINE_INSTRUCTION (28, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
a5cfddd5 365{
45dc6b34 366 SCM what, resolved;
a5cfddd5
AW
367 unsigned int objnum = FETCH ();
368 objnum <<= 8;
369 objnum += FETCH ();
370 CHECK_OBJECT (objnum);
371 what = OBJECT_REF (objnum);
372
45dc6b34 373 if (!SCM_VARIABLEP (what))
a5cfddd5
AW
374 {
375 SYNC_REGISTER ();
45dc6b34
MG
376 resolved = resolve_variable (what, scm_program_module (program));
377 if (!VARIABLE_BOUNDP (resolved))
a5cfddd5 378 {
d1079217 379 finish_args = what;
a5cfddd5
AW
380 goto vm_error_unbound;
381 }
45dc6b34 382 what = resolved;
a5cfddd5
AW
383 OBJECT_SET (objnum, what);
384 }
385
386 PUSH (VARIABLE_REF (what));
387 NEXT;
388}
389
17e90c5e
KN
390/* set */
391
cf45ff03 392VM_DEFINE_INSTRUCTION (29, local_set, "local-set", 1, 1, 0)
a98cef7e 393{
eae2438d
AW
394 SCM x;
395 POP (x);
396 LOCAL_SET (FETCH (), x);
a98cef7e
KN
397 NEXT;
398}
399
cf45ff03 400VM_DEFINE_INSTRUCTION (30, long_local_set, "long-local-set", 2, 1, 0)
a98cef7e 401{
eae2438d 402 SCM x;
80545853
AW
403 unsigned int i = FETCH ();
404 i <<= 8;
405 i += FETCH ();
eae2438d
AW
406 POP (x);
407 LOCAL_SET (i, x);
a98cef7e
KN
408 NEXT;
409}
410
cf45ff03 411VM_DEFINE_INSTRUCTION (31, variable_set, "variable-set", 0, 2, 0)
a98cef7e 412{
dce0252b
AW
413 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp[0])))
414 {
415 func_name = "variable-set!";
416 finish_args = sp[0];
417 goto vm_error_not_a_variable;
418 }
2d80426a 419 VARIABLE_SET (sp[0], sp[-1]);
11ea1aba 420 DROPN (2);
a98cef7e
KN
421 NEXT;
422}
423
cf45ff03 424VM_DEFINE_INSTRUCTION (32, toplevel_set, "toplevel-set", 1, 1, 0)
9cc649b8 425{
6297d229 426 unsigned objnum = FETCH ();
fd358575 427 SCM what;
9cc649b8 428 CHECK_OBJECT (objnum);
fd358575 429 what = OBJECT_REF (objnum);
9cc649b8 430
fd358575 431 if (!SCM_VARIABLEP (what))
9cc649b8 432 {
6287726a 433 SYNC_BEFORE_GC ();
b7393ea1 434 what = resolve_variable (what, scm_program_module (program));
fd358575 435 OBJECT_SET (objnum, what);
9cc649b8
AW
436 }
437
fd358575 438 VARIABLE_SET (what, *sp);
9cc649b8
AW
439 DROP ();
440 NEXT;
441}
442
cf45ff03 443VM_DEFINE_INSTRUCTION (33, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
a5cfddd5
AW
444{
445 SCM what;
446 unsigned int objnum = FETCH ();
447 objnum <<= 8;
448 objnum += FETCH ();
449 CHECK_OBJECT (objnum);
450 what = OBJECT_REF (objnum);
451
452 if (!SCM_VARIABLEP (what))
453 {
454 SYNC_BEFORE_GC ();
455 what = resolve_variable (what, scm_program_module (program));
456 OBJECT_SET (objnum, what);
457 }
458
459 VARIABLE_SET (what, *sp);
460 DROP ();
461 NEXT;
462}
463
a98cef7e
KN
464\f
465/*
466 * branch and jump
467 */
468
97fcf583 469/* offset must be at least 24 bits wide, and signed */
efbd5892 470#define FETCH_OFFSET(offset) \
17e90c5e 471{ \
97fcf583
AW
472 offset = FETCH () << 16; \
473 offset += FETCH () << 8; \
474 offset += FETCH (); \
475 offset -= (offset & (1<<23)) << 1; \
efbd5892
AW
476}
477
eae2438d 478#define BR(p) \
efbd5892 479{ \
97fcf583 480 scm_t_int32 offset; \
efbd5892 481 FETCH_OFFSET (offset); \
17e90c5e 482 if (p) \
97fcf583 483 ip += offset; \
5b09b37f
AW
484 if (offset < 0) \
485 VM_HANDLE_INTERRUPTS; \
17e90c5e
KN
486 NEXT; \
487}
488
cf45ff03 489VM_DEFINE_INSTRUCTION (34, br, "br", 3, 0, 0)
41f248a8 490{
97fcf583 491 scm_t_int32 offset;
e5dc27b8 492 FETCH_OFFSET (offset);
97fcf583 493 ip += offset;
5b09b37f
AW
494 if (offset < 0)
495 VM_HANDLE_INTERRUPTS;
41f248a8
KN
496 NEXT;
497}
498
cf45ff03 499VM_DEFINE_INSTRUCTION (35, br_if, "br-if", 3, 0, 0)
a98cef7e 500{
eae2438d
AW
501 SCM x;
502 POP (x);
503 BR (scm_is_true (x));
a98cef7e
KN
504}
505
cf45ff03 506VM_DEFINE_INSTRUCTION (36, br_if_not, "br-if-not", 3, 0, 0)
a98cef7e 507{
eae2438d
AW
508 SCM x;
509 POP (x);
510 BR (scm_is_false (x));
a98cef7e
KN
511}
512
cf45ff03 513VM_DEFINE_INSTRUCTION (37, br_if_eq, "br-if-eq", 3, 0, 0)
a98cef7e 514{
eae2438d
AW
515 SCM x, y;
516 POP2 (y, x);
517 BR (scm_is_eq (x, y));
a98cef7e
KN
518}
519
cf45ff03 520VM_DEFINE_INSTRUCTION (38, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
a98cef7e 521{
eae2438d
AW
522 SCM x, y;
523 POP2 (y, x);
524 BR (!scm_is_eq (x, y));
17e90c5e
KN
525}
526
cf45ff03 527VM_DEFINE_INSTRUCTION (39, br_if_null, "br-if-null", 3, 0, 0)
17e90c5e 528{
eae2438d
AW
529 SCM x;
530 POP (x);
531 BR (scm_is_null (x));
17e90c5e
KN
532}
533
cf45ff03 534VM_DEFINE_INSTRUCTION (40, br_if_not_null, "br-if-not-null", 3, 0, 0)
17e90c5e 535{
eae2438d
AW
536 SCM x;
537 POP (x);
538 BR (!scm_is_null (x));
a98cef7e
KN
539}
540
a98cef7e
KN
541\f
542/*
543 * Subprogram call
544 */
545
cf45ff03 546VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne, "br-if-nargs-ne", 5, 0, 0)
7e01997e
AW
547{
548 scm_t_ptrdiff n;
7f991c7d 549 scm_t_int32 offset;
7e01997e
AW
550 n = FETCH () << 8;
551 n += FETCH ();
7e01997e
AW
552 FETCH_OFFSET (offset);
553 if (sp - (fp - 1) != n)
554 ip += offset;
555 NEXT;
556}
557
cf45ff03 558VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
7e01997e
AW
559{
560 scm_t_ptrdiff n;
7f991c7d 561 scm_t_int32 offset;
7e01997e
AW
562 n = FETCH () << 8;
563 n += FETCH ();
7e01997e
AW
564 FETCH_OFFSET (offset);
565 if (sp - (fp - 1) < n)
566 ip += offset;
567 NEXT;
568}
569
cf45ff03 570VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
7e01997e
AW
571{
572 scm_t_ptrdiff n;
ff74e44e
AW
573 scm_t_int32 offset;
574
7e01997e
AW
575 n = FETCH () << 8;
576 n += FETCH ();
7e01997e
AW
577 FETCH_OFFSET (offset);
578 if (sp - (fp - 1) > n)
579 ip += offset;
580 NEXT;
581}
582
cf45ff03 583VM_DEFINE_INSTRUCTION (44, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
1e2a8c26
AW
584{
585 scm_t_ptrdiff n;
586 n = FETCH () << 8;
587 n += FETCH ();
a6f15a1e 588 if (sp - (fp - 1) != n)
1e2a8c26 589 goto vm_error_wrong_num_args;
1e2a8c26
AW
590 NEXT;
591}
592
cf45ff03 593VM_DEFINE_INSTRUCTION (45, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
1e2a8c26
AW
594{
595 scm_t_ptrdiff n;
596 n = FETCH () << 8;
597 n += FETCH ();
a6f15a1e 598 if (sp - (fp - 1) < n)
1e2a8c26 599 goto vm_error_wrong_num_args;
1e2a8c26
AW
600 NEXT;
601}
602
cf45ff03 603VM_DEFINE_INSTRUCTION (46, bind_optionals, "bind-optionals", 2, -1, -1)
7e01997e
AW
604{
605 scm_t_ptrdiff n;
606 n = FETCH () << 8;
607 n += FETCH ();
608 while (sp - (fp - 1) < n)
609 PUSH (SCM_UNDEFINED);
610 NEXT;
611}
612
cf45ff03 613VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle, "bind-optionals/shuffle", 6, -1, -1)
7e01997e
AW
614{
615 SCM *walk;
616 scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
617 nreq = FETCH () << 8;
618 nreq += FETCH ();
619 nreq_and_opt = FETCH () << 8;
620 nreq_and_opt += FETCH ();
621 ntotal = FETCH () << 8;
622 ntotal += FETCH ();
623
624 /* look in optionals for first keyword or last positional */
625 /* starting after the last required positional arg */
3092a14d 626 walk = fp + nreq;
7e01997e
AW
627 while (/* while we have args */
628 walk <= sp
629 /* and we still have positionals to fill */
3092a14d 630 && walk - fp < nreq_and_opt
7e01997e
AW
631 /* and we haven't reached a keyword yet */
632 && !scm_is_keyword (*walk))
633 /* bind this optional arg (by leaving it in place) */
634 walk++;
635 /* now shuffle up, from walk to ntotal */
636 {
3092a14d 637 scm_t_ptrdiff nshuf = sp - walk + 1, i;
7e01997e
AW
638 sp = (fp - 1) + ntotal + nshuf;
639 CHECK_OVERFLOW ();
3092a14d
AW
640 for (i = 0; i < nshuf; i++)
641 sp[-i] = walk[nshuf-i-1];
7e01997e
AW
642 }
643 /* and fill optionals & keyword args with SCM_UNDEFINED */
3092a14d 644 while (walk <= (fp - 1) + ntotal)
7e01997e
AW
645 *walk++ = SCM_UNDEFINED;
646
647 NEXT;
648}
649
ff74e44e
AW
650/* Flags that determine whether other keywords are allowed, and whether a
651 rest argument is expected. These values must match those used by the
652 glil->assembly compiler. */
653#define F_ALLOW_OTHER_KEYS 1
654#define F_REST 2
655
cf45ff03 656VM_DEFINE_INSTRUCTION (48, bind_kwargs, "bind-kwargs", 5, 0, 0)
7e01997e
AW
657{
658 scm_t_uint16 idx;
659 scm_t_ptrdiff nkw;
ff74e44e 660 int kw_and_rest_flags;
7e01997e
AW
661 SCM kw;
662 idx = FETCH () << 8;
663 idx += FETCH ();
ff74e44e 664 /* XXX: We don't actually use NKW. */
7e01997e
AW
665 nkw = FETCH () << 8;
666 nkw += FETCH ();
ff74e44e 667 kw_and_rest_flags = FETCH ();
7e01997e 668
ff74e44e
AW
669 if (!(kw_and_rest_flags & F_REST)
670 && ((sp - (fp - 1) - nkw) % 2))
7e01997e
AW
671 goto vm_error_kwargs_length_not_even;
672
673 CHECK_OBJECT (idx);
674 kw = OBJECT_REF (idx);
ff74e44e
AW
675
676 /* Switch NKW to be a negative index below SP. */
677 for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
7e01997e
AW
678 {
679 SCM walk;
ff74e44e
AW
680
681 if (scm_is_keyword (sp[nkw]))
682 {
683 for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
684 {
685 if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
686 {
687 SCM si = SCM_CDAR (walk);
688 LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
689 sp[nkw + 1]);
690 break;
691 }
692 }
693 if (!(kw_and_rest_flags & F_ALLOW_OTHER_KEYS) && !scm_is_pair (walk))
694 goto vm_error_kwargs_unrecognized_keyword;
695
696 nkw++;
697 }
698 else if (!(kw_and_rest_flags & F_REST))
699 goto vm_error_kwargs_invalid_keyword;
7e01997e
AW
700 }
701
702 NEXT;
703}
704
ff74e44e
AW
705#undef F_ALLOW_OTHER_KEYS
706#undef F_REST
707
708
cf45ff03 709VM_DEFINE_INSTRUCTION (49, push_rest, "push-rest", 2, -1, -1)
1e2a8c26
AW
710{
711 scm_t_ptrdiff n;
a6f15a1e 712 SCM rest = SCM_EOL;
1e2a8c26
AW
713 n = FETCH () << 8;
714 n += FETCH ();
a6f15a1e 715 while (sp - (fp - 1) > n)
1e2a8c26
AW
716 /* No need to check for underflow. */
717 CONS (rest, *sp--, rest);
718 PUSH (rest);
1e2a8c26
AW
719 NEXT;
720}
721
cf45ff03 722VM_DEFINE_INSTRUCTION (50, bind_rest, "bind-rest", 4, -1, -1)
899d37a6
AW
723{
724 scm_t_ptrdiff n;
725 scm_t_uint32 i;
726 SCM rest = SCM_EOL;
727 n = FETCH () << 8;
728 n += FETCH ();
729 i = FETCH () << 8;
730 i += FETCH ();
731 while (sp - (fp - 1) > n)
732 /* No need to check for underflow. */
733 CONS (rest, *sp--, rest);
734 LOCAL_SET (i, rest);
735 NEXT;
736}
737
cf45ff03 738VM_DEFINE_INSTRUCTION (51, reserve_locals, "reserve-locals", 2, -1, -1)
b7946e9e 739{
258344b4 740 SCM *old_sp;
55d9bc94
AW
741 scm_t_int32 n;
742 n = FETCH () << 8;
743 n += FETCH ();
258344b4
AW
744 old_sp = sp;
745 sp = (fp - 1) + n;
746
747 if (old_sp < sp)
748 {
749 CHECK_OVERFLOW ();
750 while (old_sp < sp)
751 *++old_sp = SCM_UNDEFINED;
752 }
753 else
754 NULLSTACK (old_sp - sp);
755
55d9bc94
AW
756 NEXT;
757}
758
cf45ff03 759VM_DEFINE_INSTRUCTION (52, new_frame, "new-frame", 0, 0, 3)
b7946e9e 760{
6c6a4439
AW
761 /* NB: if you change this, see frames.c:vm-frame-num-locals */
762 /* and frames.h, vm-engine.c, etc of course */
9b709b0f
AW
763
764 /* We don't initialize the dynamic link here because we don't actually
765 know that this frame will point to the current fp: it could be
766 placed elsewhere on the stack if captured in a partial
767 continuation, and invoked from some other context. */
b2b33168
AW
768 PUSH (SCM_PACK (0)); /* dynamic link */
769 PUSH (SCM_PACK (0)); /* mvra */
770 PUSH (SCM_PACK (0)); /* ra */
b7946e9e
AW
771 NEXT;
772}
773
cf45ff03 774VM_DEFINE_INSTRUCTION (53, call, "call", 1, -1, 1)
a98cef7e 775{
17e90c5e 776 nargs = FETCH ();
a98cef7e
KN
777
778 vm_call:
75c3ed28 779 program = sp[-nargs];
c8b9df71 780
e8c37772 781 VM_HANDLE_INTERRUPTS;
e311f5fa 782
75c3ed28 783 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a98cef7e 784 {
75c3ed28 785 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
42906d74 786 {
75c3ed28
AW
787 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
788 goto vm_call;
789 }
790 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
791 && SCM_SMOB_APPLICABLE_P (program))
792 {
793 SYNC_REGISTER ();
794 sp[-nargs] = scm_i_smob_apply_trampoline (program);
795 goto vm_call;
42906d74 796 }
23f276de 797 else
75c3ed28 798 goto vm_error_wrong_type_apply;
a98cef7e 799 }
a98cef7e 800
75c3ed28 801 CACHE_PROGRAM ();
9b709b0f
AW
802
803 {
804 SCM *old_fp = fp;
805
806 fp = sp - nargs + 1;
807
808 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
809 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
810 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
811 SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
812 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
813 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
814 }
815
75c3ed28 816 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 817 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
818 APPLY_HOOK ();
819 NEXT;
a98cef7e
KN
820}
821
cf45ff03 822VM_DEFINE_INSTRUCTION (54, tail_call, "tail-call", 1, -1, 1)
a98cef7e 823{
17e90c5e 824 nargs = FETCH ();
75c3ed28 825
a5bbb22e 826 vm_tail_call:
75c3ed28 827 program = sp[-nargs];
17e90c5e 828
e8c37772 829 VM_HANDLE_INTERRUPTS;
a98cef7e 830
75c3ed28
AW
831 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
832 {
833 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
834 {
835 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
836 goto vm_tail_call;
837 }
838 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
839 && SCM_SMOB_APPLICABLE_P (program))
840 {
841 SYNC_REGISTER ();
842 sp[-nargs] = scm_i_smob_apply_trampoline (program);
843 goto vm_tail_call;
844 }
845 else
846 goto vm_error_wrong_type_apply;
847 }
848 else
17e90c5e 849 {
28106f54 850 int i;
11ea1aba 851#ifdef VM_ENABLE_STACK_NULLING
a6f15a1e
AW
852 SCM *old_sp = sp;
853 CHECK_STACK_LEAK ();
11ea1aba 854#endif
28106f54 855
28106f54 856 /* switch programs */
28106f54 857 CACHE_PROGRAM ();
a6f15a1e
AW
858 /* shuffle down the program and the arguments */
859 for (i = -1, sp = sp - nargs + 1; i < nargs; i++)
860 SCM_FRAME_STACK_ADDRESS (fp)[i] = sp[i];
11ea1aba 861
03e6c165 862 sp = fp + i - 1;
28106f54 863
11ea1aba
AW
864 NULLSTACK (old_sp - sp);
865
3dbbe28d 866 ip = SCM_C_OBJCODE_BASE (bp);
11ea1aba 867
28106f54
AW
868 APPLY_HOOK ();
869 NEXT;
17e90c5e 870 }
17e90c5e
KN
871}
872
cf45ff03 873VM_DEFINE_INSTRUCTION (55, subr_call, "subr-call", 1, -1, -1)
fd629322 874{
5b46a8c2 875 SCM pointer, ret;
fd629322 876 SCM (*subr)();
5b46a8c2 877
fd629322 878 nargs = FETCH ();
5b46a8c2 879 POP (pointer);
fd629322 880
5b46a8c2 881 subr = SCM_POINTER_VALUE (pointer);
fd629322
AW
882
883 VM_HANDLE_INTERRUPTS;
884 SYNC_REGISTER ();
885
886 switch (nargs)
887 {
888 case 0:
889 ret = subr ();
890 break;
891 case 1:
892 ret = subr (sp[0]);
893 break;
894 case 2:
895 ret = subr (sp[-1], sp[0]);
896 break;
897 case 3:
898 ret = subr (sp[-2], sp[-1], sp[0]);
899 break;
900 case 4:
901 ret = subr (sp[-3], sp[-2], sp[-1], sp[0]);
902 break;
903 case 5:
904 ret = subr (sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
905 break;
906 case 6:
907 ret = subr (sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
908 break;
909 case 7:
910 ret = subr (sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
911 break;
912 case 8:
913 ret = subr (sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
914 break;
915 case 9:
916 ret = subr (sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
917 break;
918 case 10:
919 ret = subr (sp[-9], sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
920 break;
921 default:
922 abort ();
923 }
924
925 NULLSTACK_FOR_NONLOCAL_EXIT ();
fd629322
AW
926
927 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
928 {
929 /* multiple values returned to continuation */
930 ret = scm_struct_ref (ret, SCM_INUM0);
931 nvalues = scm_ilength (ret);
932 PUSH_LIST (ret, scm_is_null);
933 goto vm_return_values;
934 }
935 else
936 {
937 PUSH (ret);
938 goto vm_return;
939 }
940}
941
cf45ff03 942VM_DEFINE_INSTRUCTION (56, smob_call, "smob-call", 1, -1, -1)
75c3ed28
AW
943{
944 SCM smob, ret;
945 SCM (*subr)();
946 nargs = FETCH ();
947 POP (smob);
948
949 subr = SCM_SMOB_DESCRIPTOR (smob).apply;
950
951 VM_HANDLE_INTERRUPTS;
952 SYNC_REGISTER ();
953
954 switch (nargs)
955 {
956 case 0:
957 ret = subr (smob);
958 break;
959 case 1:
960 ret = subr (smob, sp[0]);
961 break;
962 case 2:
963 ret = subr (smob, sp[-1], sp[0]);
964 break;
965 case 3:
966 ret = subr (smob, sp[-2], sp[-1], sp[0]);
967 break;
968 default:
969 abort ();
970 }
971
972 NULLSTACK_FOR_NONLOCAL_EXIT ();
75c3ed28
AW
973
974 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
975 {
976 /* multiple values returned to continuation */
977 ret = scm_struct_ref (ret, SCM_INUM0);
978 nvalues = scm_ilength (ret);
979 PUSH_LIST (ret, scm_is_null);
980 goto vm_return_values;
981 }
982 else
983 {
984 PUSH (ret);
985 goto vm_return;
986 }
987}
988
cf45ff03 989VM_DEFINE_INSTRUCTION (57, foreign_call, "foreign-call", 1, -1, -1)
827dc8dc
AW
990{
991 SCM foreign, ret;
992 nargs = FETCH ();
993 POP (foreign);
994
995 VM_HANDLE_INTERRUPTS;
996 SYNC_REGISTER ();
997
4d9130a5 998 ret = scm_i_foreign_call (foreign, sp - nargs + 1);
827dc8dc
AW
999
1000 NULLSTACK_FOR_NONLOCAL_EXIT ();
1001
1002 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
1003 {
1004 /* multiple values returned to continuation */
1005 ret = scm_struct_ref (ret, SCM_INUM0);
1006 nvalues = scm_ilength (ret);
1007 PUSH_LIST (ret, scm_is_null);
1008 goto vm_return_values;
1009 }
1010 else
1011 {
1012 PUSH (ret);
1013 goto vm_return;
1014 }
1015}
1016
cf45ff03 1017VM_DEFINE_INSTRUCTION (58, continuation_call, "continuation-call", 0, -1, 0)
1d1cae0e
AW
1018{
1019 SCM contregs;
1020 POP (contregs);
d8873dfe 1021
f7cea645 1022 SYNC_ALL ();
d8873dfe
AW
1023 scm_i_check_continuation (contregs);
1024 vm_return_to_continuation (scm_i_contregs_vm (contregs),
1025 scm_i_contregs_vm_cont (contregs),
1026 sp - (fp - 1), fp);
1027 scm_i_reinstate_continuation (contregs);
1028
1d1cae0e
AW
1029 /* no NEXT */
1030 abort ();
1031}
1032
cf45ff03 1033VM_DEFINE_INSTRUCTION (59, partial_cont_call, "partial-cont-call", 0, -1, 0)
cee1d22c 1034{
adbdfd6d 1035 SCM vmcont, intwinds, prevwinds;
eae2438d 1036 POP2 (intwinds, vmcont);
07801437 1037 SYNC_REGISTER ();
b3950ad6
AW
1038 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont)))
1039 { finish_args = vmcont;
1040 goto vm_error_continuation_not_rewindable;
1041 }
adbdfd6d
AW
1042 prevwinds = scm_i_dynwinds ();
1043 vm_reinstate_partial_continuation (vm, vmcont, intwinds, sp + 1 - fp, fp,
1044 vm_cookie);
1045
1046 /* Rewind prompt jmpbuffers, if any. */
1047 {
1048 SCM winds = scm_i_dynwinds ();
1049 for (; !scm_is_eq (winds, prevwinds); winds = scm_cdr (winds))
1050 if (SCM_PROMPT_P (scm_car (winds)) && SCM_PROMPT_SETJMP (scm_car (winds)))
1051 break;
1052 }
1053
07801437
AW
1054 CACHE_REGISTER ();
1055 program = SCM_FRAME_PROGRAM (fp);
1056 CACHE_PROGRAM ();
cee1d22c
AW
1057 NEXT;
1058}
1059
cf45ff03 1060VM_DEFINE_INSTRUCTION (60, tail_call_nargs, "tail-call/nargs", 0, 0, 1)
efbd5892
AW
1061{
1062 SCM x;
1063 POP (x);
1064 nargs = scm_to_int (x);
d51406fe 1065 /* FIXME: should truncate values? */
a5bbb22e 1066 goto vm_tail_call;
efbd5892
AW
1067}
1068
cf45ff03 1069VM_DEFINE_INSTRUCTION (61, call_nargs, "call/nargs", 0, 0, 1)
efbd5892
AW
1070{
1071 SCM x;
1072 POP (x);
1073 nargs = scm_to_int (x);
d51406fe 1074 /* FIXME: should truncate values? */
efbd5892
AW
1075 goto vm_call;
1076}
1077
cf45ff03 1078VM_DEFINE_INSTRUCTION (62, mv_call, "mv-call", 4, -1, 1)
a222b0fa 1079{
97fcf583 1080 scm_t_int32 offset;
e5dc27b8 1081 scm_t_uint8 *mvra;
a222b0fa
AW
1082
1083 nargs = FETCH ();
efbd5892 1084 FETCH_OFFSET (offset);
97fcf583 1085 mvra = ip + offset;
a222b0fa 1086
352c87d7 1087 vm_mv_call:
75c3ed28 1088 program = sp[-nargs];
a222b0fa 1089
7d94e4af
AW
1090 VM_HANDLE_INTERRUPTS;
1091
75c3ed28 1092 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a222b0fa 1093 {
75c3ed28
AW
1094 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
1095 {
1096 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
1097 goto vm_mv_call;
1098 }
1099 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
1100 && SCM_SMOB_APPLICABLE_P (program))
a222b0fa 1101 {
75c3ed28
AW
1102 SYNC_REGISTER ();
1103 sp[-nargs] = scm_i_smob_apply_trampoline (program);
1104 goto vm_mv_call;
a222b0fa 1105 }
cc8d1f5f 1106 else
75c3ed28 1107 goto vm_error_wrong_type_apply;
a222b0fa 1108 }
a222b0fa 1109
75c3ed28 1110 CACHE_PROGRAM ();
9b709b0f
AW
1111
1112 {
1113 SCM *old_fp = fp;
1114
1115 fp = sp - nargs + 1;
1116
1117 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
1118 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
1119 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
1120 SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
1121 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
1122 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
1123 }
1124
75c3ed28 1125 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 1126 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
1127 APPLY_HOOK ();
1128 NEXT;
a222b0fa
AW
1129}
1130
cf45ff03 1131VM_DEFINE_INSTRUCTION (63, apply, "apply", 1, -1, 1)
3616e9e9 1132{
c8b9df71
KN
1133 int len;
1134 SCM ls;
1135 POP (ls);
1136
1137 nargs = FETCH ();
9a8cc8e7 1138 ASSERT (nargs >= 2);
c8b9df71
KN
1139
1140 len = scm_ilength (ls);
41e49280
AW
1141 if (SCM_UNLIKELY (len < 0))
1142 {
1143 finish_args = ls;
1144 goto vm_error_apply_to_non_list;
1145 }
c8b9df71 1146
fb10a008 1147 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
c8b9df71
KN
1148
1149 nargs += len - 2;
1150 goto vm_call;
3616e9e9
KN
1151}
1152
cf45ff03 1153VM_DEFINE_INSTRUCTION (64, tail_apply, "tail-apply", 1, -1, 1)
f03c31db
AW
1154{
1155 int len;
1156 SCM ls;
1157 POP (ls);
1158
1159 nargs = FETCH ();
9a8cc8e7 1160 ASSERT (nargs >= 2);
f03c31db
AW
1161
1162 len = scm_ilength (ls);
41e49280
AW
1163 if (SCM_UNLIKELY (len < 0))
1164 {
1165 finish_args = ls;
1166 goto vm_error_apply_to_non_list;
1167 }
f03c31db 1168
fb10a008 1169 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
f03c31db
AW
1170
1171 nargs += len - 2;
a5bbb22e 1172 goto vm_tail_call;
f03c31db
AW
1173}
1174
cf45ff03 1175VM_DEFINE_INSTRUCTION (65, call_cc, "call/cc", 0, 1, 1)
17e90c5e 1176{
76282387 1177 int first;
d8873dfe 1178 SCM proc, vm_cont, cont;
76282387
AW
1179 POP (proc);
1180 SYNC_ALL ();
cee1d22c 1181 vm_cont = scm_i_vm_capture_stack (vp->stack_base, fp, sp, ip, NULL, 0);
d8873dfe 1182 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1183 if (first)
1184 {
b2b33168
AW
1185 PUSH (SCM_PACK (0)); /* dynamic link */
1186 PUSH (SCM_PACK (0)); /* mvra */
1187 PUSH (SCM_PACK (0)); /* ra */
76282387
AW
1188 PUSH (proc);
1189 PUSH (cont);
1190 nargs = 1;
1191 goto vm_call;
1192 }
d8873dfe 1193 else
76282387 1194 {
f3120251
AW
1195 /* Otherwise, the vm continuation was reinstated, and
1196 vm_return_to_continuation pushed on one value. We know only one
1197 value was returned because we are in value context -- the
1198 previous block jumped to vm_call, not vm_mv_call, after all.
1199
1200 So, pull our regs back down from the vp, and march on to the
1201 next instruction. */
d8873dfe
AW
1202 CACHE_REGISTER ();
1203 program = SCM_FRAME_PROGRAM (fp);
1204 CACHE_PROGRAM ();
f3120251 1205 RESTORE_CONTINUATION_HOOK ();
76282387
AW
1206 NEXT;
1207 }
a98cef7e
KN
1208}
1209
cf45ff03 1210VM_DEFINE_INSTRUCTION (66, tail_call_cc, "tail-call/cc", 0, 1, 1)
f03c31db 1211{
76282387 1212 int first;
d8873dfe 1213 SCM proc, vm_cont, cont;
76282387
AW
1214 POP (proc);
1215 SYNC_ALL ();
d8873dfe
AW
1216 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1217 stack frame. */
cee1d22c
AW
1218 vm_cont = scm_i_vm_capture_stack (vp->stack_base,
1219 SCM_FRAME_DYNAMIC_LINK (fp),
1220 SCM_FRAME_LOWER_ADDRESS (fp) - 1,
1221 SCM_FRAME_RETURN_ADDRESS (fp),
1222 SCM_FRAME_MV_RETURN_ADDRESS (fp),
1223 0);
d8873dfe 1224 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1225 if (first)
1226 {
1227 PUSH (proc);
1228 PUSH (cont);
1229 nargs = 1;
a5bbb22e 1230 goto vm_tail_call;
76282387 1231 }
76282387
AW
1232 else
1233 {
d8873dfe 1234 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
f3120251
AW
1235 does a return from the frame, either to the RA or
1236 MVRA. */
d8873dfe
AW
1237 CACHE_REGISTER ();
1238 program = SCM_FRAME_PROGRAM (fp);
1239 CACHE_PROGRAM ();
f3120251
AW
1240 /* Unfortunately we don't know whether we are at the RA, and thus
1241 have one value without an nvalues marker, or we are at the
1242 MVRA and thus have multiple values and the nvalues
1243 marker. Instead of adding heuristics here, we will let hook
1244 client code do that. */
1245 RESTORE_CONTINUATION_HOOK ();
d8873dfe 1246 NEXT;
76282387 1247 }
f03c31db
AW
1248}
1249
cf45ff03 1250VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
a98cef7e 1251{
a98cef7e 1252 vm_return:
c45d4d77 1253 POP_CONTINUATION_HOOK (1);
e8c37772
AW
1254
1255 VM_HANDLE_INTERRUPTS;
1256
f13c269b 1257 {
03e6c165 1258 SCM ret;
f13c269b
AW
1259
1260 POP (ret);
6c6a4439
AW
1261
1262#ifdef VM_ENABLE_STACK_NULLING
1263 SCM *old_sp = sp;
1264#endif
f13c269b
AW
1265
1266 /* Restore registers */
1267 sp = SCM_FRAME_LOWER_ADDRESS (fp);
03e6c165
AW
1268 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1269 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 1270
11ea1aba 1271#ifdef VM_ENABLE_STACK_NULLING
6c6a4439 1272 NULLSTACK (old_sp - sp);
11ea1aba 1273#endif
f13c269b
AW
1274
1275 /* Set return value (sp is already pushed) */
1276 *sp = ret;
1277 }
17e90c5e 1278
15df3447 1279 /* Restore the last program */
af988bbf 1280 program = SCM_FRAME_PROGRAM (fp);
499a4c07 1281 CACHE_PROGRAM ();
7e4760e4 1282 CHECK_IP ();
a98cef7e
KN
1283 NEXT;
1284}
17e90c5e 1285
cf45ff03 1286VM_DEFINE_INSTRUCTION (68, return_values, "return/values", 1, -1, -1)
a222b0fa 1287{
ef24c01b
AW
1288 /* nvalues declared at top level, because for some reason gcc seems to think
1289 that perhaps it might be used without declaration. Fooey to that, I say. */
ef24c01b
AW
1290 nvalues = FETCH ();
1291 vm_return_values:
c45d4d77 1292 POP_CONTINUATION_HOOK (nvalues);
ef24c01b 1293
7d94e4af
AW
1294 VM_HANDLE_INTERRUPTS;
1295
03e6c165 1296 if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
ef24c01b 1297 {
6c6a4439
AW
1298 /* A multiply-valued continuation */
1299 SCM *vals = sp - nvalues;
ef24c01b
AW
1300 int i;
1301 /* Restore registers */
1302 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1303 ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
1304 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1305
ef24c01b
AW
1306 /* Push return values, and the number of values */
1307 for (i = 0; i < nvalues; i++)
6c6a4439 1308 *++sp = vals[i+1];
ef24c01b 1309 *++sp = SCM_I_MAKINUM (nvalues);
a222b0fa 1310
6c6a4439
AW
1311 /* Finally null the end of the stack */
1312 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1313 }
1314 else if (nvalues >= 1)
1315 {
1316 /* Multiple values for a single-valued continuation -- here's where I
1317 break with guile tradition and try and do something sensible. (Also,
1318 this block handles the single-valued return to an mv
1319 continuation.) */
6c6a4439 1320 SCM *vals = sp - nvalues;
ef24c01b
AW
1321 /* Restore registers */
1322 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1323 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1324 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1325
ef24c01b 1326 /* Push first value */
6c6a4439 1327 *++sp = vals[1];
a222b0fa 1328
6c6a4439
AW
1329 /* Finally null the end of the stack */
1330 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1331 }
1332 else
1333 goto vm_error_no_values;
a222b0fa
AW
1334
1335 /* Restore the last program */
1336 program = SCM_FRAME_PROGRAM (fp);
1337 CACHE_PROGRAM ();
a222b0fa
AW
1338 CHECK_IP ();
1339 NEXT;
1340}
1341
cf45ff03 1342VM_DEFINE_INSTRUCTION (69, return_values_star, "return/values*", 1, -1, -1)
ef24c01b
AW
1343{
1344 SCM l;
1345
1346 nvalues = FETCH ();
11ea1aba 1347 ASSERT (nvalues >= 1);
ef24c01b
AW
1348
1349 nvalues--;
1350 POP (l);
9bd48cb1 1351 while (scm_is_pair (l))
ef24c01b
AW
1352 {
1353 PUSH (SCM_CAR (l));
1354 l = SCM_CDR (l);
1355 nvalues++;
1356 }
fb10a008 1357 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
e06e857c 1358 finish_args = scm_list_1 (l);
fb10a008
AW
1359 goto vm_error_improper_list;
1360 }
ef24c01b
AW
1361
1362 goto vm_return_values;
1363}
1364
cf45ff03 1365VM_DEFINE_INSTRUCTION (70, return_nvalues, "return/nvalues", 0, 1, -1)
2d9260d1
AW
1366{
1367 SCM n;
1368 POP (n);
1369 nvalues = scm_to_int (n);
1370 ASSERT (nvalues >= 0);
1371 goto vm_return_values;
1372}
1373
cf45ff03 1374VM_DEFINE_INSTRUCTION (71, truncate_values, "truncate-values", 2, -1, -1)
d51406fe
AW
1375{
1376 SCM x;
1377 int nbinds, rest;
1378 POP (x);
1379 nvalues = scm_to_int (x);
1380 nbinds = FETCH ();
1381 rest = FETCH ();
1382
1383 if (rest)
1384 nbinds--;
1385
1386 if (nvalues < nbinds)
1387 goto vm_error_not_enough_values;
1388
1389 if (rest)
1390 POP_LIST (nvalues - nbinds);
1391 else
1392 DROPN (nvalues - nbinds);
1393
1394 NEXT;
1395}
1396
cf45ff03 1397VM_DEFINE_INSTRUCTION (72, box, "box", 1, 1, 0)
a9b0f876 1398{
8d90b356
AW
1399 SCM val;
1400 POP (val);
1401 SYNC_BEFORE_GC ();
1402 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
a9b0f876
AW
1403 NEXT;
1404}
1405
8d90b356
AW
1406/* for letrec:
1407 (let ((a *undef*) (b *undef*) ...)
1408 (set! a (lambda () (b ...)))
1409 ...)
1410 */
cf45ff03 1411VM_DEFINE_INSTRUCTION (73, empty_box, "empty-box", 1, 0, 0)
a9b0f876 1412{
8d90b356
AW
1413 SYNC_BEFORE_GC ();
1414 LOCAL_SET (FETCH (),
1415 scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1416 NEXT;
1417}
a9b0f876 1418
cf45ff03 1419VM_DEFINE_INSTRUCTION (74, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
8d90b356
AW
1420{
1421 SCM v = LOCAL_REF (FETCH ());
1422 ASSERT_BOUND_VARIABLE (v);
1423 PUSH (VARIABLE_REF (v));
1424 NEXT;
1425}
a9b0f876 1426
cf45ff03 1427VM_DEFINE_INSTRUCTION (75, local_boxed_set, "local-boxed-set", 1, 1, 0)
8d90b356
AW
1428{
1429 SCM v, val;
1430 v = LOCAL_REF (FETCH ());
1431 POP (val);
1432 ASSERT_VARIABLE (v);
1433 VARIABLE_SET (v, val);
a9b0f876
AW
1434 NEXT;
1435}
1436
cf45ff03 1437VM_DEFINE_INSTRUCTION (76, free_ref, "free-ref", 1, 0, 1)
a9b0f876 1438{
8d90b356
AW
1439 scm_t_uint8 idx = FETCH ();
1440
57ab0671
AW
1441 CHECK_FREE_VARIABLE (idx);
1442 PUSH (FREE_VARIABLE_REF (idx));
8d90b356
AW
1443 NEXT;
1444}
a9b0f876 1445
57ab0671 1446/* no free-set -- if a var is assigned, it should be in a box */
a9b0f876 1447
cf45ff03 1448VM_DEFINE_INSTRUCTION (77, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
8d90b356
AW
1449{
1450 SCM v;
1451 scm_t_uint8 idx = FETCH ();
57ab0671
AW
1452 CHECK_FREE_VARIABLE (idx);
1453 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1454 ASSERT_BOUND_VARIABLE (v);
1455 PUSH (VARIABLE_REF (v));
1456 NEXT;
1457}
1458
cf45ff03 1459VM_DEFINE_INSTRUCTION (78, free_boxed_set, "free-boxed-set", 1, 1, 0)
8d90b356
AW
1460{
1461 SCM v, val;
1462 scm_t_uint8 idx = FETCH ();
1463 POP (val);
57ab0671
AW
1464 CHECK_FREE_VARIABLE (idx);
1465 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1466 ASSERT_BOUND_VARIABLE (v);
1467 VARIABLE_SET (v, val);
1468 NEXT;
1469}
1470
cf45ff03 1471VM_DEFINE_INSTRUCTION (79, make_closure, "make-closure", 2, -1, 1)
8d90b356 1472{
6f16379e
AW
1473 size_t n, len;
1474 SCM closure;
1475
1476 len = FETCH ();
1477 len <<= 8;
1478 len += FETCH ();
8d90b356 1479 SYNC_BEFORE_GC ();
6f16379e
AW
1480 closure = scm_words (scm_tc7_program | (len<<16), len + 3);
1481 SCM_SET_CELL_OBJECT_1 (closure, SCM_PROGRAM_OBJCODE (sp[-len]));
1482 SCM_SET_CELL_OBJECT_2 (closure, SCM_PROGRAM_OBJTABLE (sp[-len]));
1483 sp[-len] = closure;
1484 for (n = 0; n < len; n++)
1485 SCM_PROGRAM_FREE_VARIABLE_SET (closure, n, sp[-len + 1 + n]);
1486 DROPN (len);
a9b0f876
AW
1487 NEXT;
1488}
1489
cf45ff03 1490VM_DEFINE_INSTRUCTION (80, make_variable, "make-variable", 0, 0, 1)
80545853
AW
1491{
1492 SYNC_BEFORE_GC ();
1493 /* fixme underflow */
1494 PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1495 NEXT;
1496}
1497
cf45ff03 1498VM_DEFINE_INSTRUCTION (81, fix_closure, "fix-closure", 2, -1, 0)
c21c89b1 1499{
6f16379e 1500 SCM x;
c21c89b1 1501 unsigned int i = FETCH ();
6f16379e 1502 size_t n, len;
c21c89b1
AW
1503 i <<= 8;
1504 i += FETCH ();
c21c89b1
AW
1505 /* FIXME CHECK_LOCAL (i) */
1506 x = LOCAL_REF (i);
1507 /* FIXME ASSERT_PROGRAM (x); */
6f16379e
AW
1508 len = SCM_PROGRAM_NUM_FREE_VARIABLES (x);
1509 for (n = 0; n < len; n++)
1510 SCM_PROGRAM_FREE_VARIABLE_SET (x, n, sp[-len + 1 + n]);
1511 DROPN (len);
c21c89b1
AW
1512 NEXT;
1513}
1514
cf45ff03 1515VM_DEFINE_INSTRUCTION (82, define, "define", 0, 0, 2)
94ff26b9
AW
1516{
1517 SCM sym, val;
eae2438d 1518 POP2 (sym, val);
94ff26b9
AW
1519 SYNC_REGISTER ();
1520 VARIABLE_SET (scm_sym2var (sym, scm_current_module_lookup_closure (),
1521 SCM_BOOL_T),
1522 val);
1523 NEXT;
1524}
1525
cf45ff03 1526VM_DEFINE_INSTRUCTION (83, make_keyword, "make-keyword", 0, 1, 1)
94ff26b9
AW
1527{
1528 CHECK_UNDERFLOW ();
1529 SYNC_REGISTER ();
1530 *sp = scm_symbol_to_keyword (*sp);
1531 NEXT;
1532}
1533
cf45ff03 1534VM_DEFINE_INSTRUCTION (84, make_symbol, "make-symbol", 0, 1, 1)
94ff26b9
AW
1535{
1536 CHECK_UNDERFLOW ();
1537 SYNC_REGISTER ();
1538 *sp = scm_string_to_symbol (*sp);
1539 NEXT;
1540}
1541
cf45ff03 1542VM_DEFINE_INSTRUCTION (85, prompt, "prompt", 4, 2, 0)
4f66bcde
AW
1543{
1544 scm_t_int32 offset;
ea6b18e8 1545 scm_t_uint8 escape_only_p;
747022e4 1546 SCM k, prompt;
4f66bcde 1547
4f66bcde
AW
1548 escape_only_p = FETCH ();
1549 FETCH_OFFSET (offset);
4f66bcde
AW
1550 POP (k);
1551
1552 SYNC_REGISTER ();
d2964315 1553 /* Push the prompt onto the dynamic stack. */
adbdfd6d
AW
1554 prompt = scm_c_make_prompt (k, fp, sp, ip + offset, escape_only_p, vm_cookie,
1555 scm_i_dynwinds ());
1556 scm_i_set_dynwinds (scm_cons (prompt, SCM_PROMPT_DYNWINDS (prompt)));
adaf86ec 1557 if (SCM_PROMPT_SETJMP (prompt))
4f66bcde
AW
1558 {
1559 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
ea6b18e8 1560 to the handler.
d2964315
AW
1561
1562 Note, at this point, we must assume that any variable local to
1563 vm_engine that can be assigned *has* been assigned. So we need to pull
1564 all our state back from the ip/fp/sp.
ea6b18e8 1565 */
d2964315
AW
1566 CACHE_REGISTER ();
1567 program = SCM_FRAME_PROGRAM (fp);
1568 CACHE_PROGRAM ();
f3120251
AW
1569 /* The stack contains the values returned to this prompt, along
1570 with a number-of-values marker -- like an MV return. */
1571 ABORT_CONTINUATION_HOOK ();
4f66bcde
AW
1572 NEXT;
1573 }
1574
1575 /* Otherwise setjmp returned for the first time, so we go to execute the
1576 prompt's body. */
1577 NEXT;
1578}
1579
cf45ff03 1580VM_DEFINE_INSTRUCTION (86, wind, "wind", 0, 2, 0)
4f66bcde
AW
1581{
1582 SCM wind, unwind;
eae2438d 1583 POP2 (unwind, wind);
4f66bcde
AW
1584 SYNC_REGISTER ();
1585 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1586 are actually called; the compiler should emit calls to wind and unwind for
1587 the normal dynamic-wind control flow. */
1588 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind))))
1589 {
1590 finish_args = wind;
1591 goto vm_error_not_a_thunk;
1592 }
1593 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind))))
1594 {
1595 finish_args = unwind;
1596 goto vm_error_not_a_thunk;
1597 }
1598 scm_i_set_dynwinds (scm_cons (scm_cons (wind, unwind), scm_i_dynwinds ()));
1599 NEXT;
1600}
1601
cf45ff03 1602VM_DEFINE_INSTRUCTION (87, abort, "abort", 1, -1, -1)
4f66bcde
AW
1603{
1604 unsigned n = FETCH ();
4f66bcde 1605 SYNC_REGISTER ();
2d026f04 1606 if (sp - n - 2 <= SCM_FRAME_UPPER_ADDRESS (fp))
eaefabee 1607 goto vm_error_stack_underflow;
cee1d22c 1608 vm_abort (vm, n, vm_cookie);
6e84cb95 1609 /* vm_abort should not return */
4f66bcde
AW
1610 abort ();
1611}
1612
cf45ff03 1613VM_DEFINE_INSTRUCTION (88, unwind, "unwind", 0, 0, 0)
4f66bcde
AW
1614{
1615 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1616 off of the dynamic stack. */
1617 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1618 NEXT;
1619}
1620
cf45ff03 1621VM_DEFINE_INSTRUCTION (89, wind_fluids, "wind-fluids", 1, -1, 0)
e084b27e
AW
1622{
1623 unsigned n = FETCH ();
1624 SCM wf;
1625
f7cea645 1626 SYNC_REGISTER ();
2b41a37b
AW
1627 sp -= 2 * n;
1628 CHECK_UNDERFLOW ();
1629 wf = scm_i_make_with_fluids (n, sp + 1, sp + 1 + n);
1630 NULLSTACK (2 * n);
1631
a2a6c0e3 1632 scm_i_swap_with_fluids (wf, current_thread->dynamic_state);
e084b27e
AW
1633 scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
1634 NEXT;
1635}
1636
cf45ff03 1637VM_DEFINE_INSTRUCTION (90, unwind_fluids, "unwind-fluids", 0, 0, 0)
e084b27e
AW
1638{
1639 SCM wf;
1640 wf = scm_car (scm_i_dynwinds ());
1641 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
a2a6c0e3 1642 scm_i_swap_with_fluids (wf, current_thread->dynamic_state);
e084b27e
AW
1643 NEXT;
1644}
4f66bcde 1645
cf45ff03 1646VM_DEFINE_INSTRUCTION (91, fluid_ref, "fluid-ref", 0, 1, 1)
1e7a0337
AW
1647{
1648 size_t num;
1649 SCM fluids;
1650
1651 CHECK_UNDERFLOW ();
a2a6c0e3 1652 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (current_thread->dynamic_state);
6f8d7b12 1653 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp))
1e7a0337
AW
1654 || ((num = SCM_I_FLUID_NUM (*sp)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1655 {
1656 /* Punt dynstate expansion and error handling to the C proc. */
1657 SYNC_REGISTER ();
1658 *sp = scm_fluid_ref (*sp);
1659 }
1660 else
ef94624e
BT
1661 {
1662 SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num);
aafb4ed7
AW
1663 if (scm_is_eq (val, SCM_UNDEFINED))
1664 val = SCM_I_FLUID_DEFAULT (*sp);
d223c3fc 1665 if (SCM_UNLIKELY (scm_is_eq (val, SCM_UNDEFINED)))
ef94624e
BT
1666 {
1667 finish_args = *sp;
1668 goto vm_error_unbound_fluid;
1669 }
1670 *sp = val;
1671 }
1e7a0337
AW
1672
1673 NEXT;
1674}
1675
cf45ff03 1676VM_DEFINE_INSTRUCTION (92, fluid_set, "fluid-set", 0, 2, 0)
1e7a0337
AW
1677{
1678 size_t num;
1679 SCM val, fluid, fluids;
1680
eae2438d 1681 POP2 (val, fluid);
a2a6c0e3 1682 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (current_thread->dynamic_state);
6f8d7b12 1683 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid))
1e7a0337
AW
1684 || ((num = SCM_I_FLUID_NUM (fluid)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1685 {
1686 /* Punt dynstate expansion and error handling to the C proc. */
1687 SYNC_REGISTER ();
1688 scm_fluid_set_x (fluid, val);
1689 }
1690 else
1691 SCM_SIMPLE_VECTOR_SET (fluids, num, val);
1692
1693 NEXT;
1694}
1695
cf45ff03 1696VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals, "assert-nargs-ee/locals", 1, 0, 0)
de45d8ee
AW
1697{
1698 scm_t_ptrdiff n;
1699 SCM *old_sp;
1700
1701 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1702 n = FETCH ();
1703
1704 if (SCM_UNLIKELY (sp - (fp - 1) != (n & 0x7)))
1705 goto vm_error_wrong_num_args;
1706
1707 old_sp = sp;
1708 sp += (n >> 3);
1709 CHECK_OVERFLOW ();
1710 while (old_sp < sp)
1711 *++old_sp = SCM_UNDEFINED;
1712
1713 NEXT;
1714}
1715
8d90b356 1716
53e28ed9
AW
1717/*
1718(defun renumber-ops ()
1719 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1720 (interactive "")
1721 (save-excursion
1722 (let ((counter -1)) (goto-char (point-min))
1723 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1724 (replace-match
1725 (number-to-string (setq counter (1+ counter)))
1726 t t nil 1)))))
ff810079 1727(renumber-ops)
53e28ed9 1728*/
17e90c5e
KN
1729/*
1730 Local Variables:
1731 c-file-style: "gnu"
1732 End:
1733*/