7 lex_ctx_t intrin::ctx() const {
8 return parser_ctx(m_parser);
11 ast_function *intrin::value(ast_value **out, const char *name, qc_type vtype) {
12 ast_value *value = nullptr;
13 ast_function *func = nullptr;
17 util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
18 util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]);
20 value = new ast_value(ctx(), buffer, TYPE_FUNCTION);
21 value->m_intrinsic = true;
22 value->m_next = new ast_value(ctx(), stype, vtype);
23 func = ast_function::make(ctx(), buffer, value);
24 value->m_flags |= AST_FLAG_ERASEABLE;
30 void intrin::reg(ast_value *const value, ast_function *const func) {
31 m_parser->functions.push_back(func);
32 m_parser->globals.push_back(value);
35 ast_expression *intrin::nullfunc() {
36 ast_value *val = nullptr;
37 ast_function *func = value(&val, nullptr, TYPE_VOID);
42 ast_expression *intrin::isfinite_() {
44 * float isfinite(float x) {
45 * return !(isnan(x) || isinf(x));
48 ast_value *val = nullptr;
49 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
50 ast_function *func = value(&val, "isfinite", TYPE_FLOAT);
51 ast_call *callisnan = ast_call::make(ctx(), func_self("isnan", "isfinite"));
52 ast_call *callisinf = ast_call::make(ctx(), func_self("isinf", "isfinite"));
53 ast_block *block = new ast_block(ctx());
56 val->m_type_params.emplace_back(x);
58 /* <callisnan> = isnan(x); */
59 callisnan->m_params.push_back(x);
61 /* <callisinf> = isinf(x); */
62 callisinf->m_params.push_back(x);
64 /* return (!<callisnan> || <callisinf>); */
65 block->m_exprs.push_back(
81 func->m_blocks.emplace_back(block);
87 ast_expression *intrin::isinf_() {
89 * float isinf(float x) {
90 * return (x != 0.0) && (x + x == x);
93 ast_value *val = nullptr;
94 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
95 ast_block *body = new ast_block(ctx());
96 ast_function *func = value(&val, "isinf", TYPE_FLOAT);
98 body->m_exprs.push_back(
108 m_fold->m_imm_float[0]
125 val->m_type_params.emplace_back(x);
126 func->m_blocks.emplace_back(body);
133 ast_expression *intrin::isnan_() {
135 * float isnan(float x) {
139 * return (x != local);
142 ast_value *val = nullptr;
143 ast_value *arg1 = new ast_value(ctx(), "x",TYPE_FLOAT);
144 ast_value *local = new ast_value(ctx(), "local", TYPE_FLOAT);
145 ast_block *body = new ast_block(ctx());
146 ast_function *func = value(&val, "isnan", TYPE_FLOAT);
148 body->m_locals.push_back(local);
149 body->m_exprs.push_back(
158 body->m_exprs.push_back(
170 val->m_type_params.emplace_back(arg1);
171 func->m_blocks.emplace_back(body);
178 ast_expression *intrin::isnormal_() {
180 * float isnormal(float x) {
181 * return isfinite(x);
184 ast_value *val = nullptr;
185 ast_call *callisfinite = ast_call::make(ctx(), func_self("isfinite", "isnormal"));
186 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
187 ast_block *body = new ast_block(ctx());
188 ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
190 val->m_type_params.emplace_back(x);
191 callisfinite->m_params.push_back(x);
193 /* return <callisfinite> */
194 body->m_exprs.push_back(
201 func->m_blocks.emplace_back(body);
206 ast_expression *intrin::signbit_() {
208 * float signbit(float x) {
212 ast_value *val = nullptr;
213 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
214 ast_block *body = new ast_block(ctx());
215 ast_function *func = value(&val, "signbit", TYPE_FLOAT);
217 val->m_type_params.emplace_back(x);
219 /* return (x < 0); */
220 body->m_exprs.push_back(
229 m_fold->m_imm_float[0]
231 m_fold->m_imm_float[1],
232 m_fold->m_imm_float[0]
237 func->m_blocks.emplace_back(body);
242 ast_expression *intrin::acosh_() {
244 * float acosh(float x) {
245 * return log(x + sqrt((x * x) - 1));
248 ast_value *val = nullptr;
249 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
250 ast_call *calllog = ast_call::make(ctx(), func_self("log", "acosh"));
251 ast_call *callsqrt = ast_call::make(ctx(), func_self("sqrt", "acosh"));
252 ast_block *body = new ast_block(ctx());
253 ast_function *func = value(&val, "acosh", TYPE_FLOAT);
255 val->m_type_params.emplace_back(x);
257 /* <callsqrt> = sqrt((x * x) - 1); */
258 callsqrt->m_params.push_back(
268 m_fold->m_imm_float[1]
272 /* <calllog> = log(x + <callsqrt>); */
273 calllog->m_params.push_back(
282 /* return <calllog>; */
283 body->m_exprs.push_back(
290 func->m_blocks.emplace_back(body);
295 ast_expression *intrin::asinh_() {
297 * float asinh(float x) {
298 * return log(x + sqrt((x * x) + 1));
301 ast_value *val = nullptr;
302 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
303 ast_call *calllog = ast_call::make(ctx(), func_self("log", "asinh"));
304 ast_call *callsqrt = ast_call::make(ctx(), func_self("sqrt", "asinh"));
305 ast_block *body = new ast_block(ctx());
306 ast_function *func = value(&val, "asinh", TYPE_FLOAT);
308 val->m_type_params.emplace_back(x);
310 /* <callsqrt> = sqrt((x * x) + 1); */
311 callsqrt->m_params.push_back(
321 m_fold->m_imm_float[1]
325 /* <calllog> = log(x + <callsqrt>); */
326 calllog->m_params.push_back(
335 /* return <calllog>; */
336 body->m_exprs.push_back(
343 func->m_blocks.emplace_back(body);
348 ast_expression *intrin::atanh_() {
350 * float atanh(float x) {
351 * return 0.5 * log((1 + x) / (1 - x))
354 ast_value *val = nullptr;
355 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
356 ast_call *calllog = ast_call::make(ctx(), func_self("log", "atanh"));
357 ast_block *body = new ast_block(ctx());
358 ast_function *func = value(&val, "atanh", TYPE_FLOAT);
360 val->m_type_params.emplace_back(x);
362 /* <callog> = log((1 + x) / (1 - x)); */
363 calllog->m_params.push_back(
370 m_fold->m_imm_float[1],
376 m_fold->m_imm_float[1],
382 /* return 0.5 * <calllog>; */
383 body->m_exprs.push_back(
387 m_fold->constgen_float(0.5, false),
392 func->m_blocks.emplace_back(body);
397 ast_expression *intrin::exp_() {
399 * float exp(float x) {
403 * for (i = 1; i < 200; ++i)
404 * sum += (acc *= x / i);
409 ast_value *val = nullptr;
410 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
411 ast_value *sum = new ast_value(ctx(), "sum", TYPE_FLOAT);
412 ast_value *acc = new ast_value(ctx(), "acc", TYPE_FLOAT);
413 ast_value *i = new ast_value(ctx(), "i", TYPE_FLOAT);
414 ast_block *body = new ast_block(ctx());
415 ast_function *func = value(&val, "exp", TYPE_FLOAT);
417 val->m_type_params.emplace_back(x);
419 body->m_locals.push_back(sum);
420 body->m_locals.push_back(acc);
421 body->m_locals.push_back(i);
424 body->m_exprs.push_back(
429 m_fold->m_imm_float[1]
434 body->m_exprs.push_back(
439 m_fold->m_imm_float[1]
444 * for (i = 1; i < 200; ++i)
445 * sum += (acc *= x / i);
447 body->m_exprs.push_back(
455 m_fold->m_imm_float[1]
462 m_fold->constgen_float(200.0f, false)
473 m_fold->m_imm_float[1]
475 /* sum += (acc *= (x / i)) */
498 body->m_exprs.push_back(
505 func->m_blocks.emplace_back(body);
510 ast_expression *intrin::exp2_() {
512 * float exp2(float x) {
516 ast_value *val = nullptr;
517 ast_call *callpow = ast_call::make(ctx(), func_self("pow", "exp2"));
518 ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT);
519 ast_block *body = new ast_block(ctx());
520 ast_function *func = value(&val, "exp2", TYPE_FLOAT);
522 val->m_type_params.emplace_back(arg1);
524 callpow->m_params.push_back(m_fold->m_imm_float[3]);
525 callpow->m_params.push_back(arg1);
527 /* return <callpow> */
528 body->m_exprs.push_back(
535 func->m_blocks.emplace_back(body);
540 ast_expression *intrin::expm1_() {
542 * float expm1(float x) {
546 ast_value *val = nullptr;
547 ast_call *callexp = ast_call::make(ctx(), func_self("exp", "expm1"));
548 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
549 ast_block *body = new ast_block(ctx());
550 ast_function *func = value(&val, "expm1", TYPE_FLOAT);
552 val->m_type_params.emplace_back(x);
554 /* <callexp> = exp(x); */
555 callexp->m_params.push_back(x);
557 /* return <callexp> - 1; */
558 body->m_exprs.push_back(
565 m_fold->m_imm_float[1]
570 func->m_blocks.emplace_back(body);
575 ast_expression *intrin::pow_() {
576 #define QC_POW_EPSILON 0.00001f
580 * float pow(float base, float exp) {
593 * return 1.0 / pow(base, -exp);
595 * result = pow(base, exp / 2);
596 * return result * result;
601 * square = sqrt(base);
602 * accumulate = square;
605 * while (fabs(mid - exp) > QC_POW_EPSILON) {
606 * square = sqrt(square);
609 * accumulate *= square;
612 * accumulate *= (1.0f / square);
614 * mid = (low + high) / 2;
619 ast_value *val = nullptr;
620 ast_function *func = value(&val, "pow", TYPE_FLOAT);
622 /* prepare some calls for later */
623 ast_call *callpow1 = ast_call::make(ctx(), val); /* for pow(base, -exp) */
624 ast_call *callpow2 = ast_call::make(ctx(), val); /* for pow(vase, exp / 2) */
625 ast_call *callsqrt1 = ast_call::make(ctx(), func_self("sqrt", "pow")); /* for sqrt(base) */
626 ast_call *callsqrt2 = ast_call::make(ctx(), func_self("sqrt", "pow")); /* for sqrt(square) */
627 ast_call *callfabs = ast_call::make(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp) */
629 /* prepare some blocks for later */
630 ast_block *expgt1 = new ast_block(ctx());
631 ast_block *midltexp = new ast_block(ctx());
632 ast_block *midltexpelse = new ast_block(ctx());
633 ast_block *whileblock = new ast_block(ctx());
635 /* float pow(float base, float exp) */
636 ast_value *base = new ast_value(ctx(), "base", TYPE_FLOAT);
637 ast_value *exp = new ast_value(ctx(), "exp", TYPE_FLOAT);
639 ast_block *body = new ast_block(ctx());
649 ast_value *result = new ast_value(ctx(), "result", TYPE_FLOAT);
650 ast_value *low = new ast_value(ctx(), "low", TYPE_FLOAT);
651 ast_value *high = new ast_value(ctx(), "high", TYPE_FLOAT);
652 ast_value *square = new ast_value(ctx(), "square", TYPE_FLOAT);
653 ast_value *accumulate = new ast_value(ctx(), "accumulate", TYPE_FLOAT);
654 ast_value *mid = new ast_value(ctx(), "mid", TYPE_FLOAT);
655 body->m_locals.push_back(result);
656 body->m_locals.push_back(low);
657 body->m_locals.push_back(high);
658 body->m_locals.push_back(square);
659 body->m_locals.push_back(accumulate);
660 body->m_locals.push_back(mid);
662 val->m_type_params.emplace_back(base);
663 val->m_type_params.emplace_back(exp);
669 body->m_exprs.push_back(
676 m_fold->m_imm_float[0]
680 m_fold->m_imm_float[1]
690 body->m_exprs.push_back(
697 m_fold->m_imm_float[1]
707 /* <callpow1> = pow(base, -exp) */
708 callpow1->m_params.push_back(base);
709 callpow1->m_params.push_back(
719 * return 1.0 / <callpow1>;
721 body->m_exprs.push_back(
728 m_fold->m_imm_float[0]
735 m_fold->m_imm_float[1],
743 /* <callpow2> = pow(base, exp / 2) */
744 callpow2->m_params.push_back(base);
745 callpow2->m_params.push_back(
750 m_fold->m_imm_float[3] /* 2.0f */
756 * result = <callpow2>;
757 * return result * result;
760 expgt1->m_exprs.push_back(
768 expgt1->m_exprs.push_back(
785 body->m_exprs.push_back(
792 m_fold->m_imm_float[1]
800 * <callsqrt1> = sqrt(base)
802 callsqrt1->m_params.push_back(base);
807 * square = sqrt(base);
808 * accumulate = square;
811 body->m_exprs.push_back(
815 m_fold->m_imm_float[0]
818 body->m_exprs.push_back(
823 m_fold->m_imm_float[1]
827 body->m_exprs.push_back(
836 body->m_exprs.push_back(
844 body->m_exprs.push_back(
853 m_fold->m_imm_float[3] /* 2.0f */
861 * accumulate *= square;
864 midltexp->m_exprs.push_back(
872 midltexp->m_exprs.push_back(
885 * accumulate *= (1.0 / square);
888 midltexpelse->m_exprs.push_back(
896 midltexpelse->m_exprs.push_back(
905 m_fold->m_imm_float[1],
912 * <callsqrt2> = sqrt(square)
914 callsqrt2->m_params.push_back(square);
918 * square = <callsqrt2>;
924 * mid = (low + high) / 2;
927 whileblock->m_exprs.push_back(
935 whileblock->m_exprs.push_back(
948 whileblock->m_exprs.push_back(
962 m_fold->m_imm_float[3] /* 2.0f */
968 * <callabs> = fabs(mid - exp)
970 callfabs->m_params.push_back(
980 * while (<callfabs> > epsilon)
983 body->m_exprs.push_back(
993 m_fold->constgen_float(QC_POW_EPSILON, false)
1001 /* increment expression */
1008 /* return accumulate */
1009 body->m_exprs.push_back(
1017 func->m_blocks.emplace_back(body);
1022 ast_expression *intrin::mod_() {
1024 * float mod(float a, float b) {
1025 * float div = a / b;
1026 * float sign = (div < 0.0f) ? -1 : 1;
1027 * return a - b * sign * floor(sign * div);
1030 ast_value *val = nullptr;
1031 ast_call *call = ast_call::make(ctx(), func_self("floor", "mod"));
1032 ast_value *a = new ast_value(ctx(), "a", TYPE_FLOAT);
1033 ast_value *b = new ast_value(ctx(), "b", TYPE_FLOAT);
1034 ast_value *div = new ast_value(ctx(), "div", TYPE_FLOAT);
1035 ast_value *sign = new ast_value(ctx(), "sign", TYPE_FLOAT);
1036 ast_block *body = new ast_block(ctx());
1037 ast_function *func = value(&val, "mod", TYPE_FLOAT);
1039 val->m_type_params.emplace_back(a);
1040 val->m_type_params.emplace_back(b);
1042 body->m_locals.push_back(div);
1043 body->m_locals.push_back(sign);
1046 body->m_exprs.push_back(
1060 /* sign = (div < 0.0f) ? -1 : 1; */
1061 body->m_exprs.push_back(
1072 m_fold->m_imm_float[0]
1074 m_fold->m_imm_float[2],
1075 m_fold->m_imm_float[1]
1080 /* floor(sign * div) */
1081 call->m_params.push_back(
1090 /* return a - b * sign * <call> */
1091 body->m_exprs.push_back(
1113 func->m_blocks.emplace_back(body);
1118 ast_expression *intrin::fabs_() {
1120 * float fabs(float x) {
1121 * return x < 0 ? -x : x;
1124 ast_value *val = nullptr;
1125 ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT);
1126 ast_block *body = new ast_block(ctx());
1127 ast_function *func = value(&val, "fabs", TYPE_FLOAT);
1129 body->m_exprs.push_back(
1138 m_fold->m_imm_float[0]
1150 val->m_type_params.emplace_back(arg1);
1152 func->m_blocks.emplace_back(body);
1157 ast_expression *intrin::epsilon_() {
1159 * float epsilon(void) {
1161 * do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1165 ast_value *val = nullptr;
1166 ast_value *eps = new ast_value(ctx(), "eps", TYPE_FLOAT);
1167 ast_block *body = new ast_block(ctx());
1168 ast_function *func = value(&val, "epsilon", TYPE_FLOAT);
1170 body->m_locals.push_back(eps);
1173 body->m_exprs.push_back(
1178 m_fold->m_imm_float[0]
1182 body->m_exprs.push_back(
1194 m_fold->m_imm_float[1],
1199 m_fold->m_imm_float[3] /* 2.0f */
1202 m_fold->m_imm_float[1]
1211 m_fold->m_imm_float[3] /* 2.0f */
1217 body->m_exprs.push_back(
1224 func->m_blocks.emplace_back(body);
1229 ast_expression *intrin::nan_() {
1236 ast_value *val = nullptr;
1237 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
1238 ast_function *func = value(&val, "nan", TYPE_FLOAT);
1239 ast_block *block = new ast_block(ctx());
1241 block->m_locals.push_back(x);
1243 block->m_exprs.push_back(
1248 m_fold->m_imm_float[0]
1252 block->m_exprs.push_back(
1264 func->m_blocks.emplace_back(block);
1269 ast_expression *intrin::inf_() {
1277 ast_value *val = nullptr;
1278 ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT);
1279 ast_value *y = new ast_value(ctx(), "y", TYPE_FLOAT);
1280 ast_function *func = value(&val, "inf", TYPE_FLOAT);
1281 ast_block *block = new ast_block(ctx());
1284 block->m_locals.push_back(x);
1285 block->m_locals.push_back(y);
1287 /* to keep code size down */
1288 for (i = 0; i <= 1; i++) {
1289 block->m_exprs.push_back(
1294 m_fold->m_imm_float[i]
1299 block->m_exprs.push_back(
1311 func->m_blocks.emplace_back(block);
1316 ast_expression *intrin::ln_() {
1318 * float log(float power, float base) {
1321 * float sign = 1.0f;
1322 * float eps = epsilon();
1324 * if (power <= 1.0f || bbase <= 1.0) {
1325 * if (power <= 0.0f || base <= 0.0f)
1328 * if (power < 1.0f) {
1329 * power = 1.0f / power;
1333 * if (base < 1.0f) {
1335 * base = 1.0f / base;
1341 * float A_iminus1 = 0;
1342 * float B_iminus1 = 1;
1348 * while (whole >= base) {
1349 * float base2 = base;
1351 * float newbase2 = base2 * base2;
1353 * while (whole >= newbase2) {
1356 * newbase2 *= newbase2;
1363 * float b_iplus1 = n;
1364 * float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1365 * float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1372 * if (whole <= 1.0f + eps)
1378 * return sign * A_i / B_i;
1382 ast_value *val = nullptr;
1383 ast_value *power = new ast_value(ctx(), "power", TYPE_FLOAT);
1384 ast_value *base = new ast_value(ctx(), "base",TYPE_FLOAT);
1385 ast_value *whole= new ast_value(ctx(), "whole", TYPE_FLOAT);
1386 ast_value *nth = new ast_value(ctx(), "nth", TYPE_FLOAT);
1387 ast_value *sign = new ast_value(ctx(), "sign", TYPE_FLOAT);
1388 ast_value *A_i = new ast_value(ctx(), "A_i", TYPE_FLOAT);
1389 ast_value *B_i = new ast_value(ctx(), "B_i", TYPE_FLOAT);
1390 ast_value *A_iminus1 = new ast_value(ctx(), "A_iminus1", TYPE_FLOAT);
1391 ast_value *B_iminus1 = new ast_value(ctx(), "B_iminus1", TYPE_FLOAT);
1392 ast_value *b_iplus1 = new ast_value(ctx(), "b_iplus1", TYPE_FLOAT);
1393 ast_value *A_iplus1 = new ast_value(ctx(), "A_iplus1", TYPE_FLOAT);
1394 ast_value *B_iplus1 = new ast_value(ctx(), "B_iplus1", TYPE_FLOAT);
1395 ast_value *eps = new ast_value(ctx(), "eps", TYPE_FLOAT);
1396 ast_value *base2 = new ast_value(ctx(), "base2", TYPE_FLOAT);
1397 ast_value *n2 = new ast_value(ctx(), "n2",TYPE_FLOAT);
1398 ast_value *newbase2 = new ast_value(ctx(), "newbase2", TYPE_FLOAT);
1399 ast_block *block = new ast_block(ctx());
1400 ast_block *plt1orblt1 = new ast_block(ctx()); // (power <= 1.0f || base <= 1.0f)
1401 ast_block *plt1 = new ast_block(ctx()); // (power < 1.0f)
1402 ast_block *blt1 = new ast_block(ctx()); // (base< 1.0f)
1403 ast_block *forloop = new ast_block(ctx()); // for(;;)
1404 ast_block *whileloop = new ast_block(ctx()); // while (whole >= base)
1405 ast_block *nestwhile= new ast_block(ctx()); // while (whole >= newbase2)
1406 ast_function *func = value(&val, "ln", TYPE_FLOAT);
1409 val->m_type_params.emplace_back(power);
1410 val->m_type_params.emplace_back(base);
1412 block->m_locals.push_back(whole);
1413 block->m_locals.push_back(nth);
1414 block->m_locals.push_back(sign);
1415 block->m_locals.push_back(eps);
1416 block->m_locals.push_back(A_i);
1417 block->m_locals.push_back(B_i);
1418 block->m_locals.push_back(A_iminus1);
1419 block->m_locals.push_back(B_iminus1);
1422 block->m_exprs.push_back(
1427 m_fold->m_imm_float[1]
1431 /* eps = __builtin_epsilon(); */
1432 block->m_exprs.push_back(
1439 func_self("__builtin_epsilon", "ln")
1450 for (i = 0; i <= 1; i++) {
1452 for (j = 1; j >= 0; j--) {
1453 block->m_exprs.push_back(
1457 ((j) ? ((i) ? B_iminus1 : A_i)
1458 : ((i) ? A_iminus1 : B_i)),
1459 m_fold->m_imm_float[j]
1467 * power = 1.0f / power;
1471 * base = 1.0f / base;
1475 for (i = 0; i <= 1; i++) {
1476 ((i) ? blt1 : plt1)->m_exprs.push_back(
1480 ((i) ? base : power),
1484 m_fold->m_imm_float[1],
1485 ((i) ? base : power)
1489 plt1->m_exprs.push_back(
1495 m_fold->m_imm_float[2]
1502 * if (power <= 0.0 || base <= 0.0f)
1503 * return __builtin_nan();
1510 plt1orblt1->m_exprs.push_back(
1520 m_fold->m_imm_float[0]
1526 m_fold->m_imm_float[0]
1533 func_self("__builtin_nan", "ln")
1540 for (i = 0; i <= 1; i++) {
1541 plt1orblt1->m_exprs.push_back(
1547 ((i) ? base : power),
1548 m_fold->m_imm_float[1]
1550 ((i) ? blt1 : plt1),
1556 block->m_exprs.push_back(plt1orblt1);
1559 /* whole = power; */
1560 forloop->m_exprs.push_back(
1570 forloop->m_exprs.push_back(
1575 m_fold->m_imm_float[0]
1580 whileloop->m_exprs.push_back(
1590 whileloop->m_exprs.push_back(
1595 m_fold->m_imm_float[1]
1599 /* newbase2 = base2 * base2; */
1600 whileloop->m_exprs.push_back(
1614 /* while loop locals */
1615 whileloop->m_locals.push_back(base2);
1616 whileloop->m_locals.push_back(n2);
1617 whileloop->m_locals.push_back(newbase2);
1619 /* base2 = newbase2; */
1620 nestwhile->m_exprs.push_back(
1630 nestwhile->m_exprs.push_back(
1636 m_fold->m_imm_float[3] /* 2.0f */
1640 /* newbase2 *= newbase2; */
1641 nestwhile->m_exprs.push_back(
1651 /* while (whole >= newbase2) */
1652 whileloop->m_exprs.push_back(
1670 /* whole /= base2; */
1671 whileloop->m_exprs.push_back(
1682 whileloop->m_exprs.push_back(
1692 /* while (whole >= base) */
1693 forloop->m_exprs.push_back(
1711 forloop->m_locals.push_back(b_iplus1);
1712 forloop->m_locals.push_back(A_iplus1);
1713 forloop->m_locals.push_back(B_iplus1);
1715 /* b_iplus1 = nth; */
1716 forloop->m_exprs.push_back(
1726 * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1727 * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1729 for (i = 0; i <= 1; i++) {
1730 forloop->m_exprs.push_back(
1734 ((i) ? B_iplus1 : A_iplus1),
1744 ((i) ? B_iminus1 : A_iminus1)
1754 for (i = 0; i <= 1; i++) {
1755 forloop->m_exprs.push_back(
1759 ((i) ? B_iminus1 : A_iminus1),
1769 for (i = 0; i <= 1; i++) {
1770 forloop->m_exprs.push_back(
1775 ((i) ? B_iplus1 : A_iplus1)
1781 * if (whole <= 1.0f + eps)
1784 forloop->m_exprs.push_back(
1794 m_fold->m_imm_float[1],
1811 for (i = 0; i <= 1; i++) {
1812 forloop->m_exprs.push_back(
1816 ((i) ? base : power),
1817 ((i) ? whole : base)
1822 /* add the for loop block */
1823 block->m_exprs.push_back(
1827 /* for(; 1; ) ?? (can this be nullptr too?) */
1828 m_fold->m_imm_float[1],
1837 /* return sign * A_i / B_il */
1838 block->m_exprs.push_back(
1855 func->m_blocks.emplace_back(block);
1860 ast_expression *intrin::log_variant(const char *name, float base) {
1861 ast_value *val = nullptr;
1862 ast_call *callln = ast_call::make(ctx(), func_self("__builtin_ln", name));
1863 ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT);
1864 ast_block *body = new ast_block(ctx());
1865 ast_function *func = value(&val, name, TYPE_FLOAT);
1867 val->m_type_params.emplace_back(arg1);
1869 callln->m_params.push_back(arg1);
1870 callln->m_params.push_back(m_fold->constgen_float(base, false));
1872 body->m_exprs.push_back(
1879 func->m_blocks.emplace_back(body);
1884 ast_expression *intrin::log_() {
1885 return log_variant("log", 2.7182818284590452354);
1887 ast_expression *intrin::log10_() {
1888 return log_variant("log10", 10);
1890 ast_expression *intrin::log2_() {
1891 return log_variant("log2", 2);
1893 ast_expression *intrin::logb_() {
1894 /* FLT_RADIX == 2 for now */
1895 return log_variant("log2", 2);
1898 ast_expression *intrin::shift_variant(const char *name, size_t instr) {
1900 * float [shift] (float a, float b) {
1901 * return floor(a [instr] pow(2, b));
1903 ast_value *val = nullptr;
1904 ast_call *callpow = ast_call::make(ctx(), func_self("pow", name));
1905 ast_call *callfloor = ast_call::make(ctx(), func_self("floor", name));
1906 ast_value *a = new ast_value(ctx(), "a", TYPE_FLOAT);
1907 ast_value *b = new ast_value(ctx(), "b", TYPE_FLOAT);
1908 ast_block *body = new ast_block(ctx());
1909 ast_function *func = value(&val, name, TYPE_FLOAT);
1911 val->m_type_params.emplace_back(a);
1912 val->m_type_params.emplace_back(b);
1914 /* <callpow> = pow(2, b) */
1915 callpow->m_params.push_back(m_fold->m_imm_float[3]);
1916 callpow->m_params.push_back(b);
1918 /* <callfloor> = floor(a [instr] <callpow>) */
1919 callfloor->m_params.push_back(
1928 /* return <callfloor> */
1929 body->m_exprs.push_back(
1936 func->m_blocks.emplace_back(body);
1941 ast_expression *intrin::lshift() {
1942 return shift_variant("lshift", INSTR_MUL_F);
1945 ast_expression *intrin::rshift() {
1946 return shift_variant("rshift", INSTR_DIV_F);
1949 void intrin::error(const char *fmt, ...) {
1952 vcompile_error(ctx(), fmt, ap);
1957 ast_expression *intrin::debug_typestring() {
1958 return (ast_expression*)0x1;
1961 intrin::intrin(parser_t *parser)
1963 , m_fold(&parser->m_fold)
1965 static const intrin_func_t intrinsics[] = {
1966 {&intrin::isfinite_, "__builtin_isfinite", "isfinite", 1},
1967 {&intrin::isinf_, "__builtin_isinf", "isinf", 1},
1968 {&intrin::isnan_, "__builtin_isnan", "isnan", 1},
1969 {&intrin::isnormal_, "__builtin_isnormal", "isnormal", 1},
1970 {&intrin::signbit_, "__builtin_signbit", "signbit", 1},
1971 {&intrin::acosh_, "__builtin_acosh", "acosh", 1},
1972 {&intrin::asinh_, "__builtin_asinh", "asinh", 1},
1973 {&intrin::atanh_, "__builtin_atanh", "atanh", 1},
1974 {&intrin::exp_, "__builtin_exp", "exp", 1},
1975 {&intrin::exp2_, "__builtin_exp2", "exp2", 1},
1976 {&intrin::expm1_, "__builtin_expm1", "expm1", 1},
1977 {&intrin::mod_, "__builtin_mod", "mod", 2},
1978 {&intrin::pow_, "__builtin_pow", "pow", 2},
1979 {&intrin::fabs_, "__builtin_fabs", "fabs", 1},
1980 {&intrin::log_, "__builtin_log", "log", 1},
1981 {&intrin::log10_, "__builtin_log10", "log10", 1},
1982 {&intrin::log2_, "__builtin_log2", "log2", 1},
1983 {&intrin::logb_, "__builtin_logb", "logb", 1},
1984 {&intrin::lshift, "__builtin_lshift", "", 2},
1985 {&intrin::rshift, "__builtin_rshift", "", 2},
1986 {&intrin::epsilon_, "__builtin_epsilon", "", 0},
1987 {&intrin::nan_, "__builtin_nan", "", 0},
1988 {&intrin::inf_, "__builtin_inf", "", 0},
1989 {&intrin::ln_, "__builtin_ln", "", 2},
1990 {&intrin::debug_typestring, "__builtin_debug_typestring", "", 0},
1991 {&intrin::nullfunc, "#nullfunc", "", 0}
1994 for (auto &it : intrinsics) {
1995 m_intrinsics.push_back(it);
1996 m_generated.push_back(nullptr);
2000 ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) {
2001 if (!val || !val->m_name.length())
2003 static constexpr size_t kPrefixLength = 10; // "__builtin_"
2004 for (auto &it : m_intrinsics) {
2005 if (val->m_name == it.name)
2006 return (vec_size(exprs) != it.args)
2008 : m_fold->intrinsic(val->m_name.c_str() + kPrefixLength, it.args, exprs);
2013 ast_expression *intrin::func_try(size_t offset, const char *compare) {
2014 for (auto &it : m_intrinsics) {
2015 const size_t index = &it - &m_intrinsics[0];
2016 if (strcmp(*(char **)((char *)&it + offset), compare))
2018 if (m_generated[index])
2019 return m_generated[index];
2020 return m_generated[index] = (this->*it.intrin_func_t::function)();
2025 ast_expression *intrin::func_self(const char *name, const char *from) {
2026 ast_expression *find;
2027 /* try current first */
2028 if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->m_vtype == TYPE_FUNCTION)
2029 for (auto &it : m_parser->functions)
2030 if (reinterpret_cast<ast_value*>(find)->m_name.length() && it->m_name == reinterpret_cast<ast_value*>(find)->m_name && it->m_builtin < 0)
2032 /* try name second */
2033 if ((find = func_try(offsetof(intrin_func_t, name), name)))
2035 /* try alias third */
2036 if ((find = func_try(offsetof(intrin_func_t, alias), name)))
2040 error("need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2041 return func_self("#nullfunc", nullptr);
2046 ast_expression *intrin::func(const char *name) {
2047 return func_self(name, nullptr);