summaryrefslogtreecommitdiffstats
path: root/gst/goom/goomsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/goom/goomsl.c')
-rw-r--r--gst/goom/goomsl.c1660
1 files changed, 1660 insertions, 0 deletions
diff --git a/gst/goom/goomsl.c b/gst/goom/goomsl.c
new file mode 100644
index 00000000..b07b2596
--- /dev/null
+++ b/gst/goom/goomsl.c
@@ -0,0 +1,1660 @@
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "goomsl.h"
+#include "goomsl_private.h"
+#include "goomsl_yacc.h"
+
+/*#define TRACE_SCRIPT*/
+
+ /* {{{ definition of the instructions number */
+#define INSTR_SETI_VAR_INTEGER 1
+#define INSTR_SETI_VAR_VAR 2
+#define INSTR_SETF_VAR_FLOAT 3
+#define INSTR_SETF_VAR_VAR 4
+#define INSTR_NOP 5
+/* #define INSTR_JUMP 6 */
+#define INSTR_SETP_VAR_PTR 7
+#define INSTR_SETP_VAR_VAR 8
+#define INSTR_SUBI_VAR_INTEGER 9
+#define INSTR_SUBI_VAR_VAR 10
+#define INSTR_SUBF_VAR_FLOAT 11
+#define INSTR_SUBF_VAR_VAR 12
+#define INSTR_ISLOWERF_VAR_VAR 13
+#define INSTR_ISLOWERF_VAR_FLOAT 14
+#define INSTR_ISLOWERI_VAR_VAR 15
+#define INSTR_ISLOWERI_VAR_INTEGER 16
+#define INSTR_ADDI_VAR_INTEGER 17
+#define INSTR_ADDI_VAR_VAR 18
+#define INSTR_ADDF_VAR_FLOAT 19
+#define INSTR_ADDF_VAR_VAR 20
+#define INSTR_MULI_VAR_INTEGER 21
+#define INSTR_MULI_VAR_VAR 22
+#define INSTR_MULF_VAR_FLOAT 23
+#define INSTR_MULF_VAR_VAR 24
+#define INSTR_DIVI_VAR_INTEGER 25
+#define INSTR_DIVI_VAR_VAR 26
+#define INSTR_DIVF_VAR_FLOAT 27
+#define INSTR_DIVF_VAR_VAR 28
+/* #define INSTR_JZERO 29 */
+#define INSTR_ISEQUALP_VAR_VAR 30
+#define INSTR_ISEQUALP_VAR_PTR 31
+#define INSTR_ISEQUALI_VAR_VAR 32
+#define INSTR_ISEQUALI_VAR_INTEGER 33
+#define INSTR_ISEQUALF_VAR_VAR 34
+#define INSTR_ISEQUALF_VAR_FLOAT 35
+/* #define INSTR_CALL 36 */
+/* #define INSTR_RET 37 */
+/* #define INSTR_EXT_CALL 38 */
+#define INSTR_NOT_VAR 39
+/* #define INSTR_JNZERO 40 */
+#define INSTR_SETS_VAR_VAR 41
+#define INSTR_ISEQUALS_VAR_VAR 42
+#define INSTR_ADDS_VAR_VAR 43
+#define INSTR_SUBS_VAR_VAR 44
+#define INSTR_MULS_VAR_VAR 45
+#define INSTR_DIVS_VAR_VAR 46
+
+ /* }}} */
+/* {{{ definition of the validation error types */
+static const char *VALIDATE_OK = "ok";
+
+#define VALIDATE_ERROR "error while validating "
+#define VALIDATE_TODO "todo"
+#define VALIDATE_SYNTHAX_ERROR "synthax error"
+#define VALIDATE_NO_SUCH_INT "no such integer variable"
+#define VALIDATE_NO_SUCH_VAR "no such variable"
+#define VALIDATE_NO_SUCH_DEST_VAR "no such destination variable"
+#define VALIDATE_NO_SUCH_SRC_VAR "no such src variable"
+/* }}} */
+
+ /***********************************/
+ /* PROTOTYPE OF INTERNAL FUNCTIONS */
+/***********************************/
+
+/* {{{ */
+static void gsl_instr_free (Instruction * _this);
+static const char *gsl_instr_validate (Instruction * _this);
+static void gsl_instr_display (Instruction * _this);
+
+static InstructionFlow *iflow_new (void);
+static void iflow_add_instr (InstructionFlow * _this, Instruction * instr);
+static void iflow_clean (InstructionFlow * _this);
+static void iflow_free (InstructionFlow * _this);
+static void iflow_execute (FastInstructionFlow * _this, GoomSL * gsl);
+
+/* }}} */
+
+ /************************************/
+ /* DEFINITION OF INTERNAL FUNCTIONS */
+/************************************/
+
+void
+iflow_free (InstructionFlow * _this)
+{ /* {{{ */
+ goom_hash_free (_this->labels);
+ free (_this); /*TODO: finir cette fonction */
+} /* }}} */
+
+void
+iflow_clean (InstructionFlow * _this)
+{ /* {{{ */
+ /* TODO: clean chaque instruction du flot */
+ _this->number = 0;
+ goom_hash_free (_this->labels);
+ _this->labels = goom_hash_new ();
+} /* }}} */
+
+InstructionFlow *
+iflow_new (void)
+{ /* {{{ */
+ InstructionFlow *_this =
+ (InstructionFlow *) malloc (sizeof (InstructionFlow));
+ _this->number = 0;
+ _this->tabsize = 6;
+ _this->instr =
+ (Instruction **) malloc (_this->tabsize * sizeof (Instruction *));
+ _this->labels = goom_hash_new ();
+
+ return _this;
+} /* }}} */
+
+void
+iflow_add_instr (InstructionFlow * _this, Instruction * instr)
+{ /* {{{ */
+ if (_this->number == _this->tabsize) {
+ _this->tabsize *= 2;
+ _this->instr =
+ (Instruction **) realloc (_this->instr,
+ _this->tabsize * sizeof (Instruction *));
+ }
+ _this->instr[_this->number] = instr;
+ instr->address = _this->number;
+ _this->number++;
+} /* }}} */
+
+void
+gsl_instr_set_namespace (Instruction * _this, GoomHash * ns)
+{ /* {{{ */
+ if (_this->cur_param <= 0) {
+ fprintf (stderr, "ERROR: Line %d, No more params to instructions\n",
+ _this->line_number);
+ exit (1);
+ }
+ _this->vnamespace[_this->cur_param - 1] = ns;
+} /* }}} */
+
+void
+gsl_instr_add_param (Instruction * instr, char *param, int type)
+{ /* {{{ */
+ int len;
+
+ if (instr == NULL)
+ return;
+ if (instr->cur_param == 0)
+ return;
+ --instr->cur_param;
+ len = strlen (param);
+ instr->params[instr->cur_param] = (char *) malloc (len + 1);
+ strcpy (instr->params[instr->cur_param], param);
+ instr->types[instr->cur_param] = type;
+ if (instr->cur_param == 0) {
+
+ const char *result = gsl_instr_validate (instr);
+
+ if (result != VALIDATE_OK) {
+ printf ("ERROR: Line %d: ", instr->parent->num_lines + 1);
+ gsl_instr_display (instr);
+ printf ("... %s\n", result);
+ instr->parent->compilationOK = 0;
+ exit (1);
+ }
+#if USE_JITC_X86
+ iflow_add_instr (instr->parent->iflow, instr);
+#else
+ if (instr->id != INSTR_NOP)
+ iflow_add_instr (instr->parent->iflow, instr);
+ else
+ gsl_instr_free (instr);
+#endif
+ }
+} /* }}} */
+
+Instruction *
+gsl_instr_init (GoomSL * parent, const char *name, int id, int nb_param,
+ int line_number)
+{ /* {{{ */
+ Instruction *instr = (Instruction *) malloc (sizeof (Instruction));
+ instr->params = (char **) malloc (nb_param * sizeof (char *));
+ instr->vnamespace = (GoomHash **) malloc (nb_param * sizeof (GoomHash *));
+ instr->types = (int *) malloc (nb_param * sizeof (int));
+ instr->cur_param = instr->nb_param = nb_param;
+ instr->parent = parent;
+ instr->id = id;
+ instr->name = name;
+ instr->jump_label = NULL;
+ instr->line_number = line_number;
+ return instr;
+} /* }}} */
+
+void
+gsl_instr_free (Instruction * _this)
+{ /* {{{ */
+ int i;
+
+ free (_this->types);
+ for (i = _this->cur_param; i < _this->nb_param; ++i)
+ free (_this->params[i]);
+ free (_this->params);
+ free (_this);
+} /* }}} */
+
+void
+gsl_instr_display (Instruction * _this)
+{ /* {{{ */
+ int i = _this->nb_param - 1;
+
+ printf ("%s", _this->name);
+ while (i >= _this->cur_param) {
+ printf (" %s", _this->params[i]);
+ --i;
+ }
+} /* }}} */
+
+ /****************************************/
+ /* VALIDATION OF INSTRUCTION PARAMETERS */
+/****************************************/
+
+static const char *
+validate_v_v (Instruction * _this)
+{ /* {{{ */
+ HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+ HashValue *src = goom_hash_get (_this->vnamespace[0], _this->params[0]);
+
+ if (dest == NULL) {
+ return VALIDATE_NO_SUCH_DEST_VAR;
+ }
+ if (src == NULL) {
+ return VALIDATE_NO_SUCH_SRC_VAR;
+ }
+ _this->data.udest.var = dest->ptr;
+ _this->data.usrc.var = src->ptr;
+ return VALIDATE_OK;
+} /* }}} */
+
+static const char *
+validate_v_i (Instruction * _this)
+{ /* {{{ */
+ HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+ _this->data.usrc.value_int = strtol (_this->params[0], NULL, 0);
+
+ if (dest == NULL) {
+ return VALIDATE_NO_SUCH_INT;
+ }
+ _this->data.udest.var = dest->ptr;
+ return VALIDATE_OK;
+} /* }}} */
+
+static const char *
+validate_v_p (Instruction * _this)
+{ /* {{{ */
+ HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+ _this->data.usrc.value_ptr = strtol (_this->params[0], NULL, 0);
+
+ if (dest == NULL) {
+ return VALIDATE_NO_SUCH_INT;
+ }
+ _this->data.udest.var = dest->ptr;
+ return VALIDATE_OK;
+} /* }}} */
+
+static const char *
+validate_v_f (Instruction * _this)
+{ /* {{{ */
+ HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
+
+ _this->data.usrc.value_float = atof (_this->params[0]);
+
+ if (dest == NULL) {
+ return VALIDATE_NO_SUCH_VAR;
+ }
+ _this->data.udest.var = dest->ptr;
+ return VALIDATE_OK;
+} /* }}} */
+
+static const char *
+validate (Instruction * _this,
+ int vf_f_id, int vf_v_id,
+ int vi_i_id, int vi_v_id, int vp_p_id, int vp_v_id, int vs_v_id)
+{ /* {{{ */
+ if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FLOAT)) {
+ _this->id = vf_f_id;
+ return validate_v_f (_this);
+ } else if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FVAR)) {
+ _this->id = vf_v_id;
+ return validate_v_v (_this);
+ } else if ((_this->types[1] == TYPE_IVAR)
+ && (_this->types[0] == TYPE_INTEGER)) {
+ _this->id = vi_i_id;
+ return validate_v_i (_this);
+ } else if ((_this->types[1] == TYPE_IVAR) && (_this->types[0] == TYPE_IVAR)) {
+ _this->id = vi_v_id;
+ return validate_v_v (_this);
+ } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PTR)) {
+ if (vp_p_id == INSTR_NOP)
+ return VALIDATE_ERROR;
+ _this->id = vp_p_id;
+ return validate_v_p (_this);
+ } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PVAR)) {
+ _this->id = vp_v_id;
+ if (vp_v_id == INSTR_NOP)
+ return VALIDATE_ERROR;
+ return validate_v_v (_this);
+ } else if ((_this->types[1] < FIRST_RESERVED) && (_this->types[1] >= 0)
+ && (_this->types[0] == _this->types[1])) {
+ _this->id = vs_v_id;
+ if (vs_v_id == INSTR_NOP)
+ return "Impossible operation to perform between two structs";
+ return validate_v_v (_this);
+ }
+ return VALIDATE_ERROR;
+} /* }}} */
+
+const char *
+gsl_instr_validate (Instruction * _this)
+{ /* {{{ */
+ if (_this->id != INSTR_EXT_CALL) {
+ int i = _this->nb_param;
+
+ while (i > 0) {
+ i--;
+ if (_this->types[i] == TYPE_VAR) {
+ int type = gsl_type_of_var (_this->vnamespace[i], _this->params[i]);
+
+ if (type == INSTR_INT)
+ _this->types[i] = TYPE_IVAR;
+ else if (type == INSTR_FLOAT)
+ _this->types[i] = TYPE_FVAR;
+ else if (type == INSTR_PTR)
+ _this->types[i] = TYPE_PVAR;
+ else if ((type >= 0) && (type < FIRST_RESERVED))
+ _this->types[i] = type;
+ else
+ fprintf (stderr, "WARNING: Line %d, %s has no namespace\n",
+ _this->line_number, _this->params[i]);
+ }
+ }
+ }
+
+ switch (_this->id) {
+
+ /* set */
+ case INSTR_SET:
+ return validate (_this,
+ INSTR_SETF_VAR_FLOAT, INSTR_SETF_VAR_VAR,
+ INSTR_SETI_VAR_INTEGER, INSTR_SETI_VAR_VAR,
+ INSTR_SETP_VAR_PTR, INSTR_SETP_VAR_VAR, INSTR_SETS_VAR_VAR);
+
+ /* extcall */
+ case INSTR_EXT_CALL:
+ if (_this->types[0] == TYPE_VAR) {
+ HashValue *fval =
+ goom_hash_get (_this->parent->functions, _this->params[0]);
+ if (fval) {
+ _this->data.udest.external_function =
+ (struct _ExternalFunctionStruct *) fval->ptr;
+ return VALIDATE_OK;
+ }
+ }
+ return VALIDATE_ERROR;
+
+ /* call */
+ case INSTR_CALL:
+ if (_this->types[0] == TYPE_LABEL) {
+ _this->jump_label = _this->params[0];
+ return VALIDATE_OK;
+ }
+ return VALIDATE_ERROR;
+
+ /* ret */
+ case INSTR_RET:
+ return VALIDATE_OK;
+
+ /* jump */
+ case INSTR_JUMP:
+
+ if (_this->types[0] == TYPE_LABEL) {
+ _this->jump_label = _this->params[0];
+ return VALIDATE_OK;
+ }
+ return VALIDATE_ERROR;
+
+ /* jzero / jnzero */
+ case INSTR_JZERO:
+ case INSTR_JNZERO:
+
+ if (_this->types[0] == TYPE_LABEL) {
+ _this->jump_label = _this->params[0];
+ return VALIDATE_OK;
+ }
+ return VALIDATE_ERROR;
+
+ /* label */
+ case INSTR_LABEL:
+
+ if (_this->types[0] == TYPE_LABEL) {
+ _this->id = INSTR_NOP;
+ _this->nop_label = _this->params[0];
+ goom_hash_put_int (_this->parent->iflow->labels, _this->params[0],
+ _this->parent->iflow->number);
+ return VALIDATE_OK;
+ }
+ return VALIDATE_ERROR;
+
+ /* isequal */
+ case INSTR_ISEQUAL:
+ return validate (_this,
+ INSTR_ISEQUALF_VAR_FLOAT, INSTR_ISEQUALF_VAR_VAR,
+ INSTR_ISEQUALI_VAR_INTEGER, INSTR_ISEQUALI_VAR_VAR,
+ INSTR_ISEQUALP_VAR_PTR, INSTR_ISEQUALP_VAR_VAR,
+ INSTR_ISEQUALS_VAR_VAR);
+
+ /* not */
+ case INSTR_NOT:
+ _this->id = INSTR_NOT_VAR;
+ return VALIDATE_OK;
+
+ /* islower */
+ case INSTR_ISLOWER:
+ return validate (_this,
+ INSTR_ISLOWERF_VAR_FLOAT, INSTR_ISLOWERF_VAR_VAR,
+ INSTR_ISLOWERI_VAR_INTEGER, INSTR_ISLOWERI_VAR_VAR,
+ INSTR_NOP, INSTR_NOP, INSTR_NOP);
+
+ /* add */
+ case INSTR_ADD:
+ return validate (_this,
+ INSTR_ADDF_VAR_FLOAT, INSTR_ADDF_VAR_VAR,
+ INSTR_ADDI_VAR_INTEGER, INSTR_ADDI_VAR_VAR,
+ INSTR_NOP, INSTR_NOP, INSTR_ADDS_VAR_VAR);
+
+ /* mul */
+ case INSTR_MUL:
+ return validate (_this,
+ INSTR_MULF_VAR_FLOAT, INSTR_MULF_VAR_VAR,
+ INSTR_MULI_VAR_INTEGER, INSTR_MULI_VAR_VAR,
+ INSTR_NOP, INSTR_NOP, INSTR_MULS_VAR_VAR);
+
+ /* sub */
+ case INSTR_SUB:
+ return validate (_this,
+ INSTR_SUBF_VAR_FLOAT, INSTR_SUBF_VAR_VAR,
+ INSTR_SUBI_VAR_INTEGER, INSTR_SUBI_VAR_VAR,
+ INSTR_NOP, INSTR_NOP, INSTR_SUBS_VAR_VAR);
+
+ /* div */
+ case INSTR_DIV:
+ return validate (_this,
+ INSTR_DIVF_VAR_FLOAT, INSTR_DIVF_VAR_VAR,
+ INSTR_DIVI_VAR_INTEGER, INSTR_DIVI_VAR_VAR,
+ INSTR_NOP, INSTR_NOP, INSTR_DIVS_VAR_VAR);
+
+ default:
+ return VALIDATE_TODO;
+ }
+ return VALIDATE_ERROR;
+} /* }}} */
+
+ /*************/
+ /* EXECUTION */
+/*************/
+void
+iflow_execute (FastInstructionFlow * _this, GoomSL * gsl)
+{ /* {{{ */
+ int flag = 0;
+ int ip = 0;
+ FastInstruction *instr = _this->instr;
+ int stack[0x10000];
+ int stack_pointer = 0;
+
+ stack[stack_pointer++] = -1;
+
+ /* Quelques Macro pour rendre le code plus lisible */
+#define pSRC_VAR instr[ip].data.usrc.var
+#define SRC_VAR_INT *instr[ip].data.usrc.var_int
+#define SRC_VAR_FLOAT *instr[ip].data.usrc.var_float
+#define SRC_VAR_PTR *instr[ip].data.usrc.var_ptr
+
+#define pDEST_VAR instr[ip].data.udest.var
+#define DEST_VAR_INT *instr[ip].data.udest.var_int
+#define DEST_VAR_FLOAT *instr[ip].data.udest.var_float
+#define DEST_VAR_PTR *instr[ip].data.udest.var_ptr
+
+#define VALUE_INT instr[ip].data.usrc.value_int
+#define VALUE_FLOAT instr[ip].data.usrc.value_float
+#define VALUE_PTR instr[ip].data.usrc.value_ptr
+
+#define JUMP_OFFSET instr[ip].data.udest.jump_offset
+
+#define SRC_STRUCT_ID instr[ip].data.usrc.var_int[-1]
+#define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
+#define SRC_STRUCT_IBLOCK(i) gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
+#define SRC_STRUCT_FBLOCK(i) gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
+#define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK_VAR(i,j) \
+ ((int*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
+#define DEST_STRUCT_FBLOCK_VAR(i,j) \
+ ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
+#define SRC_STRUCT_IBLOCK_VAR(i,j) \
+ ((int*)((char*)pSRC_VAR + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
+#define SRC_STRUCT_FBLOCK_VAR(i,j) \
+ ((float*)((char*)pSRC_VAR + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
+#define DEST_STRUCT_SIZE gsl->gsl_struct[DEST_STRUCT_ID]->size
+
+ while (1) {
+ int i;
+
+#ifdef TRACE_SCRIPT
+ printf ("execute ");
+ gsl_instr_display (instr[ip].proto);
+ printf ("\n");
+#endif
+ switch (instr[ip].id) {
+
+ /* SET.I */
+ case INSTR_SETI_VAR_INTEGER:
+ DEST_VAR_INT = VALUE_INT;
+ ++ip;
+ break;
+
+ case INSTR_SETI_VAR_VAR:
+ DEST_VAR_INT = SRC_VAR_INT;
+ ++ip;
+ break;
+
+ /* SET.F */
+ case INSTR_SETF_VAR_FLOAT:
+ DEST_VAR_FLOAT = VALUE_FLOAT;
+ ++ip;
+ break;
+
+ case INSTR_SETF_VAR_VAR:
+ DEST_VAR_FLOAT = SRC_VAR_FLOAT;
+ ++ip;
+ break;
+
+ /* SET.P */
+ case INSTR_SETP_VAR_VAR:
+ DEST_VAR_PTR = SRC_VAR_PTR;
+ ++ip;
+ break;
+
+ case INSTR_SETP_VAR_PTR:
+ DEST_VAR_PTR = VALUE_PTR;
+ ++ip;
+ break;
+
+ /* JUMP */
+ case INSTR_JUMP:
+ ip += JUMP_OFFSET;
+ break;
+
+ /* JZERO */
+ case INSTR_JZERO:
+ ip += (flag ? 1 : JUMP_OFFSET);
+ break;
+
+ case INSTR_NOP:
+ ++ip;
+ break;
+
+ /* ISEQUAL.P */
+ case INSTR_ISEQUALP_VAR_VAR:
+ flag = (DEST_VAR_PTR == SRC_VAR_PTR);
+ ++ip;
+ break;
+
+ case INSTR_ISEQUALP_VAR_PTR:
+ flag = (DEST_VAR_PTR == VALUE_PTR);
+ ++ip;
+ break;
+
+ /* ISEQUAL.I */
+ case INSTR_ISEQUALI_VAR_VAR:
+ flag = (DEST_VAR_INT == SRC_VAR_INT);
+ ++ip;
+ break;
+
+ case INSTR_ISEQUALI_VAR_INTEGER:
+ flag = (DEST_VAR_INT == VALUE_INT);
+ ++ip;
+ break;
+
+ /* ISEQUAL.F */
+ case INSTR_ISEQUALF_VAR_VAR:
+ flag = (DEST_VAR_FLOAT == SRC_VAR_FLOAT);
+ ++ip;
+ break;
+
+ case INSTR_ISEQUALF_VAR_FLOAT:
+ flag = (DEST_VAR_FLOAT == VALUE_FLOAT);
+ ++ip;
+ break;
+
+ /* ISLOWER.I */
+ case INSTR_ISLOWERI_VAR_VAR:
+ flag = (DEST_VAR_INT < SRC_VAR_INT);
+ ++ip;
+ break;
+
+ case INSTR_ISLOWERI_VAR_INTEGER:
+ flag = (DEST_VAR_INT < VALUE_INT);
+ ++ip;
+ break;
+
+ /* ISLOWER.F */
+ case INSTR_ISLOWERF_VAR_VAR:
+ flag = (DEST_VAR_FLOAT < SRC_VAR_FLOAT);
+ ++ip;
+ break;
+
+ case INSTR_ISLOWERF_VAR_FLOAT:
+ flag = (DEST_VAR_FLOAT < VALUE_FLOAT);
+ ++ip;
+ break;
+
+ /* ADD.I */
+ case INSTR_ADDI_VAR_VAR:
+ DEST_VAR_INT += SRC_VAR_INT;
+ ++ip;
+ break;
+
+ case INSTR_ADDI_VAR_INTEGER:
+ DEST_VAR_INT += VALUE_INT;
+ ++ip;
+ break;
+
+ /* ADD.F */
+ case INSTR_ADDF_VAR_VAR:
+ DEST_VAR_FLOAT += SRC_VAR_FLOAT;
+ ++ip;
+ break;
+
+ case INSTR_ADDF_VAR_FLOAT:
+ DEST_VAR_FLOAT += VALUE_FLOAT;
+ ++ip;
+ break;
+
+ /* MUL.I */
+ case INSTR_MULI_VAR_VAR:
+ DEST_VAR_INT *= SRC_VAR_INT;
+ ++ip;
+ break;
+
+ case INSTR_MULI_VAR_INTEGER:
+ DEST_VAR_INT *= VALUE_INT;
+ ++ip;
+ break;
+
+ /* MUL.F */
+ case INSTR_MULF_VAR_FLOAT:
+ DEST_VAR_FLOAT *= VALUE_FLOAT;
+ ++ip;
+ break;
+
+ case INSTR_MULF_VAR_VAR:
+ DEST_VAR_FLOAT *= SRC_VAR_FLOAT;
+ ++ip;
+ break;
+
+ /* DIV.I */
+ case INSTR_DIVI_VAR_VAR:
+ DEST_VAR_INT /= SRC_VAR_INT;
+ ++ip;
+ break;
+
+ case INSTR_DIVI_VAR_INTEGER:
+ DEST_VAR_INT /= VALUE_INT;
+ ++ip;
+ break;
+
+ /* DIV.F */
+ case INSTR_DIVF_VAR_FLOAT:
+ DEST_VAR_FLOAT /= VALUE_FLOAT;
+ ++ip;
+ break;
+
+ case INSTR_DIVF_VAR_VAR:
+ DEST_VAR_FLOAT /= SRC_VAR_FLOAT;
+ ++ip;
+ break;
+
+ /* SUB.I */
+ case INSTR_SUBI_VAR_VAR:
+ DEST_VAR_INT -= SRC_VAR_INT;
+ ++ip;
+ break;
+
+ case INSTR_SUBI_VAR_INTEGER:
+ DEST_VAR_INT -= VALUE_INT;
+ ++ip;
+ break;
+
+ /* SUB.F */
+ case INSTR_SUBF_VAR_FLOAT:
+ DEST_VAR_FLOAT -= VALUE_FLOAT;
+ ++ip;
+ break;
+
+ case INSTR_SUBF_VAR_VAR:
+ DEST_VAR_FLOAT -= SRC_VAR_FLOAT;
+ ++ip;
+ break;
+
+ /* CALL */
+ case INSTR_CALL:
+ stack[stack_pointer++] = ip + 1;
+ ip += JUMP_OFFSET;
+ break;
+
+ /* RET */
+ case INSTR_RET:
+ ip = stack[--stack_pointer];
+ if (ip < 0)
+ return;
+ break;
+
+ /* EXT_CALL */
+ case INSTR_EXT_CALL:
+ instr[ip].data.udest.external_function->function (gsl, gsl->vars,
+ instr[ip].data.udest.external_function->vars);
+ ++ip;
+ break;
+
+ /* NOT */
+ case INSTR_NOT_VAR:
+ flag = !flag;
+ ++ip;
+ break;
+
+ /* JNZERO */
+ case INSTR_JNZERO:
+ ip += (flag ? JUMP_OFFSET : 1);
+ break;
+
+ case INSTR_SETS_VAR_VAR:
+ memcpy (pDEST_VAR, pSRC_VAR, DEST_STRUCT_SIZE);
+ ++ip;
+ break;
+
+ case INSTR_ISEQUALS_VAR_VAR:
+ break;
+
+ case INSTR_ADDS_VAR_VAR:
+ /* process integers */
+ i = 0;
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_IBLOCK_VAR (i, j) += SRC_STRUCT_IBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ /* process floats */
+ i = 0;
+ while (DEST_STRUCT_FBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_FBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_FBLOCK_VAR (i, j) += SRC_STRUCT_FBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ ++ip;
+ break;
+
+ case INSTR_SUBS_VAR_VAR:
+ /* process integers */
+ i = 0;
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_IBLOCK_VAR (i, j) -= SRC_STRUCT_IBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ /* process floats */
+ i = 0;
+ while (DEST_STRUCT_FBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_FBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_FBLOCK_VAR (i, j) -= SRC_STRUCT_FBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ ++ip;
+ break;
+
+ case INSTR_MULS_VAR_VAR:
+ /* process integers */
+ i = 0;
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_IBLOCK_VAR (i, j) *= SRC_STRUCT_IBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ /* process floats */
+ i = 0;
+ while (DEST_STRUCT_FBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_FBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_FBLOCK_VAR (i, j) *= SRC_STRUCT_FBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ ++ip;
+ break;
+
+ case INSTR_DIVS_VAR_VAR:
+ /* process integers */
+ i = 0;
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_IBLOCK_VAR (i, j) /= SRC_STRUCT_IBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ /* process floats */
+ i = 0;
+ while (DEST_STRUCT_FBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_FBLOCK (i).size;
+
+ while (j--) {
+ DEST_STRUCT_FBLOCK_VAR (i, j) /= SRC_STRUCT_FBLOCK_VAR (i, j);
+ }
+ ++i;
+ }
+ ++ip;
+ break;
+
+ default:
+ printf ("NOT IMPLEMENTED : %d\n", instr[ip].id);
+ ++ip;
+ exit (1);
+ }
+ }
+} /* }}} */
+
+int
+gsl_malloc (GoomSL * _this, int size)
+{ /* {{{ */
+ if (_this->nbPtr >= _this->ptrArraySize) {
+ _this->ptrArraySize *= 2;
+ _this->ptrArray =
+ (void **) realloc (_this->ptrArray,
+ sizeof (void *) * _this->ptrArraySize);
+ }
+ _this->ptrArray[_this->nbPtr] = malloc (size);
+ return _this->nbPtr++;
+} /* }}} */
+
+void *
+gsl_get_ptr (GoomSL * _this, int id)
+{ /* {{{ */
+ if ((id >= 0) && (id < _this->nbPtr))
+ return _this->ptrArray[id];
+ fprintf (stderr, "INVALID GET PTR 0x%08x\n", id);
+ return NULL;
+} /* }}} */
+
+void
+gsl_free_ptr (GoomSL * _this, int id)
+{ /* {{{ */
+ if ((id >= 0) && (id < _this->nbPtr)) {
+ free (_this->ptrArray[id]);
+ _this->ptrArray[id] = 0;
+ }
+} /* }}} */
+
+void
+gsl_enternamespace (const char *name)
+{ /* {{{ */
+ HashValue *val = goom_hash_get (currentGoomSL->functions, name);
+
+ if (val) {
+ ExternalFunctionStruct *function = (ExternalFunctionStruct *) val->ptr;
+
+ currentGoomSL->currentNS++;
+ currentGoomSL->namespaces[currentGoomSL->currentNS] = function->vars;
+ } else {
+ fprintf (stderr, "ERROR: Line %d, Could not find namespace: %s\n",
+ currentGoomSL->num_lines, name);
+ exit (1);
+ }
+} /* }}} */
+
+void
+gsl_reenternamespace (GoomHash * nsinfo)
+{
+ currentGoomSL->currentNS++;
+ currentGoomSL->namespaces[currentGoomSL->currentNS] = nsinfo;
+}
+
+GoomHash *
+gsl_leavenamespace (void)
+{ /* {{{ */
+ currentGoomSL->currentNS--;
+ return currentGoomSL->namespaces[currentGoomSL->currentNS + 1];
+} /* }}} */
+
+GoomHash *
+gsl_find_namespace (const char *name)
+{ /* {{{ */
+ int i;
+
+ for (i = currentGoomSL->currentNS; i >= 0; --i) {
+ if (goom_hash_get (currentGoomSL->namespaces[i], name))
+ return currentGoomSL->namespaces[i];
+ }
+ return NULL;
+} /* }}} */
+
+void
+gsl_declare_task (const char *name)
+{ /* {{{ */
+ if (goom_hash_get (currentGoomSL->functions, name)) {
+ return;
+ } else {
+ ExternalFunctionStruct *gef =
+ (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
+ gef->function = 0;
+ gef->vars = goom_hash_new ();
+ gef->is_extern = 0;
+ goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
+ }
+} /* }}} */
+
+void
+gsl_declare_external_task (const char *name)
+{ /* {{{ */
+ if (goom_hash_get (currentGoomSL->functions, name)) {
+ fprintf (stderr, "ERROR: Line %d, Duplicate declaration of %s\n",
+ currentGoomSL->num_lines, name);
+ return;
+ } else {
+ ExternalFunctionStruct *gef =
+ (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
+ gef->function = 0;
+ gef->vars = goom_hash_new ();
+ gef->is_extern = 1;
+ goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
+ }
+} /* }}} */
+
+static void
+reset_scanner (GoomSL * gss)
+{ /* {{{ */
+ gss->num_lines = 0;
+ gss->instr = NULL;
+ iflow_clean (gss->iflow);
+
+ /* reset variables */
+ goom_hash_free (gss->vars);
+ gss->vars = goom_hash_new ();
+ gss->currentNS = 0;
+ gss->namespaces[0] = gss->vars;
+
+ goom_hash_free (gss->structIDS);
+ gss->structIDS = goom_hash_new ();
+
+ while (gss->nbStructID > 0) {
+ int i;
+
+ gss->nbStructID--;
+ for (i = 0; i < gss->gsl_struct[gss->nbStructID]->nbFields; ++i)
+ free (gss->gsl_struct[gss->nbStructID]->fields[i]);
+ free (gss->gsl_struct[gss->nbStructID]);
+ }
+
+ gss->compilationOK = 1;
+
+ goom_heap_delete (gss->data_heap);
+ gss->data_heap = goom_heap_new ();
+} /* }}} */
+
+static void
+calculate_labels (InstructionFlow * iflow)
+{ /* {{{ */
+ int i = 0;
+
+ while (i < iflow->number) {
+ Instruction *instr = iflow->instr[i];
+
+ if (instr->jump_label) {
+ HashValue *label = goom_hash_get (iflow->labels, instr->jump_label);
+
+ if (label) {
+ instr->data.udest.jump_offset = -instr->address + label->i;
+ } else {
+ fprintf (stderr, "ERROR: Line %d, Could not find label %s\n",
+ instr->line_number, instr->jump_label);
+ instr->id = INSTR_NOP;
+ instr->nop_label = 0;
+ exit (1);
+ }
+ }
+ ++i;
+ }
+} /* }}} */
+
+static int
+powerOfTwo (int i)
+{
+ int b;
+
+ for (b = 0; b < 31; b++)
+ if (i == (1 << b))
+ return b;
+ return 0;
+}
+
+/* Cree un flow d'instruction optimise */
+static void
+gsl_create_fast_iflow (void)
+{ /* {{{ */
+ int number = currentGoomSL->iflow->number;
+ int i;
+
+#ifdef USE_JITC_X86
+
+ /* pour compatibilite avec les MACROS servant a execution */
+ int ip = 0;
+ GoomSL *gsl = currentGoomSL;
+
+ JitcX86Env *jitc;
+
+ if (currentGoomSL->jitc != NULL)
+ jitc_x86_delete (currentGoomSL->jitc);
+ jitc = currentGoomSL->jitc = jitc_x86_env_new (0xffff);
+ currentGoomSL->jitc_func = jitc_prepare_func (jitc);
+
+#if 0
+#define SRC_STRUCT_ID instr[ip].data.usrc.var_int[-1]
+#define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
+#define SRC_STRUCT_IBLOCK(i) gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
+#define SRC_STRUCT_FBLOCK(i) gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
+#define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
+#define DEST_STRUCT_IBLOCK_VAR(i,j) \
+ ((int*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
+#define DEST_STRUCT_FBLOCK_VAR(i,j) \
+ ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
+#define SRC_STRUCT_IBLOCK_VAR(i,j) \
+ ((int*)((char*)pSRC_VAR + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
+#define SRC_STRUCT_FBLOCK_VAR(i,j) \
+ ((float*)((char*)pSRC_VAR + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
+#define DEST_STRUCT_SIZE gsl->gsl_struct[DEST_STRUCT_ID]->size
+#endif
+
+ JITC_JUMP_LABEL (jitc, "__very_end__");
+ JITC_ADD_LABEL (jitc, "__very_start__");
+
+ for (i = 0; i < number; ++i) {
+ Instruction *instr = currentGoomSL->iflow->instr[i];
+
+ switch (instr->id) {
+ case INSTR_SETI_VAR_INTEGER:
+ jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_int,
+ instr->data.usrc.value_int);
+ break;
+ case INSTR_SETI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ break;
+ /* SET.F */
+ case INSTR_SETF_VAR_FLOAT:
+ jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_float,
+ *(int *) (&instr->data.usrc.value_float));
+ break;
+ case INSTR_SETF_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_float);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_float);
+ break;
+ case INSTR_NOP:
+ if (instr->nop_label != 0)
+ JITC_ADD_LABEL (jitc, instr->nop_label);
+ break;
+ case INSTR_JUMP:
+ JITC_JUMP_LABEL (jitc, instr->jump_label);
+ break;
+ case INSTR_SETP_VAR_PTR:
+ jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_ptr,
+ instr->data.usrc.value_ptr);
+ break;
+ case INSTR_SETP_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_ptr);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_ptr);
+ break;
+ case INSTR_SUBI_VAR_INTEGER:
+ jitc_add (jitc, "add [$d], $d", instr->data.udest.var_int,
+ -instr->data.usrc.value_int);
+ break;
+ case INSTR_SUBI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "sub eax, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ break;
+ case INSTR_SUBF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_SUBF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_ISLOWERF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_ISLOWERF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_ISLOWERI_VAR_VAR:
+ jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "sub edx, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "shr edx, $d", 31);
+ break;
+ case INSTR_ISLOWERI_VAR_INTEGER:
+ jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "sub edx, $d", instr->data.usrc.value_int);
+ jitc_add (jitc, "shr edx, $d", 31);
+ break;
+ case INSTR_ADDI_VAR_INTEGER:
+ jitc_add (jitc, "add [$d], $d", instr->data.udest.var_int,
+ instr->data.usrc.value_int);
+ break;
+ case INSTR_ADDI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "add eax, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ break;
+ case INSTR_ADDF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_ADDF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_MULI_VAR_INTEGER:
+ if (instr->data.usrc.value_int != 1) {
+ int po2 = powerOfTwo (instr->data.usrc.value_int);
+
+ if (po2) {
+ /* performs (V / 2^n) by doing V >> n */
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "sal eax, $d", po2);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ } else {
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "imul eax, $d", instr->data.usrc.value_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ }
+ }
+ break;
+ case INSTR_MULI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "imul eax, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ break;
+ case INSTR_MULF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_MULF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_DIVI_VAR_INTEGER:
+ if ((instr->data.usrc.value_int != 1)
+ && (instr->data.usrc.value_int != 0)) {
+ int po2 = powerOfTwo (instr->data.usrc.value_int);
+
+ if (po2) {
+ /* performs (V / 2^n) by doing V >> n */
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "sar eax, $d", po2);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ } else {
+ /* performs (V/n) by doing (V*(32^2/n)) */
+ long coef;
+ double dcoef =
+ (double) 4294967296.0 / (double) instr->data.usrc.value_int;
+ if (dcoef < 0.0)
+ dcoef = -dcoef;
+ coef = (long) floor (dcoef);
+ dcoef -= floor (dcoef);
+ if (dcoef < 0.5)
+ coef += 1;
+
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "mov edx, $d", coef);
+ jitc_add (jitc, "imul edx");
+ if (instr->data.usrc.value_int < 0)
+ jitc_add (jitc, "neg edx");
+ jitc_add (jitc, "mov [$d], edx", instr->data.udest.var_int);
+ }
+ }
+ break;
+ case INSTR_DIVI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "cdq"); /* sign extend eax into edx */
+ jitc_add (jitc, "idiv [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
+ break;
+ case INSTR_DIVF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_DIVF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_JZERO:
+ jitc_add (jitc, "cmp edx, $d", 0);
+ jitc_add (jitc, "je $s", instr->jump_label);
+ break;
+ case INSTR_ISEQUALP_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
+ jitc_add (jitc, "mov edx, $d", 0);
+ jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_ptr);
+ jitc_add (jitc, "jne $d", 1);
+ jitc_add (jitc, "inc edx");
+ break;
+ case INSTR_ISEQUALP_VAR_PTR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
+ jitc_add (jitc, "mov edx, $d", 0);
+ jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_ptr);
+ jitc_add (jitc, "jne $d", 1);
+ jitc_add (jitc, "inc edx");
+ break;
+ case INSTR_ISEQUALI_VAR_VAR:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "mov edx, $d", 0);
+ jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_int);
+ jitc_add (jitc, "jne $d", 1);
+ jitc_add (jitc, "inc edx");
+ break;
+ case INSTR_ISEQUALI_VAR_INTEGER:
+ jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
+ jitc_add (jitc, "mov edx, $d", 0);
+ jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_int);
+ jitc_add (jitc, "jne $d", 1);
+ jitc_add (jitc, "inc edx");
+ break;
+ case INSTR_ISEQUALF_VAR_VAR:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_ISEQUALF_VAR_FLOAT:
+ printf ("NOT IMPLEMENTED : %d\n", instr->id);
+ break;
+ case INSTR_CALL:
+ jitc_add (jitc, "call $s", instr->jump_label);
+ break;
+ case INSTR_RET:
+ jitc_add (jitc, "ret");
+ break;
+ case INSTR_EXT_CALL:
+ jitc_add (jitc, "mov eax, [$d]",
+ &(instr->data.udest.external_function->vars));
+ jitc_add (jitc, "push eax");
+ jitc_add (jitc, "mov edx, [$d]", &(currentGoomSL->vars));
+ jitc_add (jitc, "push edx");
+ jitc_add (jitc, "mov eax, [$d]", &(currentGoomSL));
+ jitc_add (jitc, "push eax");
+
+ jitc_add (jitc, "mov eax, [$d]",
+ &(instr->data.udest.external_function));
+ jitc_add (jitc, "mov eax, [eax]");
+ jitc_add (jitc, "call [eax]");
+ jitc_add (jitc, "add esp, $d", 12);
+ break;
+ case INSTR_NOT_VAR:
+ jitc_add (jitc, "mov eax, edx");
+ jitc_add (jitc, "mov edx, $d", 1);
+ jitc_add (jitc, "sub edx, eax");
+ break;
+ case INSTR_JNZERO:
+ jitc_add (jitc, "cmp edx, $d", 0);
+ jitc_add (jitc, "jne $s", instr->jump_label);
+ break;
+ case INSTR_SETS_VAR_VAR:
+ {
+ int loop = DEST_STRUCT_SIZE / sizeof (int);
+ int dst = (int) pDEST_VAR;
+ int src = (int) pSRC_VAR;
+
+ while (loop--) {
+ jitc_add (jitc, "mov eax, [$d]", src);
+ jitc_add (jitc, "mov [$d], eax", dst);
+ src += 4;
+ dst += 4;
+ }
+ }
+ break;
+ case INSTR_ISEQUALS_VAR_VAR:
+ break;
+ case INSTR_ADDS_VAR_VAR:
+ {
+ /* process integers */
+ int i = 0;
+
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) { /* TODO interlace 2 */
+ jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "add eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ }
+ ++i;
+ }
+ /* process floats */
+ i = 0;
+ while (DEST_STRUCT_FBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_FBLOCK (i).size;
+
+ while (j--) {
+ /* DEST_STRUCT_FBLOCK_VAR(i,j) += SRC_STRUCT_FBLOCK_VAR(i,j); */
+ /* TODO */
+ }
+ ++i;
+ }
+ break;
+ }
+ case INSTR_SUBS_VAR_VAR:
+ {
+ /* process integers */
+ int i = 0;
+
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "sub eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ }
+ ++i;
+ }
+ break;
+ }
+ case INSTR_MULS_VAR_VAR:
+ {
+ /* process integers */
+ int i = 0;
+
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "imul eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ }
+ ++i;
+ }
+ break;
+ }
+ case INSTR_DIVS_VAR_VAR:
+ {
+ /* process integers */
+ int i = 0;
+
+ while (DEST_STRUCT_IBLOCK (i).size > 0) {
+ int j = DEST_STRUCT_IBLOCK (i).size;
+
+ while (j--) {
+ jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "cdq");
+ jitc_add (jitc, "idiv [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
+ jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
+ }
+ ++i;
+ }
+ break;
+ }
+ }
+ }
+
+ JITC_ADD_LABEL (jitc, "__very_end__");
+ jitc_add (jitc, "call $s", "__very_start__");
+ jitc_add (jitc, "mov eax, $d", 0);
+ jitc_validate_func (jitc);
+#else
+ InstructionFlow *iflow = currentGoomSL->iflow;
+ FastInstructionFlow *fastiflow =
+ (FastInstructionFlow *) malloc (sizeof (FastInstructionFlow));
+ fastiflow->mallocedInstr = calloc (number * 16, sizeof (FastInstruction));
+ /* fastiflow->instr = (FastInstruction*)(((int)fastiflow->mallocedInstr) + 16 - (((int)fastiflow->mallocedInstr)%16)); */
+ fastiflow->instr = (FastInstruction *) fastiflow->mallocedInstr;
+ fastiflow->number = number;
+ for (i = 0; i < number; ++i) {
+ fastiflow->instr[i].id = iflow->instr[i]->id;
+ fastiflow->instr[i].data = iflow->instr[i]->data;
+ fastiflow->instr[i].proto = iflow->instr[i];
+ }
+ currentGoomSL->fastiflow = fastiflow;
+#endif
+} /* }}} */
+
+void yy_scan_string (const char *str);
+void yyparse (void);
+
+GoomHash *
+gsl_globals (GoomSL * _this)
+{
+ return _this->vars;
+}
+
+
+/**
+ * Some native external functions
+ */
+static void
+ext_charAt (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+ char *string = GSL_LOCAL_PTR (gsl, local, "value");
+ int index = GSL_LOCAL_INT (gsl, local, "index");
+
+ GSL_GLOBAL_INT (gsl, "charAt") = 0;
+ if (string == NULL) {
+ return;
+ }
+ if (index < strlen (string))
+ GSL_GLOBAL_INT (gsl, "charAt") = string[index];
+}
+
+static void
+ext_i2f (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+ int i = GSL_LOCAL_INT (gsl, local, "value");
+
+ GSL_GLOBAL_FLOAT (gsl, "i2f") = i;
+}
+
+static void
+ext_f2i (GoomSL * gsl, GoomHash * global, GoomHash * local)
+{
+ float f = GSL_LOCAL_FLOAT (gsl, local, "value");
+
+ GSL_GLOBAL_INT (gsl, "f2i") = f;
+}
+
+/**
+ *
+ */
+void
+gsl_compile (GoomSL * _currentGoomSL, const char *script)
+{ /* {{{ */
+ char *script_and_externals;
+ static const char *sBinds =
+ "external <charAt: string value, int index> : int\n"
+ "external <f2i: float value> : int\n"
+ "external <i2f: int value> : float\n";
+
+#ifdef VERBOSE
+ printf ("\n=== Starting Compilation ===\n");
+#endif
+
+ script_and_externals = malloc (strlen (script) + strlen (sBinds) + 2);
+ strcpy (script_and_externals, sBinds);
+ strcat (script_and_externals, script);
+
+ /* 0- reset */
+ currentGoomSL = _currentGoomSL;
+ reset_scanner (currentGoomSL);
+
+ /* 1- create the syntaxic tree */
+ yy_scan_string (script_and_externals);
+ yyparse ();
+
+ /* 2- generate code */
+ gsl_commit_compilation ();
+
+ /* 3- resolve symbols */
+ calculate_labels (currentGoomSL->iflow);
+
+ /* 4- optimize code */
+ gsl_create_fast_iflow ();
+
+ /* 5- bind a few internal functions */
+ gsl_bind_function (currentGoomSL, "charAt", ext_charAt);
+ gsl_bind_function (currentGoomSL, "f2i", ext_f2i);
+ gsl_bind_function (currentGoomSL, "i2f", ext_i2f);
+ free (script_and_externals);
+
+#ifdef VERBOSE
+ printf ("=== Compilation done. # of lines: %d. # of instr: %d ===\n",
+ currentGoomSL->num_lines, currentGoomSL->iflow->number);
+#endif
+} /* }}} */
+
+void
+gsl_execute (GoomSL * scanner)
+{ /* {{{ */
+ if (scanner->compilationOK) {
+#if USE_JITC_X86
+ scanner->jitc_func ();
+#else
+ iflow_execute (scanner->fastiflow, scanner);
+#endif
+ }
+} /* }}} */
+
+GoomSL *
+gsl_new (void)
+{ /* {{{ */
+ GoomSL *gss = (GoomSL *) malloc (sizeof (GoomSL));
+
+ gss->iflow = iflow_new ();
+ gss->vars = goom_hash_new ();
+ gss->functions = goom_hash_new ();
+ gss->nbStructID = 0;
+ gss->structIDS = goom_hash_new ();
+ gss->gsl_struct_size = 32;
+ gss->gsl_struct =
+ (GSL_Struct **) malloc (gss->gsl_struct_size * sizeof (GSL_Struct *));
+ gss->currentNS = 0;
+ gss->namespaces[0] = gss->vars;
+ gss->data_heap = goom_heap_new ();
+
+ reset_scanner (gss);
+
+ gss->compilationOK = 0;
+ gss->nbPtr = 0;
+ gss->ptrArraySize = 256;
+ gss->ptrArray = (void **) malloc (gss->ptrArraySize * sizeof (void *));
+#ifdef USE_JITC_X86
+ gss->jitc = NULL;
+#endif
+ return gss;
+} /* }}} */
+
+void
+gsl_bind_function (GoomSL * gss, const char *fname,
+ GoomSL_ExternalFunction func)
+{ /* {{{ */
+ HashValue *val = goom_hash_get (gss->functions, fname);
+
+ if (val) {
+ ExternalFunctionStruct *gef = (ExternalFunctionStruct *) val->ptr;
+
+ gef->function = func;
+ } else
+ fprintf (stderr, "Unable to bind function %s\n", fname);
+} /* }}} */
+
+int
+gsl_is_compiled (GoomSL * gss)
+{ /* {{{ */
+ return gss->compilationOK;
+} /* }}} */
+
+void
+gsl_free (GoomSL * gss)
+{ /* {{{ */
+ iflow_free (gss->iflow);
+ free (gss->vars);
+ free (gss->functions);
+ free (gss);
+} /* }}} */
+
+
+static int gsl_nb_import;
+static char gsl_already_imported[256][256];
+
+char *
+gsl_init_buffer (const char *fname)
+{
+ char *fbuffer;
+
+ fbuffer = (char *) malloc (512);
+ fbuffer[0] = 0;
+ gsl_nb_import = 0;
+ if (fname)
+ gsl_append_file_to_buffer (fname, &fbuffer);
+ return fbuffer;
+}
+
+static char *
+gsl_read_file (const char *fname)
+{
+ FILE *f;
+ char *buffer;
+ int fsize;
+
+ f = fopen (fname, "rt");
+ if (!f) {
+ fprintf (stderr, "ERROR: Could not load file %s\n", fname);
+ exit (1);
+ }
+ fseek (f, 0, SEEK_END);
+ fsize = ftell (f);
+ rewind (f);
+ buffer = (char *) malloc (fsize + 512);
+ fread (buffer, 1, fsize, f);
+ fclose (f);
+ buffer[fsize] = 0;
+ return buffer;
+}
+
+void
+gsl_append_file_to_buffer (const char *fname, char **buffer)
+{
+ char *fbuffer;
+ int size, fsize, i = 0;
+ char reset_msg[256];
+
+ /* look if the file have not been already imported */
+ for (i = 0; i < gsl_nb_import; ++i) {
+ if (strcmp (gsl_already_imported[i], fname) == 0)
+ return;
+ }
+
+ /* add fname to the already imported files. */
+ strcpy (gsl_already_imported[gsl_nb_import++], fname);
+
+ /* load the file */
+ fbuffer = gsl_read_file (fname);
+ fsize = strlen (fbuffer);
+
+ /* look for #import */
+ while (fbuffer[i]) {
+ if ((fbuffer[i] == '#') && (fbuffer[i + 1] == 'i')) {
+ char impName[256];
+ int j;
+
+ while (fbuffer[i] && (fbuffer[i] != ' '))
+ i++;
+ i++;
+ j = 0;
+ while (fbuffer[i] && (fbuffer[i] != '\n'))
+ impName[j++] = fbuffer[i++];
+ impName[j++] = 0;
+ gsl_append_file_to_buffer (impName, buffer);
+ }
+ i++;
+ }
+
+ sprintf (reset_msg, "\n#FILE %s#\n#RST_LINE#\n", fname);
+ strcat (*buffer, reset_msg);
+ size = strlen (*buffer);
+ *buffer = (char *) realloc (*buffer, size + fsize + 256);
+ strcat ((*buffer) + size, fbuffer);
+ free (fbuffer);
+}