1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/***********************************************************************/
/* */
/* Coq Compiler */
/* */
/* Benjamin Gregoire, projets Logical and Cristal */
/* INRIA Rocquencourt */
/* */
/* */
/***********************************************************************/
/* Arnaud Spiwack: expanded the virtual machine with operators used
for fast computation of bounded (31bits) integers */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <caml/config.h>
#include <caml/misc.h>
#include <caml/mlvalues.h>
#include <caml/fail.h>
#include <caml/alloc.h>
#include <caml/memory.h>
#include "coq_instruct.h"
#include "coq_arity.h"
#include "coq_fix_code.h"
#ifdef THREADED_CODE
static char ** coq_instr_table;
static char * coq_instr_base;
#define VALINSTR(instr) ((opcode_t)(coq_instr_table[instr] - coq_instr_base))
void coq_init_thread_code(void ** instr_table, void * instr_base)
{
coq_instr_table = (char **) instr_table;
coq_instr_base = (char *) instr_base;
}
#else
#define VALINSTR(instr) instr
#endif /* THREADED_CODE */
int coq_is_instruction(opcode_t instr1, opcode_t instr2)
{
return instr1 == VALINSTR(instr2);
}
void * coq_stat_alloc (asize_t sz)
{
void * result = malloc (sz);
if (result == NULL) caml_raise_out_of_memory ();
return result;
}
static opcode_t accu_instr;
code_t accumulate = &accu_instr;
value coq_accumulate(value unit)
{
CAMLparam1(unit);
CAMLlocal1(res);
accu_instr = VALINSTR(ACCUMULATE);
res = caml_alloc_small(1, Abstract_tag);
Code_val(res) = accumulate;
CAMLreturn(res);
}
value coq_makeaccu (value i) {
CAMLparam1(i);
CAMLlocal1(res);
code_t q = coq_stat_alloc(2 * sizeof(opcode_t));
res = caml_alloc_small(1, Abstract_tag);
Code_val(res) = q;
*q++ = VALINSTR(MAKEACCU);
*q = (opcode_t)Int_val(i);
CAMLreturn(res);
}
value coq_pushpop (value i) {
CAMLparam1(i);
CAMLlocal1(res);
code_t q;
res = caml_alloc_small(1, Abstract_tag);
int n = Int_val(i);
if (n == 0) {
q = coq_stat_alloc(sizeof(opcode_t));
Code_val(res) = q;
*q = VALINSTR(STOP);
CAMLreturn(res);
}
else {
q = coq_stat_alloc(3 * sizeof(opcode_t));
Code_val(res) = q;
*q++ = VALINSTR(POP);
*q++ = (opcode_t)n;
*q = VALINSTR(STOP);
CAMLreturn(res);
}
}
#ifdef ARCH_BIG_ENDIAN
#define Reverse_32(dst,src) { \
char * _p, * _q; \
char _a, _b; \
_p = (char *) (src); \
_q = (char *) (dst); \
_a = _p[0]; \
_b = _p[1]; \
_q[0] = _p[3]; \
_q[1] = _p[2]; \
_q[3] = _a; \
_q[2] = _b; \
}
#define COPY32(dst,src) Reverse_32(dst,src)
#else
#define COPY32(dst,src) (*dst=*src)
#endif /* ARCH_BIG_ENDIAN */
value coq_tcode_of_code (value code) {
CAMLparam1 (code);
CAMLlocal1 (res);
code_t p, q;
asize_t len = (asize_t) caml_string_length(code);
res = caml_alloc_small(1, Abstract_tag);
q = coq_stat_alloc(len);
Code_val(res) = q;
len /= sizeof(opcode_t);
for (p = (code_t)code; p < (code_t)code + len; /*nothing*/) {
opcode_t instr;
COPY32(&instr,p);
p++;
if (instr < 0 || instr > STOP) abort();
*q++ = VALINSTR(instr);
if (instr == SWITCH) {
uint32_t i, sizes, const_size, block_size;
COPY32(q,p); p++;
sizes=*q++;
const_size = sizes >> 8;
block_size = sizes & 0xFF;
sizes = const_size + block_size;
for(i=0; i<sizes; i++) { COPY32(q,p); p++; q++; };
} else if (instr == CLOSUREREC || instr==CLOSURECOFIX) {
uint32_t i, n;
COPY32(q,p); p++; /* ndefs */
n = 3 + 2*(*q); /* ndefs, nvars, start, typlbls,lbls*/
q++;
for(i=1; i<n; i++) { COPY32(q,p); p++; q++; };
} else {
int i, ar;
ar = arity[instr];
if (ar < 0) abort();
for(i=0; i<ar; i++) { COPY32(q,p); p++; q++; };
}
}
CAMLreturn(res);
}
|