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