X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=intrin.c;h=9ddb1a2670ad0d2356e2bc795fb796df0e73b969;hp=4df403b82dfdd0bef92f3095ce7c8e21afcdfbe1;hb=ff37abb0c7c60481e1264914fa5e02e9986c5cd9;hpb=2024b3bd7179b3b5a3033c9f485e9fa88e3086dc diff --git a/intrin.c b/intrin.c index 4df403b..9ddb1a2 100644 --- a/intrin.c +++ b/intrin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014, 2015 * Dale Weiler * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -422,7 +422,7 @@ static ast_expression *intrin_atanh(intrin_t *intrin) { (ast_expression*)ast_binary_new( intrin_ctx(intrin), INSTR_MUL_F, - (ast_expression*)fold_constgen_float(intrin->fold, 0.5), + (ast_expression*)fold_constgen_float(intrin->fold, 0.5, false), (ast_expression*)calllog ) ); @@ -496,7 +496,7 @@ static ast_expression *intrin_exp(intrin_t *intrin) { intrin_ctx(intrin), INSTR_LT, (ast_expression*)i, - (ast_expression*)fold_constgen_float(intrin->fold, 200.0f) + (ast_expression*)fold_constgen_float(intrin->fold, 200.0f, false) ), false, NULL, @@ -1027,7 +1027,7 @@ static ast_expression *intrin_pow(intrin_t *intrin) { intrin_ctx(intrin), INSTR_GT, (ast_expression*)callfabs, - (ast_expression*)fold_constgen_float(intrin->fold, QC_POW_EPSILON) + (ast_expression*)fold_constgen_float(intrin->fold, QC_POW_EPSILON, false) ), /* pre not */ false, @@ -1901,31 +1901,95 @@ static ast_expression *intrin_ln(intrin_t *intrin) { return (ast_expression*)value; } -#define LOG_VARIANT(NAME, BASE) \ -static ast_expression *intrin_##NAME(intrin_t *intrin) { \ - ast_value *value = NULL; \ - ast_call *callln = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "__builtin_ln", #NAME)); \ - ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT); \ - ast_block *body = ast_block_new(intrin_ctx(intrin)); \ - ast_function *func = intrin_value(intrin, &value, #NAME, TYPE_FLOAT); \ - vec_push(value->expression.params, arg1); \ - vec_push(callln->params, (ast_expression*)arg1); \ - vec_push(callln->params, (ast_expression*)fold_constgen_float(intrin->fold, BASE)); \ - vec_push(body->exprs, \ - (ast_expression*)ast_return_new( \ - intrin_ctx(intrin), \ - (ast_expression*)callln \ - ) \ - ); \ - vec_push(func->blocks, body); \ - intrin_reg(intrin, value, func); \ - return (ast_expression*)value; \ +static ast_expression *intrin_log_variant(intrin_t *intrin, const char *name, float base) { + ast_value *value = NULL; + ast_call *callln = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "__builtin_ln", name)); + ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT); + ast_block *body = ast_block_new(intrin_ctx(intrin)); + ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT); + + vec_push(value->expression.params, arg1); + + vec_push(callln->params, (ast_expression*)arg1); + vec_push(callln->params, (ast_expression*)fold_constgen_float(intrin->fold, base, false)); + + vec_push(body->exprs, + (ast_expression*)ast_return_new( + intrin_ctx(intrin), + (ast_expression*)callln + ) + ); + + vec_push(func->blocks, body); + intrin_reg(intrin, value, func); + return (ast_expression*)value; +} + +static ast_expression *intrin_log(intrin_t *intrin) { + return intrin_log_variant(intrin, "log", 2.7182818284590452354); +} +static ast_expression *intrin_log10(intrin_t *intrin) { + return intrin_log_variant(intrin, "log10", 10); +} +static ast_expression *intrin_log2(intrin_t *intrin) { + return intrin_log_variant(intrin, "log2", 2); +} +static ast_expression *intrin_logb(intrin_t *intrin) { + /* FLT_RADIX == 2 for now */ + return intrin_log_variant(intrin, "log2", 2); +} + +static ast_expression *intrin_shift_variant(intrin_t *intrin, const char *name, size_t instr) { + /* + * float [shift] (float a, float b) { + * return floor(a [instr] pow(2, b)); + */ + ast_value *value = NULL; + ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name)); + ast_call *callfloor = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", name)); + ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT); + ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT); + ast_block *body = ast_block_new(intrin_ctx(intrin)); + ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT); + + vec_push(value->expression.params, a); + vec_push(value->expression.params, b); + + /* = pow(2, b) */ + vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]); + vec_push(callpow->params, (ast_expression*)b); + + /* = floor(a [instr] ) */ + vec_push( + callfloor->params, + (ast_expression*)ast_binary_new( + intrin_ctx(intrin), + instr, + (ast_expression*)a, + (ast_expression*)callpow + ) + ); + + /* return */ + vec_push(body->exprs, + (ast_expression*)ast_return_new( + intrin_ctx(intrin), + (ast_expression*)callfloor + ) + ); + + vec_push(func->blocks, body); + intrin_reg(intrin, value, func); + return (ast_expression*)value; +} + +static ast_expression *intrin_lshift(intrin_t *intrin) { + return intrin_shift_variant(intrin, "lshift", INSTR_MUL_F); +} + +static ast_expression *intrin_rshift(intrin_t *intrin) { + return intrin_shift_variant(intrin, "rshift", INSTR_DIV_F); } -LOG_VARIANT(log, 2.7182818284590452354) -LOG_VARIANT(log10, 10) -LOG_VARIANT(log2, 2) -LOG_VARIANT(logb, 2) /* FLT_RADIX == 2 for now */ -#undef LOG_VARIANT /* * TODO: make static (and handle ast_type_string) here for the builtin @@ -1955,6 +2019,8 @@ static const intrin_func_t intrinsics[] = { {&intrin_log10, "__builtin_log10", "log10", 1}, {&intrin_log2, "__builtin_log2", "log2", 1}, {&intrin_logb, "__builtin_logb", "logb", 1}, + {&intrin_lshift, "__builtin_lshift", "", 2}, + {&intrin_rshift, "__builtin_rshift", "", 2}, {&intrin_epsilon, "__builtin_epsilon", "", 0}, {&intrin_nan, "__builtin_nan", "", 0}, {&intrin_inf, "__builtin_inf", "", 0},