gstreamer/gst/goom/goomsl.c

1663 lines
48 KiB
C
Raw Normal View History

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib.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;
}
} /* }}} */
/*************/
/* 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 <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);
}