#include #include #include #include #include #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; } } /* }}} */ /*************/ /* 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; } } /* }}} */ #ifdef USE_JITC_X86 static int powerOfTwo (int i) { int b; for (b = 0; b < 31; b++) if (i == (1 << b)) return b; return 0; } #endif /* 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 : int\n" "external : int\n" "external : 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); }