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 = ast_value_new(ctx(), buffer, TYPE_FUNCTION);
21 value->m_intrinsic = true;
22 value->m_next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
23 func = ast_function_new(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((ast_expression*)value);
35 #define QC_POW_EPSILON 0.00001f
37 ast_expression *intrin::nullfunc() {
38 ast_value *val = nullptr;
39 ast_function *func = value(&val, nullptr, TYPE_VOID);
41 return (ast_expression*)val;
44 ast_expression *intrin::isfinite_() {
46 * float isfinite(float x) {
47 * return !(isnan(x) || isinf(x));
50 ast_value *val = nullptr;
51 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
52 ast_function *func = value(&val, "isfinite", TYPE_FLOAT);
53 ast_call *callisnan = ast_call_new(ctx(), func_self("isnan", "isfinite"));
54 ast_call *callisinf = ast_call_new(ctx(), func_self("isinf", "isfinite"));
55 ast_block *block = ast_block_new(ctx());
58 val->m_type_params.push_back(x);
60 /* <callisnan> = isnan(x); */
61 callisnan->m_params.push_back((ast_expression*)x);
63 /* <callisinf> = isinf(x); */
64 callisinf->m_params.push_back((ast_expression*)x);
66 /* return (!<callisnan> || <callisinf>); */
67 block->m_exprs.push_back(
68 (ast_expression*)ast_return_new(
70 (ast_expression*)ast_unary_new(
73 (ast_expression*)ast_binary_new(
76 (ast_expression*)callisnan,
77 (ast_expression*)callisinf
83 func->m_blocks.emplace_back(block);
86 return (ast_expression*)val;;
89 ast_expression *intrin::isinf_() {
91 * float isinf(float x) {
92 * return (x != 0.0) && (x + x == x);
95 ast_value *val = nullptr;
96 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
97 ast_block *body = ast_block_new(ctx());
98 ast_function *func = value(&val, "isinf", TYPE_FLOAT);
100 body->m_exprs.push_back(
101 (ast_expression*)ast_return_new(
103 (ast_expression*)ast_binary_new(
106 (ast_expression*)ast_binary_new(
110 (ast_expression*)m_fold->m_imm_float[0]
112 (ast_expression*)ast_binary_new(
115 (ast_expression*)ast_binary_new(
127 val->m_type_params.push_back(x);
128 func->m_blocks.emplace_back(body);
132 return (ast_expression*)val;
135 ast_expression *intrin::isnan_() {
137 * float isnan(float x) {
141 * return (x != local);
144 ast_value *val = nullptr;
145 ast_value *arg1 = ast_value_new(ctx(), "x",TYPE_FLOAT);
146 ast_value *local = ast_value_new(ctx(), "local", TYPE_FLOAT);
147 ast_block *body = ast_block_new(ctx());
148 ast_function *func = value(&val, "isnan", TYPE_FLOAT);
150 body->m_locals.push_back(local);
151 body->m_exprs.push_back(
152 (ast_expression*)ast_store_new(
155 (ast_expression*)local,
156 (ast_expression*)arg1
160 body->m_exprs.push_back(
161 (ast_expression*)ast_return_new(
163 (ast_expression*)ast_binary_new(
166 (ast_expression*)arg1,
167 (ast_expression*)local
172 val->m_type_params.push_back(arg1);
173 func->m_blocks.emplace_back(body);
177 return (ast_expression*)val;
180 ast_expression *intrin::isnormal_() {
182 * float isnormal(float x) {
183 * return isfinite(x);
186 ast_value *val = nullptr;
187 ast_call *callisfinite = ast_call_new(ctx(), func_self("isfinite", "isnormal"));
188 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
189 ast_block *body = ast_block_new(ctx());
190 ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
192 val->m_type_params.push_back(x);
193 callisfinite->m_params.push_back((ast_expression*)x);
195 /* return <callisfinite> */
196 body->m_exprs.push_back(
197 (ast_expression*)ast_return_new(
199 (ast_expression*)callisfinite
203 func->m_blocks.emplace_back(body);
205 return (ast_expression*)val;
208 ast_expression *intrin::signbit_() {
210 * float signbit(float x) {
214 ast_value *val = nullptr;
215 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
216 ast_block *body = ast_block_new(ctx());
217 ast_function *func = value(&val, "signbit", TYPE_FLOAT);
219 val->m_type_params.push_back(x);
221 /* return (x < 0); */
222 body->m_exprs.push_back(
223 (ast_expression*)ast_return_new(
225 (ast_expression*)ast_ternary_new(
227 (ast_expression*)ast_binary_new(
231 (ast_expression*)m_fold->m_imm_float[0]
233 (ast_expression*)m_fold->m_imm_float[1],
234 (ast_expression*)m_fold->m_imm_float[0]
239 func->m_blocks.emplace_back(body);
241 return (ast_expression*)val;
244 ast_expression *intrin::acosh_() {
246 * float acosh(float x) {
247 * return log(x + sqrt((x * x) - 1));
250 ast_value *val = nullptr;
251 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
252 ast_call *calllog = ast_call_new(ctx(), func_self("log", "acosh"));
253 ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "acosh"));
254 ast_block *body = ast_block_new(ctx());
255 ast_function *func = value(&val, "acosh", TYPE_FLOAT);
257 val->m_type_params.push_back(x);
259 /* <callsqrt> = sqrt((x * x) - 1); */
260 callsqrt->m_params.push_back(
261 (ast_expression*)ast_binary_new(
264 (ast_expression*)ast_binary_new(
270 (ast_expression*)m_fold->m_imm_float[1]
274 /* <calllog> = log(x + <callsqrt>); */
275 calllog->m_params.push_back(
276 (ast_expression*)ast_binary_new(
280 (ast_expression*)callsqrt
284 /* return <calllog>; */
285 body->m_exprs.push_back(
286 (ast_expression*)ast_return_new(
288 (ast_expression*)calllog
292 func->m_blocks.emplace_back(body);
294 return (ast_expression*)val;
297 ast_expression *intrin::asinh_() {
299 * float asinh(float x) {
300 * return log(x + sqrt((x * x) + 1));
303 ast_value *val = nullptr;
304 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
305 ast_call *calllog = ast_call_new(ctx(), func_self("log", "asinh"));
306 ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "asinh"));
307 ast_block *body = ast_block_new(ctx());
308 ast_function *func = value(&val, "asinh", TYPE_FLOAT);
310 val->m_type_params.push_back(x);
312 /* <callsqrt> = sqrt((x * x) + 1); */
313 callsqrt->m_params.push_back(
314 (ast_expression*)ast_binary_new(
317 (ast_expression*)ast_binary_new(
323 (ast_expression*)m_fold->m_imm_float[1]
327 /* <calllog> = log(x + <callsqrt>); */
328 calllog->m_params.push_back(
329 (ast_expression*)ast_binary_new(
333 (ast_expression*)callsqrt
337 /* return <calllog>; */
338 body->m_exprs.push_back(
339 (ast_expression*)ast_return_new(
341 (ast_expression*)calllog
345 func->m_blocks.emplace_back(body);
347 return (ast_expression*)val;
350 ast_expression *intrin::atanh_() {
352 * float atanh(float x) {
353 * return 0.5 * log((1 + x) / (1 - x))
356 ast_value *val = nullptr;
357 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
358 ast_call *calllog = ast_call_new(ctx(), func_self("log", "atanh"));
359 ast_block *body = ast_block_new(ctx());
360 ast_function *func = value(&val, "atanh", TYPE_FLOAT);
362 val->m_type_params.push_back(x);
364 /* <callog> = log((1 + x) / (1 - x)); */
365 calllog->m_params.push_back(
366 (ast_expression*)ast_binary_new(
369 (ast_expression*)ast_binary_new(
372 (ast_expression*)m_fold->m_imm_float[1],
375 (ast_expression*)ast_binary_new(
378 (ast_expression*)m_fold->m_imm_float[1],
384 /* return 0.5 * <calllog>; */
385 body->m_exprs.push_back(
386 (ast_expression*)ast_binary_new(
389 (ast_expression*)m_fold->constgen_float(0.5, false),
390 (ast_expression*)calllog
394 func->m_blocks.emplace_back(body);
396 return (ast_expression*)val;
399 ast_expression *intrin::exp_() {
401 * float exp(float x) {
405 * for (i = 1; i < 200; ++i)
406 * sum += (acc *= x / i);
411 ast_value *val = nullptr;
412 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
413 ast_value *sum = ast_value_new(ctx(), "sum", TYPE_FLOAT);
414 ast_value *acc = ast_value_new(ctx(), "acc", TYPE_FLOAT);
415 ast_value *i = ast_value_new(ctx(), "i", TYPE_FLOAT);
416 ast_block *body = ast_block_new(ctx());
417 ast_function *func = value(&val, "exp", TYPE_FLOAT);
419 val->m_type_params.push_back(x);
421 body->m_locals.push_back(sum);
422 body->m_locals.push_back(acc);
423 body->m_locals.push_back(i);
426 body->m_exprs.push_back(
427 (ast_expression*)ast_store_new(
430 (ast_expression*)sum,
431 (ast_expression*)m_fold->m_imm_float[1]
436 body->m_exprs.push_back(
437 (ast_expression*)ast_store_new(
440 (ast_expression*)acc,
441 (ast_expression*)m_fold->m_imm_float[1]
446 * for (i = 1; i < 200; ++i)
447 * sum += (acc *= x / i);
449 body->m_exprs.push_back(
450 (ast_expression*)ast_loop_new(
453 (ast_expression*)ast_store_new(
457 (ast_expression*)m_fold->m_imm_float[1]
460 (ast_expression*)ast_binary_new(
464 (ast_expression*)m_fold->constgen_float(200.0f, false)
470 (ast_expression*)ast_binstore_new(
475 (ast_expression*)m_fold->m_imm_float[1]
477 /* sum += (acc *= (x / i)) */
478 (ast_expression*)ast_binstore_new(
482 (ast_expression*)sum,
483 (ast_expression*)ast_binstore_new(
487 (ast_expression*)acc,
488 (ast_expression*)ast_binary_new(
500 body->m_exprs.push_back(
501 (ast_expression*)ast_return_new(
507 func->m_blocks.emplace_back(body);
509 return (ast_expression*)val;
512 ast_expression *intrin::exp2_() {
514 * float exp2(float x) {
518 ast_value *val = nullptr;
519 ast_call *callpow = ast_call_new(ctx(), func_self("pow", "exp2"));
520 ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
521 ast_block *body = ast_block_new(ctx());
522 ast_function *func = value(&val, "exp2", TYPE_FLOAT);
524 val->m_type_params.push_back(arg1);
526 callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]);
527 callpow->m_params.push_back((ast_expression*)arg1);
529 /* return <callpow> */
530 body->m_exprs.push_back(
531 (ast_expression*)ast_return_new(
533 (ast_expression*)callpow
537 func->m_blocks.emplace_back(body);
539 return (ast_expression*)val;
542 ast_expression *intrin::expm1_() {
544 * float expm1(float x) {
548 ast_value *val = nullptr;
549 ast_call *callexp = ast_call_new(ctx(), func_self("exp", "expm1"));
550 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
551 ast_block *body = ast_block_new(ctx());
552 ast_function *func = value(&val, "expm1", TYPE_FLOAT);
554 val->m_type_params.push_back(x);
556 /* <callexp> = exp(x); */
557 callexp->m_params.push_back((ast_expression*)x);
559 /* return <callexp> - 1; */
560 body->m_exprs.push_back(
561 (ast_expression*)ast_return_new(
563 (ast_expression*)ast_binary_new(
566 (ast_expression*)callexp,
567 (ast_expression*)m_fold->m_imm_float[1]
572 func->m_blocks.emplace_back(body);
574 return (ast_expression*)val;
577 ast_expression *intrin::pow_() {
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_new(ctx(), (ast_expression*)val); /* for pow(base, -exp) */
624 ast_call *callpow2 = ast_call_new(ctx(), (ast_expression*)val); /* for pow(vase, exp / 2) */
625 ast_call *callsqrt1 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(base) */
626 ast_call *callsqrt2 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(square) */
627 ast_call *callfabs = ast_call_new(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp) */
629 /* prepare some blocks for later */
630 ast_block *expgt1 = ast_block_new(ctx());
631 ast_block *midltexp = ast_block_new(ctx());
632 ast_block *midltexpelse = ast_block_new(ctx());
633 ast_block *whileblock = ast_block_new(ctx());
635 /* float pow(float base, float exp) */
636 ast_value *base = ast_value_new(ctx(), "base", TYPE_FLOAT);
637 ast_value *exp = ast_value_new(ctx(), "exp", TYPE_FLOAT);
639 ast_block *body = ast_block_new(ctx());
649 ast_value *result = ast_value_new(ctx(), "result", TYPE_FLOAT);
650 ast_value *low = ast_value_new(ctx(), "low", TYPE_FLOAT);
651 ast_value *high = ast_value_new(ctx(), "high", TYPE_FLOAT);
652 ast_value *square = ast_value_new(ctx(), "square", TYPE_FLOAT);
653 ast_value *accumulate = ast_value_new(ctx(), "accumulate", TYPE_FLOAT);
654 ast_value *mid = ast_value_new(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.push_back(base);
663 val->m_type_params.push_back(exp);
669 body->m_exprs.push_back(
670 (ast_expression*)ast_ifthen_new(
672 (ast_expression*)ast_binary_new(
675 (ast_expression*)exp,
676 (ast_expression*)m_fold->m_imm_float[0]
678 (ast_expression*)ast_return_new(
680 (ast_expression*)m_fold->m_imm_float[1]
690 body->m_exprs.push_back(
691 (ast_expression*)ast_ifthen_new(
693 (ast_expression*)ast_binary_new(
696 (ast_expression*)exp,
697 (ast_expression*)m_fold->m_imm_float[1]
699 (ast_expression*)ast_return_new(
701 (ast_expression*)base
707 /* <callpow1> = pow(base, -exp) */
708 callpow1->m_params.push_back((ast_expression*)base);
709 callpow1->m_params.push_back(
710 (ast_expression*)ast_unary_new(
719 * return 1.0 / <callpow1>;
721 body->m_exprs.push_back(
722 (ast_expression*)ast_ifthen_new(
724 (ast_expression*)ast_binary_new(
727 (ast_expression*)exp,
728 (ast_expression*)m_fold->m_imm_float[0]
730 (ast_expression*)ast_return_new(
732 (ast_expression*)ast_binary_new(
735 (ast_expression*)m_fold->m_imm_float[1],
736 (ast_expression*)callpow1
743 /* <callpow2> = pow(base, exp / 2) */
744 callpow2->m_params.push_back((ast_expression*)base);
745 callpow2->m_params.push_back(
746 (ast_expression*)ast_binary_new(
749 (ast_expression*)exp,
750 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
756 * result = <callpow2>;
757 * return result * result;
760 expgt1->m_exprs.push_back(
761 (ast_expression*)ast_store_new(
764 (ast_expression*)result,
765 (ast_expression*)callpow2
768 expgt1->m_exprs.push_back(
769 (ast_expression*)ast_return_new(
771 (ast_expression*)ast_binary_new(
774 (ast_expression*)result,
775 (ast_expression*)result
785 body->m_exprs.push_back(
786 (ast_expression*)ast_ifthen_new(
788 (ast_expression*)ast_binary_new(
791 (ast_expression*)exp,
792 (ast_expression*)m_fold->m_imm_float[1]
794 (ast_expression*)expgt1,
800 * <callsqrt1> = sqrt(base)
802 callsqrt1->m_params.push_back((ast_expression*)base);
807 * square = sqrt(base);
808 * accumulate = square;
811 body->m_exprs.push_back(
812 (ast_expression*)ast_store_new(ctx(),
814 (ast_expression*)low,
815 (ast_expression*)m_fold->m_imm_float[0]
818 body->m_exprs.push_back(
819 (ast_expression*)ast_store_new(
822 (ast_expression*)high,
823 (ast_expression*)m_fold->m_imm_float[1]
827 body->m_exprs.push_back(
828 (ast_expression*)ast_store_new(
831 (ast_expression*)square,
832 (ast_expression*)callsqrt1
836 body->m_exprs.push_back(
837 (ast_expression*)ast_store_new(
840 (ast_expression*)accumulate,
841 (ast_expression*)square
844 body->m_exprs.push_back(
845 (ast_expression*)ast_store_new(
848 (ast_expression*)mid,
849 (ast_expression*)ast_binary_new(
852 (ast_expression*)high,
853 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
861 * accumulate *= square;
864 midltexp->m_exprs.push_back(
865 (ast_expression*)ast_store_new(
868 (ast_expression*)low,
872 midltexp->m_exprs.push_back(
873 (ast_expression*)ast_binstore_new(
877 (ast_expression*)accumulate,
878 (ast_expression*)square
885 * accumulate *= (1.0 / square);
888 midltexpelse->m_exprs.push_back(
889 (ast_expression*)ast_store_new(
892 (ast_expression*)high,
896 midltexpelse->m_exprs.push_back(
897 (ast_expression*)ast_binstore_new(
901 (ast_expression*)accumulate,
902 (ast_expression*)ast_binary_new(
905 (ast_expression*)m_fold->m_imm_float[1],
906 (ast_expression*)square
912 * <callsqrt2> = sqrt(square)
914 callsqrt2->m_params.push_back((ast_expression*)square);
918 * square = <callsqrt2>;
924 * mid = (low + high) / 2;
927 whileblock->m_exprs.push_back(
928 (ast_expression*)ast_store_new(
931 (ast_expression*)square,
932 (ast_expression*)callsqrt2
935 whileblock->m_exprs.push_back(
936 (ast_expression*)ast_ifthen_new(
938 (ast_expression*)ast_binary_new(
941 (ast_expression*)mid,
944 (ast_expression*)midltexp,
945 (ast_expression*)midltexpelse
948 whileblock->m_exprs.push_back(
949 (ast_expression*)ast_store_new(
952 (ast_expression*)mid,
953 (ast_expression*)ast_binary_new(
956 (ast_expression*)ast_binary_new(
959 (ast_expression*)low,
960 (ast_expression*)high
962 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
968 * <callabs> = fabs(mid - exp)
970 callfabs->m_params.push_back(
971 (ast_expression*)ast_binary_new(
974 (ast_expression*)mid,
980 * while (<callfabs> > epsilon)
983 body->m_exprs.push_back(
984 (ast_expression*)ast_loop_new(
989 (ast_expression*)ast_binary_new(
992 (ast_expression*)callfabs,
993 (ast_expression*)m_fold->constgen_float(QC_POW_EPSILON, false)
1001 /* increment expression */
1004 (ast_expression*)whileblock
1008 /* return accumulate */
1009 body->m_exprs.push_back(
1010 (ast_expression*)ast_return_new(
1012 (ast_expression*)accumulate
1017 func->m_blocks.emplace_back(body);
1019 return (ast_expression*)val;
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_new(ctx(), func_self("floor", "mod"));
1032 ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT);
1033 ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT);
1034 ast_value *div = ast_value_new(ctx(), "div", TYPE_FLOAT);
1035 ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1036 ast_block *body = ast_block_new(ctx());
1037 ast_function *func = value(&val, "mod", TYPE_FLOAT);
1039 val->m_type_params.push_back(a);
1040 val->m_type_params.push_back(b);
1042 body->m_locals.push_back(div);
1043 body->m_locals.push_back(sign);
1046 body->m_exprs.push_back(
1047 (ast_expression*)ast_store_new(
1050 (ast_expression*)div,
1051 (ast_expression*)ast_binary_new(
1060 /* sign = (div < 0.0f) ? -1 : 1; */
1061 body->m_exprs.push_back(
1062 (ast_expression*)ast_store_new(
1065 (ast_expression*)sign,
1066 (ast_expression*)ast_ternary_new(
1068 (ast_expression*)ast_binary_new(
1071 (ast_expression*)div,
1072 (ast_expression*)m_fold->m_imm_float[0]
1074 (ast_expression*)m_fold->m_imm_float[2],
1075 (ast_expression*)m_fold->m_imm_float[1]
1080 /* floor(sign * div) */
1081 call->m_params.push_back(
1082 (ast_expression*)ast_binary_new(
1085 (ast_expression*)sign,
1086 (ast_expression*)div
1090 /* return a - b * sign * <call> */
1091 body->m_exprs.push_back(
1092 (ast_expression*)ast_return_new(
1094 (ast_expression*)ast_binary_new(
1098 (ast_expression*)ast_binary_new(
1102 (ast_expression*)ast_binary_new(
1105 (ast_expression*)sign,
1106 (ast_expression*)call
1113 func->m_blocks.emplace_back(body);
1115 return (ast_expression*)val;
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 = ast_value_new(ctx(), "x", TYPE_FLOAT);
1126 ast_block *body = ast_block_new(ctx());
1127 ast_function *func = value(&val, "fabs", TYPE_FLOAT);
1129 body->m_exprs.push_back(
1130 (ast_expression*)ast_return_new(
1132 (ast_expression*)ast_ternary_new(
1134 (ast_expression*)ast_binary_new(
1137 (ast_expression*)arg1,
1138 (ast_expression*)m_fold->m_imm_float[0]
1140 (ast_expression*)ast_unary_new(
1143 (ast_expression*)arg1
1145 (ast_expression*)arg1
1150 val->m_type_params.push_back(arg1);
1152 func->m_blocks.emplace_back(body);
1154 return (ast_expression*)val;
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 = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1167 ast_block *body = ast_block_new(ctx());
1168 ast_function *func = value(&val, "epsilon", TYPE_FLOAT);
1170 body->m_locals.push_back(eps);
1173 body->m_exprs.push_back(
1174 (ast_expression*)ast_store_new(
1177 (ast_expression*)eps,
1178 (ast_expression*)m_fold->m_imm_float[0]
1182 body->m_exprs.push_back(
1183 (ast_expression*)ast_loop_new(
1188 (ast_expression*)ast_binary_new(
1191 (ast_expression*)ast_binary_new(
1194 (ast_expression*)m_fold->m_imm_float[1],
1195 (ast_expression*)ast_binary_new(
1198 (ast_expression*)eps,
1199 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1202 (ast_expression*)m_fold->m_imm_float[1]
1206 (ast_expression*)ast_binstore_new(
1210 (ast_expression*)eps,
1211 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1217 body->m_exprs.push_back(
1218 (ast_expression*)ast_return_new(
1220 (ast_expression*)eps
1224 func->m_blocks.emplace_back(body);
1226 return (ast_expression*)val;
1229 ast_expression *intrin::nan_() {
1236 ast_value *val = nullptr;
1237 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
1238 ast_function *func = value(&val, "nan", TYPE_FLOAT);
1239 ast_block *block = ast_block_new(ctx());
1241 block->m_locals.push_back(x);
1243 block->m_exprs.push_back(
1244 (ast_expression*)ast_store_new(
1248 (ast_expression*)m_fold->m_imm_float[0]
1252 block->m_exprs.push_back(
1253 (ast_expression*)ast_return_new(
1255 (ast_expression*)ast_binary_new(
1264 func->m_blocks.emplace_back(block);
1266 return (ast_expression*)val;
1269 ast_expression *intrin::inf_() {
1277 ast_value *val = nullptr;
1278 ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
1279 ast_value *y = ast_value_new(ctx(), "y", TYPE_FLOAT);
1280 ast_function *func = value(&val, "inf", TYPE_FLOAT);
1281 ast_block *block = ast_block_new(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(
1290 (ast_expression*)ast_store_new(
1293 (ast_expression*)((i == 0) ? x : y),
1294 (ast_expression*)m_fold->m_imm_float[i]
1299 block->m_exprs.push_back(
1300 (ast_expression*)ast_return_new(
1302 (ast_expression*)ast_binary_new(
1311 func->m_blocks.emplace_back(block);
1313 return (ast_expression*)val;
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 = ast_value_new(ctx(), "power", TYPE_FLOAT);
1384 ast_value *base = ast_value_new(ctx(), "base",TYPE_FLOAT);
1385 ast_value *whole= ast_value_new(ctx(), "whole", TYPE_FLOAT);
1386 ast_value *nth = ast_value_new(ctx(), "nth", TYPE_FLOAT);
1387 ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1388 ast_value *A_i = ast_value_new(ctx(), "A_i", TYPE_FLOAT);
1389 ast_value *B_i = ast_value_new(ctx(), "B_i", TYPE_FLOAT);
1390 ast_value *A_iminus1 = ast_value_new(ctx(), "A_iminus1", TYPE_FLOAT);
1391 ast_value *B_iminus1 = ast_value_new(ctx(), "B_iminus1", TYPE_FLOAT);
1392 ast_value *b_iplus1 = ast_value_new(ctx(), "b_iplus1", TYPE_FLOAT);
1393 ast_value *A_iplus1 = ast_value_new(ctx(), "A_iplus1", TYPE_FLOAT);
1394 ast_value *B_iplus1 = ast_value_new(ctx(), "B_iplus1", TYPE_FLOAT);
1395 ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1396 ast_value *base2 = ast_value_new(ctx(), "base2", TYPE_FLOAT);
1397 ast_value *n2 = ast_value_new(ctx(), "n2",TYPE_FLOAT);
1398 ast_value *newbase2 = ast_value_new(ctx(), "newbase2", TYPE_FLOAT);
1399 ast_block *block = ast_block_new(ctx());
1400 ast_block *plt1orblt1 = ast_block_new(ctx()); // (power <= 1.0f || base <= 1.0f)
1401 ast_block *plt1 = ast_block_new(ctx()); // (power < 1.0f)
1402 ast_block *blt1 = ast_block_new(ctx()); // (base< 1.0f)
1403 ast_block *forloop = ast_block_new(ctx()); // for(;;)
1404 ast_block *whileloop = ast_block_new(ctx()); // while (whole >= base)
1405 ast_block *nestwhile= ast_block_new(ctx()); // while (whole >= newbase2)
1406 ast_function *func = value(&val, "ln", TYPE_FLOAT);
1409 val->m_type_params.push_back(power);
1410 val->m_type_params.push_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(
1423 (ast_expression*)ast_store_new(
1426 (ast_expression*)sign,
1427 (ast_expression*)m_fold->m_imm_float[1]
1431 /* eps = __builtin_epsilon(); */
1432 block->m_exprs.push_back(
1433 (ast_expression*)ast_store_new(
1436 (ast_expression*)eps,
1437 (ast_expression*)ast_call_new(
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(
1454 (ast_expression*)ast_store_new(
1457 (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1458 : ((i) ? A_iminus1 : B_i)),
1459 (ast_expression*)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(
1477 (ast_expression*)ast_store_new(
1480 (ast_expression*)((i) ? base : power),
1481 (ast_expression*)ast_binary_new(
1484 (ast_expression*)m_fold->m_imm_float[1],
1485 (ast_expression*)((i) ? base : power)
1489 plt1->m_exprs.push_back(
1490 (ast_expression*)ast_binstore_new(
1494 (ast_expression*)sign,
1495 (ast_expression*)m_fold->m_imm_float[2]
1502 * if (power <= 0.0 || base <= 0.0f)
1503 * return __builtin_nan();
1510 plt1orblt1->m_exprs.push_back(
1511 (ast_expression*)ast_ifthen_new(
1513 (ast_expression*)ast_binary_new(
1516 (ast_expression*)ast_binary_new(
1519 (ast_expression*)power,
1520 (ast_expression*)m_fold->m_imm_float[0]
1522 (ast_expression*)ast_binary_new(
1525 (ast_expression*)base,
1526 (ast_expression*)m_fold->m_imm_float[0]
1529 (ast_expression*)ast_return_new(
1531 (ast_expression*)ast_call_new(
1533 func_self("__builtin_nan", "ln")
1540 for (i = 0; i <= 1; i++) {
1541 plt1orblt1->m_exprs.push_back(
1542 (ast_expression*)ast_ifthen_new(
1544 (ast_expression*)ast_binary_new(
1547 (ast_expression*)((i) ? base : power),
1548 (ast_expression*)m_fold->m_imm_float[1]
1550 (ast_expression*)((i) ? blt1 : plt1),
1556 block->m_exprs.push_back((ast_expression*)plt1orblt1);
1559 /* whole = power; */
1560 forloop->m_exprs.push_back(
1561 (ast_expression*)ast_store_new(
1564 (ast_expression*)whole,
1565 (ast_expression*)power
1570 forloop->m_exprs.push_back(
1571 (ast_expression*)ast_store_new(
1574 (ast_expression*)nth,
1575 (ast_expression*)m_fold->m_imm_float[0]
1580 whileloop->m_exprs.push_back(
1581 (ast_expression*)ast_store_new(
1584 (ast_expression*)base2,
1585 (ast_expression*)base
1590 whileloop->m_exprs.push_back(
1591 (ast_expression*)ast_store_new(
1594 (ast_expression*)n2,
1595 (ast_expression*)m_fold->m_imm_float[1]
1599 /* newbase2 = base2 * base2; */
1600 whileloop->m_exprs.push_back(
1601 (ast_expression*)ast_store_new(
1604 (ast_expression*)newbase2,
1605 (ast_expression*)ast_binary_new(
1608 (ast_expression*)base2,
1609 (ast_expression*)base2
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(
1621 (ast_expression*)ast_store_new(
1624 (ast_expression*)base2,
1625 (ast_expression*)newbase2
1630 nestwhile->m_exprs.push_back(
1631 (ast_expression*)ast_binstore_new(
1635 (ast_expression*)n2,
1636 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1640 /* newbase2 *= newbase2; */
1641 nestwhile->m_exprs.push_back(
1642 (ast_expression*)ast_binstore_new(
1646 (ast_expression*)newbase2,
1647 (ast_expression*)newbase2
1651 /* while (whole >= newbase2) */
1652 whileloop->m_exprs.push_back(
1653 (ast_expression*)ast_loop_new(
1656 (ast_expression*)ast_binary_new(
1659 (ast_expression*)whole,
1660 (ast_expression*)newbase2
1666 (ast_expression*)nestwhile
1670 /* whole /= base2; */
1671 whileloop->m_exprs.push_back(
1672 (ast_expression*)ast_binstore_new(
1676 (ast_expression*)whole,
1677 (ast_expression*)base2
1682 whileloop->m_exprs.push_back(
1683 (ast_expression*)ast_binstore_new(
1687 (ast_expression*)nth,
1692 /* while (whole >= base) */
1693 forloop->m_exprs.push_back(
1694 (ast_expression*)ast_loop_new(
1697 (ast_expression*)ast_binary_new(
1700 (ast_expression*)whole,
1701 (ast_expression*)base
1707 (ast_expression*)whileloop
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(
1717 (ast_expression*)ast_store_new(
1720 (ast_expression*)b_iplus1,
1721 (ast_expression*)nth
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(
1731 (ast_expression*)ast_store_new(
1734 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1735 (ast_expression*)ast_binary_new(
1738 (ast_expression*)ast_binary_new(
1741 (ast_expression*)b_iplus1,
1742 (ast_expression*) ((i) ? B_i : A_i)
1744 (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1754 for (i = 0; i <= 1; i++) {
1755 forloop->m_exprs.push_back(
1756 (ast_expression*)ast_store_new(
1759 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1760 (ast_expression*)((i) ? B_i : A_i)
1769 for (i = 0; i <= 1; i++) {
1770 forloop->m_exprs.push_back(
1771 (ast_expression*)ast_store_new(
1774 (ast_expression*)((i) ? B_i : A_i),
1775 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1781 * if (whole <= 1.0f + eps)
1784 forloop->m_exprs.push_back(
1785 (ast_expression*)ast_ifthen_new(
1787 (ast_expression*)ast_binary_new(
1790 (ast_expression*)whole,
1791 (ast_expression*)ast_binary_new(
1794 (ast_expression*)m_fold->m_imm_float[1],
1795 (ast_expression*)eps
1798 (ast_expression*)ast_breakcont_new(
1811 for (i = 0; i <= 1; i++) {
1812 forloop->m_exprs.push_back(
1813 (ast_expression*)ast_store_new(
1816 (ast_expression*)((i) ? base : power),
1817 (ast_expression*)((i) ? whole : base)
1822 /* add the for loop block */
1823 block->m_exprs.push_back(
1824 (ast_expression*)ast_loop_new(
1827 /* for(; 1; ) ?? (can this be nullptr too?) */
1828 (ast_expression*)m_fold->m_imm_float[1],
1833 (ast_expression*)forloop
1837 /* return sign * A_i / B_il */
1838 block->m_exprs.push_back(
1839 (ast_expression*)ast_return_new(
1841 (ast_expression*)ast_binary_new(
1844 (ast_expression*)sign,
1845 (ast_expression*)ast_binary_new(
1848 (ast_expression*)A_i,
1849 (ast_expression*)B_i
1855 func->m_blocks.emplace_back(block);
1857 return (ast_expression*)val;
1860 ast_expression *intrin::log_variant(const char *name, float base) {
1861 ast_value *val = nullptr;
1862 ast_call *callln = ast_call_new (ctx(), func_self("__builtin_ln", name));
1863 ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
1864 ast_block *body = ast_block_new(ctx());
1865 ast_function *func = value(&val, name, TYPE_FLOAT);
1867 val->m_type_params.push_back(arg1);
1869 callln->m_params.push_back((ast_expression*)arg1);
1870 callln->m_params.push_back((ast_expression*)m_fold->constgen_float(base, false));
1872 body->m_exprs.push_back(
1873 (ast_expression*)ast_return_new(
1875 (ast_expression*)callln
1879 func->m_blocks.emplace_back(body);
1881 return (ast_expression*)val;
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_new(ctx(), func_self("pow", name));
1905 ast_call *callfloor = ast_call_new(ctx(), func_self("floor", name));
1906 ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT);
1907 ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT);
1908 ast_block *body = ast_block_new(ctx());
1909 ast_function *func = value(&val, name, TYPE_FLOAT);
1911 val->m_type_params.push_back(a);
1912 val->m_type_params.push_back(b);
1914 /* <callpow> = pow(2, b) */
1915 callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]);
1916 callpow->m_params.push_back((ast_expression*)b);
1918 /* <callfloor> = floor(a [instr] <callpow>) */
1919 callfloor->m_params.push_back(
1920 (ast_expression*)ast_binary_new(
1924 (ast_expression*)callpow
1928 /* return <callfloor> */
1929 body->m_exprs.push_back(
1930 (ast_expression*)ast_return_new(
1932 (ast_expression*)callfloor
1936 func->m_blocks.emplace_back(body);
1938 return (ast_expression*)val;
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)
2003 static constexpr size_t kPrefixLength = 10; // "__builtin_"
2004 for (auto &it : m_intrinsics) {
2005 if (!strcmp(val->m_name, it.name))
2006 return (vec_size(exprs) != it.args)
2008 : m_fold->intrinsic(val->m_name + kPrefixLength, 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 (((ast_value*)find)->m_name && !strcmp(it->m_name, ((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);