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