]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - intrin.h
Remove trailing whitespace
[xonotic/gmqcc.git] / intrin.h
index 2b797f6d9fc8b3124b726b9451b75945a9608615..4b4c9478afa3cb760b1c7ed216ebe86377a3d22f 100644 (file)
--- a/intrin.h
+++ b/intrin.h
@@ -44,10 +44,6 @@ ht intrin_intrinsics() {
     return intrinsics;
 }
 
-void intrin_intrinsics_destroy() {
-    util_htdel(intrin_intrinsics());
-}
-
 #define INTRIN_VAL(VALUE, NAME, FUNC, STYPE, VTYPE)                   \
     do {                                                              \
         (VALUE) = ast_value_new (                                     \
@@ -79,6 +75,20 @@ ast_expression *intrin_func (parser_t *parser, const char *name);
 #define QC_M_E 2.71828182845905
 
 ast_expression *intrin_pow(parser_t *parser) {
+    /*
+     * float pow(float x, float y) {
+     *   float local = 1.0f;
+     *   while (y > 0) {
+     *     while (!(y & 1)) {
+     *       y >>= 2;
+     *       x *=  x;
+     *     }
+     *     y--;
+     *     local *= x;
+     *   }
+     *   return local;
+     * }
+     */
     static ast_value *value = NULL;
 
     if (!value) {
@@ -212,6 +222,11 @@ ast_expression *intrin_pow(parser_t *parser) {
 }
 
 ast_expression *intrin_mod(parser_t *parser) {
+    /*
+     * float mod(float x, float y) {
+     *   return x - y * floor(x / y);
+     * }
+     */
     static ast_value *value = NULL;
 
     if (!value) {
@@ -263,8 +278,8 @@ ast_expression *intrin_mod(parser_t *parser) {
 
 ast_expression *intrin_exp(parser_t *parser) {
     /*
-     * float __builtin_exp(float x) {
-     *     return __builtin_pow(QC_M_E, x);
+     * float exp(float x) {
+     *     return pow(QC_M_E, x);
      * }
      */
     static ast_value *value = NULL;
@@ -299,12 +314,75 @@ ast_expression *intrin_exp(parser_t *parser) {
     return (ast_expression*)value;
 }
 
+ast_expression *intrin_isnan(parser_t *parser) {
+    /*
+     * float isnan(float x) {
+     *   float local;
+     *   local = x;
+     *
+     *   return (x != local);
+     * }
+     */
+    static ast_value *value = NULL;
+
+    if (!value) {
+        ast_value    *arg1   = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT);
+        ast_value    *local  = ast_value_new (parser_ctx(parser), "local", TYPE_FLOAT);
+        ast_block    *body   = ast_block_new (parser_ctx(parser));
+        ast_function *func   = NULL;
+
+        INTRIN_VAL(value, "isnan", func, "<float>", TYPE_FLOAT);
+
+        vec_push(body->locals, local);
+        vec_push(body->exprs,
+            (ast_expression*)ast_store_new(
+                parser_ctx(parser),
+                INSTR_STORE_F,
+                (ast_expression*)local,
+                (ast_expression*)arg1
+            )
+        );
+
+        vec_push(body->exprs,
+            (ast_expression*)ast_return_new(
+                parser_ctx(parser),
+                (ast_expression*)ast_binary_new(
+                    parser_ctx(parser),
+                    INSTR_NE_F,
+                    (ast_expression*)arg1,
+                    (ast_expression*)local
+                )
+            )
+        );
+
+        vec_push(value->expression.params, arg1);
+
+        vec_push(func->blocks, body);
+
+        INTRIN_REG(func, value);
+    }
+
+    return (ast_expression*)value;
+}
+
 static intrin_t intrinsics[] = {
-    {&intrin_exp, "__builtin_exp", "exp"},
-    {&intrin_mod, "__builtin_mod", "mod"},
-    {&intrin_pow, "__builtin_pow", "pow"}
+    {&intrin_exp,   "__builtin_exp",   "exp"},
+    {&intrin_mod,   "__builtin_mod",   "mod"},
+    {&intrin_pow,   "__builtin_pow",   "pow"},
+    {&intrin_isnan, "__builtin_isnan", "isnan"}
 };
 
+void intrin_intrinsics_destroy(parser_t *parser) {
+    /*size_t i;*/
+    (void)parser;
+    util_htdel(intrin_intrinsics());
+#if 0
+    for (i = 0; i < sizeof(intrinsics)/sizeof(intrin_t); i++)
+        ast_value_delete( (ast_value*) intrinsics[i].intrin(parser));
+#endif
+}
+
+
 ast_expression *intrin_func(parser_t *parser, const char *name) {
     static bool  init = false;
     size_t       i    = 0;
@@ -318,9 +396,11 @@ ast_expression *intrin_func(parser_t *parser, const char *name) {
         init = true; /* only once */
     }
 
-    /* jesus fucking christ all might Blub design something less fucking
-     * impossible to use.
-     */  
+    /*
+     * jesus fucking christ, Blub design something less fucking
+     * impossible to use, like a ast_is_builtin(ast_expression *), also
+     * use a hashtable :P
+     */
     if ((find = (void*)parser_find_global(parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
         for (i = 0; i < vec_size(parser->functions); ++i)
             if (((ast_value*)find)->name && !strcmp(parser->functions[i]->name, ((ast_value*)find)->name) && parser->functions[i]->builtin < 0)
@@ -329,7 +409,7 @@ ast_expression *intrin_func(parser_t *parser, const char *name) {
     if ((find = util_htget(intrin_intrinsics(), name))) {
         /* intrinsic is in table. This will "generate the function" so
          * to speak (if it's not already generated).
-         */  
+         */
         return ((intrin_t*)find)->intrin(parser);
     }