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