]> git.xonotic.org Git - xonotic/gmqcc.git/blob - intrin.cpp
fd7fa73a22495df304bf73c867749727066421fb
[xonotic/gmqcc.git] / intrin.cpp
1 #include <string.h>
2
3 #include "ast.h"
4 #include "fold.h"
5 #include "parser.h"
6
7 lex_ctx_t intrin::ctx() const {
8     return parser_ctx(m_parser);
9 }
10
11 ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) {
12     ast_value *value = nullptr;
13     ast_function *func  = nullptr;
14     char buffer[1024];
15     char stype [1024];
16
17     util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
18     util_snprintf(stype,  sizeof(stype),   "<%s>",        type_name[vtype]);
19
20     value = ast_value_new(ctx(), buffer, TYPE_FUNCTION);
21     value->intrinsic = true;
22     value->next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
23     func = ast_function_new(ctx(), buffer, value);
24     value->flags |= AST_FLAG_ERASEABLE;
25
26     *out = value;
27     return func;
28 }
29
30 void intrin::reg(ast_value *const value, ast_function *const func) {
31     m_parser->functions.push_back(func);
32     m_parser->globals.push_back((ast_expression*)value);
33 }
34
35 #define QC_POW_EPSILON 0.00001f
36
37 ast_expression *intrin::nullfunc() {
38     ast_value *val = nullptr;
39     ast_function *func = value(&val, nullptr, TYPE_VOID);
40     reg(val, func);
41     return (ast_expression*)val;
42 }
43
44 ast_expression *intrin::isfinite_() {
45     /*
46      * float isfinite(float x) {
47      *     return !(isnan(x) || isinf(x));
48      * }
49      */
50     ast_value    *val     = nullptr;
51     ast_value    *x         = ast_value_new(ctx(), "x", TYPE_FLOAT);
52     ast_function *func      = value(&val, "isfinite", TYPE_FLOAT);
53     ast_call     *callisnan = ast_call_new(ctx(), func_self("isnan", "isfinite"));
54     ast_call     *callisinf = ast_call_new(ctx(), func_self("isinf", "isfinite"));
55     ast_block    *block     = ast_block_new(ctx());
56
57     /* float x; */
58     val->type_params.push_back(x);
59
60     /* <callisnan> = isnan(x); */
61     callisnan->params.push_back((ast_expression*)x);
62
63     /* <callisinf> = isinf(x); */
64     callisinf->params.push_back((ast_expression*)x);
65
66     /* return (!<callisnan> || <callisinf>); */
67     block->exprs.push_back(
68         (ast_expression*)ast_return_new(
69             ctx(),
70             (ast_expression*)ast_unary_new(
71                 ctx(),
72                 INSTR_NOT_F,
73                 (ast_expression*)ast_binary_new(
74                     ctx(),
75                     INSTR_OR,
76                     (ast_expression*)callisnan,
77                     (ast_expression*)callisinf
78                 )
79             )
80         )
81     );
82
83     func->blocks.push_back(block);
84     reg(val, func);
85
86     return (ast_expression*)val;;
87 }
88
89 ast_expression *intrin::isinf_() {
90     /*
91      * float isinf(float x) {
92      *     return (x != 0.0) && (x + x == x);
93      * }
94      */
95     ast_value *val = nullptr;
96     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
97     ast_block *body = ast_block_new(ctx());
98     ast_function *func = value(&val, "isinf", TYPE_FLOAT);
99
100     body->exprs.push_back(
101         (ast_expression*)ast_return_new(
102             ctx(),
103             (ast_expression*)ast_binary_new(
104                 ctx(),
105                 INSTR_AND,
106                 (ast_expression*)ast_binary_new(
107                     ctx(),
108                     INSTR_NE_F,
109                     (ast_expression*)x,
110                     (ast_expression*)m_fold->m_imm_float[0]
111                 ),
112                 (ast_expression*)ast_binary_new(
113                     ctx(),
114                     INSTR_EQ_F,
115                     (ast_expression*)ast_binary_new(
116                         ctx(),
117                         INSTR_ADD_F,
118                         (ast_expression*)x,
119                         (ast_expression*)x
120                     ),
121                     (ast_expression*)x
122                 )
123             )
124         )
125     );
126
127     val->type_params.push_back(x);
128     func->blocks.push_back(body);
129
130     reg(val, func);
131
132     return (ast_expression*)val;
133 }
134
135 ast_expression *intrin::isnan_() {
136     /*
137      * float isnan(float x) {
138      *   float local;
139      *   local = x;
140      *
141      *   return (x != local);
142      * }
143      */
144     ast_value *val = nullptr;
145     ast_value *arg1 = ast_value_new(ctx(), "x",TYPE_FLOAT);
146     ast_value *local = ast_value_new(ctx(), "local", TYPE_FLOAT);
147     ast_block *body  = ast_block_new(ctx());
148     ast_function *func = value(&val, "isnan", TYPE_FLOAT);
149
150     body->locals.push_back(local);
151     body->exprs.push_back(
152         (ast_expression*)ast_store_new(
153             ctx(),
154             INSTR_STORE_F,
155             (ast_expression*)local,
156             (ast_expression*)arg1
157         )
158     );
159
160     body->exprs.push_back(
161         (ast_expression*)ast_return_new(
162             ctx(),
163             (ast_expression*)ast_binary_new(
164                 ctx(),
165                 INSTR_NE_F,
166                 (ast_expression*)arg1,
167                 (ast_expression*)local
168             )
169         )
170     );
171
172     val->type_params.push_back(arg1);
173     func->blocks.push_back(body);
174
175     reg(val, func);
176
177     return (ast_expression*)val;
178 }
179
180 ast_expression *intrin::isnormal_() {
181     /*
182      * float isnormal(float x) {
183      *     return isfinite(x);
184      * }
185      */
186     ast_value *val = nullptr;
187     ast_call *callisfinite = ast_call_new(ctx(), func_self("isfinite", "isnormal"));
188     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
189     ast_block *body = ast_block_new(ctx());
190     ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
191
192     val->type_params.push_back(x);
193     callisfinite->params.push_back((ast_expression*)x);
194
195     /* return <callisfinite> */
196     body->exprs.push_back(
197         (ast_expression*)ast_return_new(
198             ctx(),
199             (ast_expression*)callisfinite
200         )
201     );
202
203     func->blocks.push_back(body);
204     reg(val, func);
205     return (ast_expression*)val;
206 }
207
208 ast_expression *intrin::signbit_() {
209     /*
210      * float signbit(float x) {
211      *     return (x < 0);
212      * }
213      */
214     ast_value *val = nullptr;
215     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
216     ast_block *body = ast_block_new(ctx());
217     ast_function *func = value(&val, "signbit", TYPE_FLOAT);
218
219     val->type_params.push_back(x);
220
221     /* return (x < 0); */
222     body->exprs.push_back(
223         (ast_expression*)ast_return_new(
224             ctx(),
225             (ast_expression*)ast_ternary_new(
226                 ctx(),
227                 (ast_expression*)ast_binary_new(
228                     ctx(),
229                     INSTR_LT,
230                     (ast_expression*)x,
231                     (ast_expression*)m_fold->m_imm_float[0]
232                 ),
233                 (ast_expression*)m_fold->m_imm_float[1],
234                 (ast_expression*)m_fold->m_imm_float[0]
235             )
236         )
237     );
238
239     func->blocks.push_back(body);
240     reg(val, func);
241     return (ast_expression*)val;
242 }
243
244 ast_expression *intrin::acosh_() {
245     /*
246      * float acosh(float x) {
247      *     return log(x + sqrt((x * x) - 1));
248      * }
249      */
250     ast_value    *val    = nullptr;
251     ast_value    *x        = ast_value_new(ctx(), "x", TYPE_FLOAT);
252     ast_call     *calllog  = ast_call_new(ctx(), func_self("log", "acosh"));
253     ast_call     *callsqrt = ast_call_new(ctx(), func_self("sqrt", "acosh"));
254     ast_block    *body     = ast_block_new(ctx());
255     ast_function *func     = value(&val, "acosh", TYPE_FLOAT);
256
257     val->type_params.push_back(x);
258
259     /* <callsqrt> = sqrt((x * x) - 1); */
260     callsqrt->params.push_back(
261         (ast_expression*)ast_binary_new(
262             ctx(),
263             INSTR_SUB_F,
264             (ast_expression*)ast_binary_new(
265                 ctx(),
266                 INSTR_MUL_F,
267                 (ast_expression*)x,
268                 (ast_expression*)x
269             ),
270             (ast_expression*)m_fold->m_imm_float[1]
271         )
272     );
273
274     /* <calllog> = log(x + <callsqrt>); */
275     calllog->params.push_back(
276         (ast_expression*)ast_binary_new(
277             ctx(),
278             INSTR_ADD_F,
279             (ast_expression*)x,
280             (ast_expression*)callsqrt
281         )
282     );
283
284     /* return <calllog>; */
285     body->exprs.push_back(
286         (ast_expression*)ast_return_new(
287             ctx(),
288             (ast_expression*)calllog
289         )
290     );
291
292     func->blocks.push_back(body);
293     reg(val, func);
294     return (ast_expression*)val;
295 }
296
297 ast_expression *intrin::asinh_() {
298     /*
299      * float asinh(float x) {
300      *     return log(x + sqrt((x * x) + 1));
301      * }
302      */
303     ast_value *val = nullptr;
304     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
305     ast_call *calllog = ast_call_new(ctx(), func_self("log", "asinh"));
306     ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "asinh"));
307     ast_block *body = ast_block_new(ctx());
308     ast_function *func = value(&val, "asinh", TYPE_FLOAT);
309
310     val->type_params.push_back(x);
311
312     /* <callsqrt> = sqrt((x * x) + 1); */
313     callsqrt->params.push_back(
314         (ast_expression*)ast_binary_new(
315             ctx(),
316             INSTR_ADD_F,
317             (ast_expression*)ast_binary_new(
318                 ctx(),
319                 INSTR_MUL_F,
320                 (ast_expression*)x,
321                 (ast_expression*)x
322             ),
323             (ast_expression*)m_fold->m_imm_float[1]
324         )
325     );
326
327     /* <calllog> = log(x + <callsqrt>); */
328     calllog->params.push_back(
329         (ast_expression*)ast_binary_new(
330             ctx(),
331             INSTR_ADD_F,
332             (ast_expression*)x,
333             (ast_expression*)callsqrt
334         )
335     );
336
337     /* return <calllog>; */
338     body->exprs.push_back(
339         (ast_expression*)ast_return_new(
340             ctx(),
341             (ast_expression*)calllog
342         )
343     );
344
345     func->blocks.push_back(body);
346     reg(val, func);
347     return (ast_expression*)val;
348 }
349
350 ast_expression *intrin::atanh_() {
351     /*
352      * float atanh(float x) {
353      *     return 0.5 * log((1 + x) / (1 - x))
354      * }
355      */
356     ast_value    *val   = nullptr;
357     ast_value    *x       = ast_value_new(ctx(), "x", TYPE_FLOAT);
358     ast_call     *calllog = ast_call_new(ctx(), func_self("log", "atanh"));
359     ast_block    *body    = ast_block_new(ctx());
360     ast_function *func    = value(&val, "atanh", TYPE_FLOAT);
361
362     val->type_params.push_back(x);
363
364     /* <callog> = log((1 + x) / (1 - x)); */
365     calllog->params.push_back(
366         (ast_expression*)ast_binary_new(
367             ctx(),
368             INSTR_DIV_F,
369             (ast_expression*)ast_binary_new(
370                 ctx(),
371                 INSTR_ADD_F,
372                 (ast_expression*)m_fold->m_imm_float[1],
373                 (ast_expression*)x
374             ),
375             (ast_expression*)ast_binary_new(
376                 ctx(),
377                 INSTR_SUB_F,
378                 (ast_expression*)m_fold->m_imm_float[1],
379                 (ast_expression*)x
380             )
381         )
382     );
383
384     /* return 0.5 * <calllog>; */
385     body->exprs.push_back(
386         (ast_expression*)ast_binary_new(
387             ctx(),
388             INSTR_MUL_F,
389             (ast_expression*)m_fold->constgen_float(0.5, false),
390             (ast_expression*)calllog
391         )
392     );
393
394     func->blocks.push_back(body);
395     reg(val, func);
396     return (ast_expression*)val;
397 }
398
399 ast_expression *intrin::exp_() {
400     /*
401      * float exp(float x) {
402      *     float sum = 1.0;
403      *     float acc = 1.0;
404      *     float i;
405      *     for (i = 1; i < 200; ++i)
406      *         sum += (acc *= x / i);
407      *
408      *     return sum;
409      * }
410      */
411     ast_value *val = nullptr;
412     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
413     ast_value *sum = ast_value_new(ctx(), "sum", TYPE_FLOAT);
414     ast_value *acc = ast_value_new(ctx(), "acc", TYPE_FLOAT);
415     ast_value *i = ast_value_new(ctx(), "i",   TYPE_FLOAT);
416     ast_block *body = ast_block_new(ctx());
417     ast_function *func = value(&val, "exp", TYPE_FLOAT);
418
419     val->type_params.push_back(x);
420
421     body->locals.push_back(sum);
422     body->locals.push_back(acc);
423     body->locals.push_back(i);
424
425     /* sum = 1.0; */
426     body->exprs.push_back(
427         (ast_expression*)ast_store_new(
428             ctx(),
429             INSTR_STORE_F,
430             (ast_expression*)sum,
431             (ast_expression*)m_fold->m_imm_float[1]
432         )
433     );
434
435     /* acc = 1.0; */
436     body->exprs.push_back(
437         (ast_expression*)ast_store_new(
438             ctx(),
439             INSTR_STORE_F,
440             (ast_expression*)acc,
441             (ast_expression*)m_fold->m_imm_float[1]
442         )
443     );
444
445     /*
446      * for (i = 1; i < 200; ++i)
447      *     sum += (acc *= x / i);
448      */
449     body->exprs.push_back(
450         (ast_expression*)ast_loop_new(
451             ctx(),
452             /* i = 1; */
453             (ast_expression*)ast_store_new(
454                 ctx(),
455                 INSTR_STORE_F,
456                 (ast_expression*)i,
457                 (ast_expression*)m_fold->m_imm_float[1]
458             ),
459             /* i < 200; */
460             (ast_expression*)ast_binary_new(
461                 ctx(),
462                 INSTR_LT,
463                 (ast_expression*)i,
464                 (ast_expression*)m_fold->constgen_float(200.0f, false)
465             ),
466             false,
467             nullptr,
468             false,
469             /* ++i; */
470             (ast_expression*)ast_binstore_new(
471                 ctx(),
472                 INSTR_STORE_F,
473                 INSTR_ADD_F,
474                 (ast_expression*)i,
475                 (ast_expression*)m_fold->m_imm_float[1]
476             ),
477             /* sum += (acc *= (x / i)) */
478             (ast_expression*)ast_binstore_new(
479                 ctx(),
480                 INSTR_STORE_F,
481                 INSTR_ADD_F,
482                 (ast_expression*)sum,
483                 (ast_expression*)ast_binstore_new(
484                     ctx(),
485                     INSTR_STORE_F,
486                     INSTR_MUL_F,
487                     (ast_expression*)acc,
488                     (ast_expression*)ast_binary_new(
489                         ctx(),
490                         INSTR_DIV_F,
491                         (ast_expression*)x,
492                         (ast_expression*)i
493                     )
494                 )
495             )
496         )
497     );
498
499     /* return sum; */
500     body->exprs.push_back(
501         (ast_expression*)ast_return_new(
502             ctx(),
503             (ast_expression*)sum
504         )
505     );
506
507     func->blocks.push_back(body);
508     reg(val, func);
509     return (ast_expression*)val;
510 }
511
512 ast_expression *intrin::exp2_() {
513     /*
514      * float exp2(float x) {
515      *     return pow(2, x);
516      * }
517      */
518     ast_value *val = nullptr;
519     ast_call  *callpow = ast_call_new(ctx(), func_self("pow", "exp2"));
520     ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
521     ast_block *body = ast_block_new(ctx());
522     ast_function *func = value(&val, "exp2", TYPE_FLOAT);
523
524     val->type_params.push_back(arg1);
525
526     callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
527     callpow->params.push_back((ast_expression*)arg1);
528
529     /* return <callpow> */
530     body->exprs.push_back(
531         (ast_expression*)ast_return_new(
532             ctx(),
533             (ast_expression*)callpow
534         )
535     );
536
537     func->blocks.push_back(body);
538     reg(val, func);
539     return (ast_expression*)val;
540 }
541
542 ast_expression *intrin::expm1_() {
543     /*
544      * float expm1(float x) {
545      *     return exp(x) - 1;
546      * }
547      */
548     ast_value *val = nullptr;
549     ast_call *callexp = ast_call_new(ctx(), func_self("exp", "expm1"));
550     ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT);
551     ast_block *body = ast_block_new(ctx());
552     ast_function *func = value(&val, "expm1", TYPE_FLOAT);
553
554     val->type_params.push_back(x);
555
556     /* <callexp> = exp(x); */
557     callexp->params.push_back((ast_expression*)x);
558
559     /* return <callexp> - 1; */
560     body->exprs.push_back(
561         (ast_expression*)ast_return_new(
562             ctx(),
563             (ast_expression*)ast_binary_new(
564                 ctx(),
565                 INSTR_SUB_F,
566                 (ast_expression*)callexp,
567                 (ast_expression*)m_fold->m_imm_float[1]
568             )
569         )
570     );
571
572     func->blocks.push_back(body);
573     reg(val, func);
574     return (ast_expression*)val;
575 }
576
577 ast_expression *intrin::pow_() {
578     /*
579      *
580      * float pow(float base, float exp) {
581      *     float result;
582      *     float low;
583      *     float high;
584      *     float mid;
585      *     float square;
586      *     float accumulate;
587      *
588      *     if (exp == 0.0)
589      *         return 1;
590      *     if (exp == 1.0)
591      *         return base;
592      *     if (exp < 0)
593      *         return 1.0 / pow(base, -exp);
594      *     if (exp >= 1) {
595      *         result = pow(base, exp / 2);
596      *         return result * result;
597      *     }
598      *
599      *     low        = 0.0f;
600      *     high       = 1.0f;
601      *     square     = sqrt(base);
602      *     accumulate = square;
603      *     mid        = high / 2.0f
604      *
605      *     while (fabs(mid - exp) > QC_POW_EPSILON) {
606      *         square = sqrt(square);
607      *         if (mid < exp) {
608      *             low         = mid;
609      *             accumulate *= square;
610      *         } else {
611      *             high        = mid;
612      *             accumulate *= (1.0f / square);
613      *         }
614      *         mid = (low + high) / 2;
615      *     }
616      *     return accumulate;
617      * }
618      */
619     ast_value    *val = nullptr;
620     ast_function *func = value(&val, "pow", TYPE_FLOAT);
621
622     /* prepare some calls for later */
623     ast_call *callpow1  = ast_call_new(ctx(), (ast_expression*)val);                  /* for pow(base, -exp)    */
624     ast_call *callpow2  = ast_call_new(ctx(), (ast_expression*)val);                  /* for pow(vase, exp / 2) */
625     ast_call *callsqrt1 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(base)         */
626     ast_call *callsqrt2 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(square)       */
627     ast_call *callfabs  = ast_call_new(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp)    */
628
629     /* prepare some blocks for later */
630     ast_block *expgt1       = ast_block_new(ctx());
631     ast_block *midltexp     = ast_block_new(ctx());
632     ast_block *midltexpelse = ast_block_new(ctx());
633     ast_block *whileblock   = ast_block_new(ctx());
634
635     /* float pow(float base, float exp) */
636     ast_value    *base = ast_value_new(ctx(), "base", TYPE_FLOAT);
637     ast_value    *exp  = ast_value_new(ctx(), "exp",  TYPE_FLOAT);
638     /* { */
639     ast_block    *body = ast_block_new(ctx());
640
641     /*
642      * float result;
643      * float low;
644      * float high;
645      * float square;
646      * float accumulate;
647      * float mid;
648      */
649     ast_value *result     = ast_value_new(ctx(), "result",     TYPE_FLOAT);
650     ast_value *low        = ast_value_new(ctx(), "low",        TYPE_FLOAT);
651     ast_value *high       = ast_value_new(ctx(), "high",       TYPE_FLOAT);
652     ast_value *square     = ast_value_new(ctx(), "square",     TYPE_FLOAT);
653     ast_value *accumulate = ast_value_new(ctx(), "accumulate", TYPE_FLOAT);
654     ast_value *mid        = ast_value_new(ctx(), "mid",        TYPE_FLOAT);
655     body->locals.push_back(result);
656     body->locals.push_back(low);
657     body->locals.push_back(high);
658     body->locals.push_back(square);
659     body->locals.push_back(accumulate);
660     body->locals.push_back(mid);
661
662     val->type_params.push_back(base);
663     val->type_params.push_back(exp);
664
665     /*
666      * if (exp == 0.0)
667      *     return 1;
668      */
669     body->exprs.push_back(
670         (ast_expression*)ast_ifthen_new(
671             ctx(),
672             (ast_expression*)ast_binary_new(
673                 ctx(),
674                 INSTR_EQ_F,
675                 (ast_expression*)exp,
676                 (ast_expression*)m_fold->m_imm_float[0]
677             ),
678             (ast_expression*)ast_return_new(
679                 ctx(),
680                 (ast_expression*)m_fold->m_imm_float[1]
681             ),
682             nullptr
683         )
684     );
685
686     /*
687      * if (exp == 1.0)
688      *     return base;
689      */
690     body->exprs.push_back(
691         (ast_expression*)ast_ifthen_new(
692             ctx(),
693             (ast_expression*)ast_binary_new(
694                 ctx(),
695                 INSTR_EQ_F,
696                 (ast_expression*)exp,
697                 (ast_expression*)m_fold->m_imm_float[1]
698             ),
699             (ast_expression*)ast_return_new(
700                 ctx(),
701                 (ast_expression*)base
702             ),
703             nullptr
704         )
705     );
706
707     /* <callpow1> = pow(base, -exp) */
708     callpow1->params.push_back((ast_expression*)base);
709     callpow1->params.push_back(
710         (ast_expression*)ast_unary_new(
711             ctx(),
712             VINSTR_NEG_F,
713             (ast_expression*)exp
714         )
715     );
716
717     /*
718      * if (exp < 0)
719      *     return 1.0 / <callpow1>;
720      */
721     body->exprs.push_back(
722         (ast_expression*)ast_ifthen_new(
723             ctx(),
724             (ast_expression*)ast_binary_new(
725                 ctx(),
726                 INSTR_LT,
727                 (ast_expression*)exp,
728                 (ast_expression*)m_fold->m_imm_float[0]
729             ),
730             (ast_expression*)ast_return_new(
731                 ctx(),
732                 (ast_expression*)ast_binary_new(
733                     ctx(),
734                     INSTR_DIV_F,
735                     (ast_expression*)m_fold->m_imm_float[1],
736                     (ast_expression*)callpow1
737                 )
738             ),
739             nullptr
740         )
741     );
742
743     /* <callpow2> = pow(base, exp / 2) */
744     callpow2->params.push_back((ast_expression*)base);
745     callpow2->params.push_back(
746         (ast_expression*)ast_binary_new(
747             ctx(),
748             INSTR_DIV_F,
749             (ast_expression*)exp,
750             (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
751         )
752     );
753
754     /*
755      * <expgt1> = {
756      *     result = <callpow2>;
757      *     return result * result;
758      * }
759      */
760     expgt1->exprs.push_back(
761         (ast_expression*)ast_store_new(
762             ctx(),
763             INSTR_STORE_F,
764             (ast_expression*)result,
765             (ast_expression*)callpow2
766         )
767     );
768     expgt1->exprs.push_back(
769         (ast_expression*)ast_return_new(
770             ctx(),
771             (ast_expression*)ast_binary_new(
772                 ctx(),
773                 INSTR_MUL_F,
774                 (ast_expression*)result,
775                 (ast_expression*)result
776             )
777         )
778     );
779
780     /*
781      * if (exp >= 1) {
782      *     <expgt1>
783      * }
784      */
785     body->exprs.push_back(
786         (ast_expression*)ast_ifthen_new(
787             ctx(),
788             (ast_expression*)ast_binary_new(
789                 ctx(),
790                 INSTR_GE,
791                 (ast_expression*)exp,
792                 (ast_expression*)m_fold->m_imm_float[1]
793             ),
794             (ast_expression*)expgt1,
795             nullptr
796         )
797     );
798
799     /*
800      * <callsqrt1> = sqrt(base)
801      */
802     callsqrt1->params.push_back((ast_expression*)base);
803
804     /*
805      * low        = 0.0f;
806      * high       = 1.0f;
807      * square     = sqrt(base);
808      * accumulate = square;
809      * mid        = high / 2.0f;
810      */
811     body->exprs.push_back(
812         (ast_expression*)ast_store_new(ctx(),
813             INSTR_STORE_F,
814             (ast_expression*)low,
815             (ast_expression*)m_fold->m_imm_float[0]
816         )
817     );
818     body->exprs.push_back(
819         (ast_expression*)ast_store_new(
820             ctx(),
821             INSTR_STORE_F,
822             (ast_expression*)high,
823             (ast_expression*)m_fold->m_imm_float[1]
824         )
825     );
826
827     body->exprs.push_back(
828         (ast_expression*)ast_store_new(
829             ctx(),
830             INSTR_STORE_F,
831             (ast_expression*)square,
832             (ast_expression*)callsqrt1
833         )
834     );
835
836     body->exprs.push_back(
837         (ast_expression*)ast_store_new(
838             ctx(),
839             INSTR_STORE_F,
840             (ast_expression*)accumulate,
841             (ast_expression*)square
842         )
843     );
844     body->exprs.push_back(
845         (ast_expression*)ast_store_new(
846             ctx(),
847             INSTR_STORE_F,
848             (ast_expression*)mid,
849             (ast_expression*)ast_binary_new(
850                 ctx(),
851                 INSTR_DIV_F,
852                 (ast_expression*)high,
853                 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
854             )
855         )
856     );
857
858     /*
859      * <midltexp> = {
860      *     low         = mid;
861      *     accumulate *= square;
862      * }
863      */
864     midltexp->exprs.push_back(
865         (ast_expression*)ast_store_new(
866             ctx(),
867             INSTR_STORE_F,
868             (ast_expression*)low,
869             (ast_expression*)mid
870         )
871     );
872     midltexp->exprs.push_back(
873         (ast_expression*)ast_binstore_new(
874             ctx(),
875             INSTR_STORE_F,
876             INSTR_MUL_F,
877             (ast_expression*)accumulate,
878             (ast_expression*)square
879         )
880     );
881
882     /*
883      * <midltexpelse> = {
884      *     high        = mid;
885      *     accumulate *= (1.0 / square);
886      * }
887      */
888     midltexpelse->exprs.push_back(
889         (ast_expression*)ast_store_new(
890             ctx(),
891             INSTR_STORE_F,
892             (ast_expression*)high,
893             (ast_expression*)mid
894         )
895     );
896     midltexpelse->exprs.push_back(
897         (ast_expression*)ast_binstore_new(
898             ctx(),
899             INSTR_STORE_F,
900             INSTR_MUL_F,
901             (ast_expression*)accumulate,
902             (ast_expression*)ast_binary_new(
903                 ctx(),
904                 INSTR_DIV_F,
905                 (ast_expression*)m_fold->m_imm_float[1],
906                 (ast_expression*)square
907             )
908         )
909     );
910
911     /*
912      * <callsqrt2> = sqrt(square)
913      */
914     callsqrt2->params.push_back((ast_expression*)square);
915
916     /*
917      * <whileblock> = {
918      *     square = <callsqrt2>;
919      *     if (mid < exp)
920      *          <midltexp>;
921      *     else
922      *          <midltexpelse>;
923      *
924      *     mid = (low + high) / 2;
925      * }
926      */
927     whileblock->exprs.push_back(
928         (ast_expression*)ast_store_new(
929             ctx(),
930             INSTR_STORE_F,
931             (ast_expression*)square,
932             (ast_expression*)callsqrt2
933         )
934     );
935     whileblock->exprs.push_back(
936         (ast_expression*)ast_ifthen_new(
937             ctx(),
938             (ast_expression*)ast_binary_new(
939                 ctx(),
940                 INSTR_LT,
941                 (ast_expression*)mid,
942                 (ast_expression*)exp
943             ),
944             (ast_expression*)midltexp,
945             (ast_expression*)midltexpelse
946         )
947     );
948     whileblock->exprs.push_back(
949         (ast_expression*)ast_store_new(
950             ctx(),
951             INSTR_STORE_F,
952             (ast_expression*)mid,
953             (ast_expression*)ast_binary_new(
954                 ctx(),
955                 INSTR_DIV_F,
956                 (ast_expression*)ast_binary_new(
957                     ctx(),
958                     INSTR_ADD_F,
959                     (ast_expression*)low,
960                     (ast_expression*)high
961                 ),
962                 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
963             )
964         )
965     );
966
967     /*
968      * <callabs> = fabs(mid - exp)
969      */
970     callfabs->params.push_back(
971         (ast_expression*)ast_binary_new(
972             ctx(),
973             INSTR_SUB_F,
974             (ast_expression*)mid,
975             (ast_expression*)exp
976         )
977     );
978
979     /*
980      * while (<callfabs>  > epsilon)
981      *     <whileblock>
982      */
983     body->exprs.push_back(
984         (ast_expression*)ast_loop_new(
985             ctx(),
986             /* init */
987             nullptr,
988             /* pre condition */
989             (ast_expression*)ast_binary_new(
990                 ctx(),
991                 INSTR_GT,
992                 (ast_expression*)callfabs,
993                 (ast_expression*)m_fold->constgen_float(QC_POW_EPSILON, false)
994             ),
995             /* pre not */
996             false,
997             /* post condition */
998             nullptr,
999             /* post not */
1000             false,
1001             /* increment expression */
1002             nullptr,
1003             /* code block */
1004             (ast_expression*)whileblock
1005         )
1006     );
1007
1008     /* return accumulate */
1009     body->exprs.push_back(
1010         (ast_expression*)ast_return_new(
1011             ctx(),
1012             (ast_expression*)accumulate
1013         )
1014     );
1015
1016     /* } */
1017     func->blocks.push_back(body);
1018     reg(val, func);
1019     return (ast_expression*)val;
1020 }
1021
1022 ast_expression *intrin::mod_() {
1023     /*
1024      * float mod(float a, float b) {
1025      *     float div = a / b;
1026      *     float sign = (div < 0.0f) ? -1 : 1;
1027      *     return a - b * sign * floor(sign * div);
1028      * }
1029      */
1030     ast_value    *val = nullptr;
1031     ast_call     *call  = ast_call_new(ctx(), func_self("floor", "mod"));
1032     ast_value    *a     = ast_value_new(ctx(), "a",    TYPE_FLOAT);
1033     ast_value    *b     = ast_value_new(ctx(), "b",    TYPE_FLOAT);
1034     ast_value    *div   = ast_value_new(ctx(), "div",  TYPE_FLOAT);
1035     ast_value    *sign  = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1036     ast_block    *body  = ast_block_new(ctx());
1037     ast_function *func  = value(&val, "mod", TYPE_FLOAT);
1038
1039     val->type_params.push_back(a);
1040     val->type_params.push_back(b);
1041
1042     body->locals.push_back(div);
1043     body->locals.push_back(sign);
1044
1045     /* div = a / b; */
1046     body->exprs.push_back(
1047         (ast_expression*)ast_store_new(
1048             ctx(),
1049             INSTR_STORE_F,
1050             (ast_expression*)div,
1051             (ast_expression*)ast_binary_new(
1052                 ctx(),
1053                 INSTR_DIV_F,
1054                 (ast_expression*)a,
1055                 (ast_expression*)b
1056             )
1057         )
1058     );
1059
1060     /* sign = (div < 0.0f) ? -1 : 1; */
1061     body->exprs.push_back(
1062         (ast_expression*)ast_store_new(
1063             ctx(),
1064             INSTR_STORE_F,
1065             (ast_expression*)sign,
1066             (ast_expression*)ast_ternary_new(
1067                 ctx(),
1068                 (ast_expression*)ast_binary_new(
1069                     ctx(),
1070                     INSTR_LT,
1071                     (ast_expression*)div,
1072                     (ast_expression*)m_fold->m_imm_float[0]
1073                 ),
1074                 (ast_expression*)m_fold->m_imm_float[2],
1075                 (ast_expression*)m_fold->m_imm_float[1]
1076             )
1077         )
1078     );
1079
1080     /* floor(sign * div) */
1081     call->params.push_back(
1082         (ast_expression*)ast_binary_new(
1083             ctx(),
1084             INSTR_MUL_F,
1085             (ast_expression*)sign,
1086             (ast_expression*)div
1087         )
1088     );
1089
1090     /* return a - b * sign * <call> */
1091     body->exprs.push_back(
1092         (ast_expression*)ast_return_new(
1093             ctx(),
1094             (ast_expression*)ast_binary_new(
1095                 ctx(),
1096                 INSTR_SUB_F,
1097                 (ast_expression*)a,
1098                 (ast_expression*)ast_binary_new(
1099                     ctx(),
1100                     INSTR_MUL_F,
1101                     (ast_expression*)b,
1102                     (ast_expression*)ast_binary_new(
1103                         ctx(),
1104                         INSTR_MUL_F,
1105                         (ast_expression*)sign,
1106                         (ast_expression*)call
1107                     )
1108                 )
1109             )
1110         )
1111     );
1112
1113     func->blocks.push_back(body);
1114     reg(val, func);
1115     return (ast_expression*)val;
1116 }
1117
1118 ast_expression *intrin::fabs_() {
1119     /*
1120      * float fabs(float x) {
1121      *     return x < 0 ? -x : x;
1122      * }
1123      */
1124     ast_value    *val  = nullptr;
1125     ast_value    *arg1   = ast_value_new(ctx(), "x", TYPE_FLOAT);
1126     ast_block    *body   = ast_block_new(ctx());
1127     ast_function *func   = value(&val, "fabs", TYPE_FLOAT);
1128
1129     body->exprs.push_back(
1130         (ast_expression*)ast_return_new(
1131             ctx(),
1132             (ast_expression*)ast_ternary_new(
1133                 ctx(),
1134                 (ast_expression*)ast_binary_new(
1135                     ctx(),
1136                     INSTR_LE,
1137                     (ast_expression*)arg1,
1138                     (ast_expression*)m_fold->m_imm_float[0]
1139                 ),
1140                 (ast_expression*)ast_unary_new(
1141                     ctx(),
1142                     VINSTR_NEG_F,
1143                     (ast_expression*)arg1
1144                 ),
1145                 (ast_expression*)arg1
1146             )
1147         )
1148     );
1149
1150     val->type_params.push_back(arg1);
1151
1152     func->blocks.push_back(body);
1153     reg(val, func);
1154     return (ast_expression*)val;
1155 }
1156
1157 ast_expression *intrin::epsilon_() {
1158     /*
1159      * float epsilon(void) {
1160      *     float eps = 1.0f;
1161      *     do { eps /= 2.0f; } while ((1.0f + (eps / 2.0f)) != 1.0f);
1162      *     return eps;
1163      * }
1164      */
1165     ast_value    *val  = nullptr;
1166     ast_value    *eps    = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1167     ast_block    *body   = ast_block_new(ctx());
1168     ast_function *func   = value(&val, "epsilon", TYPE_FLOAT);
1169
1170     body->locals.push_back(eps);
1171
1172     /* eps = 1.0f; */
1173     body->exprs.push_back(
1174         (ast_expression*)ast_store_new(
1175             ctx(),
1176             INSTR_STORE_F,
1177             (ast_expression*)eps,
1178             (ast_expression*)m_fold->m_imm_float[0]
1179         )
1180     );
1181
1182     body->exprs.push_back(
1183         (ast_expression*)ast_loop_new(
1184             ctx(),
1185             nullptr,
1186             nullptr,
1187             false,
1188             (ast_expression*)ast_binary_new(
1189                 ctx(),
1190                 INSTR_NE_F,
1191                 (ast_expression*)ast_binary_new(
1192                     ctx(),
1193                     INSTR_ADD_F,
1194                     (ast_expression*)m_fold->m_imm_float[1],
1195                     (ast_expression*)ast_binary_new(
1196                         ctx(),
1197                         INSTR_MUL_F,
1198                         (ast_expression*)eps,
1199                         (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1200                     )
1201                 ),
1202                 (ast_expression*)m_fold->m_imm_float[1]
1203             ),
1204             false,
1205             nullptr,
1206             (ast_expression*)ast_binstore_new(
1207                 ctx(),
1208                 INSTR_STORE_F,
1209                 INSTR_DIV_F,
1210                 (ast_expression*)eps,
1211                 (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1212             )
1213         )
1214     );
1215
1216     /* return eps; */
1217     body->exprs.push_back(
1218         (ast_expression*)ast_return_new(
1219             ctx(),
1220             (ast_expression*)eps
1221         )
1222     );
1223
1224     func->blocks.push_back(body);
1225     reg(val, func);
1226     return (ast_expression*)val;
1227 }
1228
1229 ast_expression *intrin::nan_() {
1230     /*
1231      * float nan(void) {
1232      *     float x = 0.0f;
1233      *     return x / x;
1234      * }
1235      */
1236     ast_value    *val  = nullptr;
1237     ast_value    *x      = ast_value_new(ctx(), "x", TYPE_FLOAT);
1238     ast_function *func   = value(&val, "nan", TYPE_FLOAT);
1239     ast_block    *block  = ast_block_new(ctx());
1240
1241     block->locals.push_back(x);
1242
1243     block->exprs.push_back(
1244         (ast_expression*)ast_store_new(
1245             ctx(),
1246             INSTR_STORE_F,
1247             (ast_expression*)x,
1248             (ast_expression*)m_fold->m_imm_float[0]
1249         )
1250     );
1251
1252     block->exprs.push_back(
1253         (ast_expression*)ast_return_new(
1254             ctx(),
1255             (ast_expression*)ast_binary_new(
1256                 ctx(),
1257                 INSTR_DIV_F,
1258                 (ast_expression*)x,
1259                 (ast_expression*)x
1260             )
1261         )
1262     );
1263
1264     func->blocks.push_back(block);
1265     reg(val, func);
1266     return (ast_expression*)val;
1267 }
1268
1269 ast_expression *intrin::inf_() {
1270     /*
1271      * float inf(void) {
1272      *     float x = 1.0f;
1273      *     float y = 0.0f;
1274      *     return x / y;
1275      * }
1276      */
1277     ast_value    *val  = nullptr;
1278     ast_value    *x      = ast_value_new(ctx(), "x", TYPE_FLOAT);
1279     ast_value    *y      = ast_value_new(ctx(), "y", TYPE_FLOAT);
1280     ast_function *func   = value(&val, "inf", TYPE_FLOAT);
1281     ast_block    *block  = ast_block_new(ctx());
1282     size_t        i;
1283
1284     block->locals.push_back(x);
1285     block->locals.push_back(y);
1286
1287     /* to keep code size down */
1288     for (i = 0; i <= 1; i++) {
1289         block->exprs.push_back(
1290             (ast_expression*)ast_store_new(
1291                 ctx(),
1292                 INSTR_STORE_F,
1293                 (ast_expression*)((i == 0) ? x : y),
1294                 (ast_expression*)m_fold->m_imm_float[i]
1295             )
1296         );
1297     }
1298
1299     block->exprs.push_back(
1300         (ast_expression*)ast_return_new(
1301             ctx(),
1302             (ast_expression*)ast_binary_new(
1303                 ctx(),
1304                 INSTR_DIV_F,
1305                 (ast_expression*)x,
1306                 (ast_expression*)y
1307             )
1308         )
1309     );
1310
1311     func->blocks.push_back(block);
1312     reg(val, func);
1313     return (ast_expression*)val;
1314 }
1315
1316 ast_expression *intrin::ln_() {
1317     /*
1318      * float log(float power, float base) {
1319      *   float whole;
1320      *   float nth
1321      *   float sign = 1.0f;
1322      *   float eps  = epsilon();
1323      *
1324      *   if (power <= 1.0f || bbase <= 1.0) {
1325      *       if (power <= 0.0f || base <= 0.0f)
1326      *           return nan();
1327      *
1328      *       if (power < 1.0f) {
1329      *           power = 1.0f / power;
1330      *           sign *= -1.0f;
1331      *       }
1332      *
1333      *       if (base < 1.0f) {
1334      *           sign *= -1.0f;
1335      *           base  = 1.0f / base;
1336      *       }
1337      *   }
1338      *
1339      *   float A_i       = 1;
1340      *   float B_i       = 0;
1341      *   float A_iminus1 = 0;
1342      *   float B_iminus1 = 1;
1343      *
1344      *   for (;;) {
1345      *       whole = power;
1346      *       nth   = 0.0f;
1347      *
1348      *       while (whole >= base) {
1349      *           float base2    = base;
1350      *           float n2       = 1.0f;
1351      *           float newbase2 = base2 * base2;
1352      *
1353      *           while (whole >= newbase2) {
1354      *               base2     = newbase2;
1355      *               n2       *= 2;
1356      *               newbase2 *= newbase2;
1357      *           }
1358      *
1359      *           whole /= base2;
1360      *           nth += n2;
1361      *       }
1362      *
1363      *       float b_iplus1 = n;
1364      *       float A_iplus1 = b_iplus1 * A_i + A_iminus1;
1365      *       float B_iplus1 = b_iplus1 * B_i + B_iminus1;
1366      *
1367      *       A_iminus1 = A_i;
1368      *       B_iminus1 = B_i;
1369      *       A_i       = A_iplus1;
1370      *       B_i       = B_iplus1;
1371      *
1372      *       if (whole <= 1.0f + eps)
1373      *           break;
1374      *
1375      *       power = base;
1376      *       bower = whole;
1377      *   }
1378      *   return sign * A_i / B_i;
1379      * }
1380      */
1381
1382     ast_value *val = nullptr;
1383     ast_value *power = ast_value_new(ctx(), "power", TYPE_FLOAT);
1384     ast_value *base = ast_value_new(ctx(), "base",TYPE_FLOAT);
1385     ast_value *whole= ast_value_new(ctx(), "whole", TYPE_FLOAT);
1386     ast_value *nth = ast_value_new(ctx(), "nth", TYPE_FLOAT);
1387     ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT);
1388     ast_value *A_i = ast_value_new(ctx(), "A_i", TYPE_FLOAT);
1389     ast_value *B_i = ast_value_new(ctx(), "B_i", TYPE_FLOAT);
1390     ast_value *A_iminus1 = ast_value_new(ctx(), "A_iminus1", TYPE_FLOAT);
1391     ast_value *B_iminus1 = ast_value_new(ctx(), "B_iminus1", TYPE_FLOAT);
1392     ast_value *b_iplus1 = ast_value_new(ctx(), "b_iplus1", TYPE_FLOAT);
1393     ast_value *A_iplus1 = ast_value_new(ctx(), "A_iplus1", TYPE_FLOAT);
1394     ast_value *B_iplus1 = ast_value_new(ctx(), "B_iplus1", TYPE_FLOAT);
1395     ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT);
1396     ast_value *base2 = ast_value_new(ctx(), "base2", TYPE_FLOAT);
1397     ast_value *n2 = ast_value_new(ctx(), "n2",TYPE_FLOAT);
1398     ast_value *newbase2 = ast_value_new(ctx(), "newbase2", TYPE_FLOAT);
1399     ast_block *block = ast_block_new(ctx());
1400     ast_block *plt1orblt1 = ast_block_new(ctx()); // (power <= 1.0f || base <= 1.0f)
1401     ast_block *plt1 = ast_block_new(ctx()); // (power < 1.0f)
1402     ast_block *blt1 = ast_block_new(ctx()); // (base< 1.0f)
1403     ast_block *forloop = ast_block_new(ctx()); // for(;;)
1404     ast_block *whileloop = ast_block_new(ctx()); // while (whole >= base)
1405     ast_block *nestwhile= ast_block_new(ctx()); // while (whole >= newbase2)
1406     ast_function *func = value(&val, "ln", TYPE_FLOAT);
1407     size_t i;
1408
1409     val->type_params.push_back(power);
1410     val->type_params.push_back(base);
1411
1412     block->locals.push_back(whole);
1413     block->locals.push_back(nth);
1414     block->locals.push_back(sign);
1415     block->locals.push_back(eps);
1416     block->locals.push_back(A_i);
1417     block->locals.push_back(B_i);
1418     block->locals.push_back(A_iminus1);
1419     block->locals.push_back(B_iminus1);
1420
1421     /* sign = 1.0f; */
1422     block->exprs.push_back(
1423         (ast_expression*)ast_store_new(
1424             ctx(),
1425             INSTR_STORE_F,
1426             (ast_expression*)sign,
1427             (ast_expression*)m_fold->m_imm_float[1]
1428         )
1429     );
1430
1431     /* eps = __builtin_epsilon(); */
1432     block->exprs.push_back(
1433         (ast_expression*)ast_store_new(
1434             ctx(),
1435             INSTR_STORE_F,
1436             (ast_expression*)eps,
1437             (ast_expression*)ast_call_new(
1438                 ctx(),
1439                 func_self("__builtin_epsilon", "ln")
1440             )
1441         )
1442     );
1443
1444     /*
1445      * A_i       = 1;
1446      * B_i       = 0;
1447      * A_iminus1 = 0;
1448      * B_iminus1 = 1;
1449      */
1450     for (i = 0; i <= 1; i++) {
1451         int j;
1452         for (j = 1; j >= 0; j--) {
1453             block->exprs.push_back(
1454                 (ast_expression*)ast_store_new(
1455                     ctx(),
1456                     INSTR_STORE_F,
1457                     (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i)
1458                                           : ((i) ? A_iminus1 : B_i)),
1459                     (ast_expression*)m_fold->m_imm_float[j]
1460                 )
1461             );
1462         }
1463     }
1464
1465     /*
1466      * <plt1> = {
1467      *     power = 1.0f / power;
1468      *     sign *= -1.0f;
1469      * }
1470      * <blt1> = {
1471      *     base  = 1.0f / base;
1472      *     sign *= -1.0f;
1473      * }
1474      */
1475     for (i = 0; i <= 1; i++) {
1476         ((i) ? blt1 : plt1)->exprs.push_back(
1477             (ast_expression*)ast_store_new(
1478                 ctx(),
1479                 INSTR_STORE_F,
1480                 (ast_expression*)((i) ? base : power),
1481                 (ast_expression*)ast_binary_new(
1482                     ctx(),
1483                     INSTR_DIV_F,
1484                     (ast_expression*)m_fold->m_imm_float[1],
1485                     (ast_expression*)((i) ? base : power)
1486                 )
1487             )
1488         );
1489         plt1->exprs.push_back(
1490             (ast_expression*)ast_binstore_new(
1491                 ctx(),
1492                 INSTR_STORE_F,
1493                 INSTR_MUL_F,
1494                 (ast_expression*)sign,
1495                 (ast_expression*)m_fold->m_imm_float[2]
1496             )
1497         );
1498     }
1499
1500     /*
1501      * <plt1orblt1> = {
1502      *     if (power <= 0.0 || base <= 0.0f)
1503      *         return __builtin_nan();
1504      *     if (power < 1.0f)
1505      *         <plt1>
1506      *     if (base < 1.0f)
1507      *         <blt1>
1508      * }
1509      */
1510     plt1orblt1->exprs.push_back(
1511         (ast_expression*)ast_ifthen_new(
1512             ctx(),
1513             (ast_expression*)ast_binary_new(
1514                 ctx(),
1515                 INSTR_OR,
1516                 (ast_expression*)ast_binary_new(
1517                     ctx(),
1518                     INSTR_LE,
1519                     (ast_expression*)power,
1520                     (ast_expression*)m_fold->m_imm_float[0]
1521                 ),
1522                 (ast_expression*)ast_binary_new(
1523                     ctx(),
1524                     INSTR_LE,
1525                     (ast_expression*)base,
1526                     (ast_expression*)m_fold->m_imm_float[0]
1527                 )
1528             ),
1529             (ast_expression*)ast_return_new(
1530                 ctx(),
1531                 (ast_expression*)ast_call_new(
1532                     ctx(),
1533                     func_self("__builtin_nan", "ln")
1534                 )
1535             ),
1536             nullptr
1537         )
1538     );
1539
1540     for (i = 0; i <= 1; i++) {
1541         plt1orblt1->exprs.push_back(
1542             (ast_expression*)ast_ifthen_new(
1543                 ctx(),
1544                 (ast_expression*)ast_binary_new(
1545                     ctx(),
1546                     INSTR_LT,
1547                     (ast_expression*)((i) ? base : power),
1548                     (ast_expression*)m_fold->m_imm_float[1]
1549                 ),
1550                 (ast_expression*)((i) ? blt1 : plt1),
1551                 nullptr
1552             )
1553         );
1554     }
1555
1556     block->exprs.push_back((ast_expression*)plt1orblt1);
1557
1558
1559     /* whole = power; */
1560     forloop->exprs.push_back(
1561         (ast_expression*)ast_store_new(
1562             ctx(),
1563             INSTR_STORE_F,
1564             (ast_expression*)whole,
1565             (ast_expression*)power
1566         )
1567     );
1568
1569     /* nth = 0.0f; */
1570     forloop->exprs.push_back(
1571         (ast_expression*)ast_store_new(
1572             ctx(),
1573             INSTR_STORE_F,
1574             (ast_expression*)nth,
1575             (ast_expression*)m_fold->m_imm_float[0]
1576         )
1577     );
1578
1579     /* base2 = base; */
1580     whileloop->exprs.push_back(
1581         (ast_expression*)ast_store_new(
1582             ctx(),
1583             INSTR_STORE_F,
1584             (ast_expression*)base2,
1585             (ast_expression*)base
1586         )
1587     );
1588
1589     /* n2 = 1.0f; */
1590     whileloop->exprs.push_back(
1591         (ast_expression*)ast_store_new(
1592             ctx(),
1593             INSTR_STORE_F,
1594             (ast_expression*)n2,
1595             (ast_expression*)m_fold->m_imm_float[1]
1596         )
1597     );
1598
1599     /* newbase2 = base2 * base2; */
1600     whileloop->exprs.push_back(
1601         (ast_expression*)ast_store_new(
1602             ctx(),
1603             INSTR_STORE_F,
1604             (ast_expression*)newbase2,
1605             (ast_expression*)ast_binary_new(
1606                 ctx(),
1607                 INSTR_MUL_F,
1608                 (ast_expression*)base2,
1609                 (ast_expression*)base2
1610             )
1611         )
1612     );
1613
1614     /* while loop locals */
1615     whileloop->locals.push_back(base2);
1616     whileloop->locals.push_back(n2);
1617     whileloop->locals.push_back(newbase2);
1618
1619     /* base2 = newbase2; */
1620     nestwhile->exprs.push_back(
1621         (ast_expression*)ast_store_new(
1622             ctx(),
1623             INSTR_STORE_F,
1624             (ast_expression*)base2,
1625             (ast_expression*)newbase2
1626         )
1627     );
1628
1629     /* n2 *= 2; */
1630     nestwhile->exprs.push_back(
1631         (ast_expression*)ast_binstore_new(
1632             ctx(),
1633             INSTR_STORE_F,
1634             INSTR_MUL_F,
1635             (ast_expression*)n2,
1636             (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */
1637         )
1638     );
1639
1640     /* newbase2 *= newbase2; */
1641     nestwhile->exprs.push_back(
1642         (ast_expression*)ast_binstore_new(
1643             ctx(),
1644             INSTR_STORE_F,
1645             INSTR_MUL_F,
1646             (ast_expression*)newbase2,
1647             (ast_expression*)newbase2
1648         )
1649     );
1650
1651     /* while (whole >= newbase2) */
1652     whileloop->exprs.push_back(
1653         (ast_expression*)ast_loop_new(
1654             ctx(),
1655             nullptr,
1656             (ast_expression*)ast_binary_new(
1657                 ctx(),
1658                 INSTR_GE,
1659                 (ast_expression*)whole,
1660                 (ast_expression*)newbase2
1661             ),
1662             false,
1663             nullptr,
1664             false,
1665             nullptr,
1666             (ast_expression*)nestwhile
1667         )
1668     );
1669
1670     /* whole /= base2; */
1671     whileloop->exprs.push_back(
1672         (ast_expression*)ast_binstore_new(
1673             ctx(),
1674             INSTR_STORE_F,
1675             INSTR_DIV_F,
1676             (ast_expression*)whole,
1677             (ast_expression*)base2
1678         )
1679     );
1680
1681     /* nth += n2; */
1682     whileloop->exprs.push_back(
1683         (ast_expression*)ast_binstore_new(
1684             ctx(),
1685             INSTR_STORE_F,
1686             INSTR_ADD_F,
1687             (ast_expression*)nth,
1688             (ast_expression*)n2
1689         )
1690     );
1691
1692     /* while (whole >= base) */
1693     forloop->exprs.push_back(
1694         (ast_expression*)ast_loop_new(
1695             ctx(),
1696             nullptr,
1697             (ast_expression*)ast_binary_new(
1698                 ctx(),
1699                 INSTR_GE,
1700                 (ast_expression*)whole,
1701                 (ast_expression*)base
1702             ),
1703             false,
1704             nullptr,
1705             false,
1706             nullptr,
1707             (ast_expression*)whileloop
1708         )
1709     );
1710
1711     forloop->locals.push_back(b_iplus1);
1712     forloop->locals.push_back(A_iplus1);
1713     forloop->locals.push_back(B_iplus1);
1714
1715     /* b_iplus1 = nth; */
1716     forloop->exprs.push_back(
1717         (ast_expression*)ast_store_new(
1718             ctx(),
1719             INSTR_STORE_F,
1720             (ast_expression*)b_iplus1,
1721             (ast_expression*)nth
1722         )
1723     );
1724
1725     /*
1726      * A_iplus1 = b_iplus1 * A_i + A_iminus1;
1727      * B_iplus1 = b_iplus1 * B_i + B_iminus1;
1728      */
1729     for (i = 0; i <= 1; i++) {
1730         forloop->exprs.push_back(
1731             (ast_expression*)ast_store_new(
1732                 ctx(),
1733                 INSTR_STORE_F,
1734                 (ast_expression*)((i) ? B_iplus1 : A_iplus1),
1735                 (ast_expression*)ast_binary_new(
1736                     ctx(),
1737                     INSTR_ADD_F,
1738                     (ast_expression*)ast_binary_new(
1739                         ctx(),
1740                         INSTR_MUL_F,
1741                         (ast_expression*)b_iplus1,
1742                         (ast_expression*) ((i) ? B_i : A_i)
1743                     ),
1744                     (ast_expression*)((i) ? B_iminus1 : A_iminus1)
1745                 )
1746             )
1747         );
1748     }
1749
1750     /*
1751      * A_iminus1 = A_i;
1752      * B_iminus1 = B_i;
1753      */
1754     for (i = 0; i <= 1; i++) {
1755         forloop->exprs.push_back(
1756             (ast_expression*)ast_store_new(
1757                 ctx(),
1758                 INSTR_STORE_F,
1759                 (ast_expression*)((i) ? B_iminus1 : A_iminus1),
1760                 (ast_expression*)((i) ? B_i       : A_i)
1761             )
1762         );
1763     }
1764
1765     /*
1766      * A_i = A_iplus1;
1767      * B_i = B_iplus1;
1768      */
1769     for (i = 0; i <= 1; i++) {
1770         forloop->exprs.push_back(
1771             (ast_expression*)ast_store_new(
1772                 ctx(),
1773                 INSTR_STORE_F,
1774                 (ast_expression*)((i) ? B_i      : A_i),
1775                 (ast_expression*)((i) ? B_iplus1 : A_iplus1)
1776             )
1777         );
1778     }
1779
1780     /*
1781      * if (whole <= 1.0f + eps)
1782      *     break;
1783      */
1784     forloop->exprs.push_back(
1785         (ast_expression*)ast_ifthen_new(
1786             ctx(),
1787             (ast_expression*)ast_binary_new(
1788                 ctx(),
1789                 INSTR_LE,
1790                 (ast_expression*)whole,
1791                 (ast_expression*)ast_binary_new(
1792                     ctx(),
1793                     INSTR_ADD_F,
1794                     (ast_expression*)m_fold->m_imm_float[1],
1795                     (ast_expression*)eps
1796                 )
1797             ),
1798             (ast_expression*)ast_breakcont_new(
1799                 ctx(),
1800                 false,
1801                 0
1802             ),
1803             nullptr
1804         )
1805     );
1806
1807     /*
1808      * power = base;
1809      * base  = whole;
1810      */
1811     for (i = 0; i <= 1; i++) {
1812         forloop->exprs.push_back(
1813             (ast_expression*)ast_store_new(
1814                 ctx(),
1815                 INSTR_STORE_F,
1816                 (ast_expression*)((i) ? base  : power),
1817                 (ast_expression*)((i) ? whole : base)
1818             )
1819         );
1820     }
1821
1822     /* add the for loop block */
1823     block->exprs.push_back(
1824         (ast_expression*)ast_loop_new(
1825             ctx(),
1826             nullptr,
1827             /* for(; 1; ) ?? (can this be nullptr too?) */
1828             (ast_expression*)m_fold->m_imm_float[1],
1829             false,
1830             nullptr,
1831             false,
1832             nullptr,
1833             (ast_expression*)forloop
1834         )
1835     );
1836
1837     /* return sign * A_i / B_il */
1838     block->exprs.push_back(
1839         (ast_expression*)ast_return_new(
1840             ctx(),
1841             (ast_expression*)ast_binary_new(
1842                 ctx(),
1843                 INSTR_MUL_F,
1844                 (ast_expression*)sign,
1845                 (ast_expression*)ast_binary_new(
1846                     ctx(),
1847                     INSTR_DIV_F,
1848                     (ast_expression*)A_i,
1849                     (ast_expression*)B_i
1850                 )
1851             )
1852         )
1853     );
1854
1855     func->blocks.push_back(block);
1856     reg(val, func);
1857     return (ast_expression*)val;
1858 }
1859
1860 ast_expression *intrin::log_variant(const char *name, float base) {
1861     ast_value *val = nullptr;
1862     ast_call *callln = ast_call_new (ctx(), func_self("__builtin_ln", name));
1863     ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT);
1864     ast_block *body = ast_block_new(ctx());
1865     ast_function *func = value(&val, name, TYPE_FLOAT);
1866
1867     val->type_params.push_back(arg1);
1868
1869     callln->params.push_back((ast_expression*)arg1);
1870     callln->params.push_back((ast_expression*)m_fold->constgen_float(base, false));
1871
1872     body->exprs.push_back(
1873         (ast_expression*)ast_return_new(
1874             ctx(),
1875             (ast_expression*)callln
1876         )
1877     );
1878
1879     func->blocks.push_back(body);
1880     reg(val, func);
1881     return (ast_expression*)val;
1882 }
1883
1884 ast_expression *intrin::log_() {
1885     return log_variant("log", 2.7182818284590452354);
1886 }
1887 ast_expression *intrin::log10_() {
1888     return log_variant("log10", 10);
1889 }
1890 ast_expression *intrin::log2_() {
1891     return log_variant("log2", 2);
1892 }
1893 ast_expression *intrin::logb_() {
1894     /* FLT_RADIX == 2 for now */
1895     return log_variant("log2", 2);
1896 }
1897
1898 ast_expression *intrin::shift_variant(const char *name, size_t instr) {
1899     /*
1900      * float [shift] (float a, float b) {
1901      *   return floor(a [instr] pow(2, b));
1902      */
1903     ast_value *val = nullptr;
1904     ast_call *callpow = ast_call_new(ctx(), func_self("pow", name));
1905     ast_call *callfloor = ast_call_new(ctx(), func_self("floor", name));
1906     ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT);
1907     ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT);
1908     ast_block *body = ast_block_new(ctx());
1909     ast_function *func = value(&val, name, TYPE_FLOAT);
1910
1911     val->type_params.push_back(a);
1912     val->type_params.push_back(b);
1913
1914     /* <callpow> = pow(2, b) */
1915     callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
1916     callpow->params.push_back((ast_expression*)b);
1917
1918     /* <callfloor> = floor(a [instr] <callpow>) */
1919     callfloor->params.push_back(
1920         (ast_expression*)ast_binary_new(
1921             ctx(),
1922             instr,
1923             (ast_expression*)a,
1924             (ast_expression*)callpow
1925         )
1926     );
1927
1928     /* return <callfloor> */
1929     body->exprs.push_back(
1930         (ast_expression*)ast_return_new(
1931             ctx(),
1932             (ast_expression*)callfloor
1933         )
1934     );
1935
1936     func->blocks.push_back(body);
1937     reg(val, func);
1938     return (ast_expression*)val;
1939 }
1940
1941 ast_expression *intrin::lshift() {
1942     return shift_variant("lshift", INSTR_MUL_F);
1943 }
1944
1945 ast_expression *intrin::rshift() {
1946     return shift_variant("rshift", INSTR_DIV_F);
1947 }
1948
1949 void intrin::error(const char *fmt, ...) {
1950     va_list ap;
1951     va_start(ap, fmt);
1952     vcompile_error(ctx(), fmt, ap);
1953     va_end(ap);
1954 }
1955
1956 /* exposed */
1957 ast_expression *intrin::debug_typestring() {
1958     return (ast_expression*)0x1;
1959 }
1960
1961 intrin::intrin(parser_t *parser)
1962     : m_parser(parser)
1963     , m_fold(&parser->m_fold)
1964 {
1965     static const intrin_func_t intrinsics[] = {
1966         {&intrin::isfinite_,        "__builtin_isfinite",         "isfinite", 1},
1967         {&intrin::isinf_,           "__builtin_isinf",            "isinf",    1},
1968         {&intrin::isnan_,           "__builtin_isnan",            "isnan",    1},
1969         {&intrin::isnormal_,        "__builtin_isnormal",         "isnormal", 1},
1970         {&intrin::signbit_,         "__builtin_signbit",          "signbit",  1},
1971         {&intrin::acosh_,           "__builtin_acosh",            "acosh",    1},
1972         {&intrin::asinh_,           "__builtin_asinh",            "asinh",    1},
1973         {&intrin::atanh_,           "__builtin_atanh",            "atanh",    1},
1974         {&intrin::exp_,             "__builtin_exp",              "exp",      1},
1975         {&intrin::exp2_,            "__builtin_exp2",             "exp2",     1},
1976         {&intrin::expm1_,           "__builtin_expm1",            "expm1",    1},
1977         {&intrin::mod_,             "__builtin_mod",              "mod",      2},
1978         {&intrin::pow_,             "__builtin_pow",              "pow",      2},
1979         {&intrin::fabs_,            "__builtin_fabs",             "fabs",     1},
1980         {&intrin::log_,             "__builtin_log",              "log",      1},
1981         {&intrin::log10_,           "__builtin_log10",            "log10",    1},
1982         {&intrin::log2_,            "__builtin_log2",             "log2",     1},
1983         {&intrin::logb_,            "__builtin_logb",             "logb",     1},
1984         {&intrin::lshift,           "__builtin_lshift",           "",         2},
1985         {&intrin::rshift,           "__builtin_rshift",           "",         2},
1986         {&intrin::epsilon_,         "__builtin_epsilon",          "",         0},
1987         {&intrin::nan_,             "__builtin_nan",              "",         0},
1988         {&intrin::inf_,             "__builtin_inf",              "",         0},
1989         {&intrin::ln_,              "__builtin_ln",               "",         2},
1990         {&intrin::debug_typestring, "__builtin_debug_typestring", "",         0},
1991         {&intrin::nullfunc,         "#nullfunc",                  "",         0}
1992     };
1993
1994     for (auto &it : intrinsics) {
1995         m_intrinsics.push_back(it);
1996         m_generated.push_back(nullptr);
1997     }
1998 }
1999
2000 ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) {
2001     if (!val || !val->name)
2002         return nullptr;
2003     static constexpr size_t kPrefixLength = 10; // "__builtin_"
2004     for (auto &it : m_intrinsics) {
2005         if (!strcmp(val->name, it.name))
2006             return (vec_size(exprs) != it.args)
2007                         ? nullptr
2008                         : m_fold->intrinsic(val->name + kPrefixLength, exprs);
2009     }
2010     return nullptr;
2011 }
2012
2013 ast_expression *intrin::func_try(size_t offset, const char *compare) {
2014     for (auto &it : m_intrinsics) {
2015         const size_t index = &it - &m_intrinsics[0];
2016         if (strcmp(*(char **)((char *)&it + offset), compare))
2017             continue;
2018         if (m_generated[index])
2019             return m_generated[index];
2020         return m_generated[index] = (this->*it.intrin_func_t::function)();
2021     }
2022     return nullptr;
2023 }
2024
2025 ast_expression *intrin::func_self(const char *name, const char *from) {
2026     ast_expression *find;
2027     /* try current first */
2028     if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->vtype == TYPE_FUNCTION)
2029         for (auto &it : m_parser->functions)
2030             if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0)
2031                 return find;
2032     /* try name second */
2033     if ((find = func_try(offsetof(intrin_func_t, name),  name)))
2034         return find;
2035     /* try alias third */
2036     if ((find = func_try(offsetof(intrin_func_t, alias), name)))
2037         return find;
2038
2039     if (from) {
2040         error("need function `%s', compiler depends on it for `__builtin_%s'", name, from);
2041         return func_self("#nullfunc", nullptr);
2042     }
2043     return nullptr;
2044 }
2045
2046 ast_expression *intrin::func(const char *name) {
2047     return func_self(name, nullptr);
2048 }