X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=intrin.c;h=7e7e69e4a204022cfd3bb966f5983515ee5237c4;hb=69efb404bf42f10ff34dba401b9d601cb330df43;hp=30c7424ccae533954b26d966551952a40e5d7dfe;hpb=772dbfae26460d361ba0ee60e3becc377517b099;p=xonotic%2Fgmqcc.git diff --git a/intrin.c b/intrin.c index 30c7424..7e7e69e 100644 --- a/intrin.c +++ b/intrin.c @@ -39,6 +39,7 @@ "__builtin_" NAME, \ TYPE_FUNCTION \ ); \ + (VALUE)->intrinsic = true; \ (VALUE)->expression.next = (ast_expression*)ast_value_new ( \ parser_ctx(intrin->parser), \ STYPE, \ @@ -49,6 +50,7 @@ "__builtin_" NAME, \ (VALUE) \ ); \ + (VALUE)->expression.flags |= AST_FLAG_ERASEABLE; \ } while (0) #define INTRIN_REG(FUNC, VALUE) \ @@ -348,10 +350,56 @@ static ast_expression *intrin_isnan(intrin_t *intrin) { return (ast_expression*)value; } + +static ast_expression *intrin_fabs(intrin_t *intrin) { + /* + * float fabs(float x) { + * return x < 0 ? -x : x; + * } + */ + static ast_value *value = NULL; + if (!value) { + ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT); + ast_block *body = ast_block_new(parser_ctx(intrin->parser)); + ast_function *func = NULL; + + INTRIN_VAL(value, "fabs", func, "", TYPE_FLOAT); + + vec_push(body->exprs, + (ast_expression*)ast_return_new( + parser_ctx(intrin->parser), + (ast_expression*)ast_ternary_new( + parser_ctx(intrin->parser), + (ast_expression*)ast_binary_new( + parser_ctx(intrin->parser), + INSTR_LE, + (ast_expression*)arg1, + (ast_expression*)intrin->fold->imm_float[0] + ), + (ast_expression*)ast_binary_new( + parser_ctx(intrin->parser), + INSTR_SUB_F, + (ast_expression*)intrin->fold->imm_float[0], + (ast_expression*)arg1 + ), + (ast_expression*)arg1 + ) + ) + ); + + vec_push(value->expression.params, arg1); + vec_push(func->blocks, body); + + INTRIN_REG(func, value); + } + + return (ast_expression*)value; +} + #undef INTRIN_REG #undef INTRIN_VAL -/* +/* * TODO: make static (and handle ast_type_string) here for the builtin * instead of in SYA parse close. */ @@ -365,7 +413,8 @@ static const intrin_func_t intrinsics[] = { {&intrin_mod, "__builtin_mod", "mod"}, {&intrin_pow, "__builtin_pow", "pow"}, {&intrin_isnan, "__builtin_isnan", "isnan"}, - {&intrin_debug_typestring, "__builtin_debug_typestring", ""} + {&intrin_fabs, "__builtin_fabs", "fabs"}, + {&intrin_debug_typestring, "__builtin_debug_typestring", ""} }; static void intrin_error(intrin_t *intrin, const char *fmt, ...) { @@ -392,6 +441,19 @@ void intrin_cleanup(intrin_t *intrin) { mem_d(intrin); } +ast_expression *intrin_fold(intrin_t *intrin, ast_value *value, ast_expression **exprs) { + size_t i; + + 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); + + return NULL; +} + ast_expression *intrin_func(intrin_t *intrin, const char *name) { size_t i = 0; void *find;