From a50635bcd70c542def692e796e27eed40f18693a Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Fri, 30 Aug 2013 07:12:16 -0400 Subject: [PATCH] intrinsic folding cleanups (and improvements.) --- fold.c | 90 ++++++++++++++++++++++++-------------------------------- intrin.c | 30 +++++++++++++------ parser.h | 1 + 3 files changed, 60 insertions(+), 61 deletions(-) diff --git a/fold.c b/fold.c index f8a143c..74b9e4f 100644 --- a/fold.c +++ b/fold.c @@ -673,63 +673,49 @@ 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) +/* + * Constant folding for compiler intrinsics, simaler approach to operator + * folding, primarly: individual functions for each intrinsics to fold, + * and a generic selection function. + */ +static GMQCC_INLINE ast_expression *fold_intrin_mod(fold_t *fold, ast_value *lhs, ast_value *rhs) { + return fold_constgen_float( + fold, + fmodf( + fold_immvalue_float(lhs), + fold_immvalue_float(rhs) + ) + ); +} -ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **params) { - if (!fold) return NULL; - if (!intrin) return NULL; +static GMQCC_INLINE ast_expression *fold_intrin_pow(fold_t *fold, ast_value *lhs, ast_value *rhs) { + return fold_constgen_float( + fold, + powf( + fold_immvalue_float(lhs), + fold_immvalue_float(rhs) + ) + ); +} - 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]))); - } +static GMQCC_INLINE ast_expression *fold_intrin_exp(fold_t *fold, ast_value *value) { + return fold_constgen_float(fold, exp(fold_immvalue_float(value))); +} - 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]) - ) - ); - } +static GMQCC_INLINE ast_expression *fold_intrin_isnan(fold_t *fold, ast_value *value) { + return fold_constgen_float(fold, isnan(fold_immvalue_float(value)) != 0.0f); +} - 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]) - ) - ); - } +static GMQCC_INLINE ast_expression *fold_intrin_fabs(fold_t *fold, ast_value *value) { + return fold_constgen_float(fold, fabs(fold_immvalue_float(value))); +} - 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]))); - } +ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **arg) { + if (!strcmp(intrin, "mod")) return fold_intrin_mod (fold, (ast_value*)arg[0], (ast_value*)arg[1]); + if (!strcmp(intrin, "pow")) return fold_intrin_pow (fold, (ast_value*)arg[0], (ast_value*)arg[1]); + if (!strcmp(intrin, "exp")) return fold_intrin_exp (fold, (ast_value*)arg[0]); + if (!strcmp(intrin, "isnan")) return fold_intrin_isnan(fold, (ast_value*)arg[0]); + if (!strcmp(intrin, "fabs")) return fold_intrin_fabs (fold, (ast_value*)arg[0]); return NULL; } diff --git a/intrin.c b/intrin.c index 7e7e69e..394d044 100644 --- a/intrin.c +++ b/intrin.c @@ -409,12 +409,12 @@ ast_expression *intrin_debug_typestring(intrin_t *intrin) { } static const intrin_func_t intrinsics[] = { - {&intrin_exp, "__builtin_exp", "exp"}, - {&intrin_mod, "__builtin_mod", "mod"}, - {&intrin_pow, "__builtin_pow", "pow"}, - {&intrin_isnan, "__builtin_isnan", "isnan"}, - {&intrin_fabs, "__builtin_fabs", "fabs"}, - {&intrin_debug_typestring, "__builtin_debug_typestring", ""} + {&intrin_exp, "__builtin_exp", "exp", 1}, + {&intrin_mod, "__builtin_mod", "mod", 2}, + {&intrin_pow, "__builtin_pow", "pow", 2}, + {&intrin_isnan, "__builtin_isnan", "isnan", 1}, + {&intrin_fabs, "__builtin_fabs", "fabs", 1}, + {&intrin_debug_typestring, "__builtin_debug_typestring", "", 0} }; static void intrin_error(intrin_t *intrin, const char *fmt, ...) { @@ -447,9 +447,21 @@ ast_expression *intrin_fold(intrin_t *intrin, ast_value *value, ast_expression * if (!value || !value->name) return NULL; - for (i = 0; i < vec_size(intrin->intrinsics); i++) - if (!strcmp(value->name, intrin->intrinsics[i].name)) - return fold_intrin(intrin->fold, value->name, exprs); + for (i = 0; i < vec_size(intrin->intrinsics); i++) { + if (!strcmp(value->name, intrin->intrinsics[i].name)) { + if (intrin->intrinsics[i].args != vec_size(exprs)) { + intrin_error( + intrin, + "internal error: attempted to constant-fold with invalid paramaters for intrinsic `%s`\n" + " ==> expected %u arguments, got %u instead", + value->name, intrin->intrinsics[i].args, vec_size(exprs) + ); + return NULL; + } + /* +10 to skip the "__builtin_" substring in the string */ + return fold_intrin(intrin->fold, value->name + 10, exprs); + } + } return NULL; } diff --git a/parser.h b/parser.h index d4c8ddd..c34d39b 100644 --- a/parser.h +++ b/parser.h @@ -43,6 +43,7 @@ typedef struct { ast_expression *(*intrin)(intrin_t *); const char *name; const char *alias; + size_t args; } intrin_func_t; struct intrin_s {