X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=intrin.h;h=81af620c18a7f8e4966a94e0c8c3dad33ce88340;hb=280dfdd3f807532935217722aa9ac74e8194ef5d;hp=e2e9fb7857c2883cfc630ba48094d63ac21cf920;hpb=d4785ad6e3a27dd166e0fbdab420d22b1156364c;p=xonotic%2Fgmqcc.git diff --git a/intrin.h b/intrin.h index e2e9fb7..81af620 100644 --- a/intrin.h +++ b/intrin.h @@ -36,7 +36,7 @@ typedef struct { const char *alias; } intrin_t; -ht intrin_intrinsics() { +static ht intrin_intrinsics() { static ht intrinsics = NULL; if (!intrinsics) intrinsics = util_htnew(PARSER_HT_SIZE); @@ -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 ( \ @@ -73,12 +69,24 @@ void intrin_intrinsics_destroy() { vec_push(parser->globals, (ast_expression*)(VALUE)); \ } while (0) - -ast_expression *intrin_func (parser_t *parser, const char *name); - #define QC_M_E 2.71828182845905 -ast_expression *intrin_pow(parser_t *parser) { +static ast_expression *intrin_func(parser_t *parser, const char *name); +static 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) { @@ -211,7 +219,12 @@ ast_expression *intrin_pow(parser_t *parser) { return (ast_expression*)value; } -ast_expression *intrin_mod(parser_t *parser) { +static 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) { @@ -261,10 +274,10 @@ ast_expression *intrin_mod(parser_t *parser) { return (ast_expression*)value; } -ast_expression *intrin_exp(parser_t *parser) { +static 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,13 +312,76 @@ ast_expression *intrin_exp(parser_t *parser) { return (ast_expression*)value; } +static 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, "", 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"} }; -ast_expression *intrin_func(parser_t *parser, const char *name) { +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 +} + + +static ast_expression *intrin_func(parser_t *parser, const char *name) { static bool init = false; size_t i = 0; void *find; @@ -321,17 +397,17 @@ ast_expression *intrin_func(parser_t *parser, const char *name) { /* * jesus fucking christ, Blub design something less fucking * impossible to use, like a ast_is_builtin(ast_expression *), also - * use a hashtable :P - */ + * 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) - return find; + return (ast_expression*)find; 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); }