intrinsic folding cleanups (and improvements.)
authorDale Weiler <killfieldengine@gmail.com>
Fri, 30 Aug 2013 11:12:16 +0000 (07:12 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Fri, 30 Aug 2013 11:12:16 +0000 (07:12 -0400)
fold.c
intrin.c
parser.h

diff --git a/fold.c b/fold.c
index f8a143c..74b9e4f 100644 (file)
--- 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)
-
-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])));
-    }
+/*
+ * 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)
+                )
+            );
+}
 
-    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_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_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_exp(fold_t *fold, ast_value *value) {
+    return fold_constgen_float(fold, exp(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);
-    }
+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_fabs")) {
-        expect(1);
-        ++opts_optimizationcount[OPTIM_CONST_FOLD];
-        return fold_constgen_float(fold, fabs(fold_immvalue_float((ast_value*)params[0])));
-    }
+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) {
+    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;
 }
index 7e7e69e..394d044 100644 (file)
--- 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;
 }
index d4c8ddd..c34d39b 100644 (file)
--- 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 {