4 #define intrin_ctx(I) parser_ctx((I)->parser)
6 static GMQCC_INLINE ast_function *intrin_value(intrin_t *intrin, ast_value **out, const char *name, qcint_t vtype) {
7 ast_value *value = NULL;
8 ast_function *func = NULL;
12 util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
13 util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]);
15 value = ast_value_new(intrin_ctx(intrin), buffer, TYPE_FUNCTION);
16 value->intrinsic = true;
17 value->expression.next = (ast_expression*)ast_value_new(intrin_ctx(intrin), stype, vtype);
18 func = ast_function_new(intrin_ctx(intrin), buffer, value);
19 value->expression.flags |= AST_FLAG_ERASEABLE;
25 static GMQCC_INLINE void intrin_reg(intrin_t *intrin, ast_value *const value, ast_function *const func) {
26 vec_push(intrin->parser->functions, func);
27 vec_push(intrin->parser->globals, (ast_expression*)value);
30 #define QC_POW_EPSILON 0.00001f
33 * since some intrinsics depend on each other there is the possibility
34 * that an intrinsic will fail to get a 'depended' function that a
35 * builtin needs, causing some dependency in the chain to have a NULL
36 * function. This will cause a segmentation fault at code generation,
37 * even though an error was raised. To contiue to allow it (instead
38 * of stopping compilation right away). We need to return from the
39 * parser, before compilation stops after all the collected errors.
41 static ast_expression *intrin_func_self(intrin_t *intrin, const char *name, const char *from);
42 static ast_expression *intrin_nullfunc(intrin_t *intrin) {
43 ast_value *value = NULL;
44 ast_function *func = intrin_value(intrin, &value, NULL, TYPE_VOID);
45 intrin_reg(intrin, value, func);
46 return (ast_expression*)value;
49 static ast_expression *intrin_isfinite(intrin_t *intrin) {
51 * float isfinite(float x) {
52 * return !(isnan(x) || isinf(x));
55 ast_value *value = NULL;
56 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
57 ast_function *func = intrin_value(intrin, &value, "isfinite", TYPE_FLOAT);
58 ast_call *callisnan = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "isnan", "isfinite"));
59 ast_call *callisinf = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "isinf", "isfinite"));
60 ast_block *block = ast_block_new(intrin_ctx(intrin));
63 vec_push(value->expression.params, x);
65 /* <callisnan> = isnan(x); */
66 vec_push(callisnan->params, (ast_expression*)x);
68 /* <callisinf> = isinf(x); */
69 vec_push(callisinf->params, (ast_expression*)x);
71 /* return (!<callisnan> || <callisinf>); */
72 vec_push(block->exprs,
73 (ast_expression*)ast_return_new(
75 (ast_expression*)ast_unary_new(
78 (ast_expression*)ast_binary_new(
81 (ast_expression*)callisnan,
82 (ast_expression*)callisinf
88 vec_push(func->blocks, block);
89 intrin_reg(intrin, value, func);
91 return (ast_expression*)value;;
94 static ast_expression *intrin_isinf(intrin_t *intrin) {
96 * float isinf(float x) {
97 * return (x != 0.0) && (x + x == x);
100 ast_value *value = NULL;
101 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
102 ast_block *body = ast_block_new(intrin_ctx(intrin));
103 ast_function *func = intrin_value(intrin, &value, "isinf", TYPE_FLOAT);
105 vec_push(body->exprs,
106 (ast_expression*)ast_return_new(
108 (ast_expression*)ast_binary_new(
111 (ast_expression*)ast_binary_new(
115 (ast_expression*)intrin->fold->imm_float[0]
117 (ast_expression*)ast_binary_new(
120 (ast_expression*)ast_binary_new(
132 vec_push(value->expression.params, x);
133 vec_push(func->blocks, body);
135 intrin_reg(intrin, value, func);
137 return (ast_expression*)value;
140 static ast_expression *intrin_isnan(intrin_t *intrin) {
142 * float isnan(float x) {
146 * return (x != local);
149 ast_value *value = NULL;
150 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
151 ast_value *local = ast_value_new(intrin_ctx(intrin), "local", TYPE_FLOAT);
152 ast_block *body = ast_block_new(intrin_ctx(intrin));
153 ast_function *func = intrin_value(intrin, &value, "isnan", TYPE_FLOAT);
155 vec_push(body->locals, local);
156 vec_push(body->exprs,
157 (ast_expression*)ast_store_new(
160 (ast_expression*)local,
161 (ast_expression*)arg1
165 vec_push(body->exprs,
166 (ast_expression*)ast_return_new(
168 (ast_expression*)ast_binary_new(
171 (ast_expression*)arg1,
172 (ast_expression*)local
177 vec_push(value->expression.params, arg1);
178 vec_push(func->blocks, body);
180 intrin_reg(intrin, value, func);
182 return (ast_expression*)value;
185 static ast_expression *intrin_isnormal(intrin_t *intrin) {
187 * float isnormal(float x) {
188 * return isfinite(x);
191 ast_value *value = NULL;
192 ast_call *callisfinite = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "isfinite", "isnormal"));
193 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
194 ast_block *body = ast_block_new(intrin_ctx(intrin));
195 ast_function *func = intrin_value(intrin, &value, "isnormal", TYPE_FLOAT);
197 vec_push(value->expression.params, x);
198 vec_push(callisfinite->params, (ast_expression*)x);
200 /* return <callisfinite> */
201 vec_push(body->exprs,
202 (ast_expression*)ast_return_new(
204 (ast_expression*)callisfinite
208 vec_push(func->blocks, body);
209 intrin_reg(intrin, value, func);
210 return (ast_expression*)value;
213 static ast_expression *intrin_signbit(intrin_t *intrin) {
215 * float signbit(float x) {
219 ast_value *value = NULL;
220 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
221 ast_block *body = ast_block_new(intrin_ctx(intrin));
222 ast_function *func = intrin_value(intrin, &value, "signbit", TYPE_FLOAT);
224 vec_push(value->expression.params, x);
226 /* return (x < 0); */
227 vec_push(body->exprs,
228 (ast_expression*)ast_return_new(
230 (ast_expression*)ast_ternary_new(
232 (ast_expression*)ast_binary_new(
236 (ast_expression*)intrin->fold->imm_float[0]
238 (ast_expression*)intrin->fold->imm_float[1],
239 (ast_expression*)intrin->fold->imm_float[0]
244 vec_push(func->blocks, body);
245 intrin_reg(intrin, value, func);
246 return (ast_expression*)value;
249 static ast_expression *intrin_acosh(intrin_t *intrin) {
251 * float acosh(float x) {
252 * return log(x + sqrt((x * x) - 1));
255 ast_value *value = NULL;
256 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
257 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "acosh"));
258 ast_call *callsqrt = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "acosh"));
259 ast_block *body = ast_block_new(intrin_ctx(intrin));
260 ast_function *func = intrin_value(intrin, &value, "acosh", TYPE_FLOAT);
262 vec_push(value->expression.params, x);
264 /* <callsqrt> = sqrt((x * x) - 1); */
265 vec_push(callsqrt->params,
266 (ast_expression*)ast_binary_new(
269 (ast_expression*)ast_binary_new(
275 (ast_expression*)intrin->fold->imm_float[1]
279 /* <calllog> = log(x + <callsqrt>); */
280 vec_push(calllog->params,
281 (ast_expression*)ast_binary_new(
285 (ast_expression*)callsqrt
289 /* return <calllog>; */
290 vec_push(body->exprs,
291 (ast_expression*)ast_return_new(
293 (ast_expression*)calllog
297 vec_push(func->blocks, body);
298 intrin_reg(intrin, value, func);
299 return (ast_expression*)value;
302 static ast_expression *intrin_asinh(intrin_t *intrin) {
304 * float asinh(float x) {
305 * return log(x + sqrt((x * x) + 1));
308 ast_value *value = NULL;
309 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
310 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "asinh"));
311 ast_call *callsqrt = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "asinh"));
312 ast_block *body = ast_block_new(intrin_ctx(intrin));
313 ast_function *func = intrin_value(intrin, &value, "asinh", TYPE_FLOAT);
315 vec_push(value->expression.params, x);
317 /* <callsqrt> = sqrt((x * x) + 1); */
318 vec_push(callsqrt->params,
319 (ast_expression*)ast_binary_new(
322 (ast_expression*)ast_binary_new(
328 (ast_expression*)intrin->fold->imm_float[1]
332 /* <calllog> = log(x + <callsqrt>); */
333 vec_push(calllog->params,
334 (ast_expression*)ast_binary_new(
338 (ast_expression*)callsqrt
342 /* return <calllog>; */
343 vec_push(body->exprs,
344 (ast_expression*)ast_return_new(
346 (ast_expression*)calllog
350 vec_push(func->blocks, body);
351 intrin_reg(intrin, value, func);
352 return (ast_expression*)value;
355 static ast_expression *intrin_atanh(intrin_t *intrin) {
357 * float atanh(float x) {
358 * return 0.5 * log((1 + x) / (1 - x))
361 ast_value *value = NULL;
362 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
363 ast_call *calllog = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "log", "atanh"));
364 ast_block *body = ast_block_new(intrin_ctx(intrin));
365 ast_function *func = intrin_value(intrin, &value, "atanh", TYPE_FLOAT);
367 vec_push(value->expression.params, x);
369 /* <callog> = log((1 + x) / (1 - x)); */
370 vec_push(calllog->params,
371 (ast_expression*)ast_binary_new(
374 (ast_expression*)ast_binary_new(
377 (ast_expression*)intrin->fold->imm_float[1],
380 (ast_expression*)ast_binary_new(
383 (ast_expression*)intrin->fold->imm_float[1],
389 /* return 0.5 * <calllog>; */
390 vec_push(body->exprs,
391 (ast_expression*)ast_binary_new(
394 (ast_expression*)fold_constgen_float(intrin->fold, 0.5, false),
395 (ast_expression*)calllog
399 vec_push(func->blocks, body);
400 intrin_reg(intrin, value, func);
401 return (ast_expression*)value;
404 static ast_expression *intrin_exp(intrin_t *intrin) {
406 * float exp(float x) {
410 * for (i = 1; i < 200; ++i)
411 * sum += (acc *= x / i);
416 ast_value *value = NULL;
417 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
418 ast_value *sum = ast_value_new(intrin_ctx(intrin), "sum", TYPE_FLOAT);
419 ast_value *acc = ast_value_new(intrin_ctx(intrin), "acc", TYPE_FLOAT);
420 ast_value *i = ast_value_new(intrin_ctx(intrin), "i", TYPE_FLOAT);
421 ast_block *body = ast_block_new(intrin_ctx(intrin));
422 ast_function *func = intrin_value(intrin, &value, "exp", TYPE_FLOAT);
424 vec_push(value->expression.params, x);
425 vec_push(body->locals, sum);
426 vec_push(body->locals, acc);
427 vec_push(body->locals, i);
430 vec_push(body->exprs,
431 (ast_expression*)ast_store_new(
434 (ast_expression*)sum,
435 (ast_expression*)intrin->fold->imm_float[1]
440 vec_push(body->exprs,
441 (ast_expression*)ast_store_new(
444 (ast_expression*)acc,
445 (ast_expression*)intrin->fold->imm_float[1]
450 * for (i = 1; i < 200; ++i)
451 * sum += (acc *= x / i);
453 vec_push(body->exprs,
454 (ast_expression*)ast_loop_new(
457 (ast_expression*)ast_store_new(
461 (ast_expression*)intrin->fold->imm_float[1]
464 (ast_expression*)ast_binary_new(
468 (ast_expression*)fold_constgen_float(intrin->fold, 200.0f, false)
474 (ast_expression*)ast_binstore_new(
479 (ast_expression*)intrin->fold->imm_float[1]
481 /* sum += (acc *= (x / i)) */
482 (ast_expression*)ast_binstore_new(
486 (ast_expression*)sum,
487 (ast_expression*)ast_binstore_new(
491 (ast_expression*)acc,
492 (ast_expression*)ast_binary_new(
504 vec_push(body->exprs,
505 (ast_expression*)ast_return_new(
511 vec_push(func->blocks, body);
513 intrin_reg(intrin, value, func);
514 return (ast_expression*)value;
517 static ast_expression *intrin_exp2(intrin_t *intrin) {
519 * float exp2(float x) {
523 ast_value *value = NULL;
524 ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", "exp2"));
525 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
526 ast_block *body = ast_block_new(intrin_ctx(intrin));
527 ast_function *func = intrin_value(intrin, &value, "exp2", TYPE_FLOAT);
529 vec_push(value->expression.params, arg1);
531 vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]);
532 vec_push(callpow->params, (ast_expression*)arg1);
534 /* return <callpow> */
535 vec_push(body->exprs,
536 (ast_expression*)ast_return_new(
538 (ast_expression*)callpow
542 vec_push(func->blocks, body);
544 intrin_reg(intrin, value, func);
545 return (ast_expression*)value;
548 static ast_expression *intrin_expm1(intrin_t *intrin) {
550 * float expm1(float x) {
554 ast_value *value = NULL;
555 ast_call *callexp = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "exp", "expm1"));
556 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
557 ast_block *body = ast_block_new(intrin_ctx(intrin));
558 ast_function *func = intrin_value(intrin, &value, "expm1", TYPE_FLOAT);
560 vec_push(value->expression.params, x);
562 /* <callexp> = exp(x); */
563 vec_push(callexp->params, (ast_expression*)x);
565 /* return <callexp> - 1; */
566 vec_push(body->exprs,
567 (ast_expression*)ast_return_new(
569 (ast_expression*)ast_binary_new(
572 (ast_expression*)callexp,
573 (ast_expression*)intrin->fold->imm_float[1]
578 vec_push(func->blocks, body);
579 intrin_reg(intrin, value, func);
580 return (ast_expression*)value;
583 static ast_expression *intrin_pow(intrin_t *intrin) {
586 * float pow(float base, float exp) {
599 * return 1.0 / pow(base, -exp);
601 * result = pow(base, exp / 2);
602 * return result * result;
607 * square = sqrt(base);
608 * accumulate = square;
611 * while (fabs(mid - exp) > QC_POW_EPSILON) {
612 * square = sqrt(square);
615 * accumulate *= square;
618 * accumulate *= (1.0f / square);
620 * mid = (low + high) / 2;
625 ast_value *value = NULL;
626 ast_function *func = intrin_value(intrin, &value, "pow", TYPE_FLOAT);
628 /* prepare some calls for later */
629 ast_call *callpow1 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(base, -exp) */
630 ast_call *callpow2 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(vase, exp / 2) */
631 ast_call *callsqrt1 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(base) */
632 ast_call *callsqrt2 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(square) */
633 ast_call *callfabs = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "fabs", "pow")); /* for fabs(mid - exp) */
635 /* prepare some blocks for later */
636 ast_block *expgt1 = ast_block_new(intrin_ctx(intrin));
637 ast_block *midltexp = ast_block_new(intrin_ctx(intrin));
638 ast_block *midltexpelse = ast_block_new(intrin_ctx(intrin));
639 ast_block *whileblock = ast_block_new(intrin_ctx(intrin));
641 /* float pow(float base, float exp) */
642 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
643 ast_value *exp = ast_value_new(intrin_ctx(intrin), "exp", TYPE_FLOAT);
645 ast_block *body = ast_block_new(intrin_ctx(intrin));
655 ast_value *result = ast_value_new(intrin_ctx(intrin), "result", TYPE_FLOAT);
656 ast_value *low = ast_value_new(intrin_ctx(intrin), "low", TYPE_FLOAT);
657 ast_value *high = ast_value_new(intrin_ctx(intrin), "high", TYPE_FLOAT);
658 ast_value *square = ast_value_new(intrin_ctx(intrin), "square", TYPE_FLOAT);
659 ast_value *accumulate = ast_value_new(intrin_ctx(intrin), "accumulate", TYPE_FLOAT);
660 ast_value *mid = ast_value_new(intrin_ctx(intrin), "mid", TYPE_FLOAT);
661 vec_push(body->locals, result);
662 vec_push(body->locals, low);
663 vec_push(body->locals, high);
664 vec_push(body->locals, square);
665 vec_push(body->locals, accumulate);
666 vec_push(body->locals, mid);
668 vec_push(value->expression.params, base);
669 vec_push(value->expression.params, exp);
675 vec_push(body->exprs,
676 (ast_expression*)ast_ifthen_new(
678 (ast_expression*)ast_binary_new(
681 (ast_expression*)exp,
682 (ast_expression*)intrin->fold->imm_float[0]
684 (ast_expression*)ast_return_new(
686 (ast_expression*)intrin->fold->imm_float[1]
696 vec_push(body->exprs,
697 (ast_expression*)ast_ifthen_new(
699 (ast_expression*)ast_binary_new(
702 (ast_expression*)exp,
703 (ast_expression*)intrin->fold->imm_float[1]
705 (ast_expression*)ast_return_new(
707 (ast_expression*)base
713 /* <callpow1> = pow(base, -exp) */
714 vec_push(callpow1->params, (ast_expression*)base);
715 vec_push(callpow1->params,
716 (ast_expression*)ast_unary_new(
725 * return 1.0 / <callpow1>;
727 vec_push(body->exprs,
728 (ast_expression*)ast_ifthen_new(
730 (ast_expression*)ast_binary_new(
733 (ast_expression*)exp,
734 (ast_expression*)intrin->fold->imm_float[0]
736 (ast_expression*)ast_return_new(
738 (ast_expression*)ast_binary_new(
741 (ast_expression*)intrin->fold->imm_float[1],
742 (ast_expression*)callpow1
749 /* <callpow2> = pow(base, exp / 2) */
750 vec_push(callpow2->params, (ast_expression*)base);
751 vec_push(callpow2->params,
752 (ast_expression*)ast_binary_new(
755 (ast_expression*)exp,
756 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
762 * result = <callpow2>;
763 * return result * result;
766 vec_push(expgt1->exprs,
767 (ast_expression*)ast_store_new(
770 (ast_expression*)result,
771 (ast_expression*)callpow2
774 vec_push(expgt1->exprs,
775 (ast_expression*)ast_return_new(
777 (ast_expression*)ast_binary_new(
780 (ast_expression*)result,
781 (ast_expression*)result
791 vec_push(body->exprs,
792 (ast_expression*)ast_ifthen_new(
794 (ast_expression*)ast_binary_new(
797 (ast_expression*)exp,
798 (ast_expression*)intrin->fold->imm_float[1]
800 (ast_expression*)expgt1,
806 * <callsqrt1> = sqrt(base)
808 vec_push(callsqrt1->params, (ast_expression*)base);
813 * square = sqrt(base);
814 * accumulate = square;
817 vec_push(body->exprs,
818 (ast_expression*)ast_store_new(intrin_ctx(intrin),
820 (ast_expression*)low,
821 (ast_expression*)intrin->fold->imm_float[0]
824 vec_push(body->exprs,
825 (ast_expression*)ast_store_new(
828 (ast_expression*)high,
829 (ast_expression*)intrin->fold->imm_float[1]
833 vec_push(body->exprs,
834 (ast_expression*)ast_store_new(
837 (ast_expression*)square,
838 (ast_expression*)callsqrt1
842 vec_push(body->exprs,
843 (ast_expression*)ast_store_new(
846 (ast_expression*)accumulate,
847 (ast_expression*)square
850 vec_push(body->exprs,
851 (ast_expression*)ast_store_new(
854 (ast_expression*)mid,
855 (ast_expression*)ast_binary_new(
858 (ast_expression*)high,
859 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
867 * accumulate *= square;
870 vec_push(midltexp->exprs,
871 (ast_expression*)ast_store_new(
874 (ast_expression*)low,
878 vec_push(midltexp->exprs,
879 (ast_expression*)ast_binstore_new(
883 (ast_expression*)accumulate,
884 (ast_expression*)square
891 * accumulate *= (1.0 / square);
894 vec_push(midltexpelse->exprs,
895 (ast_expression*)ast_store_new(
898 (ast_expression*)high,
902 vec_push(midltexpelse->exprs,
903 (ast_expression*)ast_binstore_new(
907 (ast_expression*)accumulate,
908 (ast_expression*)ast_binary_new(
911 (ast_expression*)intrin->fold->imm_float[1],
912 (ast_expression*)square
918 * <callsqrt2> = sqrt(square)
920 vec_push(callsqrt2->params, (ast_expression*)square);
924 * square = <callsqrt2>;
930 * mid = (low + high) / 2;
933 vec_push(whileblock->exprs,
934 (ast_expression*)ast_store_new(
937 (ast_expression*)square,
938 (ast_expression*)callsqrt2
941 vec_push(whileblock->exprs,
942 (ast_expression*)ast_ifthen_new(
944 (ast_expression*)ast_binary_new(
947 (ast_expression*)mid,
950 (ast_expression*)midltexp,
951 (ast_expression*)midltexpelse
954 vec_push(whileblock->exprs,
955 (ast_expression*)ast_store_new(
958 (ast_expression*)mid,
959 (ast_expression*)ast_binary_new(
962 (ast_expression*)ast_binary_new(
965 (ast_expression*)low,
966 (ast_expression*)high
968 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
974 * <callabs> = fabs(mid - exp)
976 vec_push(callfabs->params,
977 (ast_expression*)ast_binary_new(
980 (ast_expression*)mid,
986 * while (<callfabs> > epsilon)
989 vec_push(body->exprs,
990 (ast_expression*)ast_loop_new(
995 (ast_expression*)ast_binary_new(
998 (ast_expression*)callfabs,
999 (ast_expression*)fold_constgen_float(intrin->fold, QC_POW_EPSILON, false)
1003 /* post condition */
1007 /* increment expression */
1010 (ast_expression*)whileblock
1014 /* return accumulate */
1015 vec_push(body->exprs,
1016 (ast_expression*)ast_return_new(
1018 (ast_expression*)accumulate
1023 vec_push(func->blocks, body);
1025 intrin_reg(intrin, value, func);
1026 return (ast_expression*)value;
1029 static ast_expression *intrin_mod(intrin_t *intrin) {
1031 * float mod(float a, float b) {
1032 * float div = a / b;
1033 * float sign = (div < 0.0f) ? -1 : 1;
1034 * return a - b * sign * floor(sign * div);
1037 ast_value *value = NULL;
1038 ast_call *call = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", "mod"));
1039 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1040 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1041 ast_value *div = ast_value_new(intrin_ctx(intrin), "div", TYPE_FLOAT);
1042 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1043 ast_block *body = ast_block_new(intrin_ctx(intrin));
1044 ast_function *func = intrin_value(intrin, &value, "mod", TYPE_FLOAT);
1046 vec_push(value->expression.params, a);
1047 vec_push(value->expression.params, b);
1049 vec_push(body->locals, div);
1050 vec_push(body->locals, sign);
1053 vec_push(body->exprs,
1054 (ast_expression*)ast_store_new(
1057 (ast_expression*)div,
1058 (ast_expression*)ast_binary_new(
1067 /* sign = (div < 0.0f) ? -1 : 1; */
1068 vec_push(body->exprs,
1069 (ast_expression*)ast_store_new(
1072 (ast_expression*)sign,
1073 (ast_expression*)ast_ternary_new(
1075 (ast_expression*)ast_binary_new(
1078 (ast_expression*)div,
1079 (ast_expression*)intrin->fold->imm_float[0]
1081 (ast_expression*)intrin->fold->imm_float[2],
1082 (ast_expression*)intrin->fold->imm_float[1]
1087 /* floor(sign * div) */
1088 vec_push(call->params,
1089 (ast_expression*)ast_binary_new(
1092 (ast_expression*)sign,
1093 (ast_expression*)div
1097 /* return a - b * sign * <call> */
1098 vec_push(body->exprs,
1099 (ast_expression*)ast_return_new(
1101 (ast_expression*)ast_binary_new(
1105 (ast_expression*)ast_binary_new(
1109 (ast_expression*)ast_binary_new(
1112 (ast_expression*)sign,
1113 (ast_expression*)call
1120 vec_push(func->blocks, body);
1121 intrin_reg(intrin, value, func);
1123 return (ast_expression*)value;
1126 static ast_expression *intrin_fabs(intrin_t *intrin) {
1128 * float fabs(float x) {
1129 * return x < 0 ? -x : x;
1132 ast_value *value = NULL;
1133 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1134 ast_block *body = ast_block_new(intrin_ctx(intrin));
1135 ast_function *func = intrin_value(intrin, &value, "fabs", TYPE_FLOAT);
1137 vec_push(body->exprs,
1138 (ast_expression*)ast_return_new(
1140 (ast_expression*)ast_ternary_new(
1142 (ast_expression*)ast_binary_new(
1145 (ast_expression*)arg1,
1146 (ast_expression*)intrin->fold->imm_float[0]
1148 (ast_expression*)ast_unary_new(
1151 (ast_expression*)arg1
1153 (ast_expression*)arg1
1158 vec_push(value->expression.params, arg1);
1159 vec_push(func->blocks, body);
1161 intrin_reg(intrin, value, func);
1163 return (ast_expression*)value;
1166 static ast_expression *intrin_epsilon(intrin_t *intrin) {
1168 * float epsilon(void) {
1170 * do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1174 ast_value *value = NULL;
1175 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1176 ast_block *body = ast_block_new(intrin_ctx(intrin));
1177 ast_function *func = intrin_value(intrin, &value, "epsilon", TYPE_FLOAT);
1179 vec_push(body->locals, eps);
1182 vec_push(body->exprs,
1183 (ast_expression*)ast_store_new(
1186 (ast_expression*)eps,
1187 (ast_expression*)intrin->fold->imm_float[0]
1191 vec_push(body->exprs,
1192 (ast_expression*)ast_loop_new(
1197 (ast_expression*)ast_binary_new(
1200 (ast_expression*)ast_binary_new(
1203 (ast_expression*)intrin->fold->imm_float[1],
1204 (ast_expression*)ast_binary_new(
1207 (ast_expression*)eps,
1208 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1211 (ast_expression*)intrin->fold->imm_float[1]
1215 (ast_expression*)ast_binstore_new(
1219 (ast_expression*)eps,
1220 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1226 vec_push(body->exprs,
1227 (ast_expression*)ast_return_new(
1229 (ast_expression*)eps
1233 vec_push(func->blocks, body);
1234 intrin_reg(intrin, value, func);
1236 return (ast_expression*)value;
1239 static ast_expression *intrin_nan(intrin_t *intrin) {
1246 ast_value *value = NULL;
1247 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1248 ast_function *func = intrin_value(intrin, &value, "nan", TYPE_FLOAT);
1249 ast_block *block = ast_block_new(intrin_ctx(intrin));
1251 vec_push(block->locals, x);
1253 vec_push(block->exprs,
1254 (ast_expression*)ast_store_new(
1258 (ast_expression*)intrin->fold->imm_float[0]
1262 vec_push(block->exprs,
1263 (ast_expression*)ast_return_new(
1265 (ast_expression*)ast_binary_new(
1274 vec_push(func->blocks, block);
1275 intrin_reg(intrin, value, func);
1277 return (ast_expression*)value;
1280 static ast_expression *intrin_inf(intrin_t *intrin) {
1288 ast_value *value = NULL;
1289 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1290 ast_value *y = ast_value_new(intrin_ctx(intrin), "y", TYPE_FLOAT);
1291 ast_function *func = intrin_value(intrin, &value, "inf", TYPE_FLOAT);
1292 ast_block *block = ast_block_new(intrin_ctx(intrin));
1295 vec_push(block->locals, x);
1296 vec_push(block->locals, y);
1298 /* to keep code size down */
1299 for (i = 0; i <= 1; i++) {
1300 vec_push(block->exprs,
1301 (ast_expression*)ast_store_new(
1304 (ast_expression*)((i == 0) ? x : y),
1305 (ast_expression*)intrin->fold->imm_float[i]
1310 vec_push(block->exprs,
1311 (ast_expression*)ast_return_new(
1313 (ast_expression*)ast_binary_new(
1322 vec_push(func->blocks, block);
1323 intrin_reg(intrin, value, func);
1325 return (ast_expression*)value;
1328 static ast_expression *intrin_ln(intrin_t *intrin) {
1330 * float log(float power, float base) {
1333 * float sign = 1.0f;
1334 * float eps = epsilon();
1336 * if (power <= 1.0f || bbase <= 1.0) {
1337 * if (power <= 0.0f || base <= 0.0f)
1340 * if (power < 1.0f) {
1341 * power = 1.0f / power;
1345 * if (base < 1.0f) {
1347 * base = 1.0f / base;
1353 * float A_iminus1 = 0;
1354 * float B_iminus1 = 1;
1360 * while (whole >= base) {
1361 * float base2 = base;
1363 * float newbase2 = base2 * base2;
1365 * while (whole >= newbase2) {
1368 * newbase2 *= newbase2;
1375 * float b_iplus1 = n;
1376 * float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1377 * float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1384 * if (whole <= 1.0f + eps)
1390 * return sign * A_i / B_i;
1394 ast_value *value = NULL;
1395 ast_value *power = ast_value_new(intrin_ctx(intrin), "power", TYPE_FLOAT);
1396 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
1397 ast_value *whole = ast_value_new(intrin_ctx(intrin), "whole", TYPE_FLOAT);
1398 ast_value *nth = ast_value_new(intrin_ctx(intrin), "nth", TYPE_FLOAT);
1399 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1400 ast_value *A_i = ast_value_new(intrin_ctx(intrin), "A_i", TYPE_FLOAT);
1401 ast_value *B_i = ast_value_new(intrin_ctx(intrin), "B_i", TYPE_FLOAT);
1402 ast_value *A_iminus1 = ast_value_new(intrin_ctx(intrin), "A_iminus1", TYPE_FLOAT);
1403 ast_value *B_iminus1 = ast_value_new(intrin_ctx(intrin), "B_iminus1", TYPE_FLOAT);
1404 ast_value *b_iplus1 = ast_value_new(intrin_ctx(intrin), "b_iplus1", TYPE_FLOAT);
1405 ast_value *A_iplus1 = ast_value_new(intrin_ctx(intrin), "A_iplus1", TYPE_FLOAT);
1406 ast_value *B_iplus1 = ast_value_new(intrin_ctx(intrin), "B_iplus1", TYPE_FLOAT);
1407 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1408 ast_value *base2 = ast_value_new(intrin_ctx(intrin), "base2", TYPE_FLOAT);
1409 ast_value *n2 = ast_value_new(intrin_ctx(intrin), "n2", TYPE_FLOAT);
1410 ast_value *newbase2 = ast_value_new(intrin_ctx(intrin), "newbase2", TYPE_FLOAT);
1411 ast_block *block = ast_block_new(intrin_ctx(intrin));
1412 ast_block *plt1orblt1 = ast_block_new(intrin_ctx(intrin)); /* (power <= 1.0f || base <= 1.0f) */
1413 ast_block *plt1 = ast_block_new(intrin_ctx(intrin)); /* (power < 1.0f) */
1414 ast_block *blt1 = ast_block_new(intrin_ctx(intrin)); /* (base < 1.0f) */
1415 ast_block *forloop = ast_block_new(intrin_ctx(intrin)); /* for(;;) */
1416 ast_block *whileloop = ast_block_new(intrin_ctx(intrin)); /* while (whole >= base) */
1417 ast_block *nestwhile = ast_block_new(intrin_ctx(intrin)); /* while (whole >= newbase2) */
1418 ast_function *func = intrin_value(intrin, &value, "ln", TYPE_FLOAT);
1421 vec_push(value->expression.params, power);
1422 vec_push(value->expression.params, base);
1424 vec_push(block->locals, whole);
1425 vec_push(block->locals, nth);
1426 vec_push(block->locals, sign);
1427 vec_push(block->locals, eps);
1428 vec_push(block->locals, A_i);
1429 vec_push(block->locals, B_i);
1430 vec_push(block->locals, A_iminus1);
1431 vec_push(block->locals, B_iminus1);
1434 vec_push(block->exprs,
1435 (ast_expression*)ast_store_new(
1438 (ast_expression*)sign,
1439 (ast_expression*)intrin->fold->imm_float[1]
1443 /* eps = __builtin_epsilon(); */
1444 vec_push(block->exprs,
1445 (ast_expression*)ast_store_new(
1448 (ast_expression*)eps,
1449 (ast_expression*)ast_call_new(
1451 intrin_func_self(intrin, "__builtin_epsilon", "ln")
1462 for (i = 0; i <= 1; i++) {
1464 for (j = 1; j >= 0; j--) {
1465 vec_push(block->exprs,
1466 (ast_expression*)ast_store_new(
1469 (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1470 : ((i) ? A_iminus1 : B_i)),
1471 (ast_expression*)intrin->fold->imm_float[j]
1479 * power = 1.0f / power;
1483 * base = 1.0f / base;
1487 for (i = 0; i <= 1; i++) {
1488 vec_push(((i) ? blt1 : plt1)->exprs,
1489 (ast_expression*)ast_store_new(
1492 (ast_expression*)((i) ? base : power),
1493 (ast_expression*)ast_binary_new(
1496 (ast_expression*)intrin->fold->imm_float[1],
1497 (ast_expression*)((i) ? base : power)
1501 vec_push(plt1->exprs,
1502 (ast_expression*)ast_binstore_new(
1506 (ast_expression*)sign,
1507 (ast_expression*)intrin->fold->imm_float[2]
1514 * if (power <= 0.0 || base <= 0.0f)
1515 * return __builtin_nan();
1522 vec_push(plt1orblt1->exprs,
1523 (ast_expression*)ast_ifthen_new(
1525 (ast_expression*)ast_binary_new(
1528 (ast_expression*)ast_binary_new(
1531 (ast_expression*)power,
1532 (ast_expression*)intrin->fold->imm_float[0]
1534 (ast_expression*)ast_binary_new(
1537 (ast_expression*)base,
1538 (ast_expression*)intrin->fold->imm_float[0]
1541 (ast_expression*)ast_return_new(
1543 (ast_expression*)ast_call_new(
1545 intrin_func_self(intrin, "__builtin_nan", "ln")
1552 for (i = 0; i <= 1; i++) {
1553 vec_push(plt1orblt1->exprs,
1554 (ast_expression*)ast_ifthen_new(
1556 (ast_expression*)ast_binary_new(
1559 (ast_expression*)((i) ? base : power),
1560 (ast_expression*)intrin->fold->imm_float[1]
1562 (ast_expression*)((i) ? blt1 : plt1),
1568 vec_push(block->exprs, (ast_expression*)plt1orblt1);
1571 /* whole = power; */
1572 vec_push(forloop->exprs,
1573 (ast_expression*)ast_store_new(
1576 (ast_expression*)whole,
1577 (ast_expression*)power
1582 vec_push(forloop->exprs,
1583 (ast_expression*)ast_store_new(
1586 (ast_expression*)nth,
1587 (ast_expression*)intrin->fold->imm_float[0]
1592 vec_push(whileloop->exprs,
1593 (ast_expression*)ast_store_new(
1596 (ast_expression*)base2,
1597 (ast_expression*)base
1602 vec_push(whileloop->exprs,
1603 (ast_expression*)ast_store_new(
1606 (ast_expression*)n2,
1607 (ast_expression*)intrin->fold->imm_float[1]
1611 /* newbase2 = base2 * base2; */
1612 vec_push(whileloop->exprs,
1613 (ast_expression*)ast_store_new(
1616 (ast_expression*)newbase2,
1617 (ast_expression*)ast_binary_new(
1620 (ast_expression*)base2,
1621 (ast_expression*)base2
1626 /* while loop locals */
1627 vec_push(whileloop->locals, base2);
1628 vec_push(whileloop->locals, n2);
1629 vec_push(whileloop->locals, newbase2);
1631 /* base2 = newbase2; */
1632 vec_push(nestwhile->exprs,
1633 (ast_expression*)ast_store_new(
1636 (ast_expression*)base2,
1637 (ast_expression*)newbase2
1642 vec_push(nestwhile->exprs,
1643 (ast_expression*)ast_binstore_new(
1647 (ast_expression*)n2,
1648 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1652 /* newbase2 *= newbase2; */
1653 vec_push(nestwhile->exprs,
1654 (ast_expression*)ast_binstore_new(
1658 (ast_expression*)newbase2,
1659 (ast_expression*)newbase2
1663 /* while (whole >= newbase2) */
1664 vec_push(whileloop->exprs,
1665 (ast_expression*)ast_loop_new(
1668 (ast_expression*)ast_binary_new(
1671 (ast_expression*)whole,
1672 (ast_expression*)newbase2
1678 (ast_expression*)nestwhile
1682 /* whole /= base2; */
1683 vec_push(whileloop->exprs,
1684 (ast_expression*)ast_binstore_new(
1688 (ast_expression*)whole,
1689 (ast_expression*)base2
1694 vec_push(whileloop->exprs,
1695 (ast_expression*)ast_binstore_new(
1699 (ast_expression*)nth,
1704 /* while (whole >= base) */
1705 vec_push(forloop->exprs,
1706 (ast_expression*)ast_loop_new(
1709 (ast_expression*)ast_binary_new(
1712 (ast_expression*)whole,
1713 (ast_expression*)base
1719 (ast_expression*)whileloop
1723 vec_push(forloop->locals, b_iplus1);
1724 vec_push(forloop->locals, A_iplus1);
1725 vec_push(forloop->locals, B_iplus1);
1727 /* b_iplus1 = nth; */
1728 vec_push(forloop->exprs,
1729 (ast_expression*)ast_store_new(
1732 (ast_expression*)b_iplus1,
1733 (ast_expression*)nth
1738 * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1739 * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1741 for (i = 0; i <= 1; i++) {
1742 vec_push(forloop->exprs,
1743 (ast_expression*)ast_store_new(
1746 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1747 (ast_expression*)ast_binary_new(
1750 (ast_expression*)ast_binary_new(
1753 (ast_expression*)b_iplus1,
1754 (ast_expression*) ((i) ? B_i : A_i)
1756 (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1766 for (i = 0; i <= 1; i++) {
1767 vec_push(forloop->exprs,
1768 (ast_expression*)ast_store_new(
1771 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1772 (ast_expression*)((i) ? B_i : A_i)
1781 for (i = 0; i <= 1; i++) {
1782 vec_push(forloop->exprs,
1783 (ast_expression*)ast_store_new(
1786 (ast_expression*)((i) ? B_i : A_i),
1787 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1793 * if (whole <= 1.0f + eps)
1796 vec_push(forloop->exprs,
1797 (ast_expression*)ast_ifthen_new(
1799 (ast_expression*)ast_binary_new(
1802 (ast_expression*)whole,
1803 (ast_expression*)ast_binary_new(
1806 (ast_expression*)intrin->fold->imm_float[1],
1807 (ast_expression*)eps
1810 (ast_expression*)ast_breakcont_new(
1823 for (i = 0; i <= 1; i++) {
1824 vec_push(forloop->exprs,
1825 (ast_expression*)ast_store_new(
1828 (ast_expression*)((i) ? base : power),
1829 (ast_expression*)((i) ? whole : base)
1834 /* add the for loop block */
1835 vec_push(block->exprs,
1836 (ast_expression*)ast_loop_new(
1839 /* for(; 1; ) ?? (can this be NULL too?) */
1840 (ast_expression*)intrin->fold->imm_float[1],
1845 (ast_expression*)forloop
1849 /* return sign * A_i / B_il */
1850 vec_push(block->exprs,
1851 (ast_expression*)ast_return_new(
1853 (ast_expression*)ast_binary_new(
1856 (ast_expression*)sign,
1857 (ast_expression*)ast_binary_new(
1860 (ast_expression*)A_i,
1861 (ast_expression*)B_i
1867 vec_push(func->blocks, block);
1868 intrin_reg(intrin, value, func);
1870 return (ast_expression*)value;
1873 static ast_expression *intrin_log_variant(intrin_t *intrin, const char *name, float base) {
1874 ast_value *value = NULL;
1875 ast_call *callln = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "__builtin_ln", name));
1876 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1877 ast_block *body = ast_block_new(intrin_ctx(intrin));
1878 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1880 vec_push(value->expression.params, arg1);
1882 vec_push(callln->params, (ast_expression*)arg1);
1883 vec_push(callln->params, (ast_expression*)fold_constgen_float(intrin->fold, base, false));
1885 vec_push(body->exprs,
1886 (ast_expression*)ast_return_new(
1888 (ast_expression*)callln
1892 vec_push(func->blocks, body);
1893 intrin_reg(intrin, value, func);
1894 return (ast_expression*)value;
1897 static ast_expression *intrin_log(intrin_t *intrin) {
1898 return intrin_log_variant(intrin, "log", 2.7182818284590452354);
1900 static ast_expression *intrin_log10(intrin_t *intrin) {
1901 return intrin_log_variant(intrin, "log10", 10);
1903 static ast_expression *intrin_log2(intrin_t *intrin) {
1904 return intrin_log_variant(intrin, "log2", 2);
1906 static ast_expression *intrin_logb(intrin_t *intrin) {
1907 /* FLT_RADIX == 2 for now */
1908 return intrin_log_variant(intrin, "log2", 2);
1911 static ast_expression *intrin_shift_variant(intrin_t *intrin, const char *name, size_t instr) {
1913 * float [shift] (float a, float b) {
1914 * return floor(a [instr] pow(2, b));
1916 ast_value *value = NULL;
1917 ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name));
1918 ast_call *callfloor = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", name));
1919 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1920 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1921 ast_block *body = ast_block_new(intrin_ctx(intrin));
1922 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1924 vec_push(value->expression.params, a);
1925 vec_push(value->expression.params, b);
1927 /* <callpow> = pow(2, b) */
1928 vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]);
1929 vec_push(callpow->params, (ast_expression*)b);
1931 /* <callfloor> = floor(a [instr] <callpow>) */
1934 (ast_expression*)ast_binary_new(
1938 (ast_expression*)callpow
1942 /* return <callfloor> */
1943 vec_push(body->exprs,
1944 (ast_expression*)ast_return_new(
1946 (ast_expression*)callfloor
1950 vec_push(func->blocks, body);
1951 intrin_reg(intrin, value, func);
1952 return (ast_expression*)value;
1955 static ast_expression *intrin_lshift(intrin_t *intrin) {
1956 return intrin_shift_variant(intrin, "lshift", INSTR_MUL_F);
1959 static ast_expression *intrin_rshift(intrin_t *intrin) {
1960 return intrin_shift_variant(intrin, "rshift", INSTR_DIV_F);
1964 * TODO: make static (and handle ast_type_string) here for the builtin
1965 * instead of in SYA parse close.
1967 ast_expression *intrin_debug_typestring(intrin_t *intrin) {
1969 return (ast_expression*)0x1;
1972 static const intrin_func_t intrinsics[] = {
1973 {&intrin_isfinite, "__builtin_isfinite", "isfinite", 1},
1974 {&intrin_isinf, "__builtin_isinf", "isinf", 1},
1975 {&intrin_isnan, "__builtin_isnan", "isnan", 1},
1976 {&intrin_isnormal, "__builtin_isnormal", "isnormal", 1},
1977 {&intrin_signbit, "__builtin_signbit", "signbit", 1},
1978 {&intrin_acosh, "__builtin_acosh", "acosh", 1},
1979 {&intrin_asinh, "__builtin_asinh", "asinh", 1},
1980 {&intrin_atanh, "__builtin_atanh", "atanh", 1},
1981 {&intrin_exp, "__builtin_exp", "exp", 1},
1982 {&intrin_exp2, "__builtin_exp2", "exp2", 1},
1983 {&intrin_expm1, "__builtin_expm1", "expm1", 1},
1984 {&intrin_mod, "__builtin_mod", "mod", 2},
1985 {&intrin_pow, "__builtin_pow", "pow", 2},
1986 {&intrin_fabs, "__builtin_fabs", "fabs", 1},
1987 {&intrin_log, "__builtin_log", "log", 1},
1988 {&intrin_log10, "__builtin_log10", "log10", 1},
1989 {&intrin_log2, "__builtin_log2", "log2", 1},
1990 {&intrin_logb, "__builtin_logb", "logb", 1},
1991 {&intrin_lshift, "__builtin_lshift", "", 2},
1992 {&intrin_rshift, "__builtin_rshift", "", 2},
1993 {&intrin_epsilon, "__builtin_epsilon", "", 0},
1994 {&intrin_nan, "__builtin_nan", "", 0},
1995 {&intrin_inf, "__builtin_inf", "", 0},
1996 {&intrin_ln, "__builtin_ln", "", 2},
1997 {&intrin_debug_typestring, "__builtin_debug_typestring", "", 0},
1998 {&intrin_nullfunc, "#nullfunc", "", 0}
2001 static void intrin_error(intrin_t *intrin, const char *fmt, ...) {
2004 vcompile_error(intrin->parser->lex->tok.ctx, fmt, ap);
2009 intrin_t *intrin_init(parser_t *parser) {
2010 intrin_t *intrin = (intrin_t*)mem_a(sizeof(intrin_t));
2013 intrin->parser = parser;
2014 intrin->fold = parser->fold;
2015 intrin->intrinsics = NULL;
2016 intrin->generated = NULL;
2018 vec_append(intrin->intrinsics, GMQCC_ARRAY_COUNT(intrinsics), intrinsics);
2020 /* populate with null pointers for tracking generation */
2021 for (i = 0; i < GMQCC_ARRAY_COUNT(intrinsics); i++)
2022 vec_push(intrin->generated, NULL);
2027 void intrin_cleanup(intrin_t *intrin) {
2028 vec_free(intrin->intrinsics);
2029 vec_free(intrin->generated);
2033 ast_expression *intrin_fold(intrin_t *intrin, ast_value *value, ast_expression **exprs) {
2035 if (!value || !value->name)
2037 for (i = 0; i < vec_size(intrin->intrinsics); i++)
2038 if (!strcmp(value->name, intrin->intrinsics[i].name))
2039 return (vec_size(exprs) != intrin->intrinsics[i].args)
2041 : fold_intrin(intrin->fold, value->name + 10, exprs);
2045 static GMQCC_INLINE ast_expression *intrin_func_try(intrin_t *intrin, size_t offset, const char *compare) {
2047 for (i = 0; i < vec_size(intrin->intrinsics); i++) {
2048 if (strcmp(*(char **)((char *)&intrin->intrinsics[i] + offset), compare))
2050 if (intrin->generated[i])
2051 return intrin->generated[i];
2052 return intrin->generated[i] = intrin->intrinsics[i].intrin(intrin);
2057 static ast_expression *intrin_func_self(intrin_t *intrin, const char *name, const char *from) {
2059 ast_expression *find;
2061 /* try current first */
2062 if ((find = parser_find_global(intrin->parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
2063 for (i = 0; i < vec_size(intrin->parser->functions); ++i)
2064 if (((ast_value*)find)->name && !strcmp(intrin->parser->functions[i]->name, ((ast_value*)find)->name) && intrin->parser->functions[i]->builtin < 0)
2066 /* try name second */
2067 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, name), name)))
2069 /* try alias third */
2070 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, alias), name)))
2074 intrin_error(intrin, "need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2075 return intrin_func_self(intrin, "#nullfunc", NULL);
2080 ast_expression *intrin_func(intrin_t *intrin, const char *name) {
2081 return intrin_func_self(intrin, name, NULL);