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 + -
显示快捷键?