X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=fold.c;h=7b87dc280ad55378cb82a38e6c2cd0acf300dbe4;hp=38190749e39c4db29ef4c0eb13eafa7418f718ad;hb=3df51c597935aa4b60da7a27883779ff584209e3;hpb=655c2482c97a30c3634c22a13f0ea43f946677b5 diff --git a/fold.c b/fold.c index 3819074..7b87dc2 100644 --- a/fold.c +++ b/fold.c @@ -52,6 +52,7 @@ typedef union { } sfloat_cast_t; typedef enum { + SFLOAT_NOEXCEPT = 0, SFLOAT_INVALID = 1, SFLOAT_DIVBYZERO = 4, SFLOAT_OVERFLOW = 8, @@ -123,7 +124,7 @@ typedef struct { (((((A) >> 22) & 0x1FF) == 0x1FE) && ((A) & 0x003FFFFF)) /* Raise exception */ #define SFLOAT_RAISE(STATE, FLAGS) \ - ((STATE)->exceptionflags |= (FLAGS)) + ((STATE)->exceptionflags = (sfloat_exceptionflags_t)((STATE)->exceptionflags | (FLAGS))) /* * Shifts `A' right `COUNT' bits. Non-zero bits are stored in LSB. Size * sets the arbitrarly-large limit. @@ -493,7 +494,7 @@ static GMQCC_INLINE void sfloat_check(lex_ctx_t ctx, sfloat_state_t *state, cons } static GMQCC_INLINE void sfloat_init(sfloat_state_t *state) { - state->exceptionflags = 0; + state->exceptionflags = SFLOAT_NOEXCEPT; state->roundingmode = FOLD_ROUNDING; state->tiny = FOLD_TINYNESS; } @@ -510,6 +511,7 @@ static GMQCC_INLINE void sfloat_init(sfloat_state_t *state) { #define isfloat(X) (((ast_expression*)(X))->vtype == TYPE_FLOAT) #define isvector(X) (((ast_expression*)(X))->vtype == TYPE_VECTOR) #define isstring(X) (((ast_expression*)(X))->vtype == TYPE_STRING) +#define isarray(X) (((ast_expression*)(X))->vtype == TYPE_ARRAY) #define isfloats(X,Y) (isfloat (X) && isfloat (Y)) /* @@ -560,11 +562,11 @@ static GMQCC_INLINE void vec3_soft_eval(vec3_soft_state_t *state, vec3_soft_t sa = vec3_soft_convert(a); vec3_soft_t sb = vec3_soft_convert(b); callback(&state->state[0], sa.x.s, sb.x.s); - if (vec3_soft_exception(state, 0)) state->faults |= VEC_COMP_X; + if (vec3_soft_exception(state, 0)) state->faults = (vec3_comp_t)(state->faults | VEC_COMP_X); callback(&state->state[1], sa.y.s, sb.y.s); - if (vec3_soft_exception(state, 1)) state->faults |= VEC_COMP_Y; + if (vec3_soft_exception(state, 1)) state->faults = (vec3_comp_t)(state->faults | VEC_COMP_Y); callback(&state->state[2], sa.z.s, sb.z.s); - if (vec3_soft_exception(state, 2)) state->faults |= VEC_COMP_Z; + if (vec3_soft_exception(state, 2)) state->faults = (vec3_comp_t)(state->faults | VEC_COMP_Z); } static GMQCC_INLINE void vec3_check_except(vec3_t a, @@ -1336,6 +1338,14 @@ static GMQCC_INLINE ast_expression *fold_op_cross(fold_t *fold, ast_value *a, as return NULL; } +static GMQCC_INLINE ast_expression *fold_op_length(fold_t *fold, ast_value *a) { + if (fold_can_1(a) && isstring(a)) + return fold_constgen_float(fold, strlen(fold_immvalue_string(a)), false); + if (isarray(a)) + return fold_constgen_float(fold, vec_size(a->initlist), false); + return NULL; +} + ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **opexprs) { ast_value *a = (ast_value*)opexprs[0]; ast_value *b = (ast_value*)opexprs[1]; @@ -1373,29 +1383,30 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op return e switch(info->id) { - fold_op_case(2, ('-', 'P'), neg, (fold, a)); - fold_op_case(2, ('!', 'P'), not, (fold, a)); - fold_op_case(1, ('+'), add, (fold, a, b)); - fold_op_case(1, ('-'), sub, (fold, a, b)); - fold_op_case(1, ('*'), mul, (fold, a, b)); - fold_op_case(1, ('/'), div, (fold, a, b)); - fold_op_case(1, ('%'), mod, (fold, a, b)); - fold_op_case(1, ('|'), bor, (fold, a, b)); - fold_op_case(1, ('&'), band, (fold, a, b)); - fold_op_case(1, ('^'), xor, (fold, a, b)); - fold_op_case(1, ('<'), ltgt, (fold, a, b, true)); - fold_op_case(1, ('>'), ltgt, (fold, a, b, false)); - fold_op_case(2, ('<', '<'), lshift, (fold, a, b)); - fold_op_case(2, ('>', '>'), rshift, (fold, a, b)); - fold_op_case(2, ('|', '|'), andor, (fold, a, b, true)); - fold_op_case(2, ('&', '&'), andor, (fold, a, b, false)); - fold_op_case(2, ('?', ':'), tern, (fold, a, b, c)); - fold_op_case(2, ('*', '*'), exp, (fold, a, b)); - fold_op_case(3, ('<','=','>'), lteqgt, (fold, a, b)); - fold_op_case(2, ('!', '='), cmp, (fold, a, b, true)); - fold_op_case(2, ('=', '='), cmp, (fold, a, b, false)); - fold_op_case(2, ('~', 'P'), bnot, (fold, a)); - fold_op_case(2, ('>', '<'), cross, (fold, a, b)); + fold_op_case(2, ('-', 'P'), neg, (fold, a)); + fold_op_case(2, ('!', 'P'), not, (fold, a)); + fold_op_case(1, ('+'), add, (fold, a, b)); + fold_op_case(1, ('-'), sub, (fold, a, b)); + fold_op_case(1, ('*'), mul, (fold, a, b)); + fold_op_case(1, ('/'), div, (fold, a, b)); + fold_op_case(1, ('%'), mod, (fold, a, b)); + fold_op_case(1, ('|'), bor, (fold, a, b)); + fold_op_case(1, ('&'), band, (fold, a, b)); + fold_op_case(1, ('^'), xor, (fold, a, b)); + fold_op_case(1, ('<'), ltgt, (fold, a, b, true)); + fold_op_case(1, ('>'), ltgt, (fold, a, b, false)); + fold_op_case(2, ('<', '<'), lshift, (fold, a, b)); + fold_op_case(2, ('>', '>'), rshift, (fold, a, b)); + fold_op_case(2, ('|', '|'), andor, (fold, a, b, true)); + fold_op_case(2, ('&', '&'), andor, (fold, a, b, false)); + fold_op_case(2, ('?', ':'), tern, (fold, a, b, c)); + fold_op_case(2, ('*', '*'), exp, (fold, a, b)); + fold_op_case(3, ('<','=','>'), lteqgt, (fold, a, b)); + fold_op_case(2, ('!', '='), cmp, (fold, a, b, true)); + fold_op_case(2, ('=', '='), cmp, (fold, a, b, false)); + fold_op_case(2, ('~', 'P'), bnot, (fold, a)); + fold_op_case(2, ('>', '<'), cross, (fold, a, b)); + fold_op_case(3, ('l', 'e', 'n'), length, (fold, a)); } #undef fold_op_case compile_error(fold_ctx(fold), "internal error: attempted to constant-fold for unsupported operator");