summaryrefslogtreecommitdiff
path: root/kernel/byterun/coq_interp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/byterun/coq_interp.c')
-rw-r--r--kernel/byterun/coq_interp.c974
1 files changed, 974 insertions, 0 deletions
diff --git a/kernel/byterun/coq_interp.c b/kernel/byterun/coq_interp.c
new file mode 100644
index 00000000..8bfe78eb
--- /dev/null
+++ b/kernel/byterun/coq_interp.c
@@ -0,0 +1,974 @@
+/***********************************************************************/
+/* */
+/* Coq Compiler */
+/* */
+/* Benjamin Gregoire, projets Logical and Cristal */
+/* INRIA Rocquencourt */
+/* */
+/* */
+/***********************************************************************/
+
+/* The bytecode interpreter */
+
+#include <stdio.h>
+#include "coq_gc.h"
+#include "coq_instruct.h"
+#include "coq_fix_code.h"
+#include "coq_memory.h"
+#include "coq_values.h"
+
+
+/* Registers for the abstract machine:
+ pc the code pointer
+ sp the stack pointer (grows downward)
+ accu the accumulator
+ env heap-allocated environment
+ trapsp pointer to the current trap frame
+ extra_args number of extra arguments provided by the caller
+
+sp is a local copy of the global variable extern_sp. */
+
+
+
+/* Instruction decoding */
+
+
+#ifdef THREADED_CODE
+# define Instruct(name) coq_lbl_##name:
+# if defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32)
+# define coq_Jumptbl_base ((char *) &&coq_lbl_ACC0)
+# else
+# define coq_Jumptbl_base ((char *) 0)
+# define coq_jumptbl_base ((char *) 0)
+# endif
+# ifdef DEBUG
+# define Next goto next_instr
+# else
+# ifdef __ia64__
+# define Next goto *(void *)(coq_jumptbl_base + *((uint32 *) pc)++)
+# else
+# define Next goto *(void *)(coq_jumptbl_base + *pc++)
+# endif
+# endif
+#else
+# define Instruct(name) case name:
+# define Next break
+#endif
+
+/* #define _COQ_DEBUG_ */
+
+#ifdef _COQ_DEBUG_
+# define print_instr(s) /*if (drawinstr)*/ printf("%s\n",s)
+# define print_int(i) /*if (drawinstr)*/ printf("%d\n",i)
+# else
+# define print_instr(s)
+# define print_int(i)
+#endif
+
+/* GC interface */
+#define Setup_for_gc { sp -= 2; sp[0] = accu; sp[1] = coq_env; coq_sp = sp; }
+#define Restore_after_gc { accu = sp[0]; coq_env = sp[1]; sp += 2; }
+
+
+/* Register optimization.
+ Some compilers underestimate the use of the local variables representing
+ the abstract machine registers, and don't put them in hardware registers,
+ which slows down the interpreter considerably.
+ For GCC, Xavier Leroy have hand-assigned hardware registers for
+ several architectures.
+*/
+
+#if defined(__GNUC__) && !defined(DEBUG)
+#ifdef __mips__
+#define PC_REG asm("$16")
+#define SP_REG asm("$17")
+#define ACCU_REG asm("$18")
+#endif
+#ifdef __sparc__
+#define PC_REG asm("%l0")
+#define SP_REG asm("%l1")
+#define ACCU_REG asm("%l2")
+#endif
+#ifdef __alpha__
+#ifdef __CRAY__
+#define PC_REG asm("r9")
+#define SP_REG asm("r10")
+#define ACCU_REG asm("r11")
+#define JUMPTBL_BASE_REG asm("r12")
+#else
+#define PC_REG asm("$9")
+#define SP_REG asm("$10")
+#define ACCU_REG asm("$11")
+#define JUMPTBL_BASE_REG asm("$12")
+#endif
+#endif
+#ifdef __i386__
+#define PC_REG asm("%esi")
+#define SP_REG asm("%edi")
+#define ACCU_REG
+#endif
+#if defined(PPC) || defined(_POWER) || defined(_IBMR2)
+#define PC_REG asm("26")
+#define SP_REG asm("27")
+#define ACCU_REG asm("28")
+#endif
+#ifdef __hppa__
+#define PC_REG asm("%r18")
+#define SP_REG asm("%r17")
+#define ACCU_REG asm("%r16")
+#endif
+#ifdef __mc68000__
+#define PC_REG asm("a5")
+#define SP_REG asm("a4")
+#define ACCU_REG asm("d7")
+#endif
+#ifdef __arm__
+#define PC_REG asm("r9")
+#define SP_REG asm("r8")
+#define ACCU_REG asm("r7")
+#endif
+#ifdef __ia64__
+#define PC_REG asm("36")
+#define SP_REG asm("37")
+#define ACCU_REG asm("38")
+#define JUMPTBL_BASE_REG asm("39")
+#endif
+#endif
+
+/* The interpreter itself */
+
+value coq_interprete
+(code_t coq_pc, value coq_accu, value coq_env, long coq_extra_args)
+{
+ /*Declaration des variables */
+#ifdef PC_REG
+ register code_t pc PC_REG;
+ register value * sp SP_REG;
+ register value accu ACCU_REG;
+#else
+ register code_t pc;
+ register value * sp;
+ register value accu;
+#endif
+#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32)
+#ifdef JUMPTBL_BASE_REG
+ register char * coq_jumptbl_base JUMPTBL_BASE_REG;
+#else
+ register char * coq_jumptbl_base;
+#endif
+#endif
+#ifdef THREADED_CODE
+ static void * coq_jumptable[] = {
+# include "coq_jumptbl.h"
+ };
+#else
+ opcode_t curr_instr;
+#endif
+ print_instr("Enter Interpreter");
+ if (coq_pc == NULL) { /* Interpreter is initializing */
+ print_instr("Interpreter is initializing");
+#ifdef THREADED_CODE
+ coq_instr_table = (char **) coq_jumptable;
+ coq_instr_base = coq_Jumptbl_base;
+#endif
+ return Val_unit;
+ }
+#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32)
+ coq_jumptbl_base = coq_Jumptbl_base;
+#endif
+
+ /* Initialisation */
+ sp = coq_sp;
+ pc = coq_pc;
+ accu = coq_accu;
+#ifdef THREADED_CODE
+ goto *(void *)(coq_jumptbl_base + *pc++); /* Jump to the first instruction */
+#else
+ while(1) {
+ curr_instr = *pc++;
+ switch(curr_instr) {
+#endif
+/* Basic stack operations */
+
+ Instruct(ACC0){
+ print_instr("ACC0");
+ accu = sp[0]; Next;
+ }
+ Instruct(ACC1){
+ print_instr("ACC1");
+ accu = sp[1]; Next;
+ }
+ Instruct(ACC2){
+ print_instr("ACC2");
+ accu = sp[2]; Next;
+ }
+ Instruct(ACC3){
+ print_instr("ACC3");
+ accu = sp[3]; Next;
+ }
+ Instruct(ACC4){
+ print_instr("ACC4");
+ accu = sp[4]; Next;
+ }
+ Instruct(ACC5){
+ print_instr("ACC5");
+ accu = sp[5]; Next;
+ }
+ Instruct(ACC6){
+ print_instr("ACC6");
+ accu = sp[6]; Next;
+ }
+ Instruct(ACC7){
+ print_instr("ACC7");
+ accu = sp[7]; Next;
+ }
+ Instruct(PUSH){
+ print_instr("PUSH");
+ *--sp = accu; Next;
+ }
+ Instruct(PUSHACC0) {
+ print_instr("PUSHACC0");
+ *--sp = accu; Next;
+ }
+ Instruct(PUSHACC1){
+ print_instr("PUSHACC1");
+ *--sp = accu; accu = sp[1]; Next;
+ }
+ Instruct(PUSHACC2){
+ print_instr("PUSHACC2");
+ *--sp = accu; accu = sp[2]; Next;
+ }
+ Instruct(PUSHACC3){
+ print_instr("PUSHACC3");
+ *--sp = accu; accu = sp[3]; Next;
+ }
+ Instruct(PUSHACC4){
+ print_instr("PUSHACC4");
+ *--sp = accu; accu = sp[4]; Next;
+ }
+ Instruct(PUSHACC5){
+ print_instr("PUSHACC5");
+ *--sp = accu; accu = sp[5]; Next;
+ }
+ Instruct(PUSHACC6){
+ print_instr("PUSHACC5");
+ *--sp = accu; accu = sp[6]; Next;
+ }
+ Instruct(PUSHACC7){
+ print_instr("PUSHACC7");
+ *--sp = accu; accu = sp[7]; Next;
+ }
+ Instruct(PUSHACC){
+ print_instr("PUSHACC");
+ *--sp = accu;
+ }
+ /* Fallthrough */
+
+ Instruct(ACC){
+ print_instr("ACC");
+ accu = sp[*pc++];
+ Next;
+ }
+
+ Instruct(POP){
+ print_instr("POP");
+ sp += *pc++;
+ Next;
+ }
+ /* Access in heap-allocated environment */
+
+ Instruct(ENVACC1){
+ print_instr("ENVACC1");
+ accu = Field(coq_env, 1); Next;
+ }
+ Instruct(ENVACC2){
+ print_instr("ENVACC2");
+ accu = Field(coq_env, 2); Next;
+ }
+ Instruct(ENVACC3){
+ print_instr("ENVACC3");
+ accu = Field(coq_env, 3); Next;
+ }
+ Instruct(ENVACC4){
+ print_instr("ENVACC4");
+ accu = Field(coq_env, 4); Next;
+ }
+ Instruct(PUSHENVACC1){
+ print_instr("PUSHENVACC1");
+ *--sp = accu; accu = Field(coq_env, 1); Next;
+ }
+ Instruct(PUSHENVACC2){
+ print_instr("PUSHENVACC2");
+ *--sp = accu; accu = Field(coq_env, 2); Next;
+ }
+ Instruct(PUSHENVACC3){
+ print_instr("PUSHENVACC3");
+ *--sp = accu; accu = Field(coq_env, 3); Next;
+ }
+ Instruct(PUSHENVACC4){
+ print_instr("PUSHENVACC4");
+ *--sp = accu; accu = Field(coq_env, 4); Next;
+ }
+ Instruct(PUSHENVACC){
+ print_instr("PUSHENVACC");
+ *--sp = accu;
+ }
+ /* Fallthrough */
+ Instruct(ENVACC){
+ print_instr("ENVACC");
+ accu = Field(coq_env, *pc++);
+ Next;
+ }
+ /* Function application */
+
+ Instruct(PUSH_RETADDR) {
+ print_instr("PUSH_RETADDR");
+ sp -= 3;
+ sp[0] = (value) (pc + *pc);
+ sp[1] = coq_env;
+ sp[2] = Val_long(coq_extra_args);
+ coq_extra_args = 0;
+ pc++;
+ Next;
+ }
+ Instruct(APPLY) {
+ print_instr("APPLY");
+ coq_extra_args = *pc - 1;
+ pc = Code_val(accu);
+ coq_env = accu;
+ goto check_stacks;
+ }
+ Instruct(APPLY1) {
+ value arg1 = sp[0];
+ print_instr("APPLY1");
+ sp -= 3;
+ sp[0] = arg1;
+ sp[1] = (value)pc;
+ sp[2] = coq_env;
+ sp[3] = Val_long(coq_extra_args);
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args = 0;
+ goto check_stacks;
+ }
+ Instruct(APPLY2) {
+ value arg1 = sp[0];
+ value arg2 = sp[1];
+ print_instr("APPLY2");
+ sp -= 3;
+ sp[0] = arg1;
+ sp[1] = arg2;
+ sp[2] = (value)pc;
+ sp[3] = coq_env;
+ sp[4] = Val_long(coq_extra_args);
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args = 1;
+ goto check_stacks;
+ }
+ Instruct(APPLY3) {
+ value arg1 = sp[0];
+ value arg2 = sp[1];
+ value arg3 = sp[2];
+ print_instr("APPLY3");
+ sp -= 3;
+ sp[0] = arg1;
+ sp[1] = arg2;
+ sp[2] = arg3;
+ sp[3] = (value)pc;
+ sp[4] = coq_env;
+ sp[5] = Val_long(coq_extra_args);
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args = 2;
+ goto check_stacks;
+ }
+
+ Instruct(APPTERM) {
+ int nargs = *pc++;
+ int slotsize = *pc;
+ value * newsp;
+ int i;
+ print_instr("APPTERM");
+ /* Slide the nargs bottom words of the current frame to the top
+ of the frame, and discard the remainder of the frame */
+ newsp = sp + slotsize - nargs;
+ for (i = nargs - 1; i >= 0; i--) newsp[i] = sp[i];
+ sp = newsp;
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args += nargs - 1;
+ goto check_stacks;
+ }
+ Instruct(APPTERM1) {
+ value arg1 = sp[0];
+ print_instr("APPTERM1");
+ sp = sp + *pc - 1;
+ sp[0] = arg1;
+ pc = Code_val(accu);
+ coq_env = accu;
+ goto check_stacks;
+ }
+ Instruct(APPTERM2) {
+ value arg1 = sp[0];
+ value arg2 = sp[1];
+ print_instr("APPTERM2");
+ sp = sp + *pc - 2;
+ sp[0] = arg1;
+ sp[1] = arg2;
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args += 1;
+ goto check_stacks;
+ }
+ Instruct(APPTERM3) {
+ value arg1 = sp[0];
+ value arg2 = sp[1];
+ value arg3 = sp[2];
+ print_instr("APPTERM3");
+ sp = sp + *pc - 3;
+ sp[0] = arg1;
+ sp[1] = arg2;
+ sp[2] = arg3;
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args += 2;
+ goto check_stacks;
+ }
+
+ Instruct(RETURN) {
+ print_instr("RETURN");
+ sp += *pc++;
+ if (coq_extra_args > 0) {
+ coq_extra_args--;
+ pc = Code_val(accu);
+ coq_env = accu;
+ } else {
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ }
+ Next;
+ }
+
+ Instruct(RESTART) {
+ int num_args = Wosize_val(coq_env) - 2;
+ int i;
+ print_instr("RESTART");
+ sp -= num_args;
+ for (i = 0; i < num_args; i++) sp[i] = Field(coq_env, i + 2);
+ coq_env = Field(coq_env, 1);
+ coq_extra_args += num_args;
+ Next;
+ }
+
+ Instruct(GRAB) {
+ int required = *pc++;
+ print_instr("GRAB");
+ /* printf("GRAB %d\n",required); */
+ if (coq_extra_args >= required) {
+ coq_extra_args -= required;
+ } else {
+ mlsize_t num_args, i;
+ num_args = 1 + coq_extra_args; /* arg1 + extra args */
+ Alloc_small(accu, num_args + 2, Closure_tag);
+ Field(accu, 1) = coq_env;
+ for (i = 0; i < num_args; i++) Field(accu, i + 2) = sp[i];
+ Code_val(accu) = pc - 3; /* Point to the preceding RESTART instr. */
+ sp += num_args;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ }
+ Next;
+ }
+
+ Instruct(COGRAB){
+ int required = *pc++;
+ print_instr("COGRAB");
+ if(forcable == Val_true) {
+ print_instr("true");
+ /* L'instruction précédante est FORCE */
+ if (coq_extra_args > 0) coq_extra_args--;
+ pc++;
+ forcable = Val_false;
+ } else { /* L'instruction précédante est APPLY */
+ mlsize_t num_args, i;
+ num_args = 1 + coq_extra_args; /* arg1 + extra args */
+ Alloc_small(accu, num_args + 2, Closure_tag);
+ Field(accu, 1) = coq_env;
+ for (i = 0; i < num_args; i++) Field(accu, i + 2) = sp[i];
+ Code_val(accu) = pc - 3; /* Point to the preceding RESTART instr. */
+ sp += num_args;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ }
+ Next;
+ }
+ Instruct(GRABREC) {
+ int rec_pos = *pc++; /* commence a zero */
+ print_instr("GRABREC");
+ if (rec_pos <= coq_extra_args && !Is_accu(sp[rec_pos])) {
+ pc++;/* On saute le Restart */
+ } else {
+ if (coq_extra_args < rec_pos) {
+ mlsize_t num_args, i;
+ num_args = 1 + coq_extra_args; /* arg1 + extra args */
+ Alloc_small(accu, num_args + 2, Closure_tag);
+ Field(accu, 1) = coq_env;
+ for (i = 0; i < num_args; i++) Field(accu, i + 2) = sp[i];
+ Code_val(accu) = pc - 3;
+ sp += num_args;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ } else {
+ /* L'argument recursif est un accumulateur */
+ mlsize_t num_args, i;
+ /* Construction du PF partiellement appliqué */
+ Alloc_small(accu, rec_pos + 2, Closure_tag);
+ Field(accu, 1) = coq_env;
+ for (i = 0; i < rec_pos; i++) Field(accu, i + 2) = sp[i];
+ Code_val(accu) = pc;
+ sp += rec_pos;
+ *--sp = accu;
+ /* Construction de l'atom */
+ Alloc_small(accu, 2, ATOM_FIX_TAG);
+ Field(accu,1) = sp[0];
+ Field(accu,0) = sp[1];
+ sp++; sp[0] = accu;
+ /* Construction de l'accumulateur */
+ num_args = coq_extra_args - rec_pos;
+ Alloc_small(accu, 2+num_args, Accu_tag);
+ Code_val(accu) = accumulate;
+ Field(accu,1) = sp[0]; sp++;
+ for (i = 0; i < num_args;i++)Field(accu, i + 2) = sp[i];
+ sp += num_args;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ }
+ }
+ Next;
+ }
+
+ Instruct(CLOSURE) {
+ int nvars = *pc++;
+ int i;
+ print_instr("CLOSURE");
+ print_int(nvars);
+ if (nvars > 0) *--sp = accu;
+ Alloc_small(accu, 1 + nvars, Closure_tag);
+ Code_val(accu) = pc + *pc;
+ pc++;
+ for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i];
+ sp += nvars;
+ Next;
+ }
+
+ Instruct(CLOSUREREC) {
+ int nfuncs = *pc++;
+ int nvars = *pc++;
+ int start = *pc++;
+ int i;
+ value * p;
+ print_instr("CLOSUREREC");
+ if (nvars > 0) *--sp = accu;
+ /* construction du vecteur de type */
+ Alloc_small(accu, nfuncs, 0);
+ for(i = 0; i < nfuncs; i++) {
+ Field(accu,i) = (value)(pc+pc[i]);
+ }
+ pc += nfuncs;
+ *--sp=accu;
+ Alloc_small(accu, nfuncs * 2 + nvars, Closure_tag);
+ Field(accu, nfuncs * 2 + nvars - 1) = *sp++;
+ /* On remplie la partie pour les variables libres */
+ p = &Field(accu, nfuncs * 2 - 1);
+ for (i = 0; i < nvars; i++) {
+ *p++ = *sp++;
+ }
+ p = &Field(accu, 0);
+ *p = (value) (pc + pc[0]);
+ p++;
+ for (i = 1; i < nfuncs; i++) {
+ *p = Make_header(i * 2, Infix_tag, Caml_white);
+ p++; /* color irrelevant. */
+ *p = (value) (pc + pc[i]);
+ p++;
+ }
+ pc += nfuncs;
+ accu = accu + 2 * start * sizeof(value);
+ Next;
+ }
+
+ Instruct(PUSHOFFSETCLOSURE) {
+ print_instr("PUSHOFFSETCLOSURE");
+ *--sp = accu;
+ } /* fallthrough */
+ Instruct(OFFSETCLOSURE) {
+ print_instr("OFFSETCLOSURE");
+ accu = coq_env + *pc++ * sizeof(value); Next;
+ }
+ Instruct(PUSHOFFSETCLOSUREM2) {
+ print_instr("PUSHOFFSETCLOSUREM2");
+ *--sp = accu;
+ } /* fallthrough */
+ Instruct(OFFSETCLOSUREM2) {
+ print_instr("OFFSETCLOSUREM2");
+ accu = coq_env - 2 * sizeof(value); Next;
+ }
+ Instruct(PUSHOFFSETCLOSURE0) {
+ print_instr("PUSHOFFSETCLOSURE0");
+ *--sp = accu;
+ }/* fallthrough */
+ Instruct(OFFSETCLOSURE0) {
+ print_instr("OFFSETCLOSURE0");
+ accu = coq_env; Next;
+ }
+ Instruct(PUSHOFFSETCLOSURE2){
+ print_instr("PUSHOFFSETCLOSURE2");
+ *--sp = accu; /* fallthrough */
+ }
+ Instruct(OFFSETCLOSURE2) {
+ print_instr("OFFSETCLOSURE2");
+ accu = coq_env + 2 * sizeof(value); Next;
+ }
+
+/* Access to global variables */
+
+ Instruct(PUSHGETGLOBAL) {
+ print_instr("PUSHGETGLOBAL");
+ *--sp = accu;
+ }
+ /* Fallthrough */
+ Instruct(GETGLOBAL){
+ print_instr("GETGLOBAL");
+ accu = Field(coq_global_data, *pc);
+ pc++;
+ Next;
+ }
+
+/* Allocation of blocks */
+
+ Instruct(MAKEBLOCK) {
+ mlsize_t wosize = *pc++;
+ tag_t tag = *pc++;
+ mlsize_t i;
+ value block;
+ print_instr("MAKEBLOCK");
+ Alloc_small(block, wosize, tag);
+ Field(block, 0) = accu;
+ for (i = 1; i < wosize; i++) Field(block, i) = *sp++;
+ accu = block;
+ Next;
+ }
+ Instruct(MAKEBLOCK1) {
+
+ tag_t tag = *pc++;
+ value block;
+ print_instr("MAKEBLOCK1");
+ Alloc_small(block, 1, tag);
+ Field(block, 0) = accu;
+ accu = block;
+ Next;
+ }
+ Instruct(MAKEBLOCK2) {
+
+ tag_t tag = *pc++;
+ value block;
+ print_instr("MAKEBLOCK2");
+ Alloc_small(block, 2, tag);
+ Field(block, 0) = accu;
+ Field(block, 1) = sp[0];
+ sp += 1;
+ accu = block;
+ Next;
+ }
+ Instruct(MAKEBLOCK3) {
+ tag_t tag = *pc++;
+ value block;
+ print_instr("MAKEBLOCK3");
+ Alloc_small(block, 3, tag);
+ Field(block, 0) = accu;
+ Field(block, 1) = sp[0];
+ Field(block, 2) = sp[1];
+ sp += 2;
+ accu = block;
+ Next;
+ }
+
+
+/* Access to components of blocks */
+
+
+/* Branches and conditional branches */
+ Instruct(FORCE) {
+ print_instr("FORCE");
+ if (Is_block(accu) && Tag_val(accu) == Closure_tag) {
+ forcable = Val_true;
+ /* On pousse l'addresse de retour et l'argument */
+ sp -= 3;
+ sp[0] = (value) (pc - 1);
+ sp[1] = coq_env;
+ sp[2] = Val_long(coq_extra_args);
+ /* On evalue le cofix */
+ coq_extra_args = 0;
+ pc = Code_val(accu);
+ coq_env = accu;
+ goto check_stacks;
+ } else {
+ if (Is_block(accu)) print_int(Tag_val(accu));
+ else print_instr("Not a block");
+ }
+ Next;
+ }
+
+
+ Instruct(SWITCH) {
+ uint32 sizes = *pc++;
+ print_instr("SWITCH");
+ print_int(sizes);
+ if (Is_block(accu)) {
+ long index = Tag_val(accu);
+ print_instr("block");
+ print_int(index);
+ pc += pc[(sizes & 0xFFFF) + index];
+ } else {
+ long index = Long_val(accu);
+ print_instr("constant");
+ print_int(index);
+ pc += pc[index];
+ }
+ Next;
+ }
+ Instruct(PUSHFIELD){
+ int i;
+ int size = *pc++;
+ print_instr("PUSHFIELD");
+ sp -= size;
+ for(i=0;i<size;i++)sp[i] = Field(accu,i);
+ Next;
+ }
+
+ Instruct(MAKESWITCHBLOCK) {
+ mlsize_t sz;
+ int i, annot;
+ code_t typlbl,swlbl;
+ print_instr("MAKESWITCHBLOCK");
+ typlbl = (code_t)pc + *pc;
+ pc++;
+ swlbl = (code_t)pc + *pc;
+ pc++;
+ annot = *pc++;
+ sz = *pc++;
+ *--sp = accu;
+ *--sp=Field(coq_global_data, annot);
+ /* On sauve la pile */
+ if (sz == 0) accu = Atom(0);
+ else {
+ Alloc_small(accu, sz, Default_tag);
+ if (Field(*sp, 2) == Val_true) {
+ for (i = 0; i < sz; i++) Field(accu, i) = sp[i+2];
+ }else{
+ for (i = 0; i < sz; i++) Field(accu, i) = sp[i+5];
+ }
+ }
+ *--sp = accu;
+ /* On cree le zipper switch */
+ Alloc_small(accu, 5, Default_tag);
+ Field(accu, 0) = (value)typlbl; Field(accu, 1) = (value)swlbl;
+ Field(accu, 2) = sp[1]; Field(accu, 3) = sp[0];
+ Field(accu, 4) = coq_env;
+ sp++;sp[0] = accu;
+ /* On cree l'atome */
+ Alloc_small(accu, 2, ATOM_SWITCH_TAG);
+ Field(accu, 0) = sp[1]; Field(accu, 1) = sp[0];
+ sp++;sp[0] = accu;
+ /* On cree l'accumulateur */
+ Alloc_small(accu, 2, Accu_tag);
+ Code_val(accu) = accumulate;
+ Field(accu,1) = *sp++;
+ Next;
+ }
+
+ /* Stack checks */
+
+ check_stacks:
+ print_instr("check_stacks");
+ if (sp < coq_stack_threshold) {
+ coq_sp = sp;
+ realloc_coq_stack(Coq_stack_threshold);
+ sp = coq_sp;
+ }
+ Next;
+ /* Fall through CHECK_SIGNALS */
+
+/* Integer constants */
+
+ Instruct(CONST0){
+ print_instr("CONST0");
+ accu = Val_int(0); Next;}
+ Instruct(CONST1){
+ print_instr("CONST1");
+ accu = Val_int(1); Next;}
+ Instruct(CONST2){
+ print_instr("CONST2");
+ accu = Val_int(2); Next;}
+ Instruct(CONST3){
+ print_instr("CONST3");
+ accu = Val_int(3); Next;}
+
+ Instruct(PUSHCONST0){
+ print_instr("PUSHCONST0");
+ *--sp = accu; accu = Val_int(0); Next;
+ }
+ Instruct(PUSHCONST1){
+ print_instr("PUSHCONST1");
+ *--sp = accu; accu = Val_int(1); Next;
+ }
+ Instruct(PUSHCONST2){
+ print_instr("PUSHCONST2");
+ *--sp = accu; accu = Val_int(2); Next;
+ }
+ Instruct(PUSHCONST3){
+ print_instr("PUSHCONST3");
+ *--sp = accu; accu = Val_int(3); Next;
+ }
+
+ Instruct(PUSHCONSTINT){
+ print_instr("PUSHCONSTINT");
+ *--sp = accu;
+ }
+ /* Fallthrough */
+ Instruct(CONSTINT) {
+ print_instr("CONSTINT");
+ accu = Val_int(*pc);
+ pc++;
+ Next;
+ }
+
+/* Debugging and machine control */
+
+ Instruct(STOP){
+ print_instr("STOP");
+ coq_sp = sp;
+ return accu;
+ }
+
+ Instruct(ACCUMULATECOND) {
+ int i, num;
+ print_instr("ACCUMULATECOND");
+ num = *pc;
+ pc++;
+ if (Field(coq_global_boxed, num) == Val_false || coq_all_transp) {
+ /* printf ("false\n");
+ printf ("tag = %d", Tag_val(Field(accu,1))); */
+ num = Wosize_val(coq_env);
+ for(i = 2; i < num; i++) *--sp = Field(accu,i);
+ coq_extra_args = coq_extra_args + (num - 2);
+ coq_env = Field(Field(accu,1),1);
+ pc = Code_val(coq_env);
+ accu = coq_env;
+ /* printf ("end\n"); */
+ Next;
+ };
+ /* printf ("true\n"); */
+ }
+
+ Instruct(ACCUMULATE) {
+ mlsize_t i, size;
+ print_instr("ACCUMULATE");
+ size = Wosize_val(coq_env);
+ Alloc_small(accu, size + coq_extra_args + 1, Accu_tag);
+ for(i = 0; i < size; i++) Field(accu, i) = Field(coq_env, i);
+ for(i = size; i <= coq_extra_args + size; i++)
+ Field(accu, i) = *sp++;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ Next;
+ }
+
+ Instruct(MAKEACCU) {
+ int i;
+ print_instr("MAKEACCU");
+ Alloc_small(accu, coq_extra_args + 3, Accu_tag);
+ Code_val(accu) = accumulate;
+ Field(accu,1) = Field(coq_atom_tbl, *pc);
+ for(i = 2; i < coq_extra_args + 3; i++) Field(accu, i) = *sp++;
+ pc = (code_t)(sp[0]);
+ coq_env = sp[1];
+ coq_extra_args = Long_val(sp[2]);
+ sp += 3;
+ Next;
+ }
+
+ Instruct(MAKEPROD) {
+ print_instr("MAKEPROD");
+ *--sp=accu;
+ Alloc_small(accu,2,0);
+ Field(accu, 0) = sp[0];
+ Field(accu, 1) = sp[1];
+ sp += 2;
+ Next;
+ }
+
+#ifndef THREADED_CODE
+ default:
+ /*fprintf(stderr, "%d\n", *pc);*/
+ failwith("Coq VM: Fatal error: bad opcode");
+ }
+ }
+#endif
+}
+
+value coq_push_ra(value tcode) {
+ print_instr("push_ra");
+ coq_sp -= 3;
+ coq_sp[0] = (value) tcode;
+ coq_sp[1] = Val_unit;
+ coq_sp[2] = Val_long(0);
+ return Val_unit;
+}
+
+value coq_push_val(value v) {
+ print_instr("push_val");
+ *--coq_sp = v;
+ return Val_unit;
+}
+
+value coq_push_arguments(value args) {
+ int nargs,i;
+ nargs = Wosize_val(args) - 2;
+ coq_sp -= nargs;
+ print_instr("push_args");print_int(nargs);
+ for(i = 0; i < nargs; i++) coq_sp[i] = Field(args, i+2);
+ return Val_unit;
+}
+
+value coq_push_vstack(value stk) {
+ int len,i;
+ len = Wosize_val(stk);
+ coq_sp -= len;
+ print_instr("push_vstack");print_int(len);
+ for(i = 0; i < len; i++) coq_sp[i] = Field(stk,i);
+ return Val_unit;
+}
+
+value coq_interprete_ml(value tcode, value a, value e, value ea) {
+ print_instr("coq_interprete");
+ return coq_interprete((code_t)tcode, a, e, Long_val(ea));
+ print_instr("end coq_interprete");
+}
+
+value coq_eval_tcode (value tcode, value e) {
+ return coq_interprete_ml(tcode, Val_unit, e, 0);
+}