X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=fold.c;h=360b4f0f86e0cbd5866f2e6dc6fb5f5a0b8533e3;hp=02335f29c411f635e64fa43894092ba2ca3e5d82;hb=3b4a5667ea8b1b7aa8a10734c57c02d1561fcdd7;hpb=bbe4927a20492e98c1b58d6f10fbe6eddcc72189 diff --git a/fold.c b/fold.c index 02335f2..360b4f0 100644 --- a/fold.c +++ b/fold.c @@ -673,12 +673,74 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op return NULL; } +#define expect(X) \ + do { \ + if (vec_size(params) != (X)) { \ + compile_error( \ + fold_ctx(fold), \ + "internal error: attempted to constant-fold with invalid paramaters for intrinsic `%s`", \ + intrin \ + ); \ + return NULL; \ + } \ + } while (0) + +ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **params) { + if (!fold) return NULL; + if (!intrin) return NULL; + + if (!strcmp(intrin, "__builtin_exp")) { + expect(1); + ++opts_optimizationcount[OPTIM_CONST_FOLD]; + return fold_constgen_float(fold, exp(fold_immvalue_float((ast_value*)params[0]))); + } + + if (!strcmp(intrin, "__builtin_mod")) { + expect(2); + ++opts_optimizationcount[OPTIM_CONST_FOLD]; + return fold_constgen_float( + fold, + fmodf( + fold_immvalue_float((ast_value*)params[0]), + fold_immvalue_float((ast_value*)params[1]) + ) + ); + } + + if (!strcmp(intrin, "__builtin_pow")) { + expect(2); + ++opts_optimizationcount[OPTIM_CONST_FOLD]; + return fold_constgen_float( + fold, + powf( + fold_immvalue_float((ast_value*)params[0]), + fold_immvalue_float((ast_value*)params[1]) + ) + ); + } + + if (!strcmp(intrin, "__builtin_isnan")) { + expect(1); + ++opts_optimizationcount[OPTIM_CONST_FOLD]; + return fold_constgen_float(fold, isnan(fold_immvalue_float((ast_value*)params[0])) != 0.0f); + } + + if (!strcmp(intrin, "__builtin_fabs")) { + expect(1); + ++opts_optimizationcount[OPTIM_CONST_FOLD]; + return fold_constgen_float(fold, fabs(fold_immvalue_float((ast_value*)params[0]))); + } + + return NULL; +} + /* * These are all the actual constant folding methods that happen in between * the AST/IR stage of the compiler , i.e eliminating branches for const * expressions, which is the only supported thing so far. We undefine the * testing macros here because an ir_value is differant than an ast_value. */ +#undef expect #undef isfloat #undef isstring #undef isvector