github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/cc/scon.c (about) 1 // Inferno utils/cc/scon.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include <u.h> 32 #include "cc.h" 33 34 static Node* 35 acast(Type *t, Node *n) 36 { 37 if(n->type->etype != t->etype || n->op == OBIT) { 38 n = new1(OCAST, n, Z); 39 if(nocast(n->left->type, t)) 40 *n = *n->left; 41 n->type = t; 42 } 43 return n; 44 } 45 46 47 void 48 evconst(Node *n) 49 { 50 Node *l, *r; 51 int et, isf; 52 vlong v; 53 double d; 54 55 if(n == Z || n->type == T) 56 return; 57 58 et = n->type->etype; 59 isf = typefd[et]; 60 61 l = n->left; 62 r = n->right; 63 64 d = 0; 65 v = 0; 66 67 switch(n->op) { 68 default: 69 return; 70 71 case ONEG: 72 if(isf) 73 d = -l->fconst; 74 else 75 v = -l->vconst; 76 break; 77 78 case OCOM: 79 v = ~l->vconst; 80 break; 81 82 case OCAST: 83 if(et == TVOID) 84 return; 85 et = l->type->etype; 86 if(isf) { 87 if(typefd[et]) 88 d = l->fconst; 89 else 90 d = l->vconst; 91 } else { 92 if(typefd[et]) 93 v = l->fconst; 94 else 95 v = convvtox(l->vconst, n->type->etype); 96 } 97 break; 98 99 case OCONST: 100 break; 101 102 case OADD: 103 if(isf) 104 d = l->fconst + r->fconst; 105 else { 106 v = l->vconst + r->vconst; 107 } 108 break; 109 110 case OSUB: 111 if(isf) 112 d = l->fconst - r->fconst; 113 else 114 v = l->vconst - r->vconst; 115 break; 116 117 case OMUL: 118 if(isf) 119 d = l->fconst * r->fconst; 120 else { 121 v = l->vconst * r->vconst; 122 } 123 break; 124 125 case OLMUL: 126 v = (uvlong)l->vconst * (uvlong)r->vconst; 127 break; 128 129 130 case ODIV: 131 if(vconst(r) == 0) { 132 warn(n, "divide by zero"); 133 return; 134 } 135 if(isf) 136 d = l->fconst / r->fconst; 137 else 138 v = l->vconst / r->vconst; 139 break; 140 141 case OLDIV: 142 if(vconst(r) == 0) { 143 warn(n, "divide by zero"); 144 return; 145 } 146 v = (uvlong)l->vconst / (uvlong)r->vconst; 147 break; 148 149 case OMOD: 150 if(vconst(r) == 0) { 151 warn(n, "modulo by zero"); 152 return; 153 } 154 v = l->vconst % r->vconst; 155 break; 156 157 case OLMOD: 158 if(vconst(r) == 0) { 159 warn(n, "modulo by zero"); 160 return; 161 } 162 v = (uvlong)l->vconst % (uvlong)r->vconst; 163 break; 164 165 case OAND: 166 v = l->vconst & r->vconst; 167 break; 168 169 case OOR: 170 v = l->vconst | r->vconst; 171 break; 172 173 case OXOR: 174 v = l->vconst ^ r->vconst; 175 break; 176 177 case OLSHR: 178 if(l->type->width != sizeof(uvlong)) 179 v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst; 180 else 181 v = (uvlong)l->vconst >> r->vconst; 182 break; 183 184 case OASHR: 185 v = l->vconst >> r->vconst; 186 break; 187 188 case OASHL: 189 v = l->vconst << r->vconst; 190 break; 191 192 case OLO: 193 v = (uvlong)l->vconst < (uvlong)r->vconst; 194 break; 195 196 case OLT: 197 if(typefd[l->type->etype]) 198 v = l->fconst < r->fconst; 199 else 200 v = l->vconst < r->vconst; 201 break; 202 203 case OHI: 204 v = (uvlong)l->vconst > (uvlong)r->vconst; 205 break; 206 207 case OGT: 208 if(typefd[l->type->etype]) 209 v = l->fconst > r->fconst; 210 else 211 v = l->vconst > r->vconst; 212 break; 213 214 case OLS: 215 v = (uvlong)l->vconst <= (uvlong)r->vconst; 216 break; 217 218 case OLE: 219 if(typefd[l->type->etype]) 220 v = l->fconst <= r->fconst; 221 else 222 v = l->vconst <= r->vconst; 223 break; 224 225 case OHS: 226 v = (uvlong)l->vconst >= (uvlong)r->vconst; 227 break; 228 229 case OGE: 230 if(typefd[l->type->etype]) 231 v = l->fconst >= r->fconst; 232 else 233 v = l->vconst >= r->vconst; 234 break; 235 236 case OEQ: 237 if(typefd[l->type->etype]) 238 v = l->fconst == r->fconst; 239 else 240 v = l->vconst == r->vconst; 241 break; 242 243 case ONE: 244 if(typefd[l->type->etype]) 245 v = l->fconst != r->fconst; 246 else 247 v = l->vconst != r->vconst; 248 break; 249 250 case ONOT: 251 if(typefd[l->type->etype]) 252 v = !l->fconst; 253 else 254 v = !l->vconst; 255 break; 256 257 case OANDAND: 258 if(typefd[l->type->etype]) 259 v = l->fconst && r->fconst; 260 else 261 v = l->vconst && r->vconst; 262 break; 263 264 case OOROR: 265 if(typefd[l->type->etype]) 266 v = l->fconst || r->fconst; 267 else 268 v = l->vconst || r->vconst; 269 break; 270 } 271 if(isf) { 272 n->fconst = d; 273 } else { 274 n->vconst = convvtox(v, n->type->etype); 275 } 276 n->oldop = n->op; 277 n->op = OCONST; 278 } 279 280 void 281 acom(Node *n) 282 { 283 Type *t; 284 Node *l, *r; 285 int i; 286 287 switch(n->op) 288 { 289 290 case ONAME: 291 case OCONST: 292 case OSTRING: 293 case OINDREG: 294 case OREGISTER: 295 return; 296 297 case ONEG: 298 l = n->left; 299 if(addo(n) && addo(l)) 300 break; 301 acom(l); 302 return; 303 304 case OADD: 305 case OSUB: 306 case OMUL: 307 l = n->left; 308 r = n->right; 309 if(addo(n)) { 310 if(addo(r)) 311 break; 312 if(addo(l)) 313 break; 314 } 315 acom(l); 316 acom(r); 317 return; 318 319 default: 320 l = n->left; 321 r = n->right; 322 if(l != Z) 323 acom(l); 324 if(r != Z) 325 acom(r); 326 return; 327 } 328 329 /* bust terms out */ 330 t = n->type; 331 term[0].mult = 0; 332 term[0].node = Z; 333 nterm = 1; 334 acom1(1, n); 335 if(debug['m']) 336 for(i=0; i<nterm; i++) { 337 print("%d %3lld ", i, term[i].mult); 338 prtree1(term[i].node, 1, 0); 339 } 340 if(nterm < NTERM) 341 acom2(n, t); 342 n->type = t; 343 } 344 345 int 346 acomcmp1(const void *a1, const void *a2) 347 { 348 vlong c1, c2; 349 Term *t1, *t2; 350 351 t1 = (Term*)a1; 352 t2 = (Term*)a2; 353 c1 = t1->mult; 354 if(c1 < 0) 355 c1 = -c1; 356 c2 = t2->mult; 357 if(c2 < 0) 358 c2 = -c2; 359 if(c1 > c2) 360 return 1; 361 if(c1 < c2) 362 return -1; 363 c1 = 1; 364 if(t1->mult < 0) 365 c1 = 0; 366 c2 = 1; 367 if(t2->mult < 0) 368 c2 = 0; 369 if(c2 -= c1) 370 return c2; 371 if(t2 > t1) 372 return 1; 373 return -1; 374 } 375 376 int 377 acomcmp2(const void *a1, const void *a2) 378 { 379 vlong c1, c2; 380 Term *t1, *t2; 381 382 t1 = (Term*)a1; 383 t2 = (Term*)a2; 384 c1 = t1->mult; 385 c2 = t2->mult; 386 if(c1 > c2) 387 return 1; 388 if(c1 < c2) 389 return -1; 390 if(t2 > t1) 391 return 1; 392 return -1; 393 } 394 395 void 396 acom2(Node *n, Type *t) 397 { 398 Node *l, *r; 399 Term trm[NTERM]; 400 int et, nt, i, j; 401 vlong c1, c2; 402 403 /* 404 * copy into automatic 405 */ 406 c2 = 0; 407 nt = nterm; 408 for(i=0; i<nt; i++) 409 trm[i] = term[i]; 410 /* 411 * recur on subtrees 412 */ 413 j = 0; 414 for(i=1; i<nt; i++) { 415 c1 = trm[i].mult; 416 if(c1 == 0) 417 continue; 418 l = trm[i].node; 419 if(l != Z) { 420 j = 1; 421 acom(l); 422 } 423 } 424 c1 = trm[0].mult; 425 if(j == 0) { 426 n->oldop = n->op; 427 n->op = OCONST; 428 n->vconst = c1; 429 return; 430 } 431 et = t->etype; 432 433 /* 434 * prepare constant term, 435 * combine it with an addressing term 436 */ 437 if(c1 != 0) { 438 l = new1(OCONST, Z, Z); 439 l->type = t; 440 l->vconst = c1; 441 trm[0].mult = 1; 442 for(i=1; i<nt; i++) { 443 if(trm[i].mult != 1) 444 continue; 445 r = trm[i].node; 446 if(r->op != OADDR) 447 continue; 448 r->type = t; 449 l = new1(OADD, r, l); 450 l->type = t; 451 trm[i].mult = 0; 452 break; 453 } 454 trm[0].node = l; 455 } 456 /* 457 * look for factorable terms 458 * c1*i + c1*c2*j -> c1*(i + c2*j) 459 */ 460 qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1); 461 for(i=nt-1; i>=0; i--) { 462 c1 = trm[i].mult; 463 if(c1 < 0) 464 c1 = -c1; 465 if(c1 <= 1) 466 continue; 467 for(j=i+1; j<nt; j++) { 468 c2 = trm[j].mult; 469 if(c2 < 0) 470 c2 = -c2; 471 if(c2 <= 1) 472 continue; 473 if(c2 % c1) 474 continue; 475 r = trm[j].node; 476 if(r->type->etype != et) 477 r = acast(t, r); 478 c2 = trm[j].mult/trm[i].mult; 479 if(c2 != 1 && c2 != -1) { 480 r = new1(OMUL, r, new(OCONST, Z, Z)); 481 r->type = t; 482 r->right->type = t; 483 r->right->vconst = c2; 484 } 485 l = trm[i].node; 486 if(l->type->etype != et) 487 l = acast(t, l); 488 r = new1(OADD, l, r); 489 r->type = t; 490 if(c2 == -1) 491 r->op = OSUB; 492 trm[i].node = r; 493 trm[j].mult = 0; 494 } 495 } 496 if(debug['m']) { 497 print("\n"); 498 for(i=0; i<nt; i++) { 499 print("%d %3lld ", i, trm[i].mult); 500 prtree1(trm[i].node, 1, 0); 501 } 502 } 503 504 /* 505 * put it all back together 506 */ 507 qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2); 508 l = Z; 509 for(i=nt-1; i>=0; i--) { 510 c1 = trm[i].mult; 511 if(c1 == 0) 512 continue; 513 r = trm[i].node; 514 if(r->type->etype != et || r->op == OBIT) 515 r = acast(t, r); 516 if(c1 != 1 && c1 != -1) { 517 r = new1(OMUL, r, new(OCONST, Z, Z)); 518 r->type = t; 519 r->right->type = t; 520 if(c1 < 0) { 521 r->right->vconst = -c1; 522 c1 = -1; 523 } else { 524 r->right->vconst = c1; 525 c1 = 1; 526 } 527 } 528 if(l == Z) { 529 l = r; 530 c2 = c1; 531 continue; 532 } 533 if(c1 < 0) 534 if(c2 < 0) 535 l = new1(OADD, l, r); 536 else 537 l = new1(OSUB, l, r); 538 else 539 if(c2 < 0) { 540 l = new1(OSUB, r, l); 541 c2 = 1; 542 } else 543 l = new1(OADD, l, r); 544 l->type = t; 545 } 546 if(c2 < 0) { 547 r = new1(OCONST, 0, 0); 548 r->vconst = 0; 549 r->type = t; 550 l = new1(OSUB, r, l); 551 l->type = t; 552 } 553 *n = *l; 554 } 555 556 void 557 acom1(vlong v, Node *n) 558 { 559 Node *l, *r; 560 561 if(v == 0 || nterm >= NTERM) 562 return; 563 if(!addo(n)) { 564 if(n->op == OCONST) 565 if(!typefd[n->type->etype]) { 566 term[0].mult += v*n->vconst; 567 return; 568 } 569 term[nterm].mult = v; 570 term[nterm].node = n; 571 nterm++; 572 return; 573 } 574 switch(n->op) { 575 576 case OCAST: 577 acom1(v, n->left); 578 break; 579 580 case ONEG: 581 acom1(-v, n->left); 582 break; 583 584 case OADD: 585 acom1(v, n->left); 586 acom1(v, n->right); 587 break; 588 589 case OSUB: 590 acom1(v, n->left); 591 acom1(-v, n->right); 592 break; 593 594 case OMUL: 595 l = n->left; 596 r = n->right; 597 if(l->op == OCONST) 598 if(!typefd[n->type->etype]) { 599 acom1(v*l->vconst, r); 600 break; 601 } 602 if(r->op == OCONST) 603 if(!typefd[n->type->etype]) { 604 acom1(v*r->vconst, l); 605 break; 606 } 607 break; 608 609 default: 610 diag(n, "not addo"); 611 } 612 } 613 614 int 615 addo(Node *n) 616 { 617 618 if(n != Z) 619 if(!typefd[n->type->etype]) 620 if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND]) 621 switch(n->op) { 622 623 case OCAST: 624 if(nilcast(n->left->type, n->type)) 625 return 1; 626 break; 627 628 case ONEG: 629 case OADD: 630 case OSUB: 631 return 1; 632 633 case OMUL: 634 if(n->left->op == OCONST) 635 return 1; 636 if(n->right->op == OCONST) 637 return 1; 638 } 639 return 0; 640 }