5 * Provides all the "intrinsics" / "builtins" for GMQCC. These can do
6 * a few things, they can provide fall back implementations for math
7 * functions if the definitions don't exist for some given engine. Or
8 * then can determine definitions for existing builtins, and simply
9 * wrap back to them instead. This is like a "portable" intrface that
10 * is entered when -fintrin is used (causing all existing builtins to
11 * be ignored by the compiler and instead interface through here.
13 #define intrin_ctx(I) parser_ctx((I)->parser)
15 static GMQCC_INLINE ast_function *intrin_value(intrin_t *intrin, ast_value **out, const char *name, qcint_t vtype) {
16 ast_value *value = NULL;
17 ast_function *func = NULL;
21 util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
22 util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]);
24 value = ast_value_new(intrin_ctx(intrin), buffer, TYPE_FUNCTION);
25 value->intrinsic = true;
26 value->expression.next = (ast_expression*)ast_value_new(intrin_ctx(intrin), stype, vtype);
27 func = ast_function_new(intrin_ctx(intrin), buffer, value);
28 value->expression.flags |= AST_FLAG_ERASEABLE;
34 static GMQCC_INLINE void intrin_reg(intrin_t *intrin, ast_value *const value, ast_function *const func) {
35 vec_push(intrin->parser->functions, func);
36 vec_push(intrin->parser->globals, (ast_expression*)value);
39 #define QC_POW_EPSILON 0.00001f
42 * since some intrinsics depend on each other there is the possibility
43 * that an intrinsic will fail to get a 'depended' function that a
44 * builtin needs, causing some dependency in the chain to have a NULL
45 * function. This will cause a segmentation fault at code generation,
46 * even though an error was raised. To contiue to allow it (instead
47 * of stopping compilation right away). We need to return from the
48 * parser, before compilation stops after all the collected errors.
50 static ast_expression *intrin_func_self(intrin_t *intrin, const char *name, const char *from);
51 static ast_expression *intrin_nullfunc(intrin_t *intrin) {
52 ast_value *value = NULL;
53 ast_function *func = intrin_value(intrin, &value, NULL, TYPE_VOID);
54 intrin_reg(intrin, value, func);
55 return (ast_expression*)value;
58 static ast_expression *intrin_isfinite(intrin_t *intrin) {
60 * float isfinite(float x) {
61 * return !(isnan(x) || isinf(x));
64 ast_value *value = NULL;
65 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
66 ast_function *func = intrin_value(intrin, &value, "isfinite", TYPE_FLOAT);
67 ast_call *callisnan = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "isnan", "isfinite"));
68 ast_call *callisinf = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "isinf", "isfinite"));
69 ast_block *block = ast_block_new(intrin_ctx(intrin));
72 vec_push(value->expression.params, x);
74 /* <callisnan> = isnan(x); */
75 vec_push(callisnan->params, (ast_expression*)x);
77 /* <callisinf> = isinf(x); */
78 vec_push(callisinf->params, (ast_expression*)x);
80 /* return (!<callisnan> || <callisinf>); */
81 vec_push(block->exprs,
82 (ast_expression*)ast_return_new(
84 (ast_expression*)ast_unary_new(
87 (ast_expression*)ast_binary_new(
90 (ast_expression*)callisnan,
91 (ast_expression*)callisinf
97 vec_push(func->blocks, block);
98 intrin_reg(intrin, value, func);
100 return (ast_expression*)value;;
103 static ast_expression *intrin_isinf(intrin_t *intrin) {
105 * float isinf(float x) {
106 * return (x != 0.0) && (x + x == x);
109 ast_value *value = NULL;
110 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
111 ast_block *body = ast_block_new(intrin_ctx(intrin));
112 ast_function *func = intrin_value(intrin, &value, "isinf", TYPE_FLOAT);
114 vec_push(body->exprs,
115 (ast_expression*)ast_return_new(
117 (ast_expression*)ast_binary_new(
120 (ast_expression*)ast_binary_new(
124 (ast_expression*)intrin->fold->imm_float[0]
126 (ast_expression*)ast_binary_new(
129 (ast_expression*)ast_binary_new(
141 vec_push(value->expression.params, x);
142 vec_push(func->blocks, body);
144 intrin_reg(intrin, value, func);
146 return (ast_expression*)value;
149 static ast_expression *intrin_isnan(intrin_t *intrin) {
151 * float isnan(float x) {
155 * return (x != local);
158 ast_value *value = NULL;
159 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
160 ast_value *local = ast_value_new(intrin_ctx(intrin), "local", TYPE_FLOAT);
161 ast_block *body = ast_block_new(intrin_ctx(intrin));
162 ast_function *func = intrin_value(intrin, &value, "isnan", TYPE_FLOAT);
164 vec_push(body->locals, local);
165 vec_push(body->exprs,
166 (ast_expression*)ast_store_new(
169 (ast_expression*)local,
170 (ast_expression*)arg1
174 vec_push(body->exprs,
175 (ast_expression*)ast_return_new(
177 (ast_expression*)ast_binary_new(
180 (ast_expression*)arg1,
181 (ast_expression*)local
186 vec_push(value->expression.params, arg1);
187 vec_push(func->blocks, body);
189 intrin_reg(intrin, value, func);
191 return (ast_expression*)value;
194 static ast_expression *intrin_isnormal(intrin_t *intrin) {
196 * float isnormal(float x) {
197 * return isfinite(x);
200 ast_value *value = NULL;
201 ast_call *callisfinite = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "isfinite", "isnormal"));
202 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
203 ast_block *body = ast_block_new(intrin_ctx(intrin));
204 ast_function *func = intrin_value(intrin, &value, "isnormal", TYPE_FLOAT);
206 vec_push(value->expression.params, x);
207 vec_push(callisfinite->params, (ast_expression*)x);
209 /* return <callisfinite> */
210 vec_push(body->exprs,
211 (ast_expression*)ast_return_new(
213 (ast_expression*)callisfinite
217 vec_push(func->blocks, body);
218 intrin_reg(intrin, value, func);
219 return (ast_expression*)value;
222 static ast_expression *intrin_signbit(intrin_t *intrin) {
224 * float signbit(float x) {
228 ast_value *value = NULL;
229 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
230 ast_block *body = ast_block_new(intrin_ctx(intrin));
231 ast_function *func = intrin_value(intrin, &value, "signbit", TYPE_FLOAT);
233 vec_push(value->expression.params, x);
235 /* return (x < 0); */
236 vec_push(body->exprs,
237 (ast_expression*)ast_return_new(
239 (ast_expression*)ast_ternary_new(
241 (ast_expression*)ast_binary_new(
245 (ast_expression*)intrin->fold->imm_float[0]
247 (ast_expression*)intrin->fold->imm_float[1],
248 (ast_expression*)intrin->fold->imm_float[0]
253 vec_push(func->blocks, body);
254 intrin_reg(intrin, value, func);
255 return (ast_expression*)value;
258 static ast_expression *intrin_acosh(intrin_t *intrin) {
260 * float acosh(float x) {
261 * return log(x + sqrt((x * x) - 1));
264 ast_value *value = NULL;
265 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
266 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "acosh"));
267 ast_call *callsqrt = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "acosh"));
268 ast_block *body = ast_block_new(intrin_ctx(intrin));
269 ast_function *func = intrin_value(intrin, &value, "acosh", TYPE_FLOAT);
271 vec_push(value->expression.params, x);
273 /* <callsqrt> = sqrt((x * x) - 1); */
274 vec_push(callsqrt->params,
275 (ast_expression*)ast_binary_new(
278 (ast_expression*)ast_binary_new(
284 (ast_expression*)intrin->fold->imm_float[1]
288 /* <calllog> = log(x + <callsqrt>); */
289 vec_push(calllog->params,
290 (ast_expression*)ast_binary_new(
294 (ast_expression*)callsqrt
298 /* return <calllog>; */
299 vec_push(body->exprs,
300 (ast_expression*)ast_return_new(
302 (ast_expression*)calllog
306 vec_push(func->blocks, body);
307 intrin_reg(intrin, value, func);
308 return (ast_expression*)value;
311 static ast_expression *intrin_asinh(intrin_t *intrin) {
313 * float asinh(float x) {
314 * return log(x + sqrt((x * x) + 1));
317 ast_value *value = NULL;
318 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
319 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "asinh"));
320 ast_call *callsqrt = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "asinh"));
321 ast_block *body = ast_block_new(intrin_ctx(intrin));
322 ast_function *func = intrin_value(intrin, &value, "asinh", TYPE_FLOAT);
324 vec_push(value->expression.params, x);
326 /* <callsqrt> = sqrt((x * x) + 1); */
327 vec_push(callsqrt->params,
328 (ast_expression*)ast_binary_new(
331 (ast_expression*)ast_binary_new(
337 (ast_expression*)intrin->fold->imm_float[1]
341 /* <calllog> = log(x + <callsqrt>); */
342 vec_push(calllog->params,
343 (ast_expression*)ast_binary_new(
347 (ast_expression*)callsqrt
351 /* return <calllog>; */
352 vec_push(body->exprs,
353 (ast_expression*)ast_return_new(
355 (ast_expression*)calllog
359 vec_push(func->blocks, body);
360 intrin_reg(intrin, value, func);
361 return (ast_expression*)value;
364 static ast_expression *intrin_atanh(intrin_t *intrin) {
366 * float atanh(float x) {
367 * return 0.5 * log((1 + x) / (1 - x))
370 ast_value *value = NULL;
371 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
372 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "atanh"));
373 ast_block *body = ast_block_new(intrin_ctx(intrin));
374 ast_function *func = intrin_value(intrin, &value, "atanh", TYPE_FLOAT);
376 vec_push(value->expression.params, x);
378 /* <callog> = log((1 + x) / (1 - x)); */
379 vec_push(calllog->params,
380 (ast_expression*)ast_binary_new(
383 (ast_expression*)ast_binary_new(
386 (ast_expression*)intrin->fold->imm_float[1],
389 (ast_expression*)ast_binary_new(
392 (ast_expression*)intrin->fold->imm_float[1],
398 /* return 0.5 * <calllog>; */
399 vec_push(body->exprs,
400 (ast_expression*)ast_binary_new(
403 (ast_expression*)fold_constgen_float(intrin->fold, 0.5, false),
404 (ast_expression*)calllog
408 vec_push(func->blocks, body);
409 intrin_reg(intrin, value, func);
410 return (ast_expression*)value;
413 static ast_expression *intrin_exp(intrin_t *intrin) {
415 * float exp(float x) {
419 * for (i = 1; i < 200; ++i)
420 * sum += (acc *= x / i);
425 ast_value *value = NULL;
426 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
427 ast_value *sum = ast_value_new(intrin_ctx(intrin), "sum", TYPE_FLOAT);
428 ast_value *acc = ast_value_new(intrin_ctx(intrin), "acc", TYPE_FLOAT);
429 ast_value *i = ast_value_new(intrin_ctx(intrin), "i", TYPE_FLOAT);
430 ast_block *body = ast_block_new(intrin_ctx(intrin));
431 ast_function *func = intrin_value(intrin, &value, "exp", TYPE_FLOAT);
433 vec_push(value->expression.params, x);
434 vec_push(body->locals, sum);
435 vec_push(body->locals, acc);
436 vec_push(body->locals, i);
439 vec_push(body->exprs,
440 (ast_expression*)ast_store_new(
443 (ast_expression*)sum,
444 (ast_expression*)intrin->fold->imm_float[1]
449 vec_push(body->exprs,
450 (ast_expression*)ast_store_new(
453 (ast_expression*)acc,
454 (ast_expression*)intrin->fold->imm_float[1]
459 * for (i = 1; i < 200; ++i)
460 * sum += (acc *= x / i);
462 vec_push(body->exprs,
463 (ast_expression*)ast_loop_new(
466 (ast_expression*)ast_store_new(
470 (ast_expression*)intrin->fold->imm_float[1]
473 (ast_expression*)ast_binary_new(
477 (ast_expression*)fold_constgen_float(intrin->fold, 200.0f, false)
483 (ast_expression*)ast_binstore_new(
488 (ast_expression*)intrin->fold->imm_float[1]
490 /* sum += (acc *= (x / i)) */
491 (ast_expression*)ast_binstore_new(
495 (ast_expression*)sum,
496 (ast_expression*)ast_binstore_new(
500 (ast_expression*)acc,
501 (ast_expression*)ast_binary_new(
513 vec_push(body->exprs,
514 (ast_expression*)ast_return_new(
520 vec_push(func->blocks, body);
522 intrin_reg(intrin, value, func);
523 return (ast_expression*)value;
526 static ast_expression *intrin_exp2(intrin_t *intrin) {
528 * float exp2(float x) {
532 ast_value *value = NULL;
533 ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", "exp2"));
534 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
535 ast_block *body = ast_block_new(intrin_ctx(intrin));
536 ast_function *func = intrin_value(intrin, &value, "exp2", TYPE_FLOAT);
538 vec_push(value->expression.params, arg1);
540 vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]);
541 vec_push(callpow->params, (ast_expression*)arg1);
543 /* return <callpow> */
544 vec_push(body->exprs,
545 (ast_expression*)ast_return_new(
547 (ast_expression*)callpow
551 vec_push(func->blocks, body);
553 intrin_reg(intrin, value, func);
554 return (ast_expression*)value;
557 static ast_expression *intrin_expm1(intrin_t *intrin) {
559 * float expm1(float x) {
563 ast_value *value = NULL;
564 ast_call *callexp = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "exp", "expm1"));
565 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
566 ast_block *body = ast_block_new(intrin_ctx(intrin));
567 ast_function *func = intrin_value(intrin, &value, "expm1", TYPE_FLOAT);
569 vec_push(value->expression.params, x);
571 /* <callexp> = exp(x); */
572 vec_push(callexp->params, (ast_expression*)x);
574 /* return <callexp> - 1; */
575 vec_push(body->exprs,
576 (ast_expression*)ast_return_new(
578 (ast_expression*)ast_binary_new(
581 (ast_expression*)callexp,
582 (ast_expression*)intrin->fold->imm_float[1]
587 vec_push(func->blocks, body);
588 intrin_reg(intrin, value, func);
589 return (ast_expression*)value;
592 static ast_expression *intrin_pow(intrin_t *intrin) {
595 * float pow(float base, float exp) {
608 * return 1.0 / pow(base, -exp);
610 * result = pow(base, exp / 2);
611 * return result * result;
616 * square = sqrt(base);
617 * accumulate = square;
620 * while (fabs(mid - exp) > QC_POW_EPSILON) {
621 * square = sqrt(square);
624 * accumulate *= square;
627 * accumulate *= (1.0f / square);
629 * mid = (low + high) / 2;
634 ast_value *value = NULL;
635 ast_function *func = intrin_value(intrin, &value, "pow", TYPE_FLOAT);
637 /* prepare some calls for later */
638 ast_call *callpow1 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(base, -exp) */
639 ast_call *callpow2 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(vase, exp / 2) */
640 ast_call *callsqrt1 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(base) */
641 ast_call *callsqrt2 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(square) */
642 ast_call *callfabs = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "fabs", "pow")); /* for fabs(mid - exp) */
644 /* prepare some blocks for later */
645 ast_block *expgt1 = ast_block_new(intrin_ctx(intrin));
646 ast_block *midltexp = ast_block_new(intrin_ctx(intrin));
647 ast_block *midltexpelse = ast_block_new(intrin_ctx(intrin));
648 ast_block *whileblock = ast_block_new(intrin_ctx(intrin));
650 /* float pow(float base, float exp) */
651 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
652 ast_value *exp = ast_value_new(intrin_ctx(intrin), "exp", TYPE_FLOAT);
654 ast_block *body = ast_block_new(intrin_ctx(intrin));
664 ast_value *result = ast_value_new(intrin_ctx(intrin), "result", TYPE_FLOAT);
665 ast_value *low = ast_value_new(intrin_ctx(intrin), "low", TYPE_FLOAT);
666 ast_value *high = ast_value_new(intrin_ctx(intrin), "high", TYPE_FLOAT);
667 ast_value *square = ast_value_new(intrin_ctx(intrin), "square", TYPE_FLOAT);
668 ast_value *accumulate = ast_value_new(intrin_ctx(intrin), "accumulate", TYPE_FLOAT);
669 ast_value *mid = ast_value_new(intrin_ctx(intrin), "mid", TYPE_FLOAT);
670 vec_push(body->locals, result);
671 vec_push(body->locals, low);
672 vec_push(body->locals, high);
673 vec_push(body->locals, square);
674 vec_push(body->locals, accumulate);
675 vec_push(body->locals, mid);
677 vec_push(value->expression.params, base);
678 vec_push(value->expression.params, exp);
684 vec_push(body->exprs,
685 (ast_expression*)ast_ifthen_new(
687 (ast_expression*)ast_binary_new(
690 (ast_expression*)exp,
691 (ast_expression*)intrin->fold->imm_float[0]
693 (ast_expression*)ast_return_new(
695 (ast_expression*)intrin->fold->imm_float[1]
705 vec_push(body->exprs,
706 (ast_expression*)ast_ifthen_new(
708 (ast_expression*)ast_binary_new(
711 (ast_expression*)exp,
712 (ast_expression*)intrin->fold->imm_float[1]
714 (ast_expression*)ast_return_new(
716 (ast_expression*)base
722 /* <callpow1> = pow(base, -exp) */
723 vec_push(callpow1->params, (ast_expression*)base);
724 vec_push(callpow1->params,
725 (ast_expression*)ast_unary_new(
734 * return 1.0 / <callpow1>;
736 vec_push(body->exprs,
737 (ast_expression*)ast_ifthen_new(
739 (ast_expression*)ast_binary_new(
742 (ast_expression*)exp,
743 (ast_expression*)intrin->fold->imm_float[0]
745 (ast_expression*)ast_return_new(
747 (ast_expression*)ast_binary_new(
750 (ast_expression*)intrin->fold->imm_float[1],
751 (ast_expression*)callpow1
758 /* <callpow2> = pow(base, exp / 2) */
759 vec_push(callpow2->params, (ast_expression*)base);
760 vec_push(callpow2->params,
761 (ast_expression*)ast_binary_new(
764 (ast_expression*)exp,
765 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
771 * result = <callpow2>;
772 * return result * result;
775 vec_push(expgt1->exprs,
776 (ast_expression*)ast_store_new(
779 (ast_expression*)result,
780 (ast_expression*)callpow2
783 vec_push(expgt1->exprs,
784 (ast_expression*)ast_return_new(
786 (ast_expression*)ast_binary_new(
789 (ast_expression*)result,
790 (ast_expression*)result
800 vec_push(body->exprs,
801 (ast_expression*)ast_ifthen_new(
803 (ast_expression*)ast_binary_new(
806 (ast_expression*)exp,
807 (ast_expression*)intrin->fold->imm_float[1]
809 (ast_expression*)expgt1,
815 * <callsqrt1> = sqrt(base)
817 vec_push(callsqrt1->params, (ast_expression*)base);
822 * square = sqrt(base);
823 * accumulate = square;
826 vec_push(body->exprs,
827 (ast_expression*)ast_store_new(intrin_ctx(intrin),
829 (ast_expression*)low,
830 (ast_expression*)intrin->fold->imm_float[0]
833 vec_push(body->exprs,
834 (ast_expression*)ast_store_new(
837 (ast_expression*)high,
838 (ast_expression*)intrin->fold->imm_float[1]
842 vec_push(body->exprs,
843 (ast_expression*)ast_store_new(
846 (ast_expression*)square,
847 (ast_expression*)callsqrt1
851 vec_push(body->exprs,
852 (ast_expression*)ast_store_new(
855 (ast_expression*)accumulate,
856 (ast_expression*)square
859 vec_push(body->exprs,
860 (ast_expression*)ast_store_new(
863 (ast_expression*)mid,
864 (ast_expression*)ast_binary_new(
867 (ast_expression*)high,
868 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
876 * accumulate *= square;
879 vec_push(midltexp->exprs,
880 (ast_expression*)ast_store_new(
883 (ast_expression*)low,
887 vec_push(midltexp->exprs,
888 (ast_expression*)ast_binstore_new(
892 (ast_expression*)accumulate,
893 (ast_expression*)square
900 * accumulate *= (1.0 / square);
903 vec_push(midltexpelse->exprs,
904 (ast_expression*)ast_store_new(
907 (ast_expression*)high,
911 vec_push(midltexpelse->exprs,
912 (ast_expression*)ast_binstore_new(
916 (ast_expression*)accumulate,
917 (ast_expression*)ast_binary_new(
920 (ast_expression*)intrin->fold->imm_float[1],
921 (ast_expression*)square
927 * <callsqrt2> = sqrt(square)
929 vec_push(callsqrt2->params, (ast_expression*)square);
933 * square = <callsqrt2>;
939 * mid = (low + high) / 2;
942 vec_push(whileblock->exprs,
943 (ast_expression*)ast_store_new(
946 (ast_expression*)square,
947 (ast_expression*)callsqrt2
950 vec_push(whileblock->exprs,
951 (ast_expression*)ast_ifthen_new(
953 (ast_expression*)ast_binary_new(
956 (ast_expression*)mid,
959 (ast_expression*)midltexp,
960 (ast_expression*)midltexpelse
963 vec_push(whileblock->exprs,
964 (ast_expression*)ast_store_new(
967 (ast_expression*)mid,
968 (ast_expression*)ast_binary_new(
971 (ast_expression*)ast_binary_new(
974 (ast_expression*)low,
975 (ast_expression*)high
977 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
983 * <callabs> = fabs(mid - exp)
985 vec_push(callfabs->params,
986 (ast_expression*)ast_binary_new(
989 (ast_expression*)mid,
995 * while (<callfabs> > epsilon)
998 vec_push(body->exprs,
999 (ast_expression*)ast_loop_new(
1004 (ast_expression*)ast_binary_new(
1007 (ast_expression*)callfabs,
1008 (ast_expression*)fold_constgen_float(intrin->fold, QC_POW_EPSILON, false)
1012 /* post condition */
1016 /* increment expression */
1019 (ast_expression*)whileblock
1023 /* return accumulate */
1024 vec_push(body->exprs,
1025 (ast_expression*)ast_return_new(
1027 (ast_expression*)accumulate
1032 vec_push(func->blocks, body);
1034 intrin_reg(intrin, value, func);
1035 return (ast_expression*)value;
1038 static ast_expression *intrin_mod(intrin_t *intrin) {
1040 * float mod(float a, float b) {
1041 * float div = a / b;
1042 * float sign = (div < 0.0f) ? -1 : 1;
1043 * return a - b * sign * floor(sign * div);
1046 ast_value *value = NULL;
1047 ast_call *call = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", "mod"));
1048 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1049 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1050 ast_value *div = ast_value_new(intrin_ctx(intrin), "div", TYPE_FLOAT);
1051 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1052 ast_block *body = ast_block_new(intrin_ctx(intrin));
1053 ast_function *func = intrin_value(intrin, &value, "mod", TYPE_FLOAT);
1055 vec_push(value->expression.params, a);
1056 vec_push(value->expression.params, b);
1058 vec_push(body->locals, div);
1059 vec_push(body->locals, sign);
1062 vec_push(body->exprs,
1063 (ast_expression*)ast_store_new(
1066 (ast_expression*)div,
1067 (ast_expression*)ast_binary_new(
1076 /* sign = (div < 0.0f) ? -1 : 1; */
1077 vec_push(body->exprs,
1078 (ast_expression*)ast_store_new(
1081 (ast_expression*)sign,
1082 (ast_expression*)ast_ternary_new(
1084 (ast_expression*)ast_binary_new(
1087 (ast_expression*)div,
1088 (ast_expression*)intrin->fold->imm_float[0]
1090 (ast_expression*)intrin->fold->imm_float[2],
1091 (ast_expression*)intrin->fold->imm_float[1]
1096 /* floor(sign * div) */
1097 vec_push(call->params,
1098 (ast_expression*)ast_binary_new(
1101 (ast_expression*)sign,
1102 (ast_expression*)div
1106 /* return a - b * sign * <call> */
1107 vec_push(body->exprs,
1108 (ast_expression*)ast_return_new(
1110 (ast_expression*)ast_binary_new(
1114 (ast_expression*)ast_binary_new(
1118 (ast_expression*)ast_binary_new(
1121 (ast_expression*)sign,
1122 (ast_expression*)call
1129 vec_push(func->blocks, body);
1130 intrin_reg(intrin, value, func);
1132 return (ast_expression*)value;
1135 static ast_expression *intrin_fabs(intrin_t *intrin) {
1137 * float fabs(float x) {
1138 * return x < 0 ? -x : x;
1141 ast_value *value = NULL;
1142 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1143 ast_block *body = ast_block_new(intrin_ctx(intrin));
1144 ast_function *func = intrin_value(intrin, &value, "fabs", TYPE_FLOAT);
1146 vec_push(body->exprs,
1147 (ast_expression*)ast_return_new(
1149 (ast_expression*)ast_ternary_new(
1151 (ast_expression*)ast_binary_new(
1154 (ast_expression*)arg1,
1155 (ast_expression*)intrin->fold->imm_float[0]
1157 (ast_expression*)ast_unary_new(
1160 (ast_expression*)arg1
1162 (ast_expression*)arg1
1167 vec_push(value->expression.params, arg1);
1168 vec_push(func->blocks, body);
1170 intrin_reg(intrin, value, func);
1172 return (ast_expression*)value;
1175 static ast_expression *intrin_epsilon(intrin_t *intrin) {
1177 * float epsilon(void) {
1179 * do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1183 ast_value *value = NULL;
1184 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1185 ast_block *body = ast_block_new(intrin_ctx(intrin));
1186 ast_function *func = intrin_value(intrin, &value, "epsilon", TYPE_FLOAT);
1188 vec_push(body->locals, eps);
1191 vec_push(body->exprs,
1192 (ast_expression*)ast_store_new(
1195 (ast_expression*)eps,
1196 (ast_expression*)intrin->fold->imm_float[0]
1200 vec_push(body->exprs,
1201 (ast_expression*)ast_loop_new(
1206 (ast_expression*)ast_binary_new(
1209 (ast_expression*)ast_binary_new(
1212 (ast_expression*)intrin->fold->imm_float[1],
1213 (ast_expression*)ast_binary_new(
1216 (ast_expression*)eps,
1217 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1220 (ast_expression*)intrin->fold->imm_float[1]
1224 (ast_expression*)ast_binstore_new(
1228 (ast_expression*)eps,
1229 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1235 vec_push(body->exprs,
1236 (ast_expression*)ast_return_new(
1238 (ast_expression*)eps
1242 vec_push(func->blocks, body);
1243 intrin_reg(intrin, value, func);
1245 return (ast_expression*)value;
1248 static ast_expression *intrin_nan(intrin_t *intrin) {
1255 ast_value *value = NULL;
1256 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1257 ast_function *func = intrin_value(intrin, &value, "nan", TYPE_FLOAT);
1258 ast_block *block = ast_block_new(intrin_ctx(intrin));
1260 vec_push(block->locals, x);
1262 vec_push(block->exprs,
1263 (ast_expression*)ast_store_new(
1267 (ast_expression*)intrin->fold->imm_float[0]
1271 vec_push(block->exprs,
1272 (ast_expression*)ast_return_new(
1274 (ast_expression*)ast_binary_new(
1283 vec_push(func->blocks, block);
1284 intrin_reg(intrin, value, func);
1286 return (ast_expression*)value;
1289 static ast_expression *intrin_inf(intrin_t *intrin) {
1297 ast_value *value = NULL;
1298 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1299 ast_value *y = ast_value_new(intrin_ctx(intrin), "y", TYPE_FLOAT);
1300 ast_function *func = intrin_value(intrin, &value, "inf", TYPE_FLOAT);
1301 ast_block *block = ast_block_new(intrin_ctx(intrin));
1304 vec_push(block->locals, x);
1305 vec_push(block->locals, y);
1307 /* to keep code size down */
1308 for (i = 0; i <= 1; i++) {
1309 vec_push(block->exprs,
1310 (ast_expression*)ast_store_new(
1313 (ast_expression*)((i == 0) ? x : y),
1314 (ast_expression*)intrin->fold->imm_float[i]
1319 vec_push(block->exprs,
1320 (ast_expression*)ast_return_new(
1322 (ast_expression*)ast_binary_new(
1331 vec_push(func->blocks, block);
1332 intrin_reg(intrin, value, func);
1334 return (ast_expression*)value;
1337 static ast_expression *intrin_ln(intrin_t *intrin) {
1339 * float log(float power, float base) {
1342 * float sign = 1.0f;
1343 * float eps = epsilon();
1345 * if (power <= 1.0f || bbase <= 1.0) {
1346 * if (power <= 0.0f || base <= 0.0f)
1349 * if (power < 1.0f) {
1350 * power = 1.0f / power;
1354 * if (base < 1.0f) {
1356 * base = 1.0f / base;
1362 * float A_iminus1 = 0;
1363 * float B_iminus1 = 1;
1369 * while (whole >= base) {
1370 * float base2 = base;
1372 * float newbase2 = base2 * base2;
1374 * while (whole >= newbase2) {
1377 * newbase2 *= newbase2;
1384 * float b_iplus1 = n;
1385 * float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1386 * float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1393 * if (whole <= 1.0f + eps)
1399 * return sign * A_i / B_i;
1403 ast_value *value = NULL;
1404 ast_value *power = ast_value_new(intrin_ctx(intrin), "power", TYPE_FLOAT);
1405 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
1406 ast_value *whole = ast_value_new(intrin_ctx(intrin), "whole", TYPE_FLOAT);
1407 ast_value *nth = ast_value_new(intrin_ctx(intrin), "nth", TYPE_FLOAT);
1408 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1409 ast_value *A_i = ast_value_new(intrin_ctx(intrin), "A_i", TYPE_FLOAT);
1410 ast_value *B_i = ast_value_new(intrin_ctx(intrin), "B_i", TYPE_FLOAT);
1411 ast_value *A_iminus1 = ast_value_new(intrin_ctx(intrin), "A_iminus1", TYPE_FLOAT);
1412 ast_value *B_iminus1 = ast_value_new(intrin_ctx(intrin), "B_iminus1", TYPE_FLOAT);
1413 ast_value *b_iplus1 = ast_value_new(intrin_ctx(intrin), "b_iplus1", TYPE_FLOAT);
1414 ast_value *A_iplus1 = ast_value_new(intrin_ctx(intrin), "A_iplus1", TYPE_FLOAT);
1415 ast_value *B_iplus1 = ast_value_new(intrin_ctx(intrin), "B_iplus1", TYPE_FLOAT);
1416 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1417 ast_value *base2 = ast_value_new(intrin_ctx(intrin), "base2", TYPE_FLOAT);
1418 ast_value *n2 = ast_value_new(intrin_ctx(intrin), "n2", TYPE_FLOAT);
1419 ast_value *newbase2 = ast_value_new(intrin_ctx(intrin), "newbase2", TYPE_FLOAT);
1420 ast_block *block = ast_block_new(intrin_ctx(intrin));
1421 ast_block *plt1orblt1 = ast_block_new(intrin_ctx(intrin)); /* (power <= 1.0f || base <= 1.0f) */
1422 ast_block *plt1 = ast_block_new(intrin_ctx(intrin)); /* (power < 1.0f) */
1423 ast_block *blt1 = ast_block_new(intrin_ctx(intrin)); /* (base < 1.0f) */
1424 ast_block *forloop = ast_block_new(intrin_ctx(intrin)); /* for(;;) */
1425 ast_block *whileloop = ast_block_new(intrin_ctx(intrin)); /* while (whole >= base) */
1426 ast_block *nestwhile = ast_block_new(intrin_ctx(intrin)); /* while (whole >= newbase2) */
1427 ast_function *func = intrin_value(intrin, &value, "ln", TYPE_FLOAT);
1430 vec_push(value->expression.params, power);
1431 vec_push(value->expression.params, base);
1433 vec_push(block->locals, whole);
1434 vec_push(block->locals, nth);
1435 vec_push(block->locals, sign);
1436 vec_push(block->locals, eps);
1437 vec_push(block->locals, A_i);
1438 vec_push(block->locals, B_i);
1439 vec_push(block->locals, A_iminus1);
1440 vec_push(block->locals, B_iminus1);
1443 vec_push(block->exprs,
1444 (ast_expression*)ast_store_new(
1447 (ast_expression*)sign,
1448 (ast_expression*)intrin->fold->imm_float[1]
1452 /* eps = __builtin_epsilon(); */
1453 vec_push(block->exprs,
1454 (ast_expression*)ast_store_new(
1457 (ast_expression*)eps,
1458 (ast_expression*)ast_call_new(
1460 intrin_func_self(intrin, "__builtin_epsilon", "ln")
1471 for (i = 0; i <= 1; i++) {
1473 for (j = 1; j >= 0; j--) {
1474 vec_push(block->exprs,
1475 (ast_expression*)ast_store_new(
1478 (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1479 : ((i) ? A_iminus1 : B_i)),
1480 (ast_expression*)intrin->fold->imm_float[j]
1488 * power = 1.0f / power;
1492 * base = 1.0f / base;
1496 for (i = 0; i <= 1; i++) {
1497 vec_push(((i) ? blt1 : plt1)->exprs,
1498 (ast_expression*)ast_store_new(
1501 (ast_expression*)((i) ? base : power),
1502 (ast_expression*)ast_binary_new(
1505 (ast_expression*)intrin->fold->imm_float[1],
1506 (ast_expression*)((i) ? base : power)
1510 vec_push(plt1->exprs,
1511 (ast_expression*)ast_binstore_new(
1515 (ast_expression*)sign,
1516 (ast_expression*)intrin->fold->imm_float[2]
1523 * if (power <= 0.0 || base <= 0.0f)
1524 * return __builtin_nan();
1531 vec_push(plt1orblt1->exprs,
1532 (ast_expression*)ast_ifthen_new(
1534 (ast_expression*)ast_binary_new(
1537 (ast_expression*)ast_binary_new(
1540 (ast_expression*)power,
1541 (ast_expression*)intrin->fold->imm_float[0]
1543 (ast_expression*)ast_binary_new(
1546 (ast_expression*)base,
1547 (ast_expression*)intrin->fold->imm_float[0]
1550 (ast_expression*)ast_return_new(
1552 (ast_expression*)ast_call_new(
1554 intrin_func_self(intrin, "__builtin_nan", "ln")
1561 for (i = 0; i <= 1; i++) {
1562 vec_push(plt1orblt1->exprs,
1563 (ast_expression*)ast_ifthen_new(
1565 (ast_expression*)ast_binary_new(
1568 (ast_expression*)((i) ? base : power),
1569 (ast_expression*)intrin->fold->imm_float[1]
1571 (ast_expression*)((i) ? blt1 : plt1),
1577 vec_push(block->exprs, (ast_expression*)plt1orblt1);
1580 /* whole = power; */
1581 vec_push(forloop->exprs,
1582 (ast_expression*)ast_store_new(
1585 (ast_expression*)whole,
1586 (ast_expression*)power
1591 vec_push(forloop->exprs,
1592 (ast_expression*)ast_store_new(
1595 (ast_expression*)nth,
1596 (ast_expression*)intrin->fold->imm_float[0]
1601 vec_push(whileloop->exprs,
1602 (ast_expression*)ast_store_new(
1605 (ast_expression*)base2,
1606 (ast_expression*)base
1611 vec_push(whileloop->exprs,
1612 (ast_expression*)ast_store_new(
1615 (ast_expression*)n2,
1616 (ast_expression*)intrin->fold->imm_float[1]
1620 /* newbase2 = base2 * base2; */
1621 vec_push(whileloop->exprs,
1622 (ast_expression*)ast_store_new(
1625 (ast_expression*)newbase2,
1626 (ast_expression*)ast_binary_new(
1629 (ast_expression*)base2,
1630 (ast_expression*)base2
1635 /* while loop locals */
1636 vec_push(whileloop->locals, base2);
1637 vec_push(whileloop->locals, n2);
1638 vec_push(whileloop->locals, newbase2);
1640 /* base2 = newbase2; */
1641 vec_push(nestwhile->exprs,
1642 (ast_expression*)ast_store_new(
1645 (ast_expression*)base2,
1646 (ast_expression*)newbase2
1651 vec_push(nestwhile->exprs,
1652 (ast_expression*)ast_binstore_new(
1656 (ast_expression*)n2,
1657 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1661 /* newbase2 *= newbase2; */
1662 vec_push(nestwhile->exprs,
1663 (ast_expression*)ast_binstore_new(
1667 (ast_expression*)newbase2,
1668 (ast_expression*)newbase2
1672 /* while (whole >= newbase2) */
1673 vec_push(whileloop->exprs,
1674 (ast_expression*)ast_loop_new(
1677 (ast_expression*)ast_binary_new(
1680 (ast_expression*)whole,
1681 (ast_expression*)newbase2
1687 (ast_expression*)nestwhile
1691 /* whole /= base2; */
1692 vec_push(whileloop->exprs,
1693 (ast_expression*)ast_binstore_new(
1697 (ast_expression*)whole,
1698 (ast_expression*)base2
1703 vec_push(whileloop->exprs,
1704 (ast_expression*)ast_binstore_new(
1708 (ast_expression*)nth,
1713 /* while (whole >= base) */
1714 vec_push(forloop->exprs,
1715 (ast_expression*)ast_loop_new(
1718 (ast_expression*)ast_binary_new(
1721 (ast_expression*)whole,
1722 (ast_expression*)base
1728 (ast_expression*)whileloop
1732 vec_push(forloop->locals, b_iplus1);
1733 vec_push(forloop->locals, A_iplus1);
1734 vec_push(forloop->locals, B_iplus1);
1736 /* b_iplus1 = nth; */
1737 vec_push(forloop->exprs,
1738 (ast_expression*)ast_store_new(
1741 (ast_expression*)b_iplus1,
1742 (ast_expression*)nth
1747 * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1748 * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1750 for (i = 0; i <= 1; i++) {
1751 vec_push(forloop->exprs,
1752 (ast_expression*)ast_store_new(
1755 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1756 (ast_expression*)ast_binary_new(
1759 (ast_expression*)ast_binary_new(
1762 (ast_expression*)b_iplus1,
1763 (ast_expression*) ((i) ? B_i : A_i)
1765 (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1775 for (i = 0; i <= 1; i++) {
1776 vec_push(forloop->exprs,
1777 (ast_expression*)ast_store_new(
1780 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1781 (ast_expression*)((i) ? B_i : A_i)
1790 for (i = 0; i <= 1; i++) {
1791 vec_push(forloop->exprs,
1792 (ast_expression*)ast_store_new(
1795 (ast_expression*)((i) ? B_i : A_i),
1796 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1802 * if (whole <= 1.0f + eps)
1805 vec_push(forloop->exprs,
1806 (ast_expression*)ast_ifthen_new(
1808 (ast_expression*)ast_binary_new(
1811 (ast_expression*)whole,
1812 (ast_expression*)ast_binary_new(
1815 (ast_expression*)intrin->fold->imm_float[1],
1816 (ast_expression*)eps
1819 (ast_expression*)ast_breakcont_new(
1832 for (i = 0; i <= 1; i++) {
1833 vec_push(forloop->exprs,
1834 (ast_expression*)ast_store_new(
1837 (ast_expression*)((i) ? base : power),
1838 (ast_expression*)((i) ? whole : base)
1843 /* add the for loop block */
1844 vec_push(block->exprs,
1845 (ast_expression*)ast_loop_new(
1848 /* for(; 1; ) ?? (can this be NULL too?) */
1849 (ast_expression*)intrin->fold->imm_float[1],
1854 (ast_expression*)forloop
1858 /* return sign * A_i / B_il */
1859 vec_push(block->exprs,
1860 (ast_expression*)ast_return_new(
1862 (ast_expression*)ast_binary_new(
1865 (ast_expression*)sign,
1866 (ast_expression*)ast_binary_new(
1869 (ast_expression*)A_i,
1870 (ast_expression*)B_i
1876 vec_push(func->blocks, block);
1877 intrin_reg(intrin, value, func);
1879 return (ast_expression*)value;
1882 static ast_expression *intrin_log_variant(intrin_t *intrin, const char *name, float base) {
1883 ast_value *value = NULL;
1884 ast_call *callln = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "__builtin_ln", name));
1885 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1886 ast_block *body = ast_block_new(intrin_ctx(intrin));
1887 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1889 vec_push(value->expression.params, arg1);
1891 vec_push(callln->params, (ast_expression*)arg1);
1892 vec_push(callln->params, (ast_expression*)fold_constgen_float(intrin->fold, base, false));
1894 vec_push(body->exprs,
1895 (ast_expression*)ast_return_new(
1897 (ast_expression*)callln
1901 vec_push(func->blocks, body);
1902 intrin_reg(intrin, value, func);
1903 return (ast_expression*)value;
1906 static ast_expression *intrin_log(intrin_t *intrin) {
1907 return intrin_log_variant(intrin, "log", 2.7182818284590452354);
1909 static ast_expression *intrin_log10(intrin_t *intrin) {
1910 return intrin_log_variant(intrin, "log10", 10);
1912 static ast_expression *intrin_log2(intrin_t *intrin) {
1913 return intrin_log_variant(intrin, "log2", 2);
1915 static ast_expression *intrin_logb(intrin_t *intrin) {
1916 /* FLT_RADIX == 2 for now */
1917 return intrin_log_variant(intrin, "log2", 2);
1920 static ast_expression *intrin_shift_variant(intrin_t *intrin, const char *name, size_t instr) {
1922 * float [shift] (float a, float b) {
1923 * return floor(a [instr] pow(2, b));
1925 ast_value *value = NULL;
1926 ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name));
1927 ast_call *callfloor = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", name));
1928 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1929 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1930 ast_block *body = ast_block_new(intrin_ctx(intrin));
1931 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1933 vec_push(value->expression.params, a);
1934 vec_push(value->expression.params, b);
1936 /* <callpow> = pow(2, b) */
1937 vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]);
1938 vec_push(callpow->params, (ast_expression*)b);
1940 /* <callfloor> = floor(a [instr] <callpow>) */
1943 (ast_expression*)ast_binary_new(
1947 (ast_expression*)callpow
1951 /* return <callfloor> */
1952 vec_push(body->exprs,
1953 (ast_expression*)ast_return_new(
1955 (ast_expression*)callfloor
1959 vec_push(func->blocks, body);
1960 intrin_reg(intrin, value, func);
1961 return (ast_expression*)value;
1964 static ast_expression *intrin_lshift(intrin_t *intrin) {
1965 return intrin_shift_variant(intrin, "lshift", INSTR_MUL_F);
1968 static ast_expression *intrin_rshift(intrin_t *intrin) {
1969 return intrin_shift_variant(intrin, "rshift", INSTR_DIV_F);
1973 * TODO: make static (and handle ast_type_string) here for the builtin
1974 * instead of in SYA parse close.
1976 ast_expression *intrin_debug_typestring(intrin_t *intrin) {
1978 return (ast_expression*)0x1;
1981 static const intrin_func_t intrinsics[] = {
1982 {&intrin_isfinite, "__builtin_isfinite", "isfinite", 1},
1983 {&intrin_isinf, "__builtin_isinf", "isinf", 1},
1984 {&intrin_isnan, "__builtin_isnan", "isnan", 1},
1985 {&intrin_isnormal, "__builtin_isnormal", "isnormal", 1},
1986 {&intrin_signbit, "__builtin_signbit", "signbit", 1},
1987 {&intrin_acosh, "__builtin_acosh", "acosh", 1},
1988 {&intrin_asinh, "__builtin_asinh", "asinh", 1},
1989 {&intrin_atanh, "__builtin_atanh", "atanh", 1},
1990 {&intrin_exp, "__builtin_exp", "exp", 1},
1991 {&intrin_exp2, "__builtin_exp2", "exp2", 1},
1992 {&intrin_expm1, "__builtin_expm1", "expm1", 1},
1993 {&intrin_mod, "__builtin_mod", "mod", 2},
1994 {&intrin_pow, "__builtin_pow", "pow", 2},
1995 {&intrin_fabs, "__builtin_fabs", "fabs", 1},
1996 {&intrin_log, "__builtin_log", "log", 1},
1997 {&intrin_log10, "__builtin_log10", "log10", 1},
1998 {&intrin_log2, "__builtin_log2", "log2", 1},
1999 {&intrin_logb, "__builtin_logb", "logb", 1},
2000 {&intrin_lshift, "__builtin_lshift", "", 2},
2001 {&intrin_rshift, "__builtin_rshift", "", 2},
2002 {&intrin_epsilon, "__builtin_epsilon", "", 0},
2003 {&intrin_nan, "__builtin_nan", "", 0},
2004 {&intrin_inf, "__builtin_inf", "", 0},
2005 {&intrin_ln, "__builtin_ln", "", 2},
2006 {&intrin_debug_typestring, "__builtin_debug_typestring", "", 0},
2007 {&intrin_nullfunc, "#nullfunc", "", 0}
2010 static void intrin_error(intrin_t *intrin, const char *fmt, ...) {
2013 vcompile_error(intrin->parser->lex->tok.ctx, fmt, ap);
2018 intrin_t *intrin_init(parser_t *parser) {
2019 intrin_t *intrin = (intrin_t*)mem_a(sizeof(intrin_t));
2022 intrin->parser = parser;
2023 intrin->fold = parser->fold;
2024 intrin->intrinsics = NULL;
2025 intrin->generated = NULL;
2027 vec_append(intrin->intrinsics, GMQCC_ARRAY_COUNT(intrinsics), intrinsics);
2029 /* populate with null pointers for tracking generation */
2030 for (i = 0; i < GMQCC_ARRAY_COUNT(intrinsics); i++)
2031 vec_push(intrin->generated, NULL);
2036 void intrin_cleanup(intrin_t *intrin) {
2037 vec_free(intrin->intrinsics);
2038 vec_free(intrin->generated);
2042 ast_expression *intrin_fold(intrin_t *intrin, ast_value *value, ast_expression **exprs) {
2044 if (!value || !value->name)
2046 for (i = 0; i < vec_size(intrin->intrinsics); i++)
2047 if (!strcmp(value->name, intrin->intrinsics[i].name))
2048 return (vec_size(exprs) != intrin->intrinsics[i].args)
2050 : fold_intrin(intrin->fold, value->name + 10, exprs);
2054 static GMQCC_INLINE ast_expression *intrin_func_try(intrin_t *intrin, size_t offset, const char *compare) {
2056 for (i = 0; i < vec_size(intrin->intrinsics); i++) {
2057 if (strcmp(*(char **)((char *)&intrin->intrinsics[i] + offset), compare))
2059 if (intrin->generated[i])
2060 return intrin->generated[i];
2061 return intrin->generated[i] = intrin->intrinsics[i].intrin(intrin);
2066 static ast_expression *intrin_func_self(intrin_t *intrin, const char *name, const char *from) {
2068 ast_expression *find;
2070 /* try current first */
2071 if ((find = parser_find_global(intrin->parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
2072 for (i = 0; i < vec_size(intrin->parser->functions); ++i)
2073 if (((ast_value*)find)->name && !strcmp(intrin->parser->functions[i]->name, ((ast_value*)find)->name) && intrin->parser->functions[i]->builtin < 0)
2075 /* try name second */
2076 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, name), name)))
2078 /* try alias third */
2079 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, alias), name)))
2083 intrin_error(intrin, "need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2084 return intrin_func_self(intrin, "#nullfunc", NULL);
2089 ast_expression *intrin_func(intrin_t *intrin, const char *name) {
2090 return intrin_func_self(intrin, name, NULL);