1 /* Copyright (C) 2000 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
42 #define SCM_DEBUG_TYPING_STRICTNESS 0
46 /* default stack size in the number of SCM */
47 #define VM_DEFAULT_STACK_SIZE (16 * 1024) /* = 64KB */
48 #define VM_MAXIMUM_STACK_SIZE (1024 * 1024) /* = 4MB */
50 /* I sometimes use this for debugging. */
51 #define vm_puts(OBJ) \
53 scm_display (OBJ, scm_def_errp); \
54 scm_newline (scm_def_errp); \
62 #define INSTRUCTION_HASH_SIZE op_last
63 #define INSTRUCTION_HASH(ADDR) (((int) (ADDR) >> 1) % INSTRUCTION_HASH_SIZE)
65 /* These variables are defined in VM engines when they are first called. */
66 static struct scm_instruction
*scm_regular_instruction_table
= 0;
67 static struct scm_instruction
*scm_debug_instruction_table
= 0;
69 /* Hash table for finding instructions from addresses */
70 static struct inst_hash
{
72 struct scm_instruction
*inst
;
73 struct inst_hash
*next
;
74 } *scm_instruction_hash_table
[INSTRUCTION_HASH_SIZE
];
76 static long scm_instruction_tag
;
79 make_instruction (struct scm_instruction
*instp
)
81 SCM_RETURN_NEWSMOB (scm_instruction_tag
, instp
);
85 print_instruction (SCM obj
, SCM port
, scm_print_state
*pstate
)
87 scm_puts ("#<instruction ", port
);
88 scm_puts (SCM_INSTRUCTION_DATA (obj
)->name
, port
);
94 init_instruction_type ()
96 scm_instruction_tag
= scm_make_smob_type ("instruction", 0);
97 scm_set_smob_print (scm_instruction_tag
, print_instruction
);
102 static struct scm_instruction
*
103 find_instruction_by_name (const char *name
)
105 struct scm_instruction
*p
;
106 for (p
= scm_regular_instruction_table
; p
->opcode
!= op_last
; p
++)
107 if (strcmp (name
, p
->name
) == 0)
112 static struct scm_instruction
*
113 find_instruction_by_code (SCM code
)
116 void *addr
= SCM_CODE_TO_ADDR (code
);
117 for (p
= scm_instruction_hash_table
[INSTRUCTION_HASH (addr
)]; p
; p
= p
->next
)
123 #ifdef HAVE_LABELS_AS_VALUES
125 instruction_code_to_debug_addr (SCM code
)
127 struct scm_instruction
*p
= find_instruction_by_code (code
);
128 return scm_debug_instruction_table
[p
->opcode
].addr
;
132 /* Scheme interface */
134 SCM_DEFINE (scm_instruction_p
, "instruction?", 1, 0, 0,
137 #define FUNC_NAME s_scm_instruction_p
139 return SCM_BOOL (SCM_INSTRUCTION_P (obj
));
143 SCM_DEFINE (scm_system_instruction_p
, "system-instruction?", 1, 0, 0,
146 #define FUNC_NAME s_scm_system_instruction_p
148 return SCM_BOOL (SCM_SYSTEM_INSTRUCTION_P (obj
));
152 SCM_DEFINE (scm_functional_instruction_p
, "functional-instruction?", 1, 0, 0,
155 #define FUNC_NAME s_scm_functional_instruction_p
157 return SCM_BOOL (SCM_FUNCTIONAL_INSTRUCTION_P (obj
));
161 SCM_DEFINE (scm_instruction_name_p
, "instruction-name?", 1, 0, 0,
164 #define FUNC_NAME s_scm_instruction_name_p
166 SCM_VALIDATE_SYMBOL (1, name
);
167 return SCM_BOOL (find_instruction_by_name (SCM_CHARS (name
)));
171 SCM_DEFINE (scm_symbol_to_instruction
, "symbol->instruction", 1, 0, 0,
174 #define FUNC_NAME s_scm_symbol_to_instruction
176 struct scm_instruction
*p
;
177 SCM_VALIDATE_SYMBOL (1, name
);
179 p
= find_instruction_by_name (SCM_CHARS (name
));
181 SCM_MISC_ERROR ("No such instruction: ~S", SCM_LIST1 (name
));
187 SCM_DEFINE (scm_instruction_list
, "instruction-list", 0, 0, 0,
190 #define FUNC_NAME s_scm_instruction_list
193 struct scm_instruction
*p
;
194 for (p
= scm_regular_instruction_table
; p
->opcode
!= op_last
; p
++)
195 list
= scm_cons (p
->obj
, list
);
196 return scm_reverse_x (list
, SCM_EOL
);
200 SCM_DEFINE (scm_instruction_opcode
, "instruction-opcode", 1, 0, 0,
203 #define FUNC_NAME s_scm_instruction_opcode
205 SCM_VALIDATE_INSTRUCTION (1, inst
);
206 return SCM_MAKINUM (SCM_INSTRUCTION_DATA (inst
)->opcode
);
210 SCM_DEFINE (scm_instruction_name
, "instruction-name", 1, 0, 0,
213 #define FUNC_NAME s_scm_instruction_name
215 SCM_VALIDATE_INSTRUCTION (1, inst
);
216 return SCM_CAR (scm_intern0 (SCM_INSTRUCTION_DATA (inst
)->name
));
220 SCM_DEFINE (scm_instruction_type
, "instruction-type", 1, 0, 0,
223 #define FUNC_NAME s_scm_instruction_type
225 SCM_VALIDATE_INSTRUCTION (1, inst
);
226 return SCM_MAKINUM (SCM_INSTRUCTION_DATA (inst
)->type
);
230 SCM_DEFINE (scm_instruction_scheme_name
, "instruction-scheme-name", 1, 0, 0,
233 #define FUNC_NAME s_scm_instruction_scheme_name
235 SCM_VALIDATE_INSTRUCTION (1, inst
);
236 if (SCM_FUNCTIONAL_INSTRUCTION_P (inst
))
237 return SCM_CAR (scm_intern0 (SCM_INSTRUCTION_DATA (inst
)->sname
));
243 SCM_DEFINE (scm_instruction_arity
, "instruction-arity", 1, 0, 0,
246 #define FUNC_NAME s_scm_instruction_arity
248 SCM_VALIDATE_INSTRUCTION (1, inst
);
249 if (SCM_FUNCTIONAL_INSTRUCTION_P (inst
))
251 struct scm_instruction
*p
= SCM_INSTRUCTION_DATA (inst
);
252 return SCM_LIST2 (SCM_MAKINUM (p
->nargs
), SCM_BOOL (p
->restp
));
264 static long scm_bytecode_tag
;
267 make_bytecode (int size
)
269 struct scm_bytecode
*p
270 = scm_must_malloc (sizeof (*p
) + (size
* sizeof (SCM
)), "make_bytecode");
272 SCM_RETURN_NEWSMOB (scm_bytecode_tag
, p
);
276 mark_bytecode (SCM bytecode
)
279 struct scm_instruction
*p
;
281 int size
= SCM_BYTECODE_SIZE (bytecode
);
282 SCM
*base
= SCM_BYTECODE_BASE (bytecode
);
284 for (i
= 0; i
< size
; i
++)
286 p
= find_instruction_by_code (base
[i
]);
295 scm_gc_mark (base
[++i
]);
297 case INST_INUM
: /* a fixed integer; we don't need to mark it */
298 case INST_ADDR
: /* real memory address; we shouldn't mark it! */
306 print_bytecode (SCM obj
, SCM port
, scm_print_state
*pstate
)
308 scm_puts ("#<bytecode 0x", port
);
309 scm_intprint ((long) SCM_BYTECODE_BASE (obj
), 16, port
);
310 scm_putc ('>', port
);
315 free_bytecode (SCM bytecode
)
317 int size
= (sizeof (struct scm_bytecode
)
318 + (SCM_BYTECODE_SIZE (bytecode
) * sizeof (SCM
)));
319 if (SCM_BYTECODE_EXTS (bytecode
))
321 size
+= (SCM_BYTECODE_EXTS (bytecode
)[0] + 1) * sizeof (int);
322 scm_must_free (SCM_BYTECODE_EXTS (bytecode
));
324 scm_must_free (SCM_BYTECODE_DATA (bytecode
));
329 init_bytecode_type ()
331 scm_bytecode_tag
= scm_make_smob_type ("bytecode", 0);
332 scm_set_smob_mark (scm_bytecode_tag
, mark_bytecode
);
333 scm_set_smob_print (scm_bytecode_tag
, print_bytecode
);
334 scm_set_smob_free (scm_bytecode_tag
, free_bytecode
);
337 /* Scheme interface */
339 SCM_DEFINE (scm_bytecode_p
, "bytecode?", 1, 0, 0,
342 #define FUNC_NAME s_scm_bytecode_p
344 return SCM_BOOL (SCM_BYTECODE_P (obj
));
348 SCM_DEFINE (scm_make_bytecode
, "make-bytecode", 1, 0, 0,
351 #define FUNC_NAME s_scm_make_bytecode
353 int i
, size
, len
, offset
;
354 SCM header
, body
, nreqs
, restp
, nvars
, nexts
, exts
, bytecode
;
355 SCM
*old
, *new, *address
;
358 SCM_VALIDATE_VECTOR (1, code
);
359 SCM_ASSERT_RANGE (1, code
, SCM_LENGTH (code
) == 2);
360 header
= SCM_VELTS (code
)[0];
361 body
= SCM_VELTS (code
)[1];
362 SCM_VALIDATE_VECTOR (1, header
);
363 SCM_VALIDATE_VECTOR (2, body
);
364 SCM_ASSERT_RANGE (1, header
, SCM_LENGTH (header
) == 5);
365 nreqs
= SCM_VELTS (header
)[0];
366 restp
= SCM_VELTS (header
)[1];
367 nvars
= SCM_VELTS (header
)[2];
368 nexts
= SCM_VELTS (header
)[3];
369 exts
= SCM_VELTS (header
)[4];
370 SCM_VALIDATE_INUM (1, nreqs
);
371 SCM_VALIDATE_BOOL (2, restp
);
372 SCM_VALIDATE_INUM (3, nvars
);
373 SCM_VALIDATE_INUM (4, nexts
);
374 SCM_VALIDATE_VECTOR (5, exts
);
376 /* Create a new bytecode */
377 size
= SCM_LENGTH (body
);
378 old
= SCM_VELTS (body
);
379 bytecode
= make_bytecode (size
);
380 new = SCM_BYTECODE_BASE (bytecode
);
382 /* Initialize the header */
383 SCM_BYTECODE_NREQS (bytecode
) = SCM_INUM (nreqs
);
384 SCM_BYTECODE_RESTP (bytecode
) = SCM_FALSEP (restp
) ? 0 : 1;
385 SCM_BYTECODE_NVARS (bytecode
) = SCM_INUM (nvars
);
386 SCM_BYTECODE_NEXTS (bytecode
) = SCM_INUM (nexts
);
387 len
= SCM_LENGTH (exts
);
390 SCM_BYTECODE_EXTS (bytecode
) = NULL
;
394 SCM_BYTECODE_EXTS (bytecode
) =
395 scm_must_malloc ((len
+ 1) * sizeof (int), FUNC_NAME
);
396 SCM_BYTECODE_EXTS (bytecode
)[0] = len
;
397 for (i
= 0; i
< len
; i
++)
398 SCM_BYTECODE_EXTS (bytecode
)[i
+ 1] = SCM_INUM (SCM_VELTS (exts
)[i
]);
401 /* Initialize the body */
402 for (i
= 0; i
< size
; i
++)
404 struct scm_instruction
*p
;
406 /* Process instruction */
407 if (!SCM_SYMBOLP (old
[i
])
408 || !(p
= find_instruction_by_name (SCM_CHARS (old
[i
]))))
409 SCM_MISC_ERROR ("Invalid instruction: ~S", SCM_LIST1 (old
[i
]));
410 new[i
] = SCM_ADDR_TO_CODE (p
->addr
);
412 /* Process arguments */
413 if (p
->type
== INST_NONE
)
416 SCM_MISC_ERROR ("Unexpected end of code", SCM_EOL
);
420 /* never come here */
422 SCM_VALIDATE_INUM (1, old
[i
]);
429 /* top-level variable */
430 SCM_VALIDATE_SYMBOL (1, old
[i
]);
431 new[i
] = scm_intern0 (SCM_CHARS (old
[i
]));
434 /* just copy for now */
435 SCM_VALIDATE_CONS (1, old
[i
]);
436 SCM_VALIDATE_INUM (1, SCM_CAR (old
[i
]));
437 SCM_VALIDATE_INUM (1, SCM_CDR (old
[i
]));
441 /* another bytecode */
442 new[i
] = scm_make_bytecode (old
[i
]);
446 SCM_VALIDATE_INUM (1, old
[i
]);
447 /* Without the following intermediate variables, type conversion
448 fails on my machine. Casting doesn't work well, why? */
449 offset
= SCM_INUM (old
[i
]);
450 address
= new + offset
;
451 new[i
] = SCM_VM_MAKE_ADDRESS (address
);
459 SCM_DEFINE (scm_bytecode_decode
, "bytecode-decode", 1, 0, 0,
462 #define FUNC_NAME s_scm_bytecode_decode
465 SCM code
, *old
, *new;
467 SCM_VALIDATE_BYTECODE (1, bytecode
);
469 size
= SCM_BYTECODE_SIZE (bytecode
);
470 old
= SCM_BYTECODE_BASE (bytecode
);
471 code
= scm_make_vector (SCM_MAKINUM (size
), SCM_BOOL_F
);
472 new = SCM_VELTS (code
);
474 for (i
= 0; i
< size
; i
++)
476 struct scm_instruction
*p
;
478 /* Process instruction */
479 p
= find_instruction_by_code (old
[i
]);
483 SCM_MISC_ERROR ("Broken bytecode", SCM_EOL
);
485 new[i
] = scm_instruction_name (p
->obj
);
487 /* Process arguments */
488 if (p
->type
== INST_NONE
)
495 /* never come here */
503 /* top-level variable */
504 new[i
] = SCM_CAR (old
[i
]);
507 /* another bytecode */
508 new[i
] = scm_bytecode_decode (old
[i
]);
511 /* program address */
512 offset
= SCM_VM_ADDRESS (old
[i
]) - old
;
513 new[i
] = SCM_MAKINUM (offset
);
526 static long scm_program_tag
;
529 make_program (SCM code
, SCM env
)
531 SCM_RETURN_NEWSMOB2 (scm_program_tag
, SCM_UNPACK (code
), SCM_UNPACK (env
));
535 mark_program (SCM program
)
537 scm_gc_mark (SCM_PROGRAM_CODE (program
));
538 return SCM_PROGRAM_ENV (program
);
541 static SCM
scm_program_name (SCM program
);
544 print_program (SCM obj
, SCM port
, scm_print_state
*pstate
)
546 SCM name
= scm_program_name (obj
);
547 scm_puts ("#<program ", port
);
548 if (SCM_FALSEP (name
))
550 scm_puts ("0x", port
);
551 scm_intprint ((long) SCM_PROGRAM_BASE (obj
), 16, port
);
555 scm_display (name
, port
);
557 scm_putc ('>', port
);
564 scm_program_tag
= scm_make_smob_type ("program", 0);
565 scm_set_smob_mark (scm_program_tag
, mark_program
);
566 scm_set_smob_print (scm_program_tag
, print_program
);
569 /* Scheme interface */
571 SCM_DEFINE (scm_program_p
, "program?", 1, 0, 0,
574 #define FUNC_NAME s_scm_program_p
576 return SCM_BOOL (SCM_PROGRAM_P (obj
));
580 SCM_DEFINE (scm_make_program
, "make-program", 2, 0, 0,
581 (SCM bytecode
, SCM parent
),
583 #define FUNC_NAME s_scm_make_program
585 SCM_VALIDATE_BYTECODE (1, bytecode
);
586 return make_program (bytecode
, parent
);
590 SCM_DEFINE (scm_program_name
, "program-name", 1, 0, 0,
593 #define FUNC_NAME s_scm_program_name
595 SCM_VALIDATE_PROGRAM (1, program
);
596 return scm_object_property (program
, scm_sym_name
);
600 SCM_DEFINE (scm_program_code
, "program-code", 1, 0, 0,
603 #define FUNC_NAME s_scm_program_code
605 SCM_VALIDATE_PROGRAM (1, program
);
606 return SCM_PROGRAM_CODE (program
);
610 SCM_DEFINE (scm_program_base
, "program-base", 1, 0, 0,
613 #define FUNC_NAME s_scm_program_base
615 SCM_VALIDATE_PROGRAM (1, program
);
616 return SCM_VM_MAKE_ADDRESS (SCM_PROGRAM_BASE (program
));
625 static long scm_vm_frame_tag
;
627 /* This is used for debugging */
628 struct scm_vm_frame
{
638 #define SCM_VM_FRAME_P(OBJ) SCM_SMOB_PREDICATE (scm_vm_frame_tag, OBJ)
639 #define SCM_VM_FRAME_DATA(FR) ((struct scm_vm_frame *) SCM_SMOB_DATA (FR))
640 #define SCM_VALIDATE_VM_FRAME(POS,OBJ) SCM_MAKE_VALIDATE (POS, OBJ, VM_FRAME_P)
643 make_vm_frame (SCM
*fp
)
646 int size
= SCM_INUM (SCM_VM_FRAME_SIZE (fp
));
647 struct scm_vm_frame
*p
= scm_must_malloc (sizeof (*p
), "make_vm_frame");
648 p
->program
= SCM_VM_FRAME_PROGRAM (fp
);
649 p
->dynamic_link
= SCM_VM_FRAME_DYNAMIC_LINK (fp
);
650 p
->external_link
= SCM_VM_FRAME_EXTERNAL_LINK (fp
);
651 p
->stack_pointer
= SCM_VM_FRAME_STACK_POINTER (fp
);
652 p
->return_address
= SCM_VM_FRAME_RETURN_ADDRESS (fp
);
654 if (!SCM_FALSEP (p
->dynamic_link
))
655 p
->dynamic_link
= make_vm_frame (SCM_VM_ADDRESS (p
->dynamic_link
));
657 size
+= SCM_PROGRAM_NREQS (p
->program
) + SCM_PROGRAM_RESTP (p
->program
);
658 p
->variables
= scm_make_vector (SCM_MAKINUM (size
), SCM_BOOL_F
);
659 for (i
= 0; i
< size
; i
++)
660 SCM_VELTS (p
->variables
)[i
] = SCM_VM_FRAME_VARIABLE (fp
, i
);
662 SCM_RETURN_NEWSMOB (scm_vm_frame_tag
, p
);
666 mark_vm_frame (SCM frame
)
668 struct scm_vm_frame
*p
= SCM_VM_FRAME_DATA (frame
);
669 scm_gc_mark (p
->program
);
670 scm_gc_mark (p
->dynamic_link
);
671 scm_gc_mark (p
->external_link
);
676 init_vm_frame_type ()
678 scm_vm_frame_tag
= scm_make_smob_type ("vm-frame", 0);
679 scm_set_smob_mark (scm_vm_frame_tag
, mark_vm_frame
);
682 /* Scheme interface */
684 SCM_DEFINE (scm_frame_p
, "frame?", 1, 0, 0,
687 #define FUNC_NAME s_scm_frame_p
689 return SCM_BOOL (SCM_VM_FRAME_P (obj
));
693 SCM_DEFINE (scm_frame_program
, "frame-program", 1, 0, 0,
696 #define FUNC_NAME s_scm_frame_program
698 SCM_VALIDATE_VM_FRAME (1, frame
);
699 return SCM_VM_FRAME_DATA (frame
)->program
;
703 SCM_DEFINE (scm_frame_variables
, "frame-variables", 1, 0, 0,
706 #define FUNC_NAME s_scm_frame_variables
708 SCM_VALIDATE_VM_FRAME (1, frame
);
709 return SCM_VM_FRAME_DATA (frame
)->variables
;
713 SCM_DEFINE (scm_frame_dynamic_link
, "frame-dynamic-link", 1, 0, 0,
716 #define FUNC_NAME s_scm_frame_dynamic_link
718 SCM_VALIDATE_VM_FRAME (1, frame
);
719 return SCM_VM_FRAME_DATA (frame
)->dynamic_link
;
723 SCM_DEFINE (scm_frame_external_link
, "frame-external-link", 1, 0, 0,
726 #define FUNC_NAME s_scm_frame_external_link
728 SCM_VALIDATE_VM_FRAME (1, frame
);
729 return SCM_VM_FRAME_DATA (frame
)->external_link
;
733 SCM_DEFINE (scm_frame_stack_pointer
, "frame-stack-pointer", 1, 0, 0,
736 #define FUNC_NAME s_scm_frame_stack_pointer
738 SCM_VALIDATE_VM_FRAME (1, frame
);
739 return SCM_VM_FRAME_DATA (frame
)->stack_pointer
;
743 SCM_DEFINE (scm_frame_return_address
, "frame-return-address", 1, 0, 0,
746 #define FUNC_NAME s_scm_frame_return_address
748 SCM_VALIDATE_VM_FRAME (1, frame
);
749 return SCM_VM_FRAME_DATA (frame
)->return_address
;
758 static long scm_vm_cont_tag
;
761 capture_vm_cont (struct scm_vm
*vmp
)
763 struct scm_vm
*p
= scm_must_malloc (sizeof (*p
), "capture_vm_cont");
764 p
->stack_size
= vmp
->stack_limit
- vmp
->sp
;
765 p
->stack_base
= scm_must_malloc (p
->stack_size
* sizeof (SCM
),
767 p
->stack_limit
= p
->stack_base
+ p
->stack_size
- 1;
769 p
->sp
= (SCM
*) (vmp
->stack_limit
- vmp
->sp
);
770 p
->fp
= (SCM
*) (vmp
->stack_limit
- vmp
->fp
);
771 memcpy (p
->stack_base
, vmp
->sp
+ 1, vmp
->stack_size
* sizeof (SCM
));
772 SCM_RETURN_NEWSMOB (scm_vm_cont_tag
, p
);
776 reinstate_vm_cont (struct scm_vm
*vmp
, SCM cont
)
778 struct scm_vm
*p
= SCM_VM_CONT_VMP (cont
);
779 if (vmp
->stack_size
< p
->stack_size
)
781 puts ("FIXME: Need to expand");
785 vmp
->sp
= vmp
->stack_limit
- (int) p
->sp
;
786 vmp
->fp
= vmp
->stack_limit
- (int) p
->fp
;
787 memcpy (vmp
->sp
+ 1, p
->stack_base
, p
->stack_size
* sizeof (SCM
));
791 mark_vm_cont (SCM cont
)
794 struct scm_vm
*vmp
= SCM_VM_CONT_VMP (cont
);
795 for (p
= vmp
->stack_base
; p
<= vmp
->stack_limit
; p
++)
802 free_vm_cont (SCM cont
)
804 struct scm_vm
*p
= SCM_VM_CONT_VMP (cont
);
805 int size
= sizeof (struct scm_vm
) + p
->stack_size
* sizeof (SCM
);
806 scm_must_free (p
->stack_base
);
814 scm_vm_cont_tag
= scm_make_smob_type ("vm-cont", 0);
815 scm_set_smob_mark (scm_vm_cont_tag
, mark_vm_cont
);
816 scm_set_smob_free (scm_vm_cont_tag
, free_vm_cont
);
824 static long scm_vm_tag
;
827 make_vm (int stack_size
)
829 struct scm_vm
*vmp
= scm_must_malloc (sizeof (struct scm_vm
), "make_vm");
830 vmp
->stack_size
= stack_size
;
831 vmp
->stack_base
= scm_must_malloc (stack_size
* sizeof (SCM
), "make_vm");
832 vmp
->stack_limit
= vmp
->stack_base
+ vmp
->stack_size
- 1;
833 vmp
->sp
= vmp
->stack_limit
;
834 vmp
->ac
= SCM_BOOL_F
;
837 vmp
->options
= SCM_EOL
;
838 vmp
->boot_hook
= scm_make_hook (SCM_MAKINUM (1));
839 vmp
->halt_hook
= scm_make_hook (SCM_MAKINUM (1));
840 vmp
->next_hook
= scm_make_hook (SCM_MAKINUM (1));
841 vmp
->call_hook
= scm_make_hook (SCM_MAKINUM (1));
842 vmp
->apply_hook
= scm_make_hook (SCM_MAKINUM (1));
843 vmp
->return_hook
= scm_make_hook (SCM_MAKINUM (1));
844 SCM_RETURN_NEWSMOB (scm_vm_tag
, vmp
);
851 struct scm_vm
*vmp
= SCM_VM_DATA (vm
);
852 for (p
= vmp
->sp
+ 1; p
<= vmp
->stack_limit
; p
++)
856 scm_gc_mark (vmp
->ac
);
857 scm_gc_mark (vmp
->boot_hook
);
858 scm_gc_mark (vmp
->halt_hook
);
859 scm_gc_mark (vmp
->next_hook
);
860 scm_gc_mark (vmp
->call_hook
);
861 scm_gc_mark (vmp
->apply_hook
);
862 scm_gc_mark (vmp
->return_hook
);
869 scm_vm_tag
= scm_make_smob_type ("vm", sizeof (struct scm_vm
));
870 scm_set_smob_mark (scm_vm_tag
, mark_vm
);
873 /* Scheme interface */
875 SCM_DEFINE (scm_vm_version
, "vm-version", 0, 0, 0,
878 #define FUNC_NAME s_scm_vm_version
880 return scm_makfrom0str (VERSION
);
884 SCM_DEFINE (scm_vm_p
, "vm?", 1, 0, 0,
887 #define FUNC_NAME s_scm_vm_p
889 return SCM_BOOL (SCM_VM_P (obj
));
893 SCM_DEFINE (scm_make_vm
, "make-vm", 0, 0, 0,
896 #define FUNC_NAME s_scm_make_vm
898 return make_vm (VM_DEFAULT_STACK_SIZE
);
902 SCM_DEFINE (scm_vm_ac
, "vm:ac", 1, 0, 0,
905 #define FUNC_NAME s_scm_vm_ac
907 SCM_VALIDATE_VM (1, vm
);
908 return SCM_VM_DATA (vm
)->ac
;
912 SCM_DEFINE (scm_vm_pc
, "vm:pc", 1, 0, 0,
915 #define FUNC_NAME s_scm_vm_pc
917 SCM_VALIDATE_VM (1, vm
);
918 return SCM_VM_MAKE_ADDRESS (SCM_VM_DATA (vm
)->pc
);
922 SCM_DEFINE (scm_vm_sp
, "vm:sp", 1, 0, 0,
925 #define FUNC_NAME s_scm_vm_sp
927 SCM_VALIDATE_VM (1, vm
);
928 return SCM_VM_MAKE_ADDRESS (SCM_VM_DATA (vm
)->sp
);
932 SCM_DEFINE (scm_vm_fp
, "vm:fp", 1, 0, 0,
935 #define FUNC_NAME s_scm_vm_fp
937 SCM_VALIDATE_VM (1, vm
);
938 return SCM_VM_MAKE_ADDRESS (SCM_VM_DATA (vm
)->fp
);
942 SCM_DEFINE (scm_vm_current_frame
, "vm-current-frame", 1, 0, 0,
945 #define FUNC_NAME s_scm_vm_current_frame
947 SCM_VALIDATE_VM (1, vm
);
948 return make_vm_frame (SCM_VM_DATA (vm
)->fp
);
952 SCM_DEFINE (scm_vm_fetch_code
, "vm-fetch-code", 2, 0, 0,
955 #define FUNC_NAME s_scm_vm_fetch_code
958 struct scm_instruction
*inst
;
960 SCM_VALIDATE_VM (1, vm
);
961 SCM_VALIDATE_INUM (2, addr
);
963 p
= SCM_VM_ADDRESS (addr
);
965 inst
= find_instruction_by_code (*p
);
967 SCM_MISC_ERROR ("Broken bytecode", SCM_LIST1 (addr
));
969 list
= SCM_LIST1 (scm_instruction_name (inst
->obj
));
970 if (inst
->type
!= INST_NONE
)
972 if (inst
->type
== INST_ADDR
)
974 p
= SCM_CODE_TO_ADDR (p
[1]);
975 SCM_SETCDR (list
, SCM_LIST1 (SCM_VM_MAKE_ADDRESS (p
)));
978 SCM_SETCDR (list
, SCM_LIST1 (p
[1]));
984 SCM_DEFINE (scm_vm_stack_to_list
, "vm-stack->list", 1, 0, 0,
987 #define FUNC_NAME s_scm_vm_stack_to_list
990 SCM
*p
, list
= SCM_EOL
;
992 SCM_VALIDATE_VM (1, vm
);
994 vmp
= SCM_VM_DATA (vm
);
995 for (p
= vmp
->sp
+ 1; p
<= vmp
->stack_limit
; p
++)
996 list
= scm_cons (*p
, list
);
1001 SCM_DEFINE (scm_vm_option
, "vm-option", 2, 0, 0,
1004 #define FUNC_NAME s_scm_vm_option
1006 SCM_VALIDATE_VM (1, vm
);
1007 SCM_VALIDATE_SYMBOL (2, key
);
1008 return scm_assq_ref (SCM_VM_DATA (vm
)->options
, key
);
1012 SCM_DEFINE (scm_vm_set_option_x
, "vm-set-option!", 3, 0, 0,
1013 (SCM vm
, SCM key
, SCM val
),
1015 #define FUNC_NAME s_scm_vm_set_option_x
1017 SCM_VALIDATE_VM (1, vm
);
1018 SCM_VALIDATE_SYMBOL (2, key
);
1019 SCM_VM_DATA (vm
)->options
1020 = scm_assq_set_x (SCM_VM_DATA (vm
)->options
, key
, val
);
1021 return SCM_UNSPECIFIED
;
1025 SCM_DEFINE (scm_vm_boot_hook
, "vm-boot-hook", 1, 0, 0,
1028 #define FUNC_NAME s_scm_vm_boot_hook
1030 SCM_VALIDATE_VM (1, vm
);
1031 return SCM_VM_DATA (vm
)->boot_hook
;
1035 SCM_DEFINE (scm_vm_halt_hook
, "vm-halt-hook", 1, 0, 0,
1038 #define FUNC_NAME s_scm_vm_halt_hook
1040 SCM_VALIDATE_VM (1, vm
);
1041 return SCM_VM_DATA (vm
)->halt_hook
;
1045 SCM_DEFINE (scm_vm_next_hook
, "vm-next-hook", 1, 0, 0,
1048 #define FUNC_NAME s_scm_vm_next_hook
1050 SCM_VALIDATE_VM (1, vm
);
1051 return SCM_VM_DATA (vm
)->next_hook
;
1055 SCM_DEFINE (scm_vm_call_hook
, "vm-call-hook", 1, 0, 0,
1058 #define FUNC_NAME s_scm_vm_call_hook
1060 SCM_VALIDATE_VM (1, vm
);
1061 return SCM_VM_DATA (vm
)->call_hook
;
1065 SCM_DEFINE (scm_vm_apply_hook
, "vm-apply-hook", 1, 0, 0,
1068 #define FUNC_NAME s_scm_vm_apply_hook
1070 SCM_VALIDATE_VM (1, vm
);
1071 return SCM_VM_DATA (vm
)->apply_hook
;
1075 SCM_DEFINE (scm_vm_return_hook
, "vm-return-hook", 1, 0, 0,
1078 #define FUNC_NAME s_scm_vm_return_hook
1080 SCM_VALIDATE_VM (1, vm
);
1081 return SCM_VM_DATA (vm
)->return_hook
;
1085 SCM_SYMBOL (sym_debug
, "debug");
1087 static SCM
scm_regular_vm (SCM vm
, SCM program
);
1088 static SCM
scm_debug_vm (SCM vm
, SCM program
);
1090 #define VM_CODE(name) SCM_ADDR_TO_CODE (find_instruction_by_name (name)->addr)
1092 SCM_DEFINE (scm_vm_run
, "vm-run", 2, 0, 0,
1093 (SCM vm
, SCM program
),
1095 #define FUNC_NAME s_scm_vm_run
1098 static SCM
template[5];
1100 SCM_VALIDATE_VM (1, vm
);
1101 SCM_VALIDATE_PROGRAM (2, program
);
1103 if (SCM_EQ_P (template[0], SCM_PACK (0)))
1105 template[0] = VM_CODE ("%loadc");
1106 template[1] = SCM_BOOL_F
;
1107 template[2] = VM_CODE ("%call");
1108 template[3] = SCM_MAKINUM (0);
1109 template[4] = VM_CODE ("%halt");
1112 /* Create a boot program */
1113 bootcode
= make_bytecode (5);
1114 memcpy (SCM_BYTECODE_BASE (bootcode
), template, sizeof (SCM
) * 5);
1115 SCM_BYTECODE_BASE (bootcode
)[1] = program
;
1116 SCM_BYTECODE_SIZE (bootcode
) = 5;
1117 SCM_BYTECODE_EXTS (bootcode
) = NULL
;
1118 SCM_BYTECODE_NREQS (bootcode
) = 0;
1119 SCM_BYTECODE_RESTP (bootcode
) = 0;
1120 SCM_BYTECODE_NVARS (bootcode
) = 0;
1121 SCM_BYTECODE_NEXTS (bootcode
) = 0;
1122 program
= SCM_MAKE_PROGRAM (bootcode
, SCM_BOOL_F
);
1124 if (SCM_FALSEP (scm_vm_option (vm
, sym_debug
)))
1125 return scm_regular_vm (vm
, program
);
1127 return scm_debug_vm (vm
, program
);
1136 /* We don't want to snarf the engines */
1137 #ifndef SCM_MAGIC_SNARFER
1139 /* the regular engine */
1140 #define VM_ENGINE SCM_VM_REGULAR_ENGINE
1141 #include "vm_engine.c"
1144 /* the debug engine */
1145 #define VM_ENGINE SCM_VM_DEBUG_ENGINE
1146 #include "vm_engine.c"
1149 #endif /* not SCM_MAGIC_SNARFER */
1156 static SCM scm_module_vm
;
1163 /* Initialize the module */
1164 scm_module_vm
= scm_make_module (scm_read_0str ("(vm vm)"));
1165 old_module
= scm_select_module (scm_module_vm
);
1167 init_instruction_type ();
1168 init_bytecode_type ();
1169 init_program_type ();
1170 init_vm_frame_type ();
1171 init_vm_cont_type ();
1176 scm_select_module (old_module
);
1178 /* Initialize instruction tables */
1181 struct scm_instruction
*p
;
1183 SCM vm
= make_vm (0);
1184 scm_regular_vm (vm
, SCM_BOOL_F
);
1185 scm_debug_vm (vm
, SCM_BOOL_F
);
1188 for (i
= 0; i
< INSTRUCTION_HASH_SIZE
; i
++)
1189 scm_instruction_hash_table
[i
] = NULL
;
1191 for (p
= scm_regular_instruction_table
; p
->opcode
!= op_last
; p
++)
1194 struct inst_hash
*data
;
1195 SCM inst
= scm_permanent_object (make_instruction (p
));
1197 if (p
->restp
) p
->type
= INST_INUM
;
1198 hash
= INSTRUCTION_HASH (p
->addr
);
1199 data
= scm_must_malloc (sizeof (*data
), "inst_hash");
1200 data
->addr
= p
->addr
;
1202 data
->next
= scm_instruction_hash_table
[hash
];
1203 scm_instruction_hash_table
[hash
] = data
;
1209 scm_init_vm_vm_module ()
1211 scm_register_module_xxx ("vm vm", (void *) scm_init_vm
);