X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.c;h=e7c7816605a637913b96694072091f2edfb80342;hp=00e729925d3067cd03273a10577f9a30336ca00e;hb=9ed62eee5845c0c3a157a732ed4de143519bd56d;hpb=d6ca5673dc7f2760faca1200477808d919a290ca diff --git a/parser.c b/parser.c index 00e7299..e7c7816 100644 --- a/parser.c +++ b/parser.c @@ -23,90 +23,12 @@ */ #include #include +#include "parser.h" -#include "gmqcc.h" -#include "lexer.h" -#include "ast.h" - -/* beginning of locals */ #define PARSER_HT_LOCALS 2 - #define PARSER_HT_SIZE 512 #define TYPEDEF_HT_SIZE 512 -typedef struct parser_s { - lex_file *lex; - int tok; - - bool ast_cleaned; - - ast_expression **globals; - ast_expression **fields; - ast_function **functions; - ast_value **imm_float; - ast_value **imm_string; - ast_value **imm_vector; - size_t translated; - - ht ht_imm_string; - ht ht_imm_string_dotranslate; - - /* must be deleted first, they reference immediates and values */ - ast_value **accessors; - - ast_value *imm_float_zero; - ast_value *imm_float_one; - ast_value *imm_float_neg_one; - - ast_value *imm_vector_zero; - - ast_value *nil; - ast_value *reserved_version; - - size_t crc_globals; - size_t crc_fields; - - ast_function *function; - ht aliases; - - /* All the labels the function defined... - * Should they be in ast_function instead? - */ - ast_label **labels; - ast_goto **gotos; - const char **breaks; - const char **continues; - - /* A list of hashtables for each scope */ - ht *variables; - ht htfields; - ht htglobals; - ht *typedefs; - - /* same as above but for the spelling corrector */ - correct_trie_t **correct_variables; - size_t ***correct_variables_score; /* vector of vector of size_t* */ - - /* not to be used directly, we use the hash table */ - ast_expression **_locals; - size_t *_blocklocals; - ast_value **_typedefs; - size_t *_blocktypedefs; - lex_ctx_t *_block_ctx; - - /* we store the '=' operator info */ - const oper_info *assign_op; - - /* magic values */ - ast_value *const_vec[3]; - - /* pragma flags */ - bool noref; - - /* collected information */ - size_t max_param_count; -} parser_t; - static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1; static void parser_enterblock(parser_t *parser); @@ -144,42 +66,6 @@ static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char * return r; } -/********************************************************************** - * some maths used for constant folding - */ - -vec3_t vec3_add(vec3_t a, vec3_t b) -{ - vec3_t out; - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - return out; -} - -vec3_t vec3_sub(vec3_t a, vec3_t b) -{ - vec3_t out; - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - return out; -} - -qcfloat_t vec3_mulvv(vec3_t a, vec3_t b) -{ - return (a.x * b.x + a.y * b.y + a.z * b.z); -} - -vec3_t vec3_mulvf(vec3_t a, float b) -{ - vec3_t out; - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - return out; -} - /********************************************************************** * parsing */ @@ -199,53 +85,8 @@ static bool parser_next(parser_t *parser) #define parser_tokval(p) ((p)->lex->tok.value) #define parser_token(p) (&((p)->lex->tok)) -#define parser_ctx(p) ((p)->lex->tok.ctx) - -static ast_value* parser_const_float(parser_t *parser, double d) -{ - size_t i; - ast_value *out; - lex_ctx_t ctx; - for (i = 0; i < vec_size(parser->imm_float); ++i) { - const double compare = parser->imm_float[i]->constval.vfloat; - if (memcmp((const void*)&compare, (const void *)&d, sizeof(double)) == 0) - return parser->imm_float[i]; - } - if (parser->lex) - ctx = parser_ctx(parser); - else { - memset(&ctx, 0, sizeof(ctx)); - } - out = ast_value_new(ctx, "#IMMEDIATE", TYPE_FLOAT); - out->cvq = CV_CONST; - out->hasvalue = true; - out->isimm = true; - out->constval.vfloat = d; - vec_push(parser->imm_float, out); - return out; -} - -static ast_value* parser_const_float_0(parser_t *parser) -{ - if (!parser->imm_float_zero) - parser->imm_float_zero = parser_const_float(parser, 0); - return parser->imm_float_zero; -} - -static ast_value* parser_const_float_neg1(parser_t *parser) { - if (!parser->imm_float_neg_one) - parser->imm_float_neg_one = parser_const_float(parser, -1); - return parser->imm_float_neg_one; -} - -static ast_value* parser_const_float_1(parser_t *parser) -{ - if (!parser->imm_float_one) - parser->imm_float_one = parser_const_float(parser, 1); - return parser->imm_float_one; -} -static char *parser_strdup(const char *str) +char *parser_strdup(const char *str) { if (str && !*str) { /* actually dup empty strings */ @@ -256,74 +97,6 @@ static char *parser_strdup(const char *str) return util_strdup(str); } -static ast_value* parser_const_string(parser_t *parser, const char *str, bool dotranslate) -{ - ht ht_string = (dotranslate) - ? parser->ht_imm_string_dotranslate - : parser->ht_imm_string; - - ast_value *out; - size_t hash = util_hthash(ht_string, str); - - if ((out = (ast_value*)util_htgeth(ht_string, str, hash))) - return out; - /* - for (i = 0; i < vec_size(parser->imm_string); ++i) { - if (!strcmp(parser->imm_string[i]->constval.vstring, str)) - return parser->imm_string[i]; - } - */ - if (dotranslate) { - char name[32]; - util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++)); - out = ast_value_new(parser_ctx(parser), name, TYPE_STRING); - out->expression.flags |= AST_FLAG_INCLUDE_DEF; - } else - out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING); - - out->cvq = CV_CONST; - out->hasvalue = true; - out->isimm = true; - out->constval.vstring = parser_strdup(str); - vec_push(parser->imm_string, out); - util_htseth(ht_string, str, hash, out); - - return out; -} - -static ast_value* parser_const_vector(parser_t *parser, vec3_t v) -{ - size_t i; - ast_value *out; - for (i = 0; i < vec_size(parser->imm_vector); ++i) { - if (!memcmp(&parser->imm_vector[i]->constval.vvec, &v, sizeof(v))) - return parser->imm_vector[i]; - } - out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR); - out->cvq = CV_CONST; - out->hasvalue = true; - out->isimm = true; - out->constval.vvec = v; - vec_push(parser->imm_vector, out); - return out; -} - -static ast_value* parser_const_vector_f(parser_t *parser, float x, float y, float z) -{ - vec3_t v; - v.x = x; - v.y = y; - v.z = z; - return parser_const_vector(parser, v); -} - -static ast_value* parser_const_vector_0(parser_t *parser) -{ - if (!parser->imm_vector_zero) - parser->imm_vector_zero = parser_const_vector_f(parser, 0, 0, 0); - return parser->imm_vector_zero; -} - static ast_expression* parser_find_field(parser_t *parser, const char *name) { return ( ast_expression*)util_htget(parser->htfields, name); @@ -514,32 +287,6 @@ static bool rotate_entfield_array_index_nodes(ast_expression **out) return true; } -static bool immediate_is_true(lex_ctx_t ctx, ast_value *v) -{ - switch (v->expression.vtype) { - case TYPE_FLOAT: - return !!v->constval.vfloat; - case TYPE_INTEGER: - return !!v->constval.vint; - case TYPE_VECTOR: - if (OPTS_FLAG(CORRECT_LOGIC)) - return v->constval.vvec.x && - v->constval.vvec.y && - v->constval.vvec.z; - else - return !!(v->constval.vvec.x); - case TYPE_STRING: - if (!v->constval.vstring) - return false; - if (v->constval.vstring && OPTS_FLAG(TRUE_EMPTY_STRINGS)) - return true; - return !!v->constval.vstring[0]; - default: - compile_error(ctx, "internal error: immediate_is_true on invalid type"); - return !!v->constval.vfunc; - } -} - static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) { const oper_info *op; @@ -606,14 +353,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) #define NotSameType(T) \ (exprs[0]->vtype != exprs[1]->vtype || \ exprs[0]->vtype != T) -#define CanConstFold1(A) \ - (ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\ - (A)->vtype != TYPE_FUNCTION) -#define CanConstFold(A, B) \ - (CanConstFold1(A) && CanConstFold1(B)) -#define ConstV(i) (asvalue[(i)]->constval.vvec) -#define ConstF(i) (asvalue[(i)]->constval.vfloat) -#define ConstS(i) (asvalue[(i)]->constval.vstring) + + /* preform any constant folding on operator usage first */ + if ((out = fold_op(parser->fold, op, exprs))) + goto complete; + switch (op->id) { default: @@ -710,20 +454,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('-','P'): switch (exprs[0]->vtype) { case TYPE_FLOAT: - if (CanConstFold1(exprs[0])) - out = (ast_expression*)parser_const_float(parser, -ConstF(0)); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, - (ast_expression*)parser_const_float_0(parser), + out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, + (ast_expression*)parser->fold->imm_float[0], exprs[0]); break; case TYPE_VECTOR: - if (CanConstFold1(exprs[0])) - out = (ast_expression*)parser_const_vector_f(parser, - -ConstV(0).x, -ConstV(0).y, -ConstV(0).z); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, - (ast_expression*)parser_const_vector_0(parser), + out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, + (ast_expression*)parser->fold->imm_vector[0], exprs[0]); break; default: @@ -736,30 +473,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('!','P'): switch (exprs[0]->vtype) { case TYPE_FLOAT: - if (CanConstFold1(exprs[0])) - out = (ast_expression*)parser_const_float(parser, !ConstF(0)); - else - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); break; case TYPE_VECTOR: - if (CanConstFold1(exprs[0])) - out = (ast_expression*)parser_const_float(parser, - (!ConstV(0).x && !ConstV(0).y && !ConstV(0).z)); - else - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]); + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]); break; case TYPE_STRING: - if (CanConstFold1(exprs[0])) { - if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) - out = (ast_expression*)parser_const_float(parser, !ConstS(0)); - else - out = (ast_expression*)parser_const_float(parser, !ConstS(0) || !*ConstS(0)); - } else { - if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); - else - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]); - } + if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); + else + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]); break; /* we don't constant-fold NOT for these types */ case TYPE_ENTITY: @@ -786,18 +509,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } switch (exprs[0]->vtype) { case TYPE_FLOAT: - if (CanConstFold(exprs[0], exprs[1])) - { - out = (ast_expression*)parser_const_float(parser, ConstF(0) + ConstF(1)); - } - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]); + out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_vector(parser, vec3_add(ConstV(0), ConstV(1))); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]); + out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot add type %s and %s", @@ -817,16 +532,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } switch (exprs[0]->vtype) { case TYPE_FLOAT: - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1)); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]); + out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_vector(parser, vec3_sub(ConstV(0), ConstV(1))); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]); + out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s", @@ -851,93 +560,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) switch (exprs[0]->vtype) { case TYPE_FLOAT: if (exprs[1]->vtype == TYPE_VECTOR) - { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0))); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); - } + out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); else - { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_float(parser, ConstF(0) * ConstF(1)); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]); - } + out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: if (exprs[1]->vtype == TYPE_FLOAT) - { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1))); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); - } + out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); else - { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_float(parser, vec3_mulvv(ConstV(0), ConstV(1))); - else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && CanConstFold1(exprs[0])) { - vec3_t vec = ConstV(0); - if (!vec.y && !vec.z) { /* 'n 0 0' * v */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.x != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out); - } - else if (!vec.x && !vec.z) { /* '0 n 0' * v */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.y != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out); - } - else if (!vec.x && !vec.y) { /* '0 n 0' * v */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.z != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out); - } - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]); - } - else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && CanConstFold1(exprs[1])) { - vec3_t vec = ConstV(1); - if (!vec.y && !vec.z) { /* v * 'n 0 0' */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.x != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x)); - } - else if (!vec.x && !vec.z) { /* v * '0 n 0' */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.y != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y)); - } - else if (!vec.x && !vec.y) { /* v * '0 n 0' */ - ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; - if (vec.z != 1) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z)); - } - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]); - } - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]); - } + out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s", @@ -953,30 +584,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2); return false; } - if (exprs[0]->vtype == TYPE_FLOAT) { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1)); - else - out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]); - } - else if (exprs[0]->vtype == TYPE_VECTOR) { - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1))); - else { - if (CanConstFold1(exprs[1])) { - out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1)); - } else { - out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, - (ast_expression*)parser_const_float_1(parser), - exprs[1]); - } - if (!out) { - compile_error(ctx, "internal error: failed to generate division"); - return false; - } - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], out); - } - } + if (exprs[0]->vtype == TYPE_FLOAT) + out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]); + else if (exprs[0]->vtype == TYPE_VECTOR) + out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], out); else { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); @@ -992,10 +603,6 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[0]->vtype], type_name[exprs[1]->vtype]); return false; - } - if (CanConstFold(exprs[0], exprs[1])) { - out = (ast_expression*)parser_const_float(parser, - (float)(((qcint_t)ConstF(0)) % ((qcint_t)ConstF(1)))); } else { /* generate a call to __builtin_mod */ ast_expression *mod = intrin_func(parser, "mod"); @@ -1022,14 +629,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[1]->vtype]); return false; } - if (CanConstFold(exprs[0], exprs[1])) - out = (ast_expression*)parser_const_float(parser, - (op->id == opid1('|') ? (float)( ((qcint_t)ConstF(0)) | ((qcint_t)ConstF(1)) ) : - (float)( ((qcint_t)ConstF(0)) & ((qcint_t)ConstF(1)) ) )); - else - out = (ast_expression*)ast_binary_new(ctx, - (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND), - exprs[0], exprs[1]); + out = (ast_expression*)ast_binary_new(ctx, + (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND), + exprs[0], exprs[1]); break; case opid1('^'): /* @@ -1084,35 +686,31 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * since scalar ^ vector is not allowed. */ if (exprs[0]->vtype == TYPE_FLOAT) { - if(CanConstFold(exprs[0], exprs[1])) { - out = (ast_expression*)parser_const_float(parser, (float)((qcint_t)(ConstF(0)) ^ ((qcint_t)(ConstF(1))))); - } else { - ast_binary *expr = ast_binary_new( + ast_binary *expr = ast_binary_new( + ctx, + INSTR_SUB_F, + (ast_expression*)parser->fold->imm_float[2], + (ast_expression*)ast_binary_new( ctx, - INSTR_SUB_F, - (ast_expression*)parser_const_float_neg1(parser), + INSTR_BITAND, + exprs[0], + exprs[1] + ) + ); + expr->refs = AST_REF_NONE; + + out = (ast_expression*) + ast_binary_new( + ctx, + INSTR_BITAND, (ast_expression*)ast_binary_new( ctx, - INSTR_BITAND, + INSTR_BITOR, exprs[0], exprs[1] - ) + ), + (ast_expression*)expr ); - expr->refs = AST_REF_NONE; - - out = (ast_expression*) - ast_binary_new( - ctx, - INSTR_BITAND, - (ast_expression*)ast_binary_new( - ctx, - INSTR_BITOR, - exprs[0], - exprs[1] - ), - (ast_expression*)expr - ); - } } else { /* * The first is a vector: vector is allowed to xor with vector and @@ -1123,33 +721,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * Xor all the values of the vector components against the * vectors components in question. */ - if (CanConstFold(exprs[0], exprs[1])) { - out = (ast_expression*)parser_const_vector_f( - parser, - (float)(((qcint_t)(ConstV(0).x)) ^ ((qcint_t)(ConstV(1).x))), - (float)(((qcint_t)(ConstV(0).y)) ^ ((qcint_t)(ConstV(1).y))), - (float)(((qcint_t)(ConstV(0).z)) ^ ((qcint_t)(ConstV(1).z))) - ); - } else { - compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against vector"); - return false; - } + compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against vector"); + return false; } else { - /* - * Xor all the values of the vector components against the - * scalar in question. - */ - if (CanConstFold(exprs[0], exprs[1])) { - out = (ast_expression*)parser_const_vector_f( - parser, - (float)(((qcint_t)(ConstV(0).x)) ^ ((qcint_t)(ConstF(1)))), - (float)(((qcint_t)(ConstV(0).y)) ^ ((qcint_t)(ConstF(1)))), - (float)(((qcint_t)(ConstV(0).z)) ^ ((qcint_t)(ConstF(1)))) - ); - } else { - compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against float"); - return false; - } + compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against float"); + return false; } } @@ -1157,13 +733,6 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('<','<'): case opid2('>','>'): - if (CanConstFold(exprs[0], exprs[1]) && ! NotSameType(TYPE_FLOAT)) { - if (op->id == opid2('<','<')) - out = (ast_expression*)parser_const_float(parser, (double)((unsigned int)(ConstF(0)) << (unsigned int)(ConstF(1)))); - else - out = (ast_expression*)parser_const_float(parser, (double)((unsigned int)(ConstF(0)) >> (unsigned int)(ConstF(1)))); - break; - } case opid3('<','<','='): case opid3('>','>','='): compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts"); @@ -1173,53 +742,37 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) generated_op += 1; /* INSTR_OR */ case opid2('&','&'): generated_op += INSTR_AND; - if (CanConstFold(exprs[0], exprs[1])) - { - if (OPTS_FLAG(PERL_LOGIC)) { - if (immediate_is_true(ctx, asvalue[0])) - out = exprs[1]; - } - else - out = (ast_expression*)parser_const_float(parser, - ( (generated_op == INSTR_OR) - ? (immediate_is_true(ctx, asvalue[0]) || immediate_is_true(ctx, asvalue[1])) - : (immediate_is_true(ctx, asvalue[0]) && immediate_is_true(ctx, asvalue[1])) ) - ? 1 : 0); + if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) { + ast_type_to_string(exprs[0], ty1, sizeof(ty1)); + ast_type_to_string(exprs[1], ty2, sizeof(ty2)); + compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2); + return false; } - else - { - if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) { - ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - ast_type_to_string(exprs[1], ty2, sizeof(ty2)); - compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2); - return false; - } - for (i = 0; i < 2; ++i) { - if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) { - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]); - if (!out) break; - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); - if (!out) break; - exprs[i] = out; out = NULL; - if (OPTS_FLAG(PERL_LOGIC)) { - /* here we want to keep the right expressions' type */ - break; - } + for (i = 0; i < 2; ++i) { + if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) { + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]); + if (!out) break; + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); + if (!out) break; + exprs[i] = out; out = NULL; + if (OPTS_FLAG(PERL_LOGIC)) { + /* here we want to keep the right expressions' type */ + break; } - else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) { - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]); - if (!out) break; - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); - if (!out) break; - exprs[i] = out; out = NULL; - if (OPTS_FLAG(PERL_LOGIC)) { - /* here we want to keep the right expressions' type */ - break; - } + } + else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) { + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]); + if (!out) break; + out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); + if (!out) break; + exprs[i] = out; out = NULL; + if (OPTS_FLAG(PERL_LOGIC)) { + /* here we want to keep the right expressions' type */ + break; } } - out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]); } + out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]); break; case opid2('?',':'): @@ -1234,10 +787,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2); return false; } - if (CanConstFold1(exprs[0])) - out = (immediate_is_true(ctx, asvalue[0]) ? exprs[1] : exprs[2]); - else - out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]); + out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]); break; case opid2('*', '*'): @@ -1248,10 +798,6 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ty1, ty2); return false; - } - - if (CanConstFold(exprs[0], exprs[1])) { - out = (ast_expression*)parser_const_float(parser, powf(ConstF(0), ConstF(1))); } else { ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser, "pow")); vec_push(gencall->params, exprs[0]); @@ -1268,15 +814,6 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ty1, ty2); return false; - } - - if (CanConstFold(exprs[0], exprs[1])) { - if (ConstF(0) < ConstF(1)) - out = (ast_expression*)parser_const_float_neg1(parser); - else if (ConstF(0) == ConstF(1)) - out = (ast_expression*)parser_const_float_0(parser); - else if (ConstF(0) > ConstF(1)) - out = (ast_expression*)parser_const_float_1(parser); } else { ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]); @@ -1286,15 +823,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)ast_ternary_new(ctx, (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]), /* out = -1 */ - (ast_expression*)parser_const_float_neg1(parser), + (ast_expression*)parser->fold->imm_float[2], /* } else { */ /* if (eq) { */ (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq, /* out = 0 */ - (ast_expression*)parser_const_float_0(parser), + (ast_expression*)parser->fold->imm_float[0], /* } else { */ /* out = 1 */ - (ast_expression*)parser_const_float_1(parser) + (ast_expression*)parser->fold->imm_float[1] /* } */ ) /* } */ @@ -1419,11 +956,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], - (ast_expression*)parser_const_float_1(parser)); + (ast_expression*)parser->fold->imm_float[1]); } else { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, exprs[0], - (ast_expression*)parser_const_float_1(parser)); + (ast_expression*)parser->fold->imm_float[1]); } break; case opid3('S','+','+'): @@ -1447,17 +984,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], - (ast_expression*)parser_const_float_1(parser)); + (ast_expression*)parser->fold->imm_float[1]); } else { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, exprs[0], - (ast_expression*)parser_const_float_1(parser)); + (ast_expression*)parser->fold->imm_float[1]); } if (!out) return false; out = (ast_expression*)ast_binary_new(ctx, subop, out, - (ast_expression*)parser_const_float_1(parser)); + (ast_expression*)parser->fold->imm_float[1]); break; case opid2('+','='): case opid2('-','='): @@ -1525,14 +1062,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF, exprs[0], exprs[1]); } else { - /* there's no DIV_VF */ - if (CanConstFold1(exprs[1])) { - out = (ast_expression*)parser_const_float(parser, 1.0 / ConstF(1)); - } else { - out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, - (ast_expression*)parser_const_float_1(parser), + out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, + (ast_expression*)parser->fold->imm_float[1], exprs[1]); - } if (!out) { compile_error(ctx, "internal error: failed to generate division"); return false; @@ -1601,16 +1133,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1); return false; } - - if(CanConstFold1(exprs[0])) - out = (ast_expression*)parser_const_float(parser, ~(qcint_t)ConstF(0)); - else - out = (ast_expression*) - ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser_const_float_neg1(parser), exprs[0]); + out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]); break; } #undef NotSameType - +complete: if (!out) { compile_error(ctx, "failed to apply operator %s", op->op); return false; @@ -1665,7 +1192,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) ast_type_to_string(vec_last(sy->out).out, ty, sizeof(ty)); ast_unref(vec_last(sy->out).out); sy->out[fid] = syexp(ast_ctx(vec_last(sy->out).out), - (ast_expression*)parser_const_string(parser, ty, false)); + (ast_expression*)fold_constgen_string(parser->fold, ty, false)); vec_shrinkby(sy->out, 1); return true; } @@ -1695,7 +1222,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) if ((fun->flags & AST_FLAG_VARIADIC) && !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin)) { - call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount); + call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount); } } @@ -1926,7 +1453,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) parseerror(parser, "expected a constant string in translatable-string extension"); return false; } - val = parser_const_string(parser, parser_tokval(parser), true); + val = (ast_value*)fold_constgen_string(parser->fold, parser_tokval(parser), true); if (!val) return false; vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val)); @@ -1951,35 +1478,31 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) return true; } else if (parser->tok == TOKEN_FLOATCONST) { - ast_value *val; - val = parser_const_float(parser, (parser_token(parser)->constval.f)); + ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f)); if (!val) return false; - vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val)); + vec_push(sy->out, syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) { - ast_value *val; - val = parser_const_float(parser, (double)(parser_token(parser)->constval.i)); + ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i)); if (!val) return false; - vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val)); + vec_push(sy->out, syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_STRINGCONST) { - ast_value *val; - val = parser_const_string(parser, parser_tokval(parser), false); + ast_expression *val = fold_constgen_string(parser->fold, parser_tokval(parser), false); if (!val) return false; - vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val)); + vec_push(sy->out, syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_VECTORCONST) { - ast_value *val; - val = parser_const_vector(parser, parser_token(parser)->constval.v); + ast_expression *val = fold_constgen_vector(parser->fold, parser_token(parser)->constval.v); if (!val) return false; - vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val)); + vec_push(sy->out, syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_IDENT) @@ -2014,7 +1537,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } } if (!var && !strcmp(parser_tokval(parser), "__FUNC__")) - var = (ast_expression*)parser_const_string(parser, parser->function->name, false); + var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false); if (!var) { /* intrinsics */ if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) { @@ -2314,7 +1837,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma { char *newstr = NULL; util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser)); - vec_last(sy.out).out = (ast_expression*)parser_const_string(parser, newstr, false); + vec_last(sy.out).out = (ast_expression*)fold_constgen_string(parser->fold, newstr, false); mem_d(newstr); concatenated = true; } @@ -4333,7 +3856,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) self_think = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think); time_plus_1 = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, - gbl_time, (ast_expression*)parser_const_float(parser, 0.1)); + gbl_time, (ast_expression*)fold_constgen_float(parser->fold, 0.1)); if (!self_frame || !self_nextthink || !self_think || !time_plus_1) { if (self_frame) ast_delete(self_frame); @@ -4447,9 +3970,8 @@ static bool parse_function_body(parser_t *parser, ast_value *var) ast_block_delete(block); goto enderrfn; } - func->varargs = varargs; - - func->fixedparams = parser_const_float(parser, vec_size(var->expression.params)); + func->varargs = varargs; + func->fixedparams = (ast_value*)fold_constgen_float(parser->fold, vec_size(var->expression.params)); } parser->function = func; @@ -4508,7 +4030,7 @@ static ast_expression *array_accessor_split( cmp = ast_binary_new(ctx, INSTR_LT, (ast_expression*)index, - (ast_expression*)parser_const_float(parser, middle)); + (ast_expression*)fold_constgen_float(parser->fold, middle)); if (!cmp) { ast_delete(left); ast_delete(right); @@ -4541,7 +4063,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STORE_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); if (!subscript) return NULL; @@ -4607,7 +4129,7 @@ static ast_expression *array_field_setter_node( if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STOREP_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); if (!subscript) return NULL; @@ -4670,7 +4192,7 @@ static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast ast_return *ret; ast_array_index *subscript; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); if (!subscript) return NULL; @@ -6305,9 +5827,6 @@ parser_t *parser_create() parser->aliases = util_htnew(PARSER_HT_SIZE); - parser->ht_imm_string = util_htnew(512); - parser->ht_imm_string_dotranslate = util_htnew(512); - /* corrector */ vec_push(parser->correct_variables, correct_trie_new()); vec_push(parser->correct_variables_score, NULL); @@ -6336,6 +5855,7 @@ parser_t *parser_create() parser->reserved_version = NULL; } + parser->fold = fold_init(parser); return parser; } @@ -6405,15 +5925,6 @@ static void parser_remove_ast(parser_t *parser) for (i = 0; i < vec_size(parser->functions); ++i) { ast_delete(parser->functions[i]); } - for (i = 0; i < vec_size(parser->imm_vector); ++i) { - ast_delete(parser->imm_vector[i]); - } - for (i = 0; i < vec_size(parser->imm_string); ++i) { - ast_delete(parser->imm_string[i]); - } - for (i = 0; i < vec_size(parser->imm_float); ++i) { - ast_delete(parser->imm_float[i]); - } for (i = 0; i < vec_size(parser->fields); ++i) { ast_delete(parser->fields[i]); } @@ -6422,11 +5933,6 @@ static void parser_remove_ast(parser_t *parser) } vec_free(parser->accessors); vec_free(parser->functions); - vec_free(parser->imm_vector); - vec_free(parser->imm_string); - util_htdel(parser->ht_imm_string_dotranslate); - util_htdel(parser->ht_imm_string); - vec_free(parser->imm_float); vec_free(parser->globals); vec_free(parser->fields); @@ -6469,6 +5975,7 @@ static void parser_remove_ast(parser_t *parser) util_htdel(parser->aliases); intrin_intrinsics_destroy(parser); + fold_cleanup(parser->fold); } void parser_cleanup(parser_t *parser) @@ -6560,27 +6067,9 @@ bool parser_finish(parser_t *parser, const char *output) } } /* Now we can generate immediates */ - for (i = 0; i < vec_size(parser->imm_float); ++i) { - if (!ast_global_codegen(parser->imm_float[i], ir, false)) { - con_out("failed to generate global %s\n", parser->imm_float[i]->name); - ir_builder_delete(ir); - return false; - } - } - for (i = 0; i < vec_size(parser->imm_string); ++i) { - if (!ast_global_codegen(parser->imm_string[i], ir, false)) { - con_out("failed to generate global %s\n", parser->imm_string[i]->name); - ir_builder_delete(ir); - return false; - } - } - for (i = 0; i < vec_size(parser->imm_vector); ++i) { - if (!ast_global_codegen(parser->imm_vector[i], ir, false)) { - con_out("failed to generate global %s\n", parser->imm_vector[i]->name); - ir_builder_delete(ir); - return false; - } - } + if (!fold_generate(parser->fold, ir)) + return false; + for (i = 0; i < vec_size(parser->globals); ++i) { ast_value *asvalue; if (!ast_istype(parser->globals[i], ast_value))