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 @nogc: 17 nothrow: 18 @safe: 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 public import dmd.backend.cgelem : swaprel; 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 immutable ubyte[OPMAX] opcost = () { 594 ubyte[OPMAX] tab = 0; 595 foreach (o; Eunary) 596 tab[o] += 2; 597 598 foreach (o; Ebinary) 599 tab[o] += 7; 600 601 foreach (o; Elogical) 602 tab[o] += 3; 603 604 tab[OPvar] += 1; 605 tab[OPmul] += 3; 606 tab[OPdiv] += 4; 607 tab[OPmod] += 4; 608 tab[OProl] += 2; 609 tab[OPror] += 2; 610 tab[OPshl] += 2; 611 tab[OPashr] += 2; 612 tab[OPshr] += 2; 613 tab[OPcall] += 10; // very high cost for function calls 614 tab[OPucall] += 10; 615 tab[OPcallns] += 10; 616 tab[OPucallns] += 10; 617 return tab; 618 } (); 619 620 static immutable string[OPMAX] debtab = 621 [ 622 OPunde: "unde", 623 OPadd: "+", 624 OPmul: "*", 625 OPand: "&", 626 OPmin: "-", 627 OPnot: "!", 628 OPcom: "~", 629 OPcond: "?", 630 OPcomma: ",", 631 OPremquo: "/%", 632 OPdiv: "/", 633 OPmod: "%", 634 OPxor: "^", 635 OPstring: "string", 636 OPrelconst: "relconst", 637 OPinp: "inp", 638 OPoutp: "outp", 639 OPasm: "asm", 640 OPinfo: "info", 641 OPdctor: "dctor", 642 OPddtor: "ddtor", 643 OPctor: "ctor", 644 OPdtor: "dtor", 645 OPmark: "mark", 646 OPvoid: "void", 647 OPhalt: "halt", 648 OPnullptr: "nullptr", 649 OPpair: "pair", 650 OPrpair: "rpair", 651 OPtoprec: "toprec", 652 653 OPor: "|", 654 OPoror: "||", 655 OPandand: "&&", 656 OProl: "<<|", 657 OPror: ">>|", 658 OPshl: "<<", 659 OPshr: ">>>", 660 OPashr: ">>", 661 OPbit: "bit", 662 OPind: "*", 663 OPaddr: "&", 664 OPneg: "-", 665 OPuadd: "+", 666 OPabs: "abs", 667 OPsqrt: "sqrt", 668 OPsin: "sin", 669 OPcos: "cos", 670 OPscale: "scale", 671 OPyl2x: "yl2x", 672 OPyl2xp1: "yl2xp1", 673 OPcmpxchg: "cas", 674 OPrint: "rint", 675 OPrndtol: "rndtol", 676 OPstrlen: "strlen", 677 OPstrcpy: "strcpy", 678 OPmemcpy: "memcpy", 679 OPmemset: "memset", 680 OPstrcat: "strcat", 681 OPstrcmp: "strcmp", 682 OPmemcmp: "memcmp", 683 OPsetjmp: "setjmp", 684 OPnegass: "negass", 685 OPpreinc: "U++", 686 OPpredec: "U--", 687 OPstreq: "streq", 688 OPpostinc: "++", 689 OPpostdec: "--", 690 OPeq: "=", 691 OPaddass: "+=", 692 OPminass: "-=", 693 OPmulass: "*=", 694 OPdivass: "/=", 695 OPmodass: "%=", 696 OPshrass: ">>>=", 697 OPashrass: ">>=", 698 OPshlass: "<<=", 699 OPandass: "&=", 700 OPxorass: "^=", 701 OPorass: "|=", 702 703 OPle: "<=", 704 OPgt: ">", 705 OPlt: "<", 706 OPge: ">=", 707 OPeqeq: "==", 708 OPne: "!=", 709 710 OPunord: "!<>=", 711 OPlg: "<>", 712 OPleg: "<>=", 713 OPule: "!>", 714 OPul: "!>=", 715 OPuge: "!<", 716 OPug: "!<=", 717 OPue: "!<>", 718 OPngt: "~>", 719 OPnge: "~>=", 720 OPnlt: "~<", 721 OPnle: "~<=", 722 OPord: "~!<>=", 723 OPnlg: "~<>", 724 OPnleg: "~<>=", 725 OPnule: "~!>", 726 OPnul: "~!>=", 727 OPnuge: "~!<", 728 OPnug: "~!<=", 729 OPnue: "~!<>", 730 731 OPvp_fp: "vptrfptr", 732 OPcvp_fp: "cvptrfptr", 733 OPoffset: "offset", 734 OPnp_fp: "ptrlptr", 735 OPnp_f16p: "tofar16", 736 OPf16p_np: "fromfar16", 737 738 OPs16_32: "s16_32", 739 OPu16_32: "u16_32", 740 OPd_s32: "d_s32", 741 OPb_8: "b_8", 742 OPs32_d: "s32_d", 743 OPd_s16: "d_s16", 744 OPs16_d: "s16_d", 745 OPd_u16: "d_u16", 746 OPu16_d: "u16_d", 747 OPd_u32: "d_u32", 748 OPu32_d: "u32_d", 749 OP32_16: "32_16", 750 OPd_f: "d_f", 751 OPf_d: "f_d", 752 OPd_ld: "d_ld", 753 OPld_d: "ld_d", 754 OPc_r: "c_r", 755 OPc_i: "c_i", 756 OPu8_16: "u8_16", 757 OPs8_16: "s8_16", 758 OP16_8: "16_8", 759 OPu32_64: "u32_64", 760 OPs32_64: "s32_64", 761 OP64_32: "64_32", 762 OPu64_128: "u64_128", 763 OPs64_128: "s64_128", 764 OP128_64: "128_64", 765 OPmsw: "msw", 766 767 OPd_s64: "d_s64", 768 OPs64_d: "s64_d", 769 OPd_u64: "d_u64", 770 OPu64_d: "u64_d", 771 OPld_u64: "ld_u64", 772 OPparam: "param", 773 OPsizeof: "sizeof", 774 OParrow: "->", 775 OParrowstar: "->*", 776 OPcolon: "colon", 777 OPcolon2: "colon2", 778 OPbool: "bool", 779 OPcall: "call", 780 OPucall: "ucall", 781 OPcallns: "callns", 782 OPucallns: "ucallns", 783 OPstrpar: "strpar", 784 OPstrctor: "strctor", 785 OPstrthis: "strthis", 786 OPconst: "const", 787 OPvar: "var", 788 OPreg: "reg", 789 OPnew: "new", 790 OPanew: "new[]", 791 OPdelete: "delete", 792 OPadelete: "delete[]", 793 OPbrack: "brack", 794 OPframeptr: "frameptr", 795 OPgot: "got", 796 797 OPbsf: "bsf", 798 OPbsr: "bsr", 799 OPbtst: "btst", 800 OPbt: "bt", 801 OPbtc: "btc", 802 OPbtr: "btr", 803 OPbts: "bts", 804 805 OPbswap: "bswap", 806 OPpopcnt: "popcnt", 807 OPvector: "vector", 808 OPvecsto: "vecsto", 809 OPvecfill: "vecfill", 810 OPva_start: "va_start", 811 OPprefetch: "prefetch", 812 ]; 813 814 private: 815 816 /**** 817 * Different categories of operators. 818 */ 819 820 static immutable Ebinary = 821 [ 822 OPadd,OPmul,OPand,OPmin,OPcond,OPcomma,OPdiv,OPmod,OPxor, 823 OPor,OPoror,OPandand,OPshl,OPshr,OPashr,OPstreq,OPstrcpy,OPstrcat,OPstrcmp, 824 OPpostinc,OPpostdec,OPeq,OPaddass,OPminass,OPmulass,OPdivass, 825 OPmodass,OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass, 826 OPle,OPgt,OPlt,OPge,OPeqeq,OPne,OPparam,OPcall,OPcallns,OPcolon,OPcolon2, 827 OPbit,OPbrack,OParrowstar,OPmemcpy,OPmemcmp,OPmemset, 828 OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge, 829 OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue, 830 OPinfo,OPpair,OPrpair, 831 OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,OPbtst, 832 OPremquo,OPcmpxchg, 833 OPoutp,OPscale,OPyl2x,OPyl2xp1, 834 OPva_start, 835 OPvecsto,OPprefetch 836 ]; 837 838 static immutable Eunary = 839 [ 840 OPnot,OPcom,OPind,OPaddr,OPneg,OPuadd, 841 OPabs,OPrndtol,OPrint, 842 OPpreinc,OPpredec, 843 OPbool,OPstrlen, 844 OPb_8,OPs16_32,OPu16_32,OPd_s32,OPd_u32, 845 OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16, 846 OPd_f,OPf_d,OPu8_16,OPs8_16,OP16_8, 847 OPd_ld, OPld_d,OPc_r,OPc_i, 848 OPu32_64,OPs32_64,OP64_32,OPmsw, 849 OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64, 850 OP128_64,OPs64_128,OPu64_128, 851 OPucall,OPucallns,OPstrpar,OPstrctor,OPu16_d,OPd_u16, 852 OParrow,OPnegass,OPtoprec, 853 OPctor,OPdtor,OPsetjmp,OPvoid, 854 OPbsf,OPbsr,OPbswap,OPpopcnt, 855 OPddtor, 856 OPvector,OPvecfill, 857 OPsqrt,OPsin,OPcos,OPinp, 858 OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset, 859 ]; 860 861 static immutable Ecommut = 862 [ 863 OPadd,OPand,OPor,OPxor,OPmul,OPeqeq,OPne,OPle,OPlt,OPge,OPgt, 864 OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge, 865 OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue, 866 ]; 867 868 static immutable Eassoc = [ OPadd,OPand,OPor,OPxor,OPmul ]; 869 870 static immutable Esideff = 871 [ 872 OPasm,OPucall,OPstrcpy,OPmemcpy,OPmemset,OPstrcat, 873 OPcall,OPeq,OPstreq,OPpostinc,OPpostdec, 874 OPaddass,OPminass,OPmulass,OPdivass,OPmodass,OPandass, 875 OPorass,OPxorass,OPshlass,OPshrass,OPashrass, 876 OPnegass,OPctor,OPdtor,OPmark,OPvoid, 877 OPbtc,OPbtr,OPbts, 878 OPhalt,OPdctor,OPddtor, 879 OPcmpxchg, 880 OPva_start, 881 OPinp,OPoutp,OPvecsto,OPprefetch, 882 ]; 883 884 static immutable Eeop0e = 885 [ 886 OPadd,OPmin,OPxor,OPor,OPshl,OPshr,OPashr,OPpostinc,OPpostdec,OPaddass, 887 OPminass,OPshrass,OPashrass,OPshlass,OPxorass,OPorass, 888 OPror,OProl, 889 ]; 890 891 static immutable Eeop00 = [ OPmul,OPand,OPmulass,OPandass ]; 892 893 static immutable Eeop1e = [ OPmul,OPdiv,OPmulass,OPdivass ]; 894 895 static immutable Elogical = 896 [ 897 OPeqeq,OPne,OPle,OPlt,OPgt,OPge,OPandand,OPoror,OPnot,OPbool, 898 OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge, 899 OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue, 900 OPbt,OPbtst, 901 ]; 902 903 static immutable Ewid = 904 [ 905 OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass, 906 OPminass,OPandass,OPorass,OPxorass,OPmulass,OPshlass,OPshl,OPshrass, 907 OPashrass, 908 ]; 909 910 static immutable Ecall = [ OPcall,OPucall,OPcallns,OPucallns ]; 911 912 static immutable Ertol = 913 [ 914 OPeq,OPstreq,OPstrcpy,OPmemcpy,OPpostinc,OPpostdec,OPaddass, 915 OPminass,OPmulass,OPdivass,OPmodass,OPandass, 916 OPorass,OPxorass,OPshlass,OPshrass,OPashrass, 917 OPcall,OPcallns,OPinfo,OPmemset, 918 OPvecsto,OPcmpxchg, 919 ]; 920 921 static immutable Eassign = 922 [ 923 OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass, 924 OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec, 925 OPnegass,OPvecsto,OPcmpxchg, 926 ]; 927 928 static immutable Edef = 929 [ 930 OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass, 931 OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass, 932 OPpostinc,OPpostdec, 933 OPcall,OPucall,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat, 934 OPnegass, 935 OPbtc,OPbtr,OPbts, 936 OPvecsto,OPcmpxchg, 937 ]; 938 939 static immutable Eae = 940 [ 941 OPvar,OPconst,OPrelconst,OPneg, 942 OPabs,OPrndtol,OPrint, 943 OPstrlen,OPstrcmp,OPind,OPaddr, 944 OPnot,OPbool,OPcom,OPadd,OPmin,OPmul,OPand,OPor,OPmemcmp, 945 OPxor,OPdiv,OPmod,OPshl,OPshr,OPashr,OPeqeq,OPne,OPle,OPlt,OPge,OPgt, 946 OPunord,OPlg,OPleg,OPule,OPul,OPuge,OPug,OPue,OPngt,OPnge, 947 OPnlt,OPnle,OPord,OPnlg,OPnleg,OPnule,OPnul,OPnuge,OPnug,OPnue, 948 OPs16_32,OPu16_32,OPd_s32,OPd_u32,OPu16_d,OPd_u16, 949 OPs32_d,OPu32_d,OPd_s16,OPs16_d,OP32_16, 950 OPd_f,OPf_d,OPu8_16,OPs8_16,OP16_8, 951 OPd_ld,OPld_d,OPc_r,OPc_i, 952 OPu32_64,OPs32_64,OP64_32,OPmsw, 953 OPd_s64,OPs64_d,OPd_u64,OPu64_d,OPld_u64, 954 OP128_64,OPs64_128,OPu64_128, 955 OPsizeof,OPtoprec, 956 OPcallns,OPucallns,OPpair,OPrpair, 957 OPbsf,OPbsr,OPbt,OPbswap,OPb_8,OPbtst,OPpopcnt, 958 OPgot,OPremquo, 959 OPnullptr, 960 OProl,OPror, 961 OPsqrt,OPsin,OPcos,OPscale, 962 OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset,OPvecfill, 963 ]; 964 965 static immutable Eboolnop = 966 [ 967 OPuadd,OPbool,OPs16_32,OPu16_32, 968 OPs16_d, 969 OPf_d,OPu8_16,OPs8_16, 970 OPd_ld, OPld_d, 971 OPu32_64,OPs32_64,/*OP64_32,OPmsw,*/ 972 OPs64_128,OPu64_128, 973 OPu16_d,OPb_8, 974 OPnullptr, 975 OPnp_fp,OPvp_fp,OPcvp_fp, 976 OPvecfill, 977 ]; 978 979 /** if invalid exception can be generated by operator */ 980 static immutable Eexception = 981 [ 982 OPgt,OPge,OPlt,OPle, 983 OPlg,OPleg, 984 OPngt,OPnge,OPnlt,OPnle,OPnlg,OPnleg, 985 ]; 986 987 /** result of unordered operands */ 988 static immutable Eunord = 989 [ 990 OPne, 991 OPunord,OPule,OPul,OPuge,OPug,OPue, 992 OPngt,OPnge,OPnlt,OPnle,OPnlg,OPnleg, 993 ];