github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8c/sgen.c (about) 1 // Inferno utils/8c/sgen.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.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 "gc.h" 32 33 Prog* 34 gtext(Sym *s, int32 stkoff) 35 { 36 int32 a; 37 38 a = 0; 39 if(!(textflag & NOSPLIT)) 40 a = argsize(); 41 else if(stkoff >= 128) 42 yyerror("stack frame too large for NOSPLIT function"); 43 44 gpseudo(ATEXT, s, nodconst(stkoff)); 45 p->to.type = D_CONST2; 46 p->to.offset2 = a; 47 return p; 48 } 49 50 void 51 noretval(int n) 52 { 53 54 if(n & 1) { 55 gins(ANOP, Z, Z); 56 p->to.type = REGRET; 57 } 58 if(n & 2) { 59 gins(ANOP, Z, Z); 60 p->to.type = FREGRET; 61 } 62 } 63 64 /* welcome to commute */ 65 static void 66 commute(Node *n) 67 { 68 Node *l, *r; 69 70 l = n->left; 71 r = n->right; 72 if(r->complex > l->complex) { 73 n->left = r; 74 n->right = l; 75 } 76 } 77 78 void 79 indexshift(Node *n) 80 { 81 int g; 82 83 if(!typechlp[n->type->etype]) 84 return; 85 simplifyshift(n); 86 if(n->op == OASHL && n->right->op == OCONST){ 87 g = vconst(n->right); 88 if(g >= 0 && g < 4) 89 n->addable = 7; 90 } 91 } 92 93 /* 94 * calculate addressability as follows 95 * NAME ==> 10/11 name+value(SB/SP) 96 * REGISTER ==> 12 register 97 * CONST ==> 20 $value 98 * *(20) ==> 21 value 99 * &(10) ==> 13 $name+value(SB) 100 * &(11) ==> 1 $name+value(SP) 101 * (13) + (20) ==> 13 fold constants 102 * (1) + (20) ==> 1 fold constants 103 * *(13) ==> 10 back to name 104 * *(1) ==> 11 back to name 105 * 106 * (20) * (X) ==> 7 multiplier in indexing 107 * (X,7) + (13,1) ==> 8 adder in indexing (addresses) 108 * (8) ==> &9(OINDEX) index, almost addressable 109 * 100 extern register 110 * 111 * calculate complexity (number of registers) 112 */ 113 void 114 xcom(Node *n) 115 { 116 Node *l, *r; 117 int g; 118 119 if(n == Z) 120 return; 121 l = n->left; 122 r = n->right; 123 n->complex = 0; 124 n->addable = 0; 125 switch(n->op) { 126 case OCONST: 127 n->addable = 20; 128 break; 129 130 case ONAME: 131 n->addable = 10; 132 if(n->class == CPARAM || n->class == CAUTO) 133 n->addable = 11; 134 break; 135 136 case OEXREG: 137 n->addable = 0; 138 break; 139 140 case OREGISTER: 141 n->addable = 12; 142 break; 143 144 case OINDREG: 145 n->addable = 12; 146 break; 147 148 case OADDR: 149 xcom(l); 150 if(l->addable == 10) 151 n->addable = 13; 152 else 153 if(l->addable == 11) 154 n->addable = 1; 155 break; 156 157 case OADD: 158 xcom(l); 159 xcom(r); 160 if(n->type->etype != TIND) 161 break; 162 163 switch(r->addable) { 164 case 20: 165 switch(l->addable) { 166 case 1: 167 case 13: 168 commadd: 169 l->type = n->type; 170 *n = *l; 171 l = new(0, Z, Z); 172 *l = *(n->left); 173 l->xoffset += r->vconst; 174 n->left = l; 175 r = n->right; 176 goto brk; 177 } 178 break; 179 180 case 1: 181 case 13: 182 case 10: 183 case 11: 184 /* l is the base, r is the index */ 185 if(l->addable != 20) 186 n->addable = 8; 187 break; 188 } 189 switch(l->addable) { 190 case 20: 191 switch(r->addable) { 192 case 13: 193 case 1: 194 r = n->left; 195 l = n->right; 196 n->left = l; 197 n->right = r; 198 goto commadd; 199 } 200 break; 201 202 case 13: 203 case 1: 204 case 10: 205 case 11: 206 /* r is the base, l is the index */ 207 if(r->addable != 20) 208 n->addable = 8; 209 break; 210 } 211 if(n->addable == 8 && !side(n)) { 212 indx(n); 213 l = new1(OINDEX, idx.basetree, idx.regtree); 214 l->scale = idx.scale; 215 l->addable = 9; 216 l->complex = l->right->complex; 217 l->type = l->left->type; 218 n->op = OADDR; 219 n->left = l; 220 n->right = Z; 221 n->addable = 8; 222 break; 223 } 224 break; 225 226 case OINDEX: 227 xcom(l); 228 xcom(r); 229 n->addable = 9; 230 break; 231 232 case OIND: 233 xcom(l); 234 if(l->op == OADDR) { 235 l = l->left; 236 l->type = n->type; 237 *n = *l; 238 return; 239 } 240 switch(l->addable) { 241 case 20: 242 n->addable = 21; 243 break; 244 case 1: 245 n->addable = 11; 246 break; 247 case 13: 248 n->addable = 10; 249 break; 250 } 251 break; 252 253 case OASHL: 254 xcom(l); 255 xcom(r); 256 indexshift(n); 257 break; 258 259 case OMUL: 260 case OLMUL: 261 xcom(l); 262 xcom(r); 263 g = vlog(l); 264 if(g >= 0) { 265 n->left = r; 266 n->right = l; 267 l = r; 268 r = n->right; 269 } 270 g = vlog(r); 271 if(g >= 0) { 272 n->op = OASHL; 273 r->vconst = g; 274 r->type = types[TINT]; 275 indexshift(n); 276 break; 277 } 278 commute(n); 279 break; 280 281 case OASLDIV: 282 xcom(l); 283 xcom(r); 284 g = vlog(r); 285 if(g >= 0) { 286 n->op = OASLSHR; 287 r->vconst = g; 288 r->type = types[TINT]; 289 } 290 break; 291 292 case OLDIV: 293 xcom(l); 294 xcom(r); 295 g = vlog(r); 296 if(g >= 0) { 297 n->op = OLSHR; 298 r->vconst = g; 299 r->type = types[TINT]; 300 indexshift(n); 301 break; 302 } 303 break; 304 305 case OASLMOD: 306 xcom(l); 307 xcom(r); 308 g = vlog(r); 309 if(g >= 0) { 310 n->op = OASAND; 311 r->vconst--; 312 } 313 break; 314 315 case OLMOD: 316 xcom(l); 317 xcom(r); 318 g = vlog(r); 319 if(g >= 0) { 320 n->op = OAND; 321 r->vconst--; 322 } 323 break; 324 325 case OASMUL: 326 case OASLMUL: 327 xcom(l); 328 xcom(r); 329 g = vlog(r); 330 if(g >= 0) { 331 n->op = OASASHL; 332 r->vconst = g; 333 } 334 break; 335 336 case OLSHR: 337 case OASHR: 338 xcom(l); 339 xcom(r); 340 indexshift(n); 341 break; 342 343 default: 344 if(l != Z) 345 xcom(l); 346 if(r != Z) 347 xcom(r); 348 break; 349 } 350 brk: 351 if(n->addable >= 10) 352 return; 353 if(l != Z) 354 n->complex = l->complex; 355 if(r != Z) { 356 if(r->complex == n->complex) 357 n->complex = r->complex+1; 358 else 359 if(r->complex > n->complex) 360 n->complex = r->complex; 361 } 362 if(n->complex == 0) 363 n->complex++; 364 365 if(com64(n)) 366 return; 367 368 switch(n->op) { 369 370 case OFUNC: 371 n->complex = FNX; 372 break; 373 374 case OLMOD: 375 case OMOD: 376 case OLMUL: 377 case OLDIV: 378 case OMUL: 379 case ODIV: 380 case OASLMUL: 381 case OASLDIV: 382 case OASLMOD: 383 case OASMUL: 384 case OASDIV: 385 case OASMOD: 386 if(r->complex >= l->complex) { 387 n->complex = l->complex + 3; 388 if(r->complex > n->complex) 389 n->complex = r->complex; 390 } else { 391 n->complex = r->complex + 3; 392 if(l->complex > n->complex) 393 n->complex = l->complex; 394 } 395 break; 396 397 case OLSHR: 398 case OASHL: 399 case OASHR: 400 case OASLSHR: 401 case OASASHL: 402 case OASASHR: 403 if(r->complex >= l->complex) { 404 n->complex = l->complex + 2; 405 if(r->complex > n->complex) 406 n->complex = r->complex; 407 } else { 408 n->complex = r->complex + 2; 409 if(l->complex > n->complex) 410 n->complex = l->complex; 411 } 412 break; 413 414 case OADD: 415 case OXOR: 416 case OAND: 417 case OOR: 418 /* 419 * immediate operators, make const on right 420 */ 421 if(l->op == OCONST) { 422 n->left = r; 423 n->right = l; 424 } 425 break; 426 427 case OEQ: 428 case ONE: 429 case OLE: 430 case OLT: 431 case OGE: 432 case OGT: 433 case OHI: 434 case OHS: 435 case OLO: 436 case OLS: 437 /* 438 * compare operators, make const on left 439 */ 440 if(r->op == OCONST) { 441 n->left = r; 442 n->right = l; 443 n->op = invrel[relindex(n->op)]; 444 } 445 break; 446 } 447 } 448 449 void 450 indx(Node *n) 451 { 452 Node *l, *r; 453 454 if(debug['x']) 455 prtree(n, "indx"); 456 457 l = n->left; 458 r = n->right; 459 if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) { 460 n->right = l; 461 n->left = r; 462 l = r; 463 r = n->right; 464 } 465 if(l->addable != 7) { 466 idx.regtree = l; 467 idx.scale = 1; 468 } else 469 if(l->right->addable == 20) { 470 idx.regtree = l->left; 471 idx.scale = 1 << l->right->vconst; 472 } else 473 if(l->left->addable == 20) { 474 idx.regtree = l->right; 475 idx.scale = 1 << l->left->vconst; 476 } else 477 diag(n, "bad index"); 478 479 idx.basetree = r; 480 if(debug['x']) { 481 print("scale = %d\n", idx.scale); 482 prtree(idx.regtree, "index"); 483 prtree(idx.basetree, "base"); 484 } 485 }