4 lex_ctx_t intrin::ctx() const {
5 return parser_ctx(m_parser);
8 ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) {
9 ast_value *value = nullptr;
10 ast_function *func = nullptr;
14 util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
15 util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]);
17 value = ast_value_new(ctx(), buffer, TYPE_FUNCTION);
18 value->intrinsic = true;
19 value->expression.next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
20 func = ast_function_new(ctx(), buffer, value);
21 value->expression.flags |= AST_FLAG_ERASEABLE;
27 void intrin::reg(ast_value *const value, ast_function *const func) {
28 m_parser->functions.push_back(func);
29 m_parser->globals.push_back((ast_expression*)value);
32 #define QC_POW_EPSILON 0.00001f
34 ast_expression *intrin::nullfunc() {
35 ast_value *val = nullptr;
36 ast_function *func = value(&val, nullptr, TYPE_VOID);
38 return (ast_expression*)val;
41 ast_expression *intrin::isfinite_() {
43 * float isfinite(float x) {
44 * return !(isnan(x) || isinf(x));
47 ast_value *val = nullptr;
48 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
49 ast_function *func = value(&val, "isfinite", TYPE_FLOAT);
50 ast_call *callisnan = ast_call_new(ctx(), func_self("isnan", "isfinite"));
51 ast_call *callisinf = ast_call_new(ctx(), func_self("isinf", "isfinite"));
52 ast_block *block = ast_block_new(ctx());
55 val->expression.params.push_back(x);
57 /* <callisnan> = isnan(x); */
58 callisnan->params.push_back((ast_expression*)x);
60 /* <callisinf> = isinf(x); */
61 callisinf->params.push_back((ast_expression*)x);
63 /* return (!<callisnan> || <callisinf>); */
64 block->exprs.push_back(
65 (ast_expression*)ast_return_new(
67 (ast_expression*)ast_unary_new(
70 (ast_expression*)ast_binary_new(
73 (ast_expression*)callisnan,
74 (ast_expression*)callisinf
80 func->blocks.push_back(block);
83 return (ast_expression*)val;;
86 ast_expression *intrin::isinf_() {
88 * float isinf(float x) {
89 * return (x != 0.0) && (x + x == x);
92 ast_value *val = nullptr;
93 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
94 ast_block *body = ast_block_new(ctx());
95 ast_function *func = value(&val, "isinf", TYPE_FLOAT);
97 body->exprs.push_back(
98 (ast_expression*)ast_return_new(
100 (ast_expression*)ast_binary_new(
103 (ast_expression*)ast_binary_new(
107 (ast_expression*)m_fold->imm_float[0]
109 (ast_expression*)ast_binary_new(
112 (ast_expression*)ast_binary_new(
124 val->expression.params.push_back(x);
125 func->blocks.push_back(body);
129 return (ast_expression*)val;
132 ast_expression *intrin::isnan_() {
134 * float isnan(float x) {
138 * return (x != local);
141 ast_value *val = nullptr;
142 ast_value *arg1 = ast_value_new(ctx(), "x",TYPE_FLOAT);
143 ast_value *local = ast_value_new(ctx(), "local", TYPE_FLOAT);
144 ast_block *body = ast_block_new(ctx());
145 ast_function *func = value(&val, "isnan", TYPE_FLOAT);
147 body->locals.push_back(local);
148 body->exprs.push_back(
149 (ast_expression*)ast_store_new(
152 (ast_expression*)local,
153 (ast_expression*)arg1
157 body->exprs.push_back(
158 (ast_expression*)ast_return_new(
160 (ast_expression*)ast_binary_new(
163 (ast_expression*)arg1,
164 (ast_expression*)local
169 val->expression.params.push_back(arg1);
170 func->blocks.push_back(body);
174 return (ast_expression*)val;
177 ast_expression *intrin::isnormal_() {
179 * float isnormal(float x) {
180 * return isfinite(x);
183 ast_value *val = nullptr;
184 ast_call *callisfinite = ast_call_new(ctx(), func_self("isfinite", "isnormal"));
185 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
186 ast_block *body = ast_block_new(ctx());
187 ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
189 val->expression.params.push_back(x);
190 callisfinite->params.push_back((ast_expression*)x);
192 /* return <callisfinite> */
193 body->exprs.push_back(
194 (ast_expression*)ast_return_new(
196 (ast_expression*)callisfinite
200 func->blocks.push_back(body);
202 return (ast_expression*)val;
205 ast_expression *intrin::signbit_() {
207 * float signbit(float x) {
211 ast_value *val = nullptr;
212 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
213 ast_block *body = ast_block_new(ctx());
214 ast_function *func = value(&val, "signbit", TYPE_FLOAT);
216 val->expression.params.push_back(x);
218 /* return (x < 0); */
219 body->exprs.push_back(
220 (ast_expression*)ast_return_new(
222 (ast_expression*)ast_ternary_new(
224 (ast_expression*)ast_binary_new(
228 (ast_expression*)m_fold->imm_float[0]
230 (ast_expression*)m_fold->imm_float[1],
231 (ast_expression*)m_fold->imm_float[0]
236 func->blocks.push_back(body);
238 return (ast_expression*)val;
241 ast_expression *intrin::acosh_() {
243 * float acosh(float x) {
244 * return log(x + sqrt((x * x) - 1));
247 ast_value *val = nullptr;
248 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
249 ast_call *calllog = ast_call_new(ctx(), func_self("log", "acosh"));
250 ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "acosh"));
251 ast_block *body = ast_block_new(ctx());
252 ast_function *func = value(&val, "acosh", TYPE_FLOAT);
254 val->expression.params.push_back(x);
256 /* <callsqrt> = sqrt((x * x) - 1); */
257 callsqrt->params.push_back(
258 (ast_expression*)ast_binary_new(
261 (ast_expression*)ast_binary_new(
267 (ast_expression*)m_fold->imm_float[1]
271 /* <calllog> = log(x + <callsqrt>); */
272 calllog->params.push_back(
273 (ast_expression*)ast_binary_new(
277 (ast_expression*)callsqrt
281 /* return <calllog>; */
282 body->exprs.push_back(
283 (ast_expression*)ast_return_new(
285 (ast_expression*)calllog
289 func->blocks.push_back(body);
291 return (ast_expression*)val;
294 ast_expression *intrin::asinh_() {
296 * float asinh(float x) {
297 * return log(x + sqrt((x * x) + 1));
300 ast_value *val = nullptr;
301 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
302 ast_call *calllog = ast_call_new(ctx(), func_self("log", "asinh"));
303 ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "asinh"));
304 ast_block *body = ast_block_new(ctx());
305 ast_function *func = value(&val, "asinh", TYPE_FLOAT);
307 val->expression.params.push_back(x);
309 /* <callsqrt> = sqrt((x * x) + 1); */
310 callsqrt->params.push_back(
311 (ast_expression*)ast_binary_new(
314 (ast_expression*)ast_binary_new(
320 (ast_expression*)m_fold->imm_float[1]
324 /* <calllog> = log(x + <callsqrt>); */
325 calllog->params.push_back(
326 (ast_expression*)ast_binary_new(
330 (ast_expression*)callsqrt
334 /* return <calllog>; */
335 body->exprs.push_back(
336 (ast_expression*)ast_return_new(
338 (ast_expression*)calllog
342 func->blocks.push_back(body);
344 return (ast_expression*)val;
347 ast_expression *intrin::atanh_() {
349 * float atanh(float x) {
350 * return 0.5 * log((1 + x) / (1 - x))
353 ast_value *val = nullptr;
354 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
355 ast_call *calllog = ast_call_new(ctx(), func_self("log", "atanh"));
356 ast_block *body = ast_block_new(ctx());
357 ast_function *func = value(&val, "atanh", TYPE_FLOAT);
359 val->expression.params.push_back(x);
361 /* <callog> = log((1 + x) / (1 - x)); */
362 calllog->params.push_back(
363 (ast_expression*)ast_binary_new(
366 (ast_expression*)ast_binary_new(
369 (ast_expression*)m_fold->imm_float[1],
372 (ast_expression*)ast_binary_new(
375 (ast_expression*)m_fold->imm_float[1],
381 /* return 0.5 * <calllog>; */
382 body->exprs.push_back(
383 (ast_expression*)ast_binary_new(
386 (ast_expression*)fold_constgen_float(m_fold, 0.5, false),
387 (ast_expression*)calllog
391 func->blocks.push_back(body);
393 return (ast_expression*)val;
396 ast_expression *intrin::exp_() {
398 * float exp(float x) {
402 * for (i = 1; i < 200; ++i)
403 * sum += (acc *= x / i);
408 ast_value *val = nullptr;
409 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
410 ast_value *sum = ast_value_new(ctx(), "sum", TYPE_FLOAT);
411 ast_value *acc = ast_value_new(ctx(), "acc", TYPE_FLOAT);
412 ast_value *i = ast_value_new(ctx(), "i", TYPE_FLOAT);
413 ast_block *body = ast_block_new(ctx());
414 ast_function *func = value(&val, "exp", TYPE_FLOAT);
416 val->expression.params.push_back(x);
418 body->locals.push_back(sum);
419 body->locals.push_back(acc);
420 body->locals.push_back(i);
423 body->exprs.push_back(
424 (ast_expression*)ast_store_new(
427 (ast_expression*)sum,
428 (ast_expression*)m_fold->imm_float[1]
433 body->exprs.push_back(
434 (ast_expression*)ast_store_new(
437 (ast_expression*)acc,
438 (ast_expression*)m_fold->imm_float[1]
443 * for (i = 1; i < 200; ++i)
444 * sum += (acc *= x / i);
446 body->exprs.push_back(
447 (ast_expression*)ast_loop_new(
450 (ast_expression*)ast_store_new(
454 (ast_expression*)m_fold->imm_float[1]
457 (ast_expression*)ast_binary_new(
461 (ast_expression*)fold_constgen_float(m_fold, 200.0f, false)
467 (ast_expression*)ast_binstore_new(
472 (ast_expression*)m_fold->imm_float[1]
474 /* sum += (acc *= (x / i)) */
475 (ast_expression*)ast_binstore_new(
479 (ast_expression*)sum,
480 (ast_expression*)ast_binstore_new(
484 (ast_expression*)acc,
485 (ast_expression*)ast_binary_new(
497 body->exprs.push_back(
498 (ast_expression*)ast_return_new(
504 func->blocks.push_back(body);
506 return (ast_expression*)val;
509 ast_expression *intrin::exp2_() {
511 * float exp2(float x) {
515 ast_value *val = nullptr;
516 ast_call *callpow = ast_call_new(ctx(), func_self("pow", "exp2"));
517 ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
518 ast_block *body = ast_block_new(ctx());
519 ast_function *func = value(&val, "exp2", TYPE_FLOAT);
521 val->expression.params.push_back(arg1);
523 callpow->params.push_back((ast_expression*)m_fold->imm_float[3]);
524 callpow->params.push_back((ast_expression*)arg1);
526 /* return <callpow> */
527 body->exprs.push_back(
528 (ast_expression*)ast_return_new(
530 (ast_expression*)callpow
534 func->blocks.push_back(body);
536 return (ast_expression*)val;
539 ast_expression *intrin::expm1_() {
541 * float expm1(float x) {
545 ast_value *val = nullptr;
546 ast_call *callexp = ast_call_new(ctx(), func_self("exp", "expm1"));
547 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
548 ast_block *body = ast_block_new(ctx());
549 ast_function *func = value(&val, "expm1", TYPE_FLOAT);
551 val->expression.params.push_back(x);
553 /* <callexp> = exp(x); */
554 callexp->params.push_back((ast_expression*)x);
556 /* return <callexp> - 1; */
557 body->exprs.push_back(
558 (ast_expression*)ast_return_new(
560 (ast_expression*)ast_binary_new(
563 (ast_expression*)callexp,
564 (ast_expression*)m_fold->imm_float[1]
569 func->blocks.push_back(body);
571 return (ast_expression*)val;
574 ast_expression *intrin::pow_() {
577 * float pow(float base, float exp) {
590 * return 1.0 / pow(base, -exp);
592 * result = pow(base, exp / 2);
593 * return result * result;
598 * square = sqrt(base);
599 * accumulate = square;
602 * while (fabs(mid - exp) > QC_POW_EPSILON) {
603 * square = sqrt(square);
606 * accumulate *= square;
609 * accumulate *= (1.0f / square);
611 * mid = (low + high) / 2;
616 ast_value *val = nullptr;
617 ast_function *func = value(&val, "pow", TYPE_FLOAT);
619 /* prepare some calls for later */
620 ast_call *callpow1 = ast_call_new(ctx(), (ast_expression*)val); /* for pow(base, -exp) */
621 ast_call *callpow2 = ast_call_new(ctx(), (ast_expression*)val); /* for pow(vase, exp / 2) */
622 ast_call *callsqrt1 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(base) */
623 ast_call *callsqrt2 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(square) */
624 ast_call *callfabs = ast_call_new(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp) */
626 /* prepare some blocks for later */
627 ast_block *expgt1 = ast_block_new(ctx());
628 ast_block *midltexp = ast_block_new(ctx());
629 ast_block *midltexpelse = ast_block_new(ctx());
630 ast_block *whileblock = ast_block_new(ctx());
632 /* float pow(float base, float exp) */
633 ast_value *base = ast_value_new(ctx(), "base", TYPE_FLOAT);
634 ast_value *exp = ast_value_new(ctx(), "exp", TYPE_FLOAT);
636 ast_block *body = ast_block_new(ctx());
646 ast_value *result = ast_value_new(ctx(), "result", TYPE_FLOAT);
647 ast_value *low = ast_value_new(ctx(), "low", TYPE_FLOAT);
648 ast_value *high = ast_value_new(ctx(), "high", TYPE_FLOAT);
649 ast_value *square = ast_value_new(ctx(), "square", TYPE_FLOAT);
650 ast_value *accumulate = ast_value_new(ctx(), "accumulate", TYPE_FLOAT);
651 ast_value *mid = ast_value_new(ctx(), "mid", TYPE_FLOAT);
652 body->locals.push_back(result);
653 body->locals.push_back(low);
654 body->locals.push_back(high);
655 body->locals.push_back(square);
656 body->locals.push_back(accumulate);
657 body->locals.push_back(mid);
659 val->expression.params.push_back(base);
660 val->expression.params.push_back(exp);
666 body->exprs.push_back(
667 (ast_expression*)ast_ifthen_new(
669 (ast_expression*)ast_binary_new(
672 (ast_expression*)exp,
673 (ast_expression*)m_fold->imm_float[0]
675 (ast_expression*)ast_return_new(
677 (ast_expression*)m_fold->imm_float[1]
687 body->exprs.push_back(
688 (ast_expression*)ast_ifthen_new(
690 (ast_expression*)ast_binary_new(
693 (ast_expression*)exp,
694 (ast_expression*)m_fold->imm_float[1]
696 (ast_expression*)ast_return_new(
698 (ast_expression*)base
704 /* <callpow1> = pow(base, -exp) */
705 callpow1->params.push_back((ast_expression*)base);
706 callpow1->params.push_back(
707 (ast_expression*)ast_unary_new(
716 * return 1.0 / <callpow1>;
718 body->exprs.push_back(
719 (ast_expression*)ast_ifthen_new(
721 (ast_expression*)ast_binary_new(
724 (ast_expression*)exp,
725 (ast_expression*)m_fold->imm_float[0]
727 (ast_expression*)ast_return_new(
729 (ast_expression*)ast_binary_new(
732 (ast_expression*)m_fold->imm_float[1],
733 (ast_expression*)callpow1
740 /* <callpow2> = pow(base, exp / 2) */
741 callpow2->params.push_back((ast_expression*)base);
742 callpow2->params.push_back(
743 (ast_expression*)ast_binary_new(
746 (ast_expression*)exp,
747 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
753 * result = <callpow2>;
754 * return result * result;
757 expgt1->exprs.push_back(
758 (ast_expression*)ast_store_new(
761 (ast_expression*)result,
762 (ast_expression*)callpow2
765 expgt1->exprs.push_back(
766 (ast_expression*)ast_return_new(
768 (ast_expression*)ast_binary_new(
771 (ast_expression*)result,
772 (ast_expression*)result
782 body->exprs.push_back(
783 (ast_expression*)ast_ifthen_new(
785 (ast_expression*)ast_binary_new(
788 (ast_expression*)exp,
789 (ast_expression*)m_fold->imm_float[1]
791 (ast_expression*)expgt1,
797 * <callsqrt1> = sqrt(base)
799 callsqrt1->params.push_back((ast_expression*)base);
804 * square = sqrt(base);
805 * accumulate = square;
808 body->exprs.push_back(
809 (ast_expression*)ast_store_new(ctx(),
811 (ast_expression*)low,
812 (ast_expression*)m_fold->imm_float[0]
815 body->exprs.push_back(
816 (ast_expression*)ast_store_new(
819 (ast_expression*)high,
820 (ast_expression*)m_fold->imm_float[1]
824 body->exprs.push_back(
825 (ast_expression*)ast_store_new(
828 (ast_expression*)square,
829 (ast_expression*)callsqrt1
833 body->exprs.push_back(
834 (ast_expression*)ast_store_new(
837 (ast_expression*)accumulate,
838 (ast_expression*)square
841 body->exprs.push_back(
842 (ast_expression*)ast_store_new(
845 (ast_expression*)mid,
846 (ast_expression*)ast_binary_new(
849 (ast_expression*)high,
850 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
858 * accumulate *= square;
861 midltexp->exprs.push_back(
862 (ast_expression*)ast_store_new(
865 (ast_expression*)low,
869 midltexp->exprs.push_back(
870 (ast_expression*)ast_binstore_new(
874 (ast_expression*)accumulate,
875 (ast_expression*)square
882 * accumulate *= (1.0 / square);
885 midltexpelse->exprs.push_back(
886 (ast_expression*)ast_store_new(
889 (ast_expression*)high,
893 midltexpelse->exprs.push_back(
894 (ast_expression*)ast_binstore_new(
898 (ast_expression*)accumulate,
899 (ast_expression*)ast_binary_new(
902 (ast_expression*)m_fold->imm_float[1],
903 (ast_expression*)square
909 * <callsqrt2> = sqrt(square)
911 callsqrt2->params.push_back((ast_expression*)square);
915 * square = <callsqrt2>;
921 * mid = (low + high) / 2;
924 whileblock->exprs.push_back(
925 (ast_expression*)ast_store_new(
928 (ast_expression*)square,
929 (ast_expression*)callsqrt2
932 whileblock->exprs.push_back(
933 (ast_expression*)ast_ifthen_new(
935 (ast_expression*)ast_binary_new(
938 (ast_expression*)mid,
941 (ast_expression*)midltexp,
942 (ast_expression*)midltexpelse
945 whileblock->exprs.push_back(
946 (ast_expression*)ast_store_new(
949 (ast_expression*)mid,
950 (ast_expression*)ast_binary_new(
953 (ast_expression*)ast_binary_new(
956 (ast_expression*)low,
957 (ast_expression*)high
959 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
965 * <callabs> = fabs(mid - exp)
967 callfabs->params.push_back(
968 (ast_expression*)ast_binary_new(
971 (ast_expression*)mid,
977 * while (<callfabs> > epsilon)
980 body->exprs.push_back(
981 (ast_expression*)ast_loop_new(
986 (ast_expression*)ast_binary_new(
989 (ast_expression*)callfabs,
990 (ast_expression*)fold_constgen_float(m_fold, QC_POW_EPSILON, false)
998 /* increment expression */
1001 (ast_expression*)whileblock
1005 /* return accumulate */
1006 body->exprs.push_back(
1007 (ast_expression*)ast_return_new(
1009 (ast_expression*)accumulate
1014 func->blocks.push_back(body);
1016 return (ast_expression*)val;
1019 ast_expression *intrin::mod_() {
1021 * float mod(float a, float b) {
1022 * float div = a / b;
1023 * float sign = (div < 0.0f) ? -1 : 1;
1024 * return a - b * sign * floor(sign * div);
1027 ast_value *val = nullptr;
1028 ast_call *call = ast_call_new(ctx(), func_self("floor", "mod"));
1029 ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT);
1030 ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT);
1031 ast_value *div = ast_value_new(ctx(), "div", TYPE_FLOAT);
1032 ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1033 ast_block *body = ast_block_new(ctx());
1034 ast_function *func = value(&val, "mod", TYPE_FLOAT);
1036 val->expression.params.push_back(a);
1037 val->expression.params.push_back(b);
1039 body->locals.push_back(div);
1040 body->locals.push_back(sign);
1043 body->exprs.push_back(
1044 (ast_expression*)ast_store_new(
1047 (ast_expression*)div,
1048 (ast_expression*)ast_binary_new(
1057 /* sign = (div < 0.0f) ? -1 : 1; */
1058 body->exprs.push_back(
1059 (ast_expression*)ast_store_new(
1062 (ast_expression*)sign,
1063 (ast_expression*)ast_ternary_new(
1065 (ast_expression*)ast_binary_new(
1068 (ast_expression*)div,
1069 (ast_expression*)m_fold->imm_float[0]
1071 (ast_expression*)m_fold->imm_float[2],
1072 (ast_expression*)m_fold->imm_float[1]
1077 /* floor(sign * div) */
1078 call->params.push_back(
1079 (ast_expression*)ast_binary_new(
1082 (ast_expression*)sign,
1083 (ast_expression*)div
1087 /* return a - b * sign * <call> */
1088 body->exprs.push_back(
1089 (ast_expression*)ast_return_new(
1091 (ast_expression*)ast_binary_new(
1095 (ast_expression*)ast_binary_new(
1099 (ast_expression*)ast_binary_new(
1102 (ast_expression*)sign,
1103 (ast_expression*)call
1110 func->blocks.push_back(body);
1112 return (ast_expression*)val;
1115 ast_expression *intrin::fabs_() {
1117 * float fabs(float x) {
1118 * return x < 0 ? -x : x;
1121 ast_value *val = nullptr;
1122 ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
1123 ast_block *body = ast_block_new(ctx());
1124 ast_function *func = value(&val, "fabs", TYPE_FLOAT);
1126 body->exprs.push_back(
1127 (ast_expression*)ast_return_new(
1129 (ast_expression*)ast_ternary_new(
1131 (ast_expression*)ast_binary_new(
1134 (ast_expression*)arg1,
1135 (ast_expression*)m_fold->imm_float[0]
1137 (ast_expression*)ast_unary_new(
1140 (ast_expression*)arg1
1142 (ast_expression*)arg1
1147 val->expression.params.push_back(arg1);
1149 func->blocks.push_back(body);
1151 return (ast_expression*)val;
1154 ast_expression *intrin::epsilon_() {
1156 * float epsilon(void) {
1158 * do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1162 ast_value *val = nullptr;
1163 ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1164 ast_block *body = ast_block_new(ctx());
1165 ast_function *func = value(&val, "epsilon", TYPE_FLOAT);
1167 body->locals.push_back(eps);
1170 body->exprs.push_back(
1171 (ast_expression*)ast_store_new(
1174 (ast_expression*)eps,
1175 (ast_expression*)m_fold->imm_float[0]
1179 body->exprs.push_back(
1180 (ast_expression*)ast_loop_new(
1185 (ast_expression*)ast_binary_new(
1188 (ast_expression*)ast_binary_new(
1191 (ast_expression*)m_fold->imm_float[1],
1192 (ast_expression*)ast_binary_new(
1195 (ast_expression*)eps,
1196 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
1199 (ast_expression*)m_fold->imm_float[1]
1203 (ast_expression*)ast_binstore_new(
1207 (ast_expression*)eps,
1208 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
1214 body->exprs.push_back(
1215 (ast_expression*)ast_return_new(
1217 (ast_expression*)eps
1221 func->blocks.push_back(body);
1223 return (ast_expression*)val;
1226 ast_expression *intrin::nan_() {
1233 ast_value *val = nullptr;
1234 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
1235 ast_function *func = value(&val, "nan", TYPE_FLOAT);
1236 ast_block *block = ast_block_new(ctx());
1238 block->locals.push_back(x);
1240 block->exprs.push_back(
1241 (ast_expression*)ast_store_new(
1245 (ast_expression*)m_fold->imm_float[0]
1249 block->exprs.push_back(
1250 (ast_expression*)ast_return_new(
1252 (ast_expression*)ast_binary_new(
1261 func->blocks.push_back(block);
1263 return (ast_expression*)val;
1266 ast_expression *intrin::inf_() {
1274 ast_value *val = nullptr;
1275 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
1276 ast_value *y = ast_value_new(ctx(), "y", TYPE_FLOAT);
1277 ast_function *func = value(&val, "inf", TYPE_FLOAT);
1278 ast_block *block = ast_block_new(ctx());
1281 block->locals.push_back(x);
1282 block->locals.push_back(y);
1284 /* to keep code size down */
1285 for (i = 0; i <= 1; i++) {
1286 block->exprs.push_back(
1287 (ast_expression*)ast_store_new(
1290 (ast_expression*)((i == 0) ? x : y),
1291 (ast_expression*)m_fold->imm_float[i]
1296 block->exprs.push_back(
1297 (ast_expression*)ast_return_new(
1299 (ast_expression*)ast_binary_new(
1308 func->blocks.push_back(block);
1310 return (ast_expression*)val;
1313 ast_expression *intrin::ln_() {
1315 * float log(float power, float base) {
1318 * float sign = 1.0f;
1319 * float eps = epsilon();
1321 * if (power <= 1.0f || bbase <= 1.0) {
1322 * if (power <= 0.0f || base <= 0.0f)
1325 * if (power < 1.0f) {
1326 * power = 1.0f / power;
1330 * if (base < 1.0f) {
1332 * base = 1.0f / base;
1338 * float A_iminus1 = 0;
1339 * float B_iminus1 = 1;
1345 * while (whole >= base) {
1346 * float base2 = base;
1348 * float newbase2 = base2 * base2;
1350 * while (whole >= newbase2) {
1353 * newbase2 *= newbase2;
1360 * float b_iplus1 = n;
1361 * float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1362 * float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1369 * if (whole <= 1.0f + eps)
1375 * return sign * A_i / B_i;
1379 ast_value *val = nullptr;
1380 ast_value *power = ast_value_new(ctx(), "power", TYPE_FLOAT);
1381 ast_value *base = ast_value_new(ctx(), "base",TYPE_FLOAT);
1382 ast_value *whole= ast_value_new(ctx(), "whole", TYPE_FLOAT);
1383 ast_value *nth = ast_value_new(ctx(), "nth", TYPE_FLOAT);
1384 ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1385 ast_value *A_i = ast_value_new(ctx(), "A_i", TYPE_FLOAT);
1386 ast_value *B_i = ast_value_new(ctx(), "B_i", TYPE_FLOAT);
1387 ast_value *A_iminus1 = ast_value_new(ctx(), "A_iminus1", TYPE_FLOAT);
1388 ast_value *B_iminus1 = ast_value_new(ctx(), "B_iminus1", TYPE_FLOAT);
1389 ast_value *b_iplus1 = ast_value_new(ctx(), "b_iplus1", TYPE_FLOAT);
1390 ast_value *A_iplus1 = ast_value_new(ctx(), "A_iplus1", TYPE_FLOAT);
1391 ast_value *B_iplus1 = ast_value_new(ctx(), "B_iplus1", TYPE_FLOAT);
1392 ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1393 ast_value *base2 = ast_value_new(ctx(), "base2", TYPE_FLOAT);
1394 ast_value *n2 = ast_value_new(ctx(), "n2",TYPE_FLOAT);
1395 ast_value *newbase2 = ast_value_new(ctx(), "newbase2", TYPE_FLOAT);
1396 ast_block *block = ast_block_new(ctx());
1397 ast_block *plt1orblt1 = ast_block_new(ctx()); // (power <= 1.0f || base <= 1.0f)
1398 ast_block *plt1 = ast_block_new(ctx()); // (power < 1.0f)
1399 ast_block *blt1 = ast_block_new(ctx()); // (base< 1.0f)
1400 ast_block *forloop = ast_block_new(ctx()); // for(;;)
1401 ast_block *whileloop = ast_block_new(ctx()); // while (whole >= base)
1402 ast_block *nestwhile= ast_block_new(ctx()); // while (whole >= newbase2)
1403 ast_function *func = value(&val, "ln", TYPE_FLOAT);
1406 val->expression.params.push_back(power);
1407 val->expression.params.push_back(base);
1409 block->locals.push_back(whole);
1410 block->locals.push_back(nth);
1411 block->locals.push_back(sign);
1412 block->locals.push_back(eps);
1413 block->locals.push_back(A_i);
1414 block->locals.push_back(B_i);
1415 block->locals.push_back(A_iminus1);
1416 block->locals.push_back(B_iminus1);
1419 block->exprs.push_back(
1420 (ast_expression*)ast_store_new(
1423 (ast_expression*)sign,
1424 (ast_expression*)m_fold->imm_float[1]
1428 /* eps = __builtin_epsilon(); */
1429 block->exprs.push_back(
1430 (ast_expression*)ast_store_new(
1433 (ast_expression*)eps,
1434 (ast_expression*)ast_call_new(
1436 func_self("__builtin_epsilon", "ln")
1447 for (i = 0; i <= 1; i++) {
1449 for (j = 1; j >= 0; j--) {
1450 block->exprs.push_back(
1451 (ast_expression*)ast_store_new(
1454 (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1455 : ((i) ? A_iminus1 : B_i)),
1456 (ast_expression*)m_fold->imm_float[j]
1464 * power = 1.0f / power;
1468 * base = 1.0f / base;
1472 for (i = 0; i <= 1; i++) {
1473 ((i) ? blt1 : plt1)->exprs.push_back(
1474 (ast_expression*)ast_store_new(
1477 (ast_expression*)((i) ? base : power),
1478 (ast_expression*)ast_binary_new(
1481 (ast_expression*)m_fold->imm_float[1],
1482 (ast_expression*)((i) ? base : power)
1486 plt1->exprs.push_back(
1487 (ast_expression*)ast_binstore_new(
1491 (ast_expression*)sign,
1492 (ast_expression*)m_fold->imm_float[2]
1499 * if (power <= 0.0 || base <= 0.0f)
1500 * return __builtin_nan();
1507 plt1orblt1->exprs.push_back(
1508 (ast_expression*)ast_ifthen_new(
1510 (ast_expression*)ast_binary_new(
1513 (ast_expression*)ast_binary_new(
1516 (ast_expression*)power,
1517 (ast_expression*)m_fold->imm_float[0]
1519 (ast_expression*)ast_binary_new(
1522 (ast_expression*)base,
1523 (ast_expression*)m_fold->imm_float[0]
1526 (ast_expression*)ast_return_new(
1528 (ast_expression*)ast_call_new(
1530 func_self("__builtin_nan", "ln")
1537 for (i = 0; i <= 1; i++) {
1538 plt1orblt1->exprs.push_back(
1539 (ast_expression*)ast_ifthen_new(
1541 (ast_expression*)ast_binary_new(
1544 (ast_expression*)((i) ? base : power),
1545 (ast_expression*)m_fold->imm_float[1]
1547 (ast_expression*)((i) ? blt1 : plt1),
1553 block->exprs.push_back((ast_expression*)plt1orblt1);
1556 /* whole = power; */
1557 forloop->exprs.push_back(
1558 (ast_expression*)ast_store_new(
1561 (ast_expression*)whole,
1562 (ast_expression*)power
1567 forloop->exprs.push_back(
1568 (ast_expression*)ast_store_new(
1571 (ast_expression*)nth,
1572 (ast_expression*)m_fold->imm_float[0]
1577 whileloop->exprs.push_back(
1578 (ast_expression*)ast_store_new(
1581 (ast_expression*)base2,
1582 (ast_expression*)base
1587 whileloop->exprs.push_back(
1588 (ast_expression*)ast_store_new(
1591 (ast_expression*)n2,
1592 (ast_expression*)m_fold->imm_float[1]
1596 /* newbase2 = base2 * base2; */
1597 whileloop->exprs.push_back(
1598 (ast_expression*)ast_store_new(
1601 (ast_expression*)newbase2,
1602 (ast_expression*)ast_binary_new(
1605 (ast_expression*)base2,
1606 (ast_expression*)base2
1611 /* while loop locals */
1612 whileloop->locals.push_back(base2);
1613 whileloop->locals.push_back(n2);
1614 whileloop->locals.push_back(newbase2);
1616 /* base2 = newbase2; */
1617 nestwhile->exprs.push_back(
1618 (ast_expression*)ast_store_new(
1621 (ast_expression*)base2,
1622 (ast_expression*)newbase2
1627 nestwhile->exprs.push_back(
1628 (ast_expression*)ast_binstore_new(
1632 (ast_expression*)n2,
1633 (ast_expression*)m_fold->imm_float[3] /* 2.0f */
1637 /* newbase2 *= newbase2; */
1638 nestwhile->exprs.push_back(
1639 (ast_expression*)ast_binstore_new(
1643 (ast_expression*)newbase2,
1644 (ast_expression*)newbase2
1648 /* while (whole >= newbase2) */
1649 whileloop->exprs.push_back(
1650 (ast_expression*)ast_loop_new(
1653 (ast_expression*)ast_binary_new(
1656 (ast_expression*)whole,
1657 (ast_expression*)newbase2
1663 (ast_expression*)nestwhile
1667 /* whole /= base2; */
1668 whileloop->exprs.push_back(
1669 (ast_expression*)ast_binstore_new(
1673 (ast_expression*)whole,
1674 (ast_expression*)base2
1679 whileloop->exprs.push_back(
1680 (ast_expression*)ast_binstore_new(
1684 (ast_expression*)nth,
1689 /* while (whole >= base) */
1690 forloop->exprs.push_back(
1691 (ast_expression*)ast_loop_new(
1694 (ast_expression*)ast_binary_new(
1697 (ast_expression*)whole,
1698 (ast_expression*)base
1704 (ast_expression*)whileloop
1708 forloop->locals.push_back(b_iplus1);
1709 forloop->locals.push_back(A_iplus1);
1710 forloop->locals.push_back(B_iplus1);
1712 /* b_iplus1 = nth; */
1713 forloop->exprs.push_back(
1714 (ast_expression*)ast_store_new(
1717 (ast_expression*)b_iplus1,
1718 (ast_expression*)nth
1723 * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1724 * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1726 for (i = 0; i <= 1; i++) {
1727 forloop->exprs.push_back(
1728 (ast_expression*)ast_store_new(
1731 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1732 (ast_expression*)ast_binary_new(
1735 (ast_expression*)ast_binary_new(
1738 (ast_expression*)b_iplus1,
1739 (ast_expression*) ((i) ? B_i : A_i)
1741 (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1751 for (i = 0; i <= 1; i++) {
1752 forloop->exprs.push_back(
1753 (ast_expression*)ast_store_new(
1756 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1757 (ast_expression*)((i) ? B_i : A_i)
1766 for (i = 0; i <= 1; i++) {
1767 forloop->exprs.push_back(
1768 (ast_expression*)ast_store_new(
1771 (ast_expression*)((i) ? B_i : A_i),
1772 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1778 * if (whole <= 1.0f + eps)
1781 forloop->exprs.push_back(
1782 (ast_expression*)ast_ifthen_new(
1784 (ast_expression*)ast_binary_new(
1787 (ast_expression*)whole,
1788 (ast_expression*)ast_binary_new(
1791 (ast_expression*)m_fold->imm_float[1],
1792 (ast_expression*)eps
1795 (ast_expression*)ast_breakcont_new(
1808 for (i = 0; i <= 1; i++) {
1809 forloop->exprs.push_back(
1810 (ast_expression*)ast_store_new(
1813 (ast_expression*)((i) ? base : power),
1814 (ast_expression*)((i) ? whole : base)
1819 /* add the for loop block */
1820 block->exprs.push_back(
1821 (ast_expression*)ast_loop_new(
1824 /* for(; 1; ) ?? (can this be nullptr too?) */
1825 (ast_expression*)m_fold->imm_float[1],
1830 (ast_expression*)forloop
1834 /* return sign * A_i / B_il */
1835 block->exprs.push_back(
1836 (ast_expression*)ast_return_new(
1838 (ast_expression*)ast_binary_new(
1841 (ast_expression*)sign,
1842 (ast_expression*)ast_binary_new(
1845 (ast_expression*)A_i,
1846 (ast_expression*)B_i
1852 func->blocks.push_back(block);
1854 return (ast_expression*)val;
1857 ast_expression *intrin::log_variant(const char *name, float base) {
1858 ast_value *val = nullptr;
1859 ast_call *callln = ast_call_new (ctx(), func_self("__builtin_ln", name));
1860 ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
1861 ast_block *body = ast_block_new(ctx());
1862 ast_function *func = value(&val, name, TYPE_FLOAT);
1864 val->expression.params.push_back(arg1);
1866 callln->params.push_back((ast_expression*)arg1);
1867 callln->params.push_back((ast_expression*)fold_constgen_float(m_fold, base, false));
1869 body->exprs.push_back(
1870 (ast_expression*)ast_return_new(
1872 (ast_expression*)callln
1876 func->blocks.push_back(body);
1878 return (ast_expression*)val;
1881 ast_expression *intrin::log_() {
1882 return log_variant("log", 2.7182818284590452354);
1884 ast_expression *intrin::log10_() {
1885 return log_variant("log10", 10);
1887 ast_expression *intrin::log2_() {
1888 return log_variant("log2", 2);
1890 ast_expression *intrin::logb_() {
1891 /* FLT_RADIX == 2 for now */
1892 return log_variant("log2", 2);
1895 ast_expression *intrin::shift_variant(const char *name, size_t instr) {
1897 * float [shift] (float a, float b) {
1898 * return floor(a [instr] pow(2, b));
1900 ast_value *val = nullptr;
1901 ast_call *callpow = ast_call_new(ctx(), func_self("pow", name));
1902 ast_call *callfloor = ast_call_new(ctx(), func_self("floor", name));
1903 ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT);
1904 ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT);
1905 ast_block *body = ast_block_new(ctx());
1906 ast_function *func = value(&val, name, TYPE_FLOAT);
1908 val->expression.params.push_back(a);
1909 val->expression.params.push_back(b);
1911 /* <callpow> = pow(2, b) */
1912 callpow->params.push_back((ast_expression*)m_fold->imm_float[3]);
1913 callpow->params.push_back((ast_expression*)b);
1915 /* <callfloor> = floor(a [instr] <callpow>) */
1916 callfloor->params.push_back(
1917 (ast_expression*)ast_binary_new(
1921 (ast_expression*)callpow
1925 /* return <callfloor> */
1926 body->exprs.push_back(
1927 (ast_expression*)ast_return_new(
1929 (ast_expression*)callfloor
1933 func->blocks.push_back(body);
1935 return (ast_expression*)val;
1938 ast_expression *intrin::lshift() {
1939 return shift_variant("lshift", INSTR_MUL_F);
1942 ast_expression *intrin::rshift() {
1943 return shift_variant("rshift", INSTR_DIV_F);
1946 void intrin::error(const char *fmt, ...) {
1949 vcompile_error(ctx(), fmt, ap);
1954 ast_expression *intrin::debug_typestring() {
1955 return (ast_expression*)0x1;
1958 intrin::intrin(parser_t *parser)
1960 , m_fold(parser->fold)
1962 static const intrin_func_t intrinsics[] = {
1963 {&intrin::isfinite_, "__builtin_isfinite", "isfinite", 1},
1964 {&intrin::isinf_, "__builtin_isinf", "isinf", 1},
1965 {&intrin::isnan_, "__builtin_isnan", "isnan", 1},
1966 {&intrin::isnormal_, "__builtin_isnormal", "isnormal", 1},
1967 {&intrin::signbit_, "__builtin_signbit", "signbit", 1},
1968 {&intrin::acosh_, "__builtin_acosh", "acosh", 1},
1969 {&intrin::asinh_, "__builtin_asinh", "asinh", 1},
1970 {&intrin::atanh_, "__builtin_atanh", "atanh", 1},
1971 {&intrin::exp_, "__builtin_exp", "exp", 1},
1972 {&intrin::exp2_, "__builtin_exp2", "exp2", 1},
1973 {&intrin::expm1_, "__builtin_expm1", "expm1", 1},
1974 {&intrin::mod_, "__builtin_mod", "mod", 2},
1975 {&intrin::pow_, "__builtin_pow", "pow", 2},
1976 {&intrin::fabs_, "__builtin_fabs", "fabs", 1},
1977 {&intrin::log_, "__builtin_log", "log", 1},
1978 {&intrin::log10_, "__builtin_log10", "log10", 1},
1979 {&intrin::log2_, "__builtin_log2", "log2", 1},
1980 {&intrin::logb_, "__builtin_logb", "logb", 1},
1981 {&intrin::lshift, "__builtin_lshift", "", 2},
1982 {&intrin::rshift, "__builtin_rshift", "", 2},
1983 {&intrin::epsilon_, "__builtin_epsilon", "", 0},
1984 {&intrin::nan_, "__builtin_nan", "", 0},
1985 {&intrin::inf_, "__builtin_inf", "", 0},
1986 {&intrin::ln_, "__builtin_ln", "", 2},
1987 {&intrin::debug_typestring, "__builtin_debug_typestring", "", 0},
1988 {&intrin::nullfunc, "#nullfunc", "", 0}
1991 for (auto &it : intrinsics) {
1992 m_intrinsics.push_back(it);
1993 m_generated.push_back(nullptr);
1997 ast_expression *intrin::fold(ast_value *val, ast_expression **exprs) {
1998 if (!val || !val->name)
2000 static constexpr size_t kPrefixLength = 10; // "__builtin_"
2001 for (auto &it : m_intrinsics) {
2002 if (!strcmp(val->name, it.name))
2003 return (vec_size(exprs) != it.args)
2005 : fold_intrin(m_fold, val->name + kPrefixLength, exprs);
2010 ast_expression *intrin::func_try(size_t offset, const char *compare) {
2011 for (auto &it : m_intrinsics) {
2012 const size_t index = &it - &m_intrinsics[0];
2013 if (strcmp(*(char **)((char *)&it + offset), compare))
2015 if (m_generated[index])
2016 return m_generated[index];
2017 return m_generated[index] = (this->*it.intrin_func_t::function)();
2022 ast_expression *intrin::func_self(const char *name, const char *from) {
2023 ast_expression *find;
2024 /* try current first */
2025 if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
2026 for (auto &it : m_parser->functions)
2027 if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0)
2029 /* try name second */
2030 if ((find = func_try(offsetof(intrin_func_t, name), name)))
2032 /* try alias third */
2033 if ((find = func_try(offsetof(intrin_func_t, alias), name)))
2037 error("need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2038 return func_self("#nullfunc", nullptr);
2043 ast_expression *intrin::func(const char *name) {
2044 return func_self(name, nullptr);