goomsl.c

来自「linux下的MPEG1」· C语言 代码 · 共 1,510 行 · 第 1/3 页

C
1,510
字号
#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:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?