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