1 /**
2  * Compiler implementation of the
3  * $(LINK2 https://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/oper.d, backend/oper.d)
10  */
11 
12 module dmd.backend.oper;
13 
14 // Online documentation: https://dlang.org/phobos/dmd_backend_oper.html
15 
16 extern (C++):
17 @nogc:
18 nothrow:
19 @safe:
20 
21 alias OPER = int;
22 enum
23 {
24         OPunde,                 // place holder for undefined operator
25 
26         OPadd,
27         OPmin,
28         OPmul,
29         OPdiv,
30         OPmod,
31         OPshr,                  // unsigned right shift
32         OPshl,
33         OPand,
34         OPxor,
35         OPor,
36         OPashr,                 // signed right shift
37         OPnot,
38         OPbool,                 // "booleanize"
39         OPcom,
40         OPcond,
41         OPcomma,
42         OPoror,
43         OPandand,
44         OPbit,                  // ref to bit field
45         OPind,                  // *E
46         OPaddr,                 // &E
47         OPneg,                  // unary -
48         OPuadd,                 // unary +
49         OPvoid,                 // where casting to void is not a no-op
50         OPabs,                  // absolute value
51         OPtoprec,               // round to precision (for 80 bit reals)
52         OPrndtol,               // round to short, long, long long (inline 8087 only)
53         OPrint,                 // round to int
54 
55         OPsqrt,                 // square root
56         OPsin,                  // sine
57         OPcos,                  // cosine
58         OPscale,                // ldexp
59         OPyl2x,                 // y * log2(x)
60         OPyl2xp1,               // y * log2(x + 1)
61         OPcmpxchg,              // cmpxchg
62 
63         OPstrlen,               // strlen()
64         OPstrcpy,               // strcpy()
65         OPstrcat,               // strcat()
66         OPstrcmp,               // strcmp()
67         OPmemcpy,
68         OPmemcmp,
69         OPmemset,
70         OPsetjmp,               // setjmp()
71 
72         OPremquo,               // / and % in one operation
73 
74         OPbsf,                  // bit scan forward
75         OPbsr,                  // bit scan reverse
76         OPbt,                   // bit test
77         OPbtc,                  // bit test and complement
78         OPbtr,                  // bit test and reset
79         OPbts,                  // bit test and set
80         OPbswap,                // swap bytes
81         OProl,                  // rotate left
82         OPror,                  // rotate right
83         OPbtst,                 // bit test
84         OPpopcnt,               // count of number of bits set to 1
85 
86         OPstreq,                // structure assignment
87 
88         OPnegass,               // x = -x
89         OPpostinc,              // x++
90         OPpostdec,              // x--
91 
92         OPeq,
93         OPaddass,
94         OPminass,
95         OPmulass,
96         OPdivass,
97         OPmodass,
98         OPshrass,
99         OPshlass,
100         OPandass,
101         OPxorass,
102         OPorass,
103 
104         OPashrass,
105 
106         // relational operators (in same order as corresponding tokens)
107         RELOPMIN,
108         OPle = RELOPMIN,
109         OPgt,
110         OPlt,
111         OPge,
112         OPeqeq,
113         OPne,
114 
115         OPunord,        // !<>=
116         OPlg,           // <>
117         OPleg,          // <>=
118         OPule,          // !>
119         OPul,           // !>=
120         OPuge,          // !<
121         OPug,           // !<=
122         OPue,           // !<>
123         OPngt,
124         OPnge,
125         OPnlt,
126         OPnle,
127         OPord,
128         OPnlg,
129         OPnleg,
130         OPnule,
131         OPnul,
132         OPnuge,
133         OPnug,
134         RELOPMAX,
135         OPnue = RELOPMAX,
136 
137 //**************** End of relational operators *****************
138 
139 /*      8,16,32,64      integral type of unspecified sign
140         s,u             signed/unsigned
141         f,d,ld          float/double/long double
142         np,fp,vp,f16p   near pointer/far pointer/handle pointer/far16 pointer
143         cvp             const handle pointer
144 */
145 
146         CNVOPMIN,
147         OPb_8 = CNVOPMIN,   // convert bit to byte
148         OPd_s32,
149         OPs32_d,
150         OPd_s16,
151         OPs16_d,
152         OPd_u16,
153         OPu16_d,
154         OPd_u32,
155         OPu32_d,
156         OPd_s64,
157         OPs64_d,
158         OPd_u64,
159         OPu64_d,
160         OPd_f,
161         OPf_d,
162         OPs16_32,       // short to long
163         OPu16_32,       // unsigned short to long
164         OP32_16,        // long to short
165         OPu8_16,        // unsigned char to short
166         OPs8_16,        // signed char to short
167         OP16_8,         // short to 8 bits
168         OPu32_64,       // unsigned long to long long
169         OPs32_64,       // long to long long
170         OP64_32,        // long long to long
171         OPu64_128,
172         OPs64_128,
173         OP128_64,
174 
175         // segmented
176         OPvp_fp,
177         OPcvp_fp,       // const handle * => far *
178         OPoffset,       // get offset of far pointer
179         OPnp_fp,        // convert near pointer to far
180         OPnp_f16p,      // from 0:32 to 16:16
181         OPf16p_np,      // from 16:16 to 0:32
182 
183         OPld_d,
184         OPd_ld,
185         CNVOPMAX,
186         OPld_u64 = CNVOPMAX,
187 
188 //**************** End of conversion operators *****************
189 
190         OPc_r,          // complex to real
191         OPc_i,          // complex to imaginary
192         OPmsw,          // top 32 bits of 64 bit word (32 bit code gen)
193                         // top 16 bits of 32 bit word (16 bit code gen)
194 
195         OPparam,                // function parameter separator
196         OPcall,                 // binary function call
197         OPucall,                // unary function call
198         OPcallns,               // binary function call, no side effects
199         OPucallns,              // unary function call, no side effects
200 
201         OPsizeof,               // for forward-ref'd structs
202         OPstrctor,              // call ctor on struct param
203         OPstrthis,              // 'this' pointer for OPstrctor
204         OPstrpar,               // structure func param
205         OPconst,                // constant
206         OPrelconst,             // constant that contains an address
207         OPvar,                  // variable
208         OPreg,                  // register (used in inline asm operand expressions)
209         OPcolon,                // : as in ?:
210         OPcolon2,               // alternate version with different EH semantics
211         OPstring,               // address of string
212         OPnullptr,              // null pointer
213         OPasm,                  // in-line assembly code
214         OPinfo,                 // attach info (used to attach ctor/dtor
215                                 // info for exception handling)
216         OPhalt,                 // insert HLT instruction
217         OPctor,
218         OPdtor,
219         OPmark,
220         OPdctor,                // D constructor
221         OPddtor,                // D destructor
222 
223         OPpair,                 // build register pair, E1 is lsb, E2 = msb
224         OPrpair,                // build reversed register pair, E1 is msb, E2 = lsb
225         OPframeptr,             // load pointer to base of frame
226         OPgot,                  // load pointer to global offset table
227         OPvector,               // SIMD vector operations
228         OPvecsto,               // SIMD vector store operations
229         OPvecfill,              // fill SIMD vector with E1
230 
231         OPinp,                  // input from I/O port
232         OPoutp,                 // output to I/O port
233 
234         // C++ operators
235         OPnew,                  // operator new
236         OPanew,                 // operator new[]
237         OPdelete,               // operator delete
238         OPadelete,              // operator delete[]
239         OPbrack,                // [] subscript
240         OParrow,                // for -> overloading
241         OParrowstar,            // for ->* overloading
242         OPpreinc,               // ++x overloading
243         OPpredec,               // --x overloading
244 
245         OPva_start,             // va_start intrinsic (dmd)
246         OPprefetch,             // prefetch intrinsic (dmd)
247 
248         OPMAX                   // 1 past last operator
249 }
250 
251 
252 /************************************
253  * Determine things about relational operators.
254  */
255 
256 OPER rel_not(OPER op)       { return _rel_not      [op - RELOPMIN]; }
257 OPER rel_swap(OPER op)      { return _rel_swap     [op - RELOPMIN]; }
258 OPER rel_integral(OPER op)  { return _rel_integral [op - RELOPMIN]; }
259 OPER rel_exception(OPER op) { return _rel_exception[op - RELOPMIN]; }
260 OPER rel_unord(OPER op)     { return _rel_unord    [op - RELOPMIN]; }
261 
262 /****************************************
263  * Conversion operators.
264  * Convert from conversion operator to conversion index
265  * parallel array invconvtab[] in cgelem.c
266  * Params:
267  *   op = conversion operator
268  */
269 int convidx(OPER op) { return op - CNVOPMIN; }
270 
271 
272 /**********************************
273  * Various types of operators:
274  *      OTbinary        binary
275  *      OTunary         unary
276  *      OTleaf          leaf
277  *      OTcommut        commutative (e1 op e2) == (e2 op e1)
278  *                      (assoc == !=)
279  *      OTassoc         associative (e1 op (e2 op e3)) == ((e1 op e2) op e3)
280  *                      (also commutative)
281  *      OTassign        assignment = op= i++ i-- i=-i str=
282  *      OTpost          post inc or post dec operator
283  *      OTeop0e         if (e op 0) => e
284  *      OTeop00         if (e op 0) => 0
285  *      OTeop1e         if (e op 1) => e
286  *      OTsideff        there are side effects to the operator (assign call
287  *                      post ?: && ||)
288  *      OTconv          type conversion operator that could appear on lhs of
289  *                      assignment operator
290  *      OTlogical       logical operator (result is 0 or 1)
291  *      OTwid           high order bits of operation are irrelevant
292  *      OTopeq          an op= operator
293  *      OTop            an operator that has a corresponding op=
294  *      OTcall          function call
295  *      OTrtol          operators that evaluate right subtree first then left
296  *      OTrel           == != < <= > >= operators
297  *      OTrel2          < <= > >= operators
298  *      OTdef           definition operator (assign call post asm)
299  *      OTae            potential common subexpression operator
300  *      OTboolnop       operation is a nop if boolean result is desired
301  */
302 
303 /* optab1[]     */      /* Use byte arrays to avoid index scaling       */
304 enum
305 {
306     _OTbinary       = 1,
307     _OTunary        = 2,
308     _OTcommut       = 4,
309     _OTassoc        = 8,
310     _OTsideff       = 0x10,
311     _OTeop0e        = 0x20,
312     _OTeop00        = 0x40,
313     _OTeop1e        = 0x80,
314 }
315 
316 /* optab2[]     */
317 enum
318 {
319     _OTlogical      = 1,
320     _OTwid          = 2,
321     _OTcall         = 4,
322     _OTrtol         = 8,
323     _OTassign       = 0x10,
324     _OTdef          = 0x20,
325     _OTae           = 0x40,
326 }
327 
328 // optab3[]
329 enum
330 {
331     _OTboolnop      = 1,
332 }
333 
334 ubyte OTbinary(OPER op)    { return optab1[op] & _OTbinary; }
335 ubyte OTunary(OPER op)     { return optab1[op] & _OTunary; }
336 bool  OTleaf(OPER op)      { return !(optab1[op] & (_OTunary|_OTbinary)); }
337 ubyte OTcommut(OPER op)    { return optab1[op] & _OTcommut; }
338 ubyte OTassoc(OPER op)     { return optab1[op] & _OTassoc; }
339 ubyte OTassign(OPER op)    { return optab2[op]&_OTassign; }
340 bool  OTpost(OPER op)      { return op == OPpostinc || op == OPpostdec; }
341 ubyte OTeop0e(OPER op)     { return optab1[op] & _OTeop0e; }
342 ubyte OTeop00(OPER op)     { return optab1[op] & _OTeop00; }
343 ubyte OTeop1e(OPER op)     { return optab1[op] & _OTeop1e; }
344 ubyte OTsideff(OPER op)    { return optab1[op] & _OTsideff; }
345 bool  OTconv(OPER op)      { return op >= CNVOPMIN && op <= CNVOPMAX; }
346 ubyte OTlogical(OPER op)   { return optab2[op] & _OTlogical; }
347 ubyte OTwid(OPER op)       { return optab2[op] & _OTwid; }
348 bool  OTopeq(OPER op)      { return op >= OPaddass && op <= OPashrass; }
349 bool  OTop(OPER op)        { return op >= OPadd && op <= OPor; }
350 ubyte OTcall(OPER op)      { return optab2[op] & _OTcall; }
351 ubyte OTrtol(OPER op)      { return optab2[op] & _OTrtol; }
352 bool  OTrel(OPER op)       { return op >= OPle && op <= OPnue; }
353 bool  OTrel2(OPER op)      { return op >= OPle && op <= OPge; }
354 ubyte OTdef(OPER op)       { return optab2[op] & _OTdef; }
355 ubyte OTae(OPER op)        { return optab2[op] & _OTae; }
356 ubyte OTboolnop(OPER op)   { return optab3[op] & _OTboolnop; }
357 bool  OTcalldef(OPER op)   { return OTcall(op) || op == OPstrcpy || op == OPstrcat || op == OPmemcpy; }
358 
359 /* Convert op= to op    */
360 OPER opeqtoop(OPER opx)   { return opx - OPaddass + OPadd; }
361 
362 /* Convert op to op=    */
363 OPER optoopeq(OPER opx)   { return opx - OPadd + OPaddass; }
364 
365 OPER swaprel(OPER);
366 
367 /***************************
368  * Determine properties of an elem.
369  * EBIN         binary node?
370  * EUNA         unary node?
371  * EOP          operator node (unary or binary)?
372  * ERTOL        right to left evaluation (left to right is default)
373  * Eunambig     unambiguous definition elem?
374  */
375 
376 //#define EBIN(e) (OTbinary((e)->Eoper))
377 //#define EUNA(e) (OTunary((e)->Eoper))
378 
379 /* ERTOL(e) is moved to el.c    */
380 
381 //#define Elvalue(e)      ((e)->E1)
382 //#define Eunambig(e)     (OTassign((e)->Eoper) && (e)->E1->Eoper == OPvar)
383 
384 //#define EOP(e)  (!OTleaf((e)->Eoper))
385 
386 extern (D):
387 
388 extern (C) immutable ubyte[OPMAX] optab1 =
389 () {
390     ubyte[OPMAX] tab;
391     foreach (i; Ebinary) { tab[i] |= _OTbinary; }
392     foreach (i; Eunary)  { tab[i] |= _OTunary;  }
393     foreach (i; Ecommut) { tab[i] |= _OTcommut; }
394     foreach (i; Eassoc)  { tab[i] |= _OTassoc;  }
395     foreach (i; Esideff) { tab[i] |= _OTsideff; }
396     foreach (i; Eeop0e)  { tab[i] |= _OTeop0e;  }
397     foreach (i; Eeop00)  { tab[i] |= _OTeop00;  }
398     foreach (i; Eeop1e)  { tab[i] |= _OTeop1e;  }
399     return tab;
400 } ();
401 
402 immutable ubyte[OPMAX] optab2 =
403 () {
404     ubyte[OPMAX] tab;
405     foreach (i; Elogical) { tab[i] |= _OTlogical; }
406     foreach (i; Ewid)     { tab[i] |= _OTwid;     }
407     foreach (i; Ecall)    { tab[i] |= _OTcall;    }
408     foreach (i; Ertol)    { tab[i] |= _OTrtol;    }
409     foreach (i; Eassign)  { tab[i] |= _OTassign;  }
410     foreach (i; Edef)     { tab[i] |= _OTdef;     }
411     foreach (i; Eae)      { tab[i] |= _OTae;      }
412     return tab;
413 } ();
414 
415 immutable ubyte[OPMAX] optab3 =
416 () {
417     ubyte[OPMAX] tab;
418     foreach (i; Eboolnop) { tab[i] |= _OTboolnop; }
419     return tab;
420 } ();
421 
422 private enum RELMAX = RELOPMAX - RELOPMIN + 1;
423 
424 immutable ubyte[RELMAX] _rel_exception =
425 () {
426     ubyte[RELMAX] tab;
427     foreach (i; Eexception) { tab[cast(int)i - RELOPMIN] = 1; }
428     return tab;
429 } ();
430 
431 immutable ubyte[RELMAX] _rel_unord =
432 () {
433     ubyte[RELMAX] tab;
434     foreach (i; Eunord) { tab[cast(int)i - RELOPMIN] = 1; }
435     return tab;
436 } ();
437 
438 /// Logical negation
439 immutable ubyte[RELMAX] _rel_not =
440 () {
441     ubyte[RELMAX] tab;
442     foreach (op; RELOPMIN .. RELOPMAX + 1)
443     {
444         OPER opnot;
445         switch (op)
446         {
447             case OPeqeq:  opnot = OPne;    break;
448             case OPne:    opnot = OPeqeq;  break;
449             case OPgt:    opnot = OPngt;   break;
450             case OPge:    opnot = OPnge;   break;
451             case OPlt:    opnot = OPnlt;   break;
452             case OPle:    opnot = OPnle;   break;
453 
454             case OPunord: opnot = OPord;   break;
455             case OPlg:    opnot = OPnlg;   break;
456             case OPleg:   opnot = OPnleg;  break;
457             case OPule:   opnot = OPnule;  break;
458             case OPul:    opnot = OPnul;   break;
459             case OPuge:   opnot = OPnuge;  break;
460             case OPug:    opnot = OPnug;   break;
461             case OPue:    opnot = OPnue;   break;
462 
463             case OPngt:   opnot = OPgt;    break;
464             case OPnge:   opnot = OPge;    break;
465             case OPnlt:   opnot = OPlt;    break;
466             case OPnle:   opnot = OPle;    break;
467             case OPord:   opnot = OPunord; break;
468             case OPnlg:   opnot = OPlg;    break;
469             case OPnleg:  opnot = OPleg;   break;
470             case OPnule:  opnot = OPule;   break;
471             case OPnul:   opnot = OPul;    break;
472             case OPnuge:  opnot = OPuge;   break;
473             case OPnug:   opnot = OPug;    break;
474             case OPnue:   opnot = OPue;    break;
475 
476             default:
477                 assert(0);
478         }
479         tab[cast(int)op - RELOPMIN] = cast(ubyte)opnot;
480     }
481 
482     foreach (op; RELOPMIN .. RELOPMAX + 1)
483     {
484         OPER opnot = tab[cast(int)op - RELOPMIN];
485         assert(op == tab[cast(int)opnot - RELOPMIN]);  // symmetry check
486     }
487     return tab;
488 } ();
489 
490 
491 /// Operand swap
492 immutable ubyte[RELMAX] _rel_swap =
493 () {
494     ubyte[RELMAX] tab;
495     foreach (op; RELOPMIN .. RELOPMAX + 1)
496     {
497         OPER opswap;
498         switch (op)
499         {
500             case OPeqeq:  opswap = op;      break;
501             case OPne:    opswap = op;      break;
502             case OPgt:    opswap = OPlt;    break;
503             case OPge:    opswap = OPle;    break;
504             case OPlt:    opswap = OPgt;    break;
505             case OPle:    opswap = OPge;    break;
506 
507             case OPunord: opswap = op;      break;
508             case OPlg:    opswap = op;      break;
509             case OPleg:   opswap = op;      break;
510             case OPule:   opswap = OPuge;   break;
511             case OPul:    opswap = OPug;    break;
512             case OPuge:   opswap = OPule;   break;
513             case OPug:    opswap = OPul;    break;
514             case OPue:    opswap = op;      break;
515 
516             case OPngt:   opswap = OPnlt;   break;
517             case OPnge:   opswap = OPnle;   break;
518             case OPnlt:   opswap = OPngt;   break;
519             case OPnle:   opswap = OPnge;   break;
520             case OPord:   opswap = op;      break;
521             case OPnlg:   opswap = op;      break;
522             case OPnleg:  opswap = op;      break;
523             case OPnule:  opswap = OPnuge;  break;
524             case OPnul:   opswap = OPnug;   break;
525             case OPnuge:  opswap = OPnule;  break;
526             case OPnug:   opswap = OPnul;   break;
527             case OPnue:   opswap = op;      break;
528 
529             default:
530                 assert(0);
531         }
532         tab[cast(int)op - RELOPMIN] = cast(ubyte)opswap;
533     }
534 
535     foreach (op; RELOPMIN .. RELOPMAX + 1)
536     {
537         OPER opswap = tab[cast(int)op - RELOPMIN];
538         assert(op == tab[cast(int)opswap - RELOPMIN]);  // symmetry check
539     }
540     return tab;
541 } ();
542 
543 /// If operands are integral types
544 immutable ubyte[RELMAX] _rel_integral =
545 () {
546     ubyte[RELMAX] tab;
547     foreach (op; RELOPMIN .. RELOPMAX + 1)
548     {
549         OPER opintegral;
550         switch (op)
551         {
552             case OPeqeq:  opintegral = op;          break;
553             case OPne:    opintegral = op;          break;
554             case OPgt:    opintegral = op;          break;
555             case OPge:    opintegral = op;          break;
556             case OPlt:    opintegral = op;          break;
557             case OPle:    opintegral = op;          break;
558 
559             case OPunord: opintegral = cast(OPER)0; break;
560             case OPlg:    opintegral = OPne;        break;
561             case OPleg:   opintegral = cast(OPER)1; break;
562             case OPule:   opintegral = OPle;        break;
563             case OPul:    opintegral = OPlt;        break;
564             case OPuge:   opintegral = OPge;        break;
565             case OPug:    opintegral = OPgt;        break;
566             case OPue:    opintegral = OPeqeq;      break;
567 
568             case OPngt:   opintegral = OPle;        break;
569             case OPnge:   opintegral = OPlt;        break;
570             case OPnlt:   opintegral = OPge;        break;
571             case OPnle:   opintegral = OPgt;        break;
572             case OPord:   opintegral = cast(OPER)1; break;
573             case OPnlg:   opintegral = OPeqeq;      break;
574             case OPnleg:  opintegral = cast(OPER)0; break;
575             case OPnule:  opintegral = OPgt;        break;
576             case OPnul:   opintegral = OPge;        break;
577             case OPnuge:  opintegral = OPlt;        break;
578             case OPnug:   opintegral = OPle;        break;
579             case OPnue:   opintegral = OPne;        break;
580 
581             default:
582                 assert(0);
583         }
584         tab[cast(int)op - RELOPMIN] = cast(ubyte)opintegral;
585     }
586     return tab;
587 } ();
588 
589 /*************************************
590  * Determine the cost of evaluating an operator.
591  *
592  * Used for reordering elem trees to minimize register usage.
593  */
594 
595 immutable ubyte[OPMAX] opcost =
596 () {
597     ubyte[OPMAX] tab;
598     foreach (op; 0 .. OPMAX)
599     {
600         ubyte c = 0;        // default cost
601         foreach (o; Eunary)
602         {
603             if (o == op)
604             {
605                 c += 2;
606                 break;
607             }
608         }
609 
610         foreach (o; Ebinary)
611         {
612             if (o == op)
613             {
614                 c += 7;
615                 break;
616             }
617         }
618 
619         foreach (o; Elogical)
620         {
621             if (o == op)
622             {
623                 c += 3;
624                 break;
625             }
626         }
627 
628         switch (op)
629         {
630             case OPvar: c += 1; break;
631             case OPmul: c += 3; break;
632             case OPdiv:
633             case OPmod: c += 4; break;
634             case OProl:
635             case OPror:
636             case OPshl:
637             case OPashr:
638             case OPshr: c += 2; break;
639             case OPcall:
640             case OPucall:
641             case OPcallns:
642             case OPucallns:
643                         c += 10; break; // very high cost for function calls
644             default:
645                 break;
646         }
647         tab[op] = c;
648     }
649     return tab;
650 } ();
651 
652 static immutable string[OPMAX] debtab =
653 [
654     OPunde:    "unde",
655     OPadd:     "+",
656     OPmul:     "*",
657     OPand:     "&",
658     OPmin:     "-",
659     OPnot:     "!",
660     OPcom:     "~",
661     OPcond:    "?",
662     OPcomma:   ",",
663     OPremquo:  "/%",
664     OPdiv:     "/",
665     OPmod:     "%",
666     OPxor:     "^",
667     OPstring:  "string",
668     OPrelconst: "relconst",
669     OPinp:     "inp",
670     OPoutp:    "outp",
671     OPasm:     "asm",
672     OPinfo:    "info",
673     OPdctor:   "dctor",
674     OPddtor:   "ddtor",
675     OPctor:    "ctor",
676     OPdtor:    "dtor",
677     OPmark:    "mark",
678     OPvoid:    "void",
679     OPhalt:    "halt",
680     OPnullptr: "nullptr",
681     OPpair:    "pair",
682     OPrpair:   "rpair",
683     OPtoprec:  "toprec",
684 
685     OPor:      "|",
686     OPoror:    "||",
687     OPandand:  "&&",
688     OProl:     "<<|",
689     OPror:     ">>|",
690     OPshl:     "<<",
691     OPshr:     ">>>",
692     OPashr:    ">>",
693     OPbit:     "bit",
694     OPind:     "*",
695     OPaddr:    "&",
696     OPneg:     "-",
697     OPuadd:    "+",
698     OPabs:     "abs",
699     OPsqrt:    "sqrt",
700     OPsin:     "sin",
701     OPcos:     "cos",
702     OPscale:   "scale",
703     OPyl2x:    "yl2x",
704     OPyl2xp1:  "yl2xp1",
705     OPcmpxchg:     "cas",
706     OPrint:    "rint",
707     OPrndtol:  "rndtol",
708     OPstrlen:  "strlen",
709     OPstrcpy:  "strcpy",
710     OPmemcpy:  "memcpy",
711     OPmemset:  "memset",
712     OPstrcat:  "strcat",
713     OPstrcmp:  "strcmp",
714     OPmemcmp:  "memcmp",
715     OPsetjmp:  "setjmp",
716     OPnegass:  "negass",
717     OPpreinc:  "U++",
718     OPpredec:  "U--",
719     OPstreq:   "streq",
720     OPpostinc: "++",
721     OPpostdec: "--",
722     OPeq:      "=",
723     OPaddass:  "+=",
724     OPminass:  "-=",
725     OPmulass:  "*=",
726     OPdivass:  "/=",
727     OPmodass:  "%=",
728     OPshrass:  ">>>=",
729     OPashrass: ">>=",
730     OPshlass:  "<<=",
731     OPandass:  "&=",
732     OPxorass:  "^=",
733     OPorass:   "|=",
734 
735     OPle:      "<=",
736     OPgt:      ">",
737     OPlt:      "<",
738     OPge:      ">=",
739     OPeqeq:    "==",
740     OPne:      "!=",
741 
742     OPunord:   "!<>=",
743     OPlg:      "<>",
744     OPleg:     "<>=",
745     OPule:     "!>",
746     OPul:      "!>=",
747     OPuge:     "!<",
748     OPug:      "!<=",
749     OPue:      "!<>",
750     OPngt:     "~>",
751     OPnge:     "~>=",
752     OPnlt:     "~<",
753     OPnle:     "~<=",
754     OPord:     "~!<>=",
755     OPnlg:     "~<>",
756     OPnleg:    "~<>=",
757     OPnule:    "~!>",
758     OPnul:     "~!>=",
759     OPnuge:    "~!<",
760     OPnug:     "~!<=",
761     OPnue:     "~!<>",
762 
763     OPvp_fp:   "vptrfptr",
764     OPcvp_fp:  "cvptrfptr",
765     OPoffset:  "offset",
766     OPnp_fp:   "ptrlptr",
767     OPnp_f16p: "tofar16",
768     OPf16p_np: "fromfar16",
769 
770     OPs16_32:  "s16_32",
771     OPu16_32:  "u16_32",
772     OPd_s32:   "d_s32",
773     OPb_8:     "b_8",
774     OPs32_d:   "s32_d",
775     OPd_s16:   "d_s16",
776     OPs16_d:   "s16_d",
777     OPd_u16:   "d_u16",
778     OPu16_d:   "u16_d",
779     OPd_u32:   "d_u32",
780     OPu32_d:   "u32_d",
781     OP32_16:   "32_16",
782     OPd_f:     "d_f",
783     OPf_d:     "f_d",
784     OPd_ld:    "d_ld",
785     OPld_d:    "ld_d",
786     OPc_r:     "c_r",
787     OPc_i:     "c_i",
788     OPu8_16:   "u8_16",
789     OPs8_16:   "s8_16",
790     OP16_8:    "16_8",
791     OPu32_64:  "u32_64",
792     OPs32_64:  "s32_64",
793     OP64_32:   "64_32",
794     OPu64_128: "u64_128",
795     OPs64_128: "s64_128",
796     OP128_64:  "128_64",
797     OPmsw:     "msw",
798 
799     OPd_s64:   "d_s64",
800     OPs64_d:   "s64_d",
801     OPd_u64:   "d_u64",
802     OPu64_d:   "u64_d",
803     OPld_u64:  "ld_u64",
804     OPparam:   "param",
805     OPsizeof:  "sizeof",
806     OParrow:   "->",
807     OParrowstar: "->*",
808     OPcolon:   "colon",
809     OPcolon2:  "colon2",
810     OPbool:    "bool",
811     OPcall:    "call",
812     OPucall:   "ucall",
813     OPcallns:  "callns",
814     OPucallns: "ucallns",
815     OPstrpar:  "strpar",
816     OPstrctor: "strctor",
817     OPstrthis: "strthis",
818     OPconst:   "const",
819     OPvar:     "var",
820     OPreg:     "reg",
821     OPnew:     "new",
822     OPanew:    "new[]",
823     OPdelete:  "delete",
824     OPadelete: "delete[]",
825     OPbrack:   "brack",
826     OPframeptr: "frameptr",
827     OPgot:     "got",
828 
829     OPbsf:     "bsf",
830     OPbsr:     "bsr",
831     OPbtst:    "btst",
832     OPbt:      "bt",
833     OPbtc:     "btc",
834     OPbtr:     "btr",
835     OPbts:     "bts",
836 
837     OPbswap:   "bswap",
838     OPpopcnt:  "popcnt",
839     OPvector:  "vector",
840     OPvecsto:  "vecsto",
841     OPvecfill: "vecfill",
842     OPva_start: "va_start",
843     OPprefetch: "prefetch",
844 ];
845 
846 private:
847 
848 /****
849  * Different categories of operators.
850  */
851 
852 static immutable Ebinary =
853     [
854         OPadd,OPmul,OPand,OPmin,OPcond,OPcomma,OPdiv,OPmod,OPxor,
855         OPor,OPoror,OPandand,OPshl,OPshr,OPashr,OPstreq,OPstrcpy,OPstrcat,OPstrcmp,
856         OPpostinc,OPpostdec,OPeq,OPaddass,OPminass,OPmulass,OPdivass,
857         OPmodass,OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,
858         OPle,OPgt,OPlt,OPge,OPeqeq,OPne,OPparam,OPcall,OPcallns,OPcolon,OPcolon2,
859         OPbit,OPbrack,OParrowstar,OPmemcpy,OPmemcmp,OPmemset,
860         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
861         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
862         OPinfo,OPpair,OPrpair,
863         OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,OPbtst,
864         OPremquo,OPcmpxchg,
865         OPoutp,OPscale,OPyl2x,OPyl2xp1,
866         OPvecsto,OPprefetch
867     ];
868 
869 static immutable Eunary =
870     [
871         OPnot,OPcom,OPind,OPaddr,OPneg,OPuadd,
872         OPabs,OPrndtol,OPrint,
873         OPpreinc,OPpredec,
874         OPbool,OPstrlen,
875         OPb_8,OPs16_32,OPu16_32,OPd_s32,OPd_u32,
876         OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16,
877         OPd_f,OPf_d,OPu8_16,OPs8_16,OP16_8,
878         OPd_ld, OPld_d,OPc_r,OPc_i,
879         OPu32_64,OPs32_64,OP64_32,OPmsw,
880         OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64,
881         OP128_64,OPs64_128,OPu64_128,
882         OPucall,OPucallns,OPstrpar,OPstrctor,OPu16_d,OPd_u16,
883         OParrow,OPnegass,OPtoprec,
884         OPctor,OPdtor,OPsetjmp,OPvoid,
885         OPbsf,OPbsr,OPbswap,OPpopcnt,
886         OPddtor,
887         OPvector,OPvecfill,
888         OPva_start,
889         OPsqrt,OPsin,OPcos,OPinp,
890         OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset,
891     ];
892 
893 static immutable Ecommut =
894     [
895         OPadd,OPand,OPor,OPxor,OPmul,OPeqeq,OPne,OPle,OPlt,OPge,OPgt,
896         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
897         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
898     ];
899 
900 static immutable Eassoc = [ OPadd,OPand,OPor,OPxor,OPmul ];
901 
902 static immutable Esideff =
903     [
904         OPasm,OPucall,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
905         OPcall,OPeq,OPstreq,OPpostinc,OPpostdec,
906         OPaddass,OPminass,OPmulass,OPdivass,OPmodass,OPandass,
907         OPorass,OPxorass,OPshlass,OPshrass,OPashrass,
908         OPnegass,OPctor,OPdtor,OPmark,OPvoid,
909         OPbtc,OPbtr,OPbts,
910         OPhalt,OPdctor,OPddtor,
911         OPcmpxchg,
912         OPva_start,
913         OPinp,OPoutp,OPvecsto,OPprefetch,
914     ];
915 
916 static immutable Eeop0e =
917     [
918         OPadd,OPmin,OPxor,OPor,OPshl,OPshr,OPashr,OPpostinc,OPpostdec,OPaddass,
919         OPminass,OPshrass,OPashrass,OPshlass,OPxorass,OPorass,
920         OPror,OProl,
921     ];
922 
923 static immutable Eeop00 = [ OPmul,OPand,OPmulass,OPandass ];
924 
925 static immutable Eeop1e = [ OPmul,OPdiv,OPmulass,OPdivass ];
926 
927 static immutable Elogical =
928     [
929         OPeqeq,OPne,OPle,OPlt,OPgt,OPge,OPandand,OPoror,OPnot,OPbool,
930         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
931         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
932         OPbt,OPbtst,
933     ];
934 
935 static immutable Ewid =
936     [
937         OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass,
938         OPminass,OPandass,OPorass,OPxorass,OPmulass,OPshlass,OPshl,OPshrass,
939         OPashrass,
940     ];
941 
942 static immutable Ecall = [ OPcall,OPucall,OPcallns,OPucallns ];
943 
944 static immutable Ertol =
945     [
946         OPeq,OPstreq,OPstrcpy,OPmemcpy,OPpostinc,OPpostdec,OPaddass,
947         OPminass,OPmulass,OPdivass,OPmodass,OPandass,
948         OPorass,OPxorass,OPshlass,OPshrass,OPashrass,
949         OPcall,OPcallns,OPinfo,OPmemset,
950         OPvecsto,OPcmpxchg,
951     ];
952 
953 static immutable Eassign =
954     [
955         OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
956         OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec,
957         OPnegass,OPvecsto,OPcmpxchg,
958     ];
959 
960 static immutable Edef =
961     [
962         OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
963         OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,
964         OPpostinc,OPpostdec,
965         OPcall,OPucall,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
966         OPnegass,
967         OPbtc,OPbtr,OPbts,
968         OPvecsto,OPcmpxchg,
969     ];
970 
971 static immutable Eae =
972     [
973         OPvar,OPconst,OPrelconst,OPneg,
974         OPabs,OPrndtol,OPrint,
975         OPstrlen,OPstrcmp,OPind,OPaddr,
976         OPnot,OPbool,OPcom,OPadd,OPmin,OPmul,OPand,OPor,OPmemcmp,
977         OPxor,OPdiv,OPmod,OPshl,OPshr,OPashr,OPeqeq,OPne,OPle,OPlt,OPge,OPgt,
978         OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge,
979         OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue,
980         OPs16_32,OPu16_32,OPd_s32,OPd_u32,OPu16_d,OPd_u16,
981         OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16,
982         OPd_f,OPf_d,OPu8_16,OPs8_16,OP16_8,
983         OPd_ld,OPld_d,OPc_r,OPc_i,
984         OPu32_64,OPs32_64,OP64_32,OPmsw,
985         OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64,
986         OP128_64,OPs64_128,OPu64_128,
987         OPsizeof,OPtoprec,
988         OPcallns,OPucallns,OPpair,OPrpair,
989         OPbsf,OPbsr,OPbt,OPbswap,OPb_8,OPbtst,OPpopcnt,
990         OPgot,OPremquo,
991         OPnullptr,
992         OProl,OPror,
993         OPsqrt,OPsin,OPcos,OPscale,
994         OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset,OPvecfill,
995     ];
996 
997 static immutable Eboolnop =
998     [
999         OPuadd,OPbool,OPs16_32,OPu16_32,
1000         OPs16_d,
1001         OPf_d,OPu8_16,OPs8_16,
1002         OPd_ld, OPld_d,
1003         OPu32_64,OPs32_64,/*OP64_32,OPmsw,*/
1004         OPs64_128,OPu64_128,
1005         OPu16_d,OPb_8,
1006         OPnullptr,
1007         OPnp_fp,OPvp_fp,OPcvp_fp,
1008         OPvecfill,
1009     ];
1010 
1011 /** if invalid exception can be generated by operator */
1012 static immutable Eexception =
1013     [
1014         OPgt,OPge,OPlt,OPle,
1015         OPlg,OPleg,
1016         OPngt,OPnge,OPnlt,OPnle,OPnlg,OPnleg,
1017     ];
1018 
1019 /** result of unordered operands */
1020 static immutable Eunord =
1021     [
1022         OPne,
1023         OPunord,OPule,OPul,OPuge,OPug,OPue,
1024         OPngt,OPnge,OPnlt,OPnle,OPnlg,OPnleg,
1025     ];