+/*
+ * 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)
+ )
+ );
+}
+
+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)
+ )
+ );
+}
+
+static GMQCC_INLINE ast_expression *fold_intrin_exp(fold_t *fold, ast_value *value) {
+ return fold_constgen_float(fold, exp(fold_immvalue_float(value)));
+}
+
+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);
+}
+
+static GMQCC_INLINE ast_expression *fold_intrin_fabs(fold_t *fold, ast_value *value) {
+ return fold_constgen_float(fold, fabs(fold_immvalue_float(value)));
+}
+
+ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **arg) {
+ ast_expression *ret = NULL;
+
+ if (!strcmp(intrin, "mod")) ret = fold_intrin_mod (fold, (ast_value*)arg[0], (ast_value*)arg[1]);
+ if (!strcmp(intrin, "pow")) ret = fold_intrin_pow (fold, (ast_value*)arg[0], (ast_value*)arg[1]);
+ if (!strcmp(intrin, "exp")) ret = fold_intrin_exp (fold, (ast_value*)arg[0]);
+ if (!strcmp(intrin, "isnan")) ret = fold_intrin_isnan(fold, (ast_value*)arg[0]);
+ if (!strcmp(intrin, "fabs")) ret = fold_intrin_fabs (fold, (ast_value*)arg[0]);
+
+ if (ret)
+ ++opts_optimizationcount[OPTIM_CONST_FOLD];
+
+ return ret;
+}
+