X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=intrin.c;h=94b420210a2652a0c9c7781f0bada9623108be0f;hb=82afdb1e2cc2b9171ac79ef45b1d3743c590f0ec;hp=50f90bfacdf72f0bfee32c9f3b1211319506feb3;hpb=bbe4927a20492e98c1b58d6f10fbe6eddcc72189;p=xonotic%2Fgmqcc.git diff --git a/intrin.c b/intrin.c index 50f90bf..94b4202 100644 --- a/intrin.c +++ b/intrin.c @@ -32,30 +32,29 @@ * is entered when -fintrin is used (causing all existing builtins to * be ignored by the compiler and instead interface through here. */ -#define INTRIN_VAL(VALUE, NAME, FUNC, STYPE, VTYPE) \ - do { \ - (VALUE) = ast_value_new ( \ - parser_ctx(intrin->parser), \ - "__builtin_" NAME, \ - TYPE_FUNCTION \ - ); \ - (VALUE)->expression.next = (ast_expression*)ast_value_new ( \ - parser_ctx(intrin->parser), \ - STYPE, \ - VTYPE \ - ); \ - (FUNC) = ast_function_new ( \ - parser_ctx(intrin->parser), \ - "__builtin_" NAME, \ - (VALUE) \ - ); \ - } while (0) - -#define INTRIN_REG(FUNC, VALUE) \ - do { \ - vec_push(intrin->parser->functions, (FUNC)); \ - vec_push(intrin->parser->globals, (ast_expression*)(VALUE)); \ - } while (0) +#define intrin_ctx(I) parser_ctx((I)->parser) + +static GMQCC_INLINE ast_function *intrin_value(intrin_t *intrin, ast_value **value, const char *name, qcint_t vtype) { + ast_function *func = NULL; + char buffer[1024]; + char stype [1024]; + + util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name); + util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]); + + *value = ast_value_new(intrin_ctx(intrin), buffer, TYPE_FUNCTION); + (*value)->intrinsic = true; + (*value)->expression.next = (ast_expression*)ast_value_new(intrin_ctx(intrin), stype, vtype); + func = ast_function_new(intrin_ctx(intrin), buffer, *value); + (*value)->expression.flags |= AST_FLAG_ERASEABLE; + + return func; +} + +static GMQCC_INLINE void intrin_reg(intrin_t *intrin, ast_value *const value, ast_function *const func) { + vec_push(intrin->parser->functions, func); + vec_push(intrin->parser->globals, (ast_expression*)value); +} #define QC_M_E 2.71828182845905f @@ -85,9 +84,7 @@ static ast_expression *intrin_pow (intrin_t *intrin) { ast_block *l2b = ast_block_new(parser_ctx(intrin->parser)); /* loop 2 body */ ast_loop *loop1 = NULL; ast_loop *loop2 = NULL; - ast_function *func = NULL; - - INTRIN_VAL(value, "pow", func, "", TYPE_FLOAT); + ast_function *func = intrin_value(intrin, &value, "pow", TYPE_FLOAT); /* arguments */ vec_push(value->expression.params, arg1); @@ -200,7 +197,7 @@ static ast_expression *intrin_pow (intrin_t *intrin) { /* push block and register intrin for codegen */ vec_push(func->blocks, body); - INTRIN_REG(func, value); + intrin_reg(intrin, value, func); } return (ast_expression*)value; @@ -219,9 +216,7 @@ static ast_expression *intrin_mod(intrin_t *intrin) { ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT); ast_value *arg2 = ast_value_new(parser_ctx(intrin->parser), "y", TYPE_FLOAT); ast_block *body = ast_block_new(parser_ctx(intrin->parser)); - ast_function *func = NULL; - - INTRIN_VAL(value, "mod", func, "", TYPE_FLOAT); + ast_function *func = intrin_value(intrin, &value, "mod", TYPE_FLOAT); /* floor(x/y) */ vec_push(call->params, @@ -255,7 +250,7 @@ static ast_expression *intrin_mod(intrin_t *intrin) { vec_push(func->blocks, body); /* {{{ body }}} */ - INTRIN_REG(func, value); + intrin_reg(intrin, value, func); } return (ast_expression*)value; @@ -273,9 +268,7 @@ static ast_expression *intrin_exp(intrin_t *intrin) { ast_call *call = ast_call_new (parser_ctx(intrin->parser), intrin_func(intrin, "pow")); 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, "exp", func, "", TYPE_FLOAT); + ast_function *func = intrin_value(intrin, &value, "exp", TYPE_FLOAT); /* push arguments for params to call */ vec_push(call->params, (ast_expression*)fold_constgen_float(intrin->fold, QC_M_E)); @@ -293,7 +286,7 @@ static ast_expression *intrin_exp(intrin_t *intrin) { vec_push(func->blocks, body); /* {{{ body }}} */ - INTRIN_REG(func, value); + intrin_reg(intrin, value, func); } return (ast_expression*)value; @@ -314,9 +307,7 @@ static ast_expression *intrin_isnan(intrin_t *intrin) { ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT); ast_value *local = ast_value_new(parser_ctx(intrin->parser), "local", TYPE_FLOAT); ast_block *body = ast_block_new(parser_ctx(intrin->parser)); - ast_function *func = NULL; - - INTRIN_VAL(value, "isnan", func, "", TYPE_FLOAT); + ast_function *func = intrin_value(intrin, &value, "isnan", TYPE_FLOAT); vec_push(body->locals, local); vec_push(body->exprs, @@ -343,7 +334,7 @@ static ast_expression *intrin_isnan(intrin_t *intrin) { vec_push(value->expression.params, arg1); vec_push(func->blocks, body); - INTRIN_REG(func, value); + intrin_reg(intrin, value, func); } return (ast_expression*)value; @@ -359,9 +350,7 @@ static ast_expression *intrin_fabs(intrin_t *intrin) { 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); + ast_function *func = intrin_value(intrin, &value, "fabs", TYPE_FLOAT); vec_push(body->exprs, (ast_expression*)ast_return_new( @@ -388,15 +377,12 @@ static ast_expression *intrin_fabs(intrin_t *intrin) { vec_push(value->expression.params, arg1); vec_push(func->blocks, body); - INTRIN_REG(func, value); + intrin_reg(intrin, value, func); } 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. @@ -407,12 +393,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, ...) { @@ -439,6 +425,24 @@ 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)) { + if (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; +} + ast_expression *intrin_func(intrin_t *intrin, const char *name) { size_t i = 0; void *find;