diff options
Diffstat (limited to 'gst/goom/goomsl.c')
-rw-r--r-- | gst/goom/goomsl.c | 1660 |
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); +} |