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