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 intrin->parser->functions.push_back(func);
27 intrin->parser->globals.push_back((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 value->expression.params.push_back(x);
65 /* <callisnan> = isnan(x); */
66 callisnan->params.push_back((ast_expression*)x);
68 /* <callisinf> = isinf(x); */
69 callisinf->params.push_back((ast_expression*)x);
71 /* return (!<callisnan> || <callisinf>); */
72 block->exprs.push_back(
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 func->blocks.push_back(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 body->exprs.push_back(
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 value->expression.params.push_back(x);
133 func->blocks.push_back(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 body->locals.push_back(local);
156 body->exprs.push_back(
157 (ast_expression*)ast_store_new(
160 (ast_expression*)local,
161 (ast_expression*)arg1
165 body->exprs.push_back(
166 (ast_expression*)ast_return_new(
168 (ast_expression*)ast_binary_new(
171 (ast_expression*)arg1,
172 (ast_expression*)local
177 value->expression.params.push_back(arg1);
178 func->blocks.push_back(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 value->expression.params.push_back(x);
198 callisfinite->params.push_back((ast_expression*)x);
200 /* return <callisfinite> */
201 body->exprs.push_back(
202 (ast_expression*)ast_return_new(
204 (ast_expression*)callisfinite
208 func->blocks.push_back(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 value->expression.params.push_back(x);
226 /* return (x < 0); */
227 body->exprs.push_back(
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 func->blocks.push_back(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 value->expression.params.push_back(x);
264 /* <callsqrt> = sqrt((x * x) - 1); */
265 callsqrt->params.push_back(
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 calllog->params.push_back(
281 (ast_expression*)ast_binary_new(
285 (ast_expression*)callsqrt
289 /* return <calllog>; */
290 body->exprs.push_back(
291 (ast_expression*)ast_return_new(
293 (ast_expression*)calllog
297 func->blocks.push_back(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 value->expression.params.push_back(x);
317 /* <callsqrt> = sqrt((x * x) + 1); */
318 callsqrt->params.push_back(
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 calllog->params.push_back(
334 (ast_expression*)ast_binary_new(
338 (ast_expression*)callsqrt
342 /* return <calllog>; */
343 body->exprs.push_back(
344 (ast_expression*)ast_return_new(
346 (ast_expression*)calllog
350 func->blocks.push_back(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 value->expression.params.push_back(x);
369 /* <callog> = log((1 + x) / (1 - x)); */
370 calllog->params.push_back(
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 body->exprs.push_back(
391 (ast_expression*)ast_binary_new(
394 (ast_expression*)fold_constgen_float(intrin->fold, 0.5, false),
395 (ast_expression*)calllog
399 func->blocks.push_back(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 value->expression.params.push_back(x);
426 body->locals.push_back(sum);
427 body->locals.push_back(acc);
428 body->locals.push_back(i);
431 body->exprs.push_back(
432 (ast_expression*)ast_store_new(
435 (ast_expression*)sum,
436 (ast_expression*)intrin->fold->imm_float[1]
441 body->exprs.push_back(
442 (ast_expression*)ast_store_new(
445 (ast_expression*)acc,
446 (ast_expression*)intrin->fold->imm_float[1]
451 * for (i = 1; i < 200; ++i)
452 * sum += (acc *= x / i);
454 body->exprs.push_back(
455 (ast_expression*)ast_loop_new(
458 (ast_expression*)ast_store_new(
462 (ast_expression*)intrin->fold->imm_float[1]
465 (ast_expression*)ast_binary_new(
469 (ast_expression*)fold_constgen_float(intrin->fold, 200.0f, false)
475 (ast_expression*)ast_binstore_new(
480 (ast_expression*)intrin->fold->imm_float[1]
482 /* sum += (acc *= (x / i)) */
483 (ast_expression*)ast_binstore_new(
487 (ast_expression*)sum,
488 (ast_expression*)ast_binstore_new(
492 (ast_expression*)acc,
493 (ast_expression*)ast_binary_new(
505 body->exprs.push_back(
506 (ast_expression*)ast_return_new(
512 func->blocks.push_back(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 value->expression.params.push_back(arg1);
531 callpow->params.push_back((ast_expression*)intrin->fold->imm_float[3]);
532 callpow->params.push_back((ast_expression*)arg1);
534 /* return <callpow> */
535 body->exprs.push_back(
536 (ast_expression*)ast_return_new(
538 (ast_expression*)callpow
542 func->blocks.push_back(body);
543 intrin_reg(intrin, value, func);
544 return (ast_expression*)value;
547 static ast_expression *intrin_expm1(intrin_t *intrin) {
549 * float expm1(float x) {
553 ast_value *value = NULL;
554 ast_call *callexp = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "exp", "expm1"));
555 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
556 ast_block *body = ast_block_new(intrin_ctx(intrin));
557 ast_function *func = intrin_value(intrin, &value, "expm1", TYPE_FLOAT);
559 value->expression.params.push_back(x);
561 /* <callexp> = exp(x); */
562 callexp->params.push_back((ast_expression*)x);
564 /* return <callexp> - 1; */
565 body->exprs.push_back(
566 (ast_expression*)ast_return_new(
568 (ast_expression*)ast_binary_new(
571 (ast_expression*)callexp,
572 (ast_expression*)intrin->fold->imm_float[1]
577 func->blocks.push_back(body);
578 intrin_reg(intrin, value, func);
579 return (ast_expression*)value;
582 static ast_expression *intrin_pow(intrin_t *intrin) {
585 * float pow(float base, float exp) {
598 * return 1.0 / pow(base, -exp);
600 * result = pow(base, exp / 2);
601 * return result * result;
606 * square = sqrt(base);
607 * accumulate = square;
610 * while (fabs(mid - exp) > QC_POW_EPSILON) {
611 * square = sqrt(square);
614 * accumulate *= square;
617 * accumulate *= (1.0f / square);
619 * mid = (low + high) / 2;
624 ast_value *value = NULL;
625 ast_function *func = intrin_value(intrin, &value, "pow", TYPE_FLOAT);
627 /* prepare some calls for later */
628 ast_call *callpow1 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(base, -exp) */
629 ast_call *callpow2 = ast_call_new(intrin_ctx(intrin), (ast_expression*)value); /* for pow(vase, exp / 2) */
630 ast_call *callsqrt1 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(base) */
631 ast_call *callsqrt2 = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "sqrt", "pow")); /* for sqrt(square) */
632 ast_call *callfabs = ast_call_new(intrin_ctx(intrin), intrin_func_self(intrin, "fabs", "pow")); /* for fabs(mid - exp) */
634 /* prepare some blocks for later */
635 ast_block *expgt1 = ast_block_new(intrin_ctx(intrin));
636 ast_block *midltexp = ast_block_new(intrin_ctx(intrin));
637 ast_block *midltexpelse = ast_block_new(intrin_ctx(intrin));
638 ast_block *whileblock = ast_block_new(intrin_ctx(intrin));
640 /* float pow(float base, float exp) */
641 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
642 ast_value *exp = ast_value_new(intrin_ctx(intrin), "exp", TYPE_FLOAT);
644 ast_block *body = ast_block_new(intrin_ctx(intrin));
654 ast_value *result = ast_value_new(intrin_ctx(intrin), "result", TYPE_FLOAT);
655 ast_value *low = ast_value_new(intrin_ctx(intrin), "low", TYPE_FLOAT);
656 ast_value *high = ast_value_new(intrin_ctx(intrin), "high", TYPE_FLOAT);
657 ast_value *square = ast_value_new(intrin_ctx(intrin), "square", TYPE_FLOAT);
658 ast_value *accumulate = ast_value_new(intrin_ctx(intrin), "accumulate", TYPE_FLOAT);
659 ast_value *mid = ast_value_new(intrin_ctx(intrin), "mid", TYPE_FLOAT);
660 body->locals.push_back(result);
661 body->locals.push_back(low);
662 body->locals.push_back(high);
663 body->locals.push_back(square);
664 body->locals.push_back(accumulate);
665 body->locals.push_back(mid);
667 value->expression.params.push_back(base);
668 value->expression.params.push_back(exp);
674 body->exprs.push_back(
675 (ast_expression*)ast_ifthen_new(
677 (ast_expression*)ast_binary_new(
680 (ast_expression*)exp,
681 (ast_expression*)intrin->fold->imm_float[0]
683 (ast_expression*)ast_return_new(
685 (ast_expression*)intrin->fold->imm_float[1]
695 body->exprs.push_back(
696 (ast_expression*)ast_ifthen_new(
698 (ast_expression*)ast_binary_new(
701 (ast_expression*)exp,
702 (ast_expression*)intrin->fold->imm_float[1]
704 (ast_expression*)ast_return_new(
706 (ast_expression*)base
712 /* <callpow1> = pow(base, -exp) */
713 callpow1->params.push_back((ast_expression*)base);
714 callpow1->params.push_back(
715 (ast_expression*)ast_unary_new(
724 * return 1.0 / <callpow1>;
726 body->exprs.push_back(
727 (ast_expression*)ast_ifthen_new(
729 (ast_expression*)ast_binary_new(
732 (ast_expression*)exp,
733 (ast_expression*)intrin->fold->imm_float[0]
735 (ast_expression*)ast_return_new(
737 (ast_expression*)ast_binary_new(
740 (ast_expression*)intrin->fold->imm_float[1],
741 (ast_expression*)callpow1
748 /* <callpow2> = pow(base, exp / 2) */
749 callpow2->params.push_back((ast_expression*)base);
750 callpow2->params.push_back(
751 (ast_expression*)ast_binary_new(
754 (ast_expression*)exp,
755 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
761 * result = <callpow2>;
762 * return result * result;
765 expgt1->exprs.push_back(
766 (ast_expression*)ast_store_new(
769 (ast_expression*)result,
770 (ast_expression*)callpow2
773 expgt1->exprs.push_back(
774 (ast_expression*)ast_return_new(
776 (ast_expression*)ast_binary_new(
779 (ast_expression*)result,
780 (ast_expression*)result
790 body->exprs.push_back(
791 (ast_expression*)ast_ifthen_new(
793 (ast_expression*)ast_binary_new(
796 (ast_expression*)exp,
797 (ast_expression*)intrin->fold->imm_float[1]
799 (ast_expression*)expgt1,
805 * <callsqrt1> = sqrt(base)
807 callsqrt1->params.push_back((ast_expression*)base);
812 * square = sqrt(base);
813 * accumulate = square;
816 body->exprs.push_back(
817 (ast_expression*)ast_store_new(intrin_ctx(intrin),
819 (ast_expression*)low,
820 (ast_expression*)intrin->fold->imm_float[0]
823 body->exprs.push_back(
824 (ast_expression*)ast_store_new(
827 (ast_expression*)high,
828 (ast_expression*)intrin->fold->imm_float[1]
832 body->exprs.push_back(
833 (ast_expression*)ast_store_new(
836 (ast_expression*)square,
837 (ast_expression*)callsqrt1
841 body->exprs.push_back(
842 (ast_expression*)ast_store_new(
845 (ast_expression*)accumulate,
846 (ast_expression*)square
849 body->exprs.push_back(
850 (ast_expression*)ast_store_new(
853 (ast_expression*)mid,
854 (ast_expression*)ast_binary_new(
857 (ast_expression*)high,
858 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
866 * accumulate *= square;
869 midltexp->exprs.push_back(
870 (ast_expression*)ast_store_new(
873 (ast_expression*)low,
877 midltexp->exprs.push_back(
878 (ast_expression*)ast_binstore_new(
882 (ast_expression*)accumulate,
883 (ast_expression*)square
890 * accumulate *= (1.0 / square);
893 midltexpelse->exprs.push_back(
894 (ast_expression*)ast_store_new(
897 (ast_expression*)high,
901 midltexpelse->exprs.push_back(
902 (ast_expression*)ast_binstore_new(
906 (ast_expression*)accumulate,
907 (ast_expression*)ast_binary_new(
910 (ast_expression*)intrin->fold->imm_float[1],
911 (ast_expression*)square
917 * <callsqrt2> = sqrt(square)
919 callsqrt2->params.push_back((ast_expression*)square);
923 * square = <callsqrt2>;
929 * mid = (low + high) / 2;
932 whileblock->exprs.push_back(
933 (ast_expression*)ast_store_new(
936 (ast_expression*)square,
937 (ast_expression*)callsqrt2
940 whileblock->exprs.push_back(
941 (ast_expression*)ast_ifthen_new(
943 (ast_expression*)ast_binary_new(
946 (ast_expression*)mid,
949 (ast_expression*)midltexp,
950 (ast_expression*)midltexpelse
953 whileblock->exprs.push_back(
954 (ast_expression*)ast_store_new(
957 (ast_expression*)mid,
958 (ast_expression*)ast_binary_new(
961 (ast_expression*)ast_binary_new(
964 (ast_expression*)low,
965 (ast_expression*)high
967 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
973 * <callabs> = fabs(mid - exp)
975 callfabs->params.push_back(
976 (ast_expression*)ast_binary_new(
979 (ast_expression*)mid,
985 * while (<callfabs> > epsilon)
988 body->exprs.push_back(
989 (ast_expression*)ast_loop_new(
994 (ast_expression*)ast_binary_new(
997 (ast_expression*)callfabs,
998 (ast_expression*)fold_constgen_float(intrin->fold, QC_POW_EPSILON, false)
1002 /* post condition */
1006 /* increment expression */
1009 (ast_expression*)whileblock
1013 /* return accumulate */
1014 body->exprs.push_back(
1015 (ast_expression*)ast_return_new(
1017 (ast_expression*)accumulate
1022 func->blocks.push_back(body);
1023 intrin_reg(intrin, value, func);
1024 return (ast_expression*)value;
1027 static ast_expression *intrin_mod(intrin_t *intrin) {
1029 * float mod(float a, float b) {
1030 * float div = a / b;
1031 * float sign = (div < 0.0f) ? -1 : 1;
1032 * return a - b * sign * floor(sign * div);
1035 ast_value *value = NULL;
1036 ast_call *call = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", "mod"));
1037 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1038 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1039 ast_value *div = ast_value_new(intrin_ctx(intrin), "div", TYPE_FLOAT);
1040 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1041 ast_block *body = ast_block_new(intrin_ctx(intrin));
1042 ast_function *func = intrin_value(intrin, &value, "mod", TYPE_FLOAT);
1044 value->expression.params.push_back(a);
1045 value->expression.params.push_back(b);
1047 body->locals.push_back(div);
1048 body->locals.push_back(sign);
1051 body->exprs.push_back(
1052 (ast_expression*)ast_store_new(
1055 (ast_expression*)div,
1056 (ast_expression*)ast_binary_new(
1065 /* sign = (div < 0.0f) ? -1 : 1; */
1066 body->exprs.push_back(
1067 (ast_expression*)ast_store_new(
1070 (ast_expression*)sign,
1071 (ast_expression*)ast_ternary_new(
1073 (ast_expression*)ast_binary_new(
1076 (ast_expression*)div,
1077 (ast_expression*)intrin->fold->imm_float[0]
1079 (ast_expression*)intrin->fold->imm_float[2],
1080 (ast_expression*)intrin->fold->imm_float[1]
1085 /* floor(sign * div) */
1086 call->params.push_back(
1087 (ast_expression*)ast_binary_new(
1090 (ast_expression*)sign,
1091 (ast_expression*)div
1095 /* return a - b * sign * <call> */
1096 body->exprs.push_back(
1097 (ast_expression*)ast_return_new(
1099 (ast_expression*)ast_binary_new(
1103 (ast_expression*)ast_binary_new(
1107 (ast_expression*)ast_binary_new(
1110 (ast_expression*)sign,
1111 (ast_expression*)call
1118 func->blocks.push_back(body);
1119 intrin_reg(intrin, value, func);
1120 return (ast_expression*)value;
1123 static ast_expression *intrin_fabs(intrin_t *intrin) {
1125 * float fabs(float x) {
1126 * return x < 0 ? -x : x;
1129 ast_value *value = NULL;
1130 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1131 ast_block *body = ast_block_new(intrin_ctx(intrin));
1132 ast_function *func = intrin_value(intrin, &value, "fabs", TYPE_FLOAT);
1134 body->exprs.push_back(
1135 (ast_expression*)ast_return_new(
1137 (ast_expression*)ast_ternary_new(
1139 (ast_expression*)ast_binary_new(
1142 (ast_expression*)arg1,
1143 (ast_expression*)intrin->fold->imm_float[0]
1145 (ast_expression*)ast_unary_new(
1148 (ast_expression*)arg1
1150 (ast_expression*)arg1
1155 value->expression.params.push_back(arg1);
1157 func->blocks.push_back(body);
1158 intrin_reg(intrin, value, func);
1159 return (ast_expression*)value;
1162 static ast_expression *intrin_epsilon(intrin_t *intrin) {
1164 * float epsilon(void) {
1166 * do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1170 ast_value *value = NULL;
1171 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1172 ast_block *body = ast_block_new(intrin_ctx(intrin));
1173 ast_function *func = intrin_value(intrin, &value, "epsilon", TYPE_FLOAT);
1175 body->locals.push_back(eps);
1178 body->exprs.push_back(
1179 (ast_expression*)ast_store_new(
1182 (ast_expression*)eps,
1183 (ast_expression*)intrin->fold->imm_float[0]
1187 body->exprs.push_back(
1188 (ast_expression*)ast_loop_new(
1193 (ast_expression*)ast_binary_new(
1196 (ast_expression*)ast_binary_new(
1199 (ast_expression*)intrin->fold->imm_float[1],
1200 (ast_expression*)ast_binary_new(
1203 (ast_expression*)eps,
1204 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1207 (ast_expression*)intrin->fold->imm_float[1]
1211 (ast_expression*)ast_binstore_new(
1215 (ast_expression*)eps,
1216 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1222 body->exprs.push_back(
1223 (ast_expression*)ast_return_new(
1225 (ast_expression*)eps
1229 func->blocks.push_back(body);
1230 intrin_reg(intrin, value, func);
1231 return (ast_expression*)value;
1234 static ast_expression *intrin_nan(intrin_t *intrin) {
1241 ast_value *value = NULL;
1242 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1243 ast_function *func = intrin_value(intrin, &value, "nan", TYPE_FLOAT);
1244 ast_block *block = ast_block_new(intrin_ctx(intrin));
1246 block->locals.push_back(x);
1248 block->exprs.push_back(
1249 (ast_expression*)ast_store_new(
1253 (ast_expression*)intrin->fold->imm_float[0]
1257 block->exprs.push_back(
1258 (ast_expression*)ast_return_new(
1260 (ast_expression*)ast_binary_new(
1269 func->blocks.push_back(block);
1270 intrin_reg(intrin, value, func);
1271 return (ast_expression*)value;
1274 static ast_expression *intrin_inf(intrin_t *intrin) {
1282 ast_value *value = NULL;
1283 ast_value *x = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1284 ast_value *y = ast_value_new(intrin_ctx(intrin), "y", TYPE_FLOAT);
1285 ast_function *func = intrin_value(intrin, &value, "inf", TYPE_FLOAT);
1286 ast_block *block = ast_block_new(intrin_ctx(intrin));
1289 block->locals.push_back(x);
1290 block->locals.push_back(y);
1292 /* to keep code size down */
1293 for (i = 0; i <= 1; i++) {
1294 block->exprs.push_back(
1295 (ast_expression*)ast_store_new(
1298 (ast_expression*)((i == 0) ? x : y),
1299 (ast_expression*)intrin->fold->imm_float[i]
1304 block->exprs.push_back(
1305 (ast_expression*)ast_return_new(
1307 (ast_expression*)ast_binary_new(
1316 func->blocks.push_back(block);
1317 intrin_reg(intrin, value, func);
1318 return (ast_expression*)value;
1321 static ast_expression *intrin_ln(intrin_t *intrin) {
1323 * float log(float power, float base) {
1326 * float sign = 1.0f;
1327 * float eps = epsilon();
1329 * if (power <= 1.0f || bbase <= 1.0) {
1330 * if (power <= 0.0f || base <= 0.0f)
1333 * if (power < 1.0f) {
1334 * power = 1.0f / power;
1338 * if (base < 1.0f) {
1340 * base = 1.0f / base;
1346 * float A_iminus1 = 0;
1347 * float B_iminus1 = 1;
1353 * while (whole >= base) {
1354 * float base2 = base;
1356 * float newbase2 = base2 * base2;
1358 * while (whole >= newbase2) {
1361 * newbase2 *= newbase2;
1368 * float b_iplus1 = n;
1369 * float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1370 * float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1377 * if (whole <= 1.0f + eps)
1383 * return sign * A_i / B_i;
1387 ast_value *value = NULL;
1388 ast_value *power = ast_value_new(intrin_ctx(intrin), "power", TYPE_FLOAT);
1389 ast_value *base = ast_value_new(intrin_ctx(intrin), "base", TYPE_FLOAT);
1390 ast_value *whole = ast_value_new(intrin_ctx(intrin), "whole", TYPE_FLOAT);
1391 ast_value *nth = ast_value_new(intrin_ctx(intrin), "nth", TYPE_FLOAT);
1392 ast_value *sign = ast_value_new(intrin_ctx(intrin), "sign", TYPE_FLOAT);
1393 ast_value *A_i = ast_value_new(intrin_ctx(intrin), "A_i", TYPE_FLOAT);
1394 ast_value *B_i = ast_value_new(intrin_ctx(intrin), "B_i", TYPE_FLOAT);
1395 ast_value *A_iminus1 = ast_value_new(intrin_ctx(intrin), "A_iminus1", TYPE_FLOAT);
1396 ast_value *B_iminus1 = ast_value_new(intrin_ctx(intrin), "B_iminus1", TYPE_FLOAT);
1397 ast_value *b_iplus1 = ast_value_new(intrin_ctx(intrin), "b_iplus1", TYPE_FLOAT);
1398 ast_value *A_iplus1 = ast_value_new(intrin_ctx(intrin), "A_iplus1", TYPE_FLOAT);
1399 ast_value *B_iplus1 = ast_value_new(intrin_ctx(intrin), "B_iplus1", TYPE_FLOAT);
1400 ast_value *eps = ast_value_new(intrin_ctx(intrin), "eps", TYPE_FLOAT);
1401 ast_value *base2 = ast_value_new(intrin_ctx(intrin), "base2", TYPE_FLOAT);
1402 ast_value *n2 = ast_value_new(intrin_ctx(intrin), "n2", TYPE_FLOAT);
1403 ast_value *newbase2 = ast_value_new(intrin_ctx(intrin), "newbase2", TYPE_FLOAT);
1404 ast_block *block = ast_block_new(intrin_ctx(intrin));
1405 ast_block *plt1orblt1 = ast_block_new(intrin_ctx(intrin)); /* (power <= 1.0f || base <= 1.0f) */
1406 ast_block *plt1 = ast_block_new(intrin_ctx(intrin)); /* (power < 1.0f) */
1407 ast_block *blt1 = ast_block_new(intrin_ctx(intrin)); /* (base < 1.0f) */
1408 ast_block *forloop = ast_block_new(intrin_ctx(intrin)); /* for(;;) */
1409 ast_block *whileloop = ast_block_new(intrin_ctx(intrin)); /* while (whole >= base) */
1410 ast_block *nestwhile = ast_block_new(intrin_ctx(intrin)); /* while (whole >= newbase2) */
1411 ast_function *func = intrin_value(intrin, &value, "ln", TYPE_FLOAT);
1414 value->expression.params.push_back(power);
1415 value->expression.params.push_back(base);
1417 block->locals.push_back(whole);
1418 block->locals.push_back(nth);
1419 block->locals.push_back(sign);
1420 block->locals.push_back(eps);
1421 block->locals.push_back(A_i);
1422 block->locals.push_back(B_i);
1423 block->locals.push_back(A_iminus1);
1424 block->locals.push_back(B_iminus1);
1427 block->exprs.push_back(
1428 (ast_expression*)ast_store_new(
1431 (ast_expression*)sign,
1432 (ast_expression*)intrin->fold->imm_float[1]
1436 /* eps = __builtin_epsilon(); */
1437 block->exprs.push_back(
1438 (ast_expression*)ast_store_new(
1441 (ast_expression*)eps,
1442 (ast_expression*)ast_call_new(
1444 intrin_func_self(intrin, "__builtin_epsilon", "ln")
1455 for (i = 0; i <= 1; i++) {
1457 for (j = 1; j >= 0; j--) {
1458 block->exprs.push_back(
1459 (ast_expression*)ast_store_new(
1462 (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1463 : ((i) ? A_iminus1 : B_i)),
1464 (ast_expression*)intrin->fold->imm_float[j]
1472 * power = 1.0f / power;
1476 * base = 1.0f / base;
1480 for (i = 0; i <= 1; i++) {
1481 ((i) ? blt1 : plt1)->exprs.push_back(
1482 (ast_expression*)ast_store_new(
1485 (ast_expression*)((i) ? base : power),
1486 (ast_expression*)ast_binary_new(
1489 (ast_expression*)intrin->fold->imm_float[1],
1490 (ast_expression*)((i) ? base : power)
1494 plt1->exprs.push_back(
1495 (ast_expression*)ast_binstore_new(
1499 (ast_expression*)sign,
1500 (ast_expression*)intrin->fold->imm_float[2]
1507 * if (power <= 0.0 || base <= 0.0f)
1508 * return __builtin_nan();
1515 plt1orblt1->exprs.push_back(
1516 (ast_expression*)ast_ifthen_new(
1518 (ast_expression*)ast_binary_new(
1521 (ast_expression*)ast_binary_new(
1524 (ast_expression*)power,
1525 (ast_expression*)intrin->fold->imm_float[0]
1527 (ast_expression*)ast_binary_new(
1530 (ast_expression*)base,
1531 (ast_expression*)intrin->fold->imm_float[0]
1534 (ast_expression*)ast_return_new(
1536 (ast_expression*)ast_call_new(
1538 intrin_func_self(intrin, "__builtin_nan", "ln")
1545 for (i = 0; i <= 1; i++) {
1546 plt1orblt1->exprs.push_back(
1547 (ast_expression*)ast_ifthen_new(
1549 (ast_expression*)ast_binary_new(
1552 (ast_expression*)((i) ? base : power),
1553 (ast_expression*)intrin->fold->imm_float[1]
1555 (ast_expression*)((i) ? blt1 : plt1),
1561 block->exprs.push_back((ast_expression*)plt1orblt1);
1564 /* whole = power; */
1565 forloop->exprs.push_back(
1566 (ast_expression*)ast_store_new(
1569 (ast_expression*)whole,
1570 (ast_expression*)power
1575 forloop->exprs.push_back(
1576 (ast_expression*)ast_store_new(
1579 (ast_expression*)nth,
1580 (ast_expression*)intrin->fold->imm_float[0]
1585 whileloop->exprs.push_back(
1586 (ast_expression*)ast_store_new(
1589 (ast_expression*)base2,
1590 (ast_expression*)base
1595 whileloop->exprs.push_back(
1596 (ast_expression*)ast_store_new(
1599 (ast_expression*)n2,
1600 (ast_expression*)intrin->fold->imm_float[1]
1604 /* newbase2 = base2 * base2; */
1605 whileloop->exprs.push_back(
1606 (ast_expression*)ast_store_new(
1609 (ast_expression*)newbase2,
1610 (ast_expression*)ast_binary_new(
1613 (ast_expression*)base2,
1614 (ast_expression*)base2
1619 /* while loop locals */
1620 whileloop->locals.push_back(base2);
1621 whileloop->locals.push_back(n2);
1622 whileloop->locals.push_back(newbase2);
1624 /* base2 = newbase2; */
1625 nestwhile->exprs.push_back(
1626 (ast_expression*)ast_store_new(
1629 (ast_expression*)base2,
1630 (ast_expression*)newbase2
1635 nestwhile->exprs.push_back(
1636 (ast_expression*)ast_binstore_new(
1640 (ast_expression*)n2,
1641 (ast_expression*)intrin->fold->imm_float[3] /* 2.0f */
1645 /* newbase2 *= newbase2; */
1646 nestwhile->exprs.push_back(
1647 (ast_expression*)ast_binstore_new(
1651 (ast_expression*)newbase2,
1652 (ast_expression*)newbase2
1656 /* while (whole >= newbase2) */
1657 whileloop->exprs.push_back(
1658 (ast_expression*)ast_loop_new(
1661 (ast_expression*)ast_binary_new(
1664 (ast_expression*)whole,
1665 (ast_expression*)newbase2
1671 (ast_expression*)nestwhile
1675 /* whole /= base2; */
1676 whileloop->exprs.push_back(
1677 (ast_expression*)ast_binstore_new(
1681 (ast_expression*)whole,
1682 (ast_expression*)base2
1687 whileloop->exprs.push_back(
1688 (ast_expression*)ast_binstore_new(
1692 (ast_expression*)nth,
1697 /* while (whole >= base) */
1698 forloop->exprs.push_back(
1699 (ast_expression*)ast_loop_new(
1702 (ast_expression*)ast_binary_new(
1705 (ast_expression*)whole,
1706 (ast_expression*)base
1712 (ast_expression*)whileloop
1716 forloop->locals.push_back(b_iplus1);
1717 forloop->locals.push_back(A_iplus1);
1718 forloop->locals.push_back(B_iplus1);
1720 /* b_iplus1 = nth; */
1721 forloop->exprs.push_back(
1722 (ast_expression*)ast_store_new(
1725 (ast_expression*)b_iplus1,
1726 (ast_expression*)nth
1731 * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1732 * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1734 for (i = 0; i <= 1; i++) {
1735 forloop->exprs.push_back(
1736 (ast_expression*)ast_store_new(
1739 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1740 (ast_expression*)ast_binary_new(
1743 (ast_expression*)ast_binary_new(
1746 (ast_expression*)b_iplus1,
1747 (ast_expression*) ((i) ? B_i : A_i)
1749 (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1759 for (i = 0; i <= 1; i++) {
1760 forloop->exprs.push_back(
1761 (ast_expression*)ast_store_new(
1764 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1765 (ast_expression*)((i) ? B_i : A_i)
1774 for (i = 0; i <= 1; i++) {
1775 forloop->exprs.push_back(
1776 (ast_expression*)ast_store_new(
1779 (ast_expression*)((i) ? B_i : A_i),
1780 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1786 * if (whole <= 1.0f + eps)
1789 forloop->exprs.push_back(
1790 (ast_expression*)ast_ifthen_new(
1792 (ast_expression*)ast_binary_new(
1795 (ast_expression*)whole,
1796 (ast_expression*)ast_binary_new(
1799 (ast_expression*)intrin->fold->imm_float[1],
1800 (ast_expression*)eps
1803 (ast_expression*)ast_breakcont_new(
1816 for (i = 0; i <= 1; i++) {
1817 forloop->exprs.push_back(
1818 (ast_expression*)ast_store_new(
1821 (ast_expression*)((i) ? base : power),
1822 (ast_expression*)((i) ? whole : base)
1827 /* add the for loop block */
1828 block->exprs.push_back(
1829 (ast_expression*)ast_loop_new(
1832 /* for(; 1; ) ?? (can this be NULL too?) */
1833 (ast_expression*)intrin->fold->imm_float[1],
1838 (ast_expression*)forloop
1842 /* return sign * A_i / B_il */
1843 block->exprs.push_back(
1844 (ast_expression*)ast_return_new(
1846 (ast_expression*)ast_binary_new(
1849 (ast_expression*)sign,
1850 (ast_expression*)ast_binary_new(
1853 (ast_expression*)A_i,
1854 (ast_expression*)B_i
1860 func->blocks.push_back(block);
1861 intrin_reg(intrin, value, func);
1862 return (ast_expression*)value;
1865 static ast_expression *intrin_log_variant(intrin_t *intrin, const char *name, float base) {
1866 ast_value *value = NULL;
1867 ast_call *callln = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "__builtin_ln", name));
1868 ast_value *arg1 = ast_value_new(intrin_ctx(intrin), "x", TYPE_FLOAT);
1869 ast_block *body = ast_block_new(intrin_ctx(intrin));
1870 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1872 value->expression.params.push_back(arg1);
1874 callln->params.push_back((ast_expression*)arg1);
1875 callln->params.push_back((ast_expression*)fold_constgen_float(intrin->fold, base, false));
1877 body->exprs.push_back(
1878 (ast_expression*)ast_return_new(
1880 (ast_expression*)callln
1884 func->blocks.push_back(body);
1885 intrin_reg(intrin, value, func);
1886 return (ast_expression*)value;
1889 static ast_expression *intrin_log(intrin_t *intrin) {
1890 return intrin_log_variant(intrin, "log", 2.7182818284590452354);
1892 static ast_expression *intrin_log10(intrin_t *intrin) {
1893 return intrin_log_variant(intrin, "log10", 10);
1895 static ast_expression *intrin_log2(intrin_t *intrin) {
1896 return intrin_log_variant(intrin, "log2", 2);
1898 static ast_expression *intrin_logb(intrin_t *intrin) {
1899 /* FLT_RADIX == 2 for now */
1900 return intrin_log_variant(intrin, "log2", 2);
1903 static ast_expression *intrin_shift_variant(intrin_t *intrin, const char *name, size_t instr) {
1905 * float [shift] (float a, float b) {
1906 * return floor(a [instr] pow(2, b));
1908 ast_value *value = NULL;
1909 ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name));
1910 ast_call *callfloor = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", name));
1911 ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
1912 ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
1913 ast_block *body = ast_block_new(intrin_ctx(intrin));
1914 ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
1916 value->expression.params.push_back(a);
1917 value->expression.params.push_back(b);
1919 /* <callpow> = pow(2, b) */
1920 callpow->params.push_back((ast_expression*)intrin->fold->imm_float[3]);
1921 callpow->params.push_back((ast_expression*)b);
1923 /* <callfloor> = floor(a [instr] <callpow>) */
1924 callfloor->params.push_back(
1925 (ast_expression*)ast_binary_new(
1929 (ast_expression*)callpow
1933 /* return <callfloor> */
1934 body->exprs.push_back(
1935 (ast_expression*)ast_return_new(
1937 (ast_expression*)callfloor
1941 func->blocks.push_back(body);
1942 intrin_reg(intrin, value, func);
1943 return (ast_expression*)value;
1946 static ast_expression *intrin_lshift(intrin_t *intrin) {
1947 return intrin_shift_variant(intrin, "lshift", INSTR_MUL_F);
1950 static ast_expression *intrin_rshift(intrin_t *intrin) {
1951 return intrin_shift_variant(intrin, "rshift", INSTR_DIV_F);
1955 * TODO: make static (and handle ast_type_string) here for the builtin
1956 * instead of in SYA parse close.
1958 ast_expression *intrin_debug_typestring(intrin_t *intrin) {
1960 return (ast_expression*)0x1;
1963 static const intrin_func_t intrinsics[] = {
1964 {&intrin_isfinite, "__builtin_isfinite", "isfinite", 1},
1965 {&intrin_isinf, "__builtin_isinf", "isinf", 1},
1966 {&intrin_isnan, "__builtin_isnan", "isnan", 1},
1967 {&intrin_isnormal, "__builtin_isnormal", "isnormal", 1},
1968 {&intrin_signbit, "__builtin_signbit", "signbit", 1},
1969 {&intrin_acosh, "__builtin_acosh", "acosh", 1},
1970 {&intrin_asinh, "__builtin_asinh", "asinh", 1},
1971 {&intrin_atanh, "__builtin_atanh", "atanh", 1},
1972 {&intrin_exp, "__builtin_exp", "exp", 1},
1973 {&intrin_exp2, "__builtin_exp2", "exp2", 1},
1974 {&intrin_expm1, "__builtin_expm1", "expm1", 1},
1975 {&intrin_mod, "__builtin_mod", "mod", 2},
1976 {&intrin_pow, "__builtin_pow", "pow", 2},
1977 {&intrin_fabs, "__builtin_fabs", "fabs", 1},
1978 {&intrin_log, "__builtin_log", "log", 1},
1979 {&intrin_log10, "__builtin_log10", "log10", 1},
1980 {&intrin_log2, "__builtin_log2", "log2", 1},
1981 {&intrin_logb, "__builtin_logb", "logb", 1},
1982 {&intrin_lshift, "__builtin_lshift", "", 2},
1983 {&intrin_rshift, "__builtin_rshift", "", 2},
1984 {&intrin_epsilon, "__builtin_epsilon", "", 0},
1985 {&intrin_nan, "__builtin_nan", "", 0},
1986 {&intrin_inf, "__builtin_inf", "", 0},
1987 {&intrin_ln, "__builtin_ln", "", 2},
1988 {&intrin_debug_typestring, "__builtin_debug_typestring", "", 0},
1989 {&intrin_nullfunc, "#nullfunc", "", 0}
1992 static void intrin_error(intrin_t *intrin, const char *fmt, ...) {
1995 vcompile_error(intrin->parser->lex->tok.ctx, fmt, ap);
2000 intrin_t *intrin_init(parser_t *parser) {
2001 intrin_t *intrin = new intrin_t;
2003 intrin->parser = parser;
2004 intrin->fold = parser->fold;
2006 for (auto &it : intrinsics) {
2007 intrin->intrinsics.push_back(it);
2008 intrin->generated.push_back(nullptr);
2014 void intrin_cleanup(intrin_t *intrin) {
2018 ast_expression *intrin_fold(intrin_t *intrin, ast_value *value, ast_expression **exprs) {
2019 if (!value || !value->name)
2021 for (auto &it : intrin->intrinsics) {
2022 if (!strcmp(value->name, it.name))
2023 return (vec_size(exprs) != it.args)
2025 : fold_intrin(intrin->fold, value->name + 10, exprs);
2030 static GMQCC_INLINE ast_expression *intrin_func_try(intrin_t *intrin, size_t offset, const char *compare) {
2031 for (auto &it : intrin->intrinsics) {
2032 const size_t index = &it - &intrin->intrinsics[0];
2033 if (strcmp(*(char **)((char *)&it + offset), compare))
2035 if (intrin->generated[index])
2036 return intrin->generated[index];
2037 return intrin->generated[index] = it.intrin(intrin);
2042 static ast_expression *intrin_func_self(intrin_t *intrin, const char *name, const char *from) {
2043 ast_expression *find;
2044 /* try current first */
2045 if ((find = parser_find_global(intrin->parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
2046 for (auto &it : intrin->parser->functions)
2047 if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0)
2049 /* try name second */
2050 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, name), name)))
2052 /* try alias third */
2053 if ((find = intrin_func_try(intrin, offsetof(intrin_func_t, alias), name)))
2057 intrin_error(intrin, "need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2058 return intrin_func_self(intrin, "#nullfunc", NULL);
2063 ast_expression *intrin_func(intrin_t *intrin, const char *name) {
2064 return intrin_func_self(intrin, name, NULL);