github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5l/pass.c (about) 1 // Inferno utils/5l/pass.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/pass.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 // Code and data passes. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 36 static void xfol(Prog*, Prog**); 37 38 Prog* 39 brchain(Prog *p) 40 { 41 int i; 42 43 for(i=0; i<20; i++) { 44 if(p == P || p->as != AB) 45 return p; 46 p = p->cond; 47 } 48 return P; 49 } 50 51 int 52 relinv(int a) 53 { 54 switch(a) { 55 case ABEQ: return ABNE; 56 case ABNE: return ABEQ; 57 case ABCS: return ABCC; 58 case ABHS: return ABLO; 59 case ABCC: return ABCS; 60 case ABLO: return ABHS; 61 case ABMI: return ABPL; 62 case ABPL: return ABMI; 63 case ABVS: return ABVC; 64 case ABVC: return ABVS; 65 case ABHI: return ABLS; 66 case ABLS: return ABHI; 67 case ABGE: return ABLT; 68 case ABLT: return ABGE; 69 case ABGT: return ABLE; 70 case ABLE: return ABGT; 71 } 72 diag("unknown relation: %s", anames[a]); 73 return a; 74 } 75 76 void 77 follow(void) 78 { 79 Prog *firstp, *lastp; 80 81 if(debug['v']) 82 Bprint(&bso, "%5.2f follow\n", cputime()); 83 Bflush(&bso); 84 85 for(cursym = textp; cursym != nil; cursym = cursym->next) { 86 firstp = prg(); 87 lastp = firstp; 88 xfol(cursym->text, &lastp); 89 lastp->link = nil; 90 cursym->text = firstp->link; 91 } 92 } 93 94 static void 95 xfol(Prog *p, Prog **last) 96 { 97 Prog *q, *r; 98 int a, i; 99 100 loop: 101 if(p == P) 102 return; 103 a = p->as; 104 if(a == AB) { 105 q = p->cond; 106 if(q != P && q->as != ATEXT) { 107 p->mark |= FOLL; 108 p = q; 109 if(!(p->mark & FOLL)) 110 goto loop; 111 } 112 } 113 if(p->mark & FOLL) { 114 for(i=0,q=p; i<4; i++,q=q->link) { 115 if(q == *last || q == nil) 116 break; 117 a = q->as; 118 if(a == ANOP) { 119 i--; 120 continue; 121 } 122 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF) 123 goto copy; 124 if(q->cond == P || (q->cond->mark&FOLL)) 125 continue; 126 if(a != ABEQ && a != ABNE) 127 continue; 128 copy: 129 for(;;) { 130 r = prg(); 131 *r = *p; 132 if(!(r->mark&FOLL)) 133 print("cant happen 1\n"); 134 r->mark |= FOLL; 135 if(p != q) { 136 p = p->link; 137 (*last)->link = r; 138 *last = r; 139 continue; 140 } 141 (*last)->link = r; 142 *last = r; 143 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE || a == AUNDEF) 144 return; 145 r->as = ABNE; 146 if(a == ABNE) 147 r->as = ABEQ; 148 r->cond = p->link; 149 r->link = p->cond; 150 if(!(r->link->mark&FOLL)) 151 xfol(r->link, last); 152 if(!(r->cond->mark&FOLL)) 153 print("cant happen 2\n"); 154 return; 155 } 156 } 157 a = AB; 158 q = prg(); 159 q->as = a; 160 q->line = p->line; 161 q->to.type = D_BRANCH; 162 q->to.offset = p->pc; 163 q->cond = p; 164 p = q; 165 } 166 p->mark |= FOLL; 167 (*last)->link = p; 168 *last = p; 169 if(a == AB || (a == ARET && p->scond == 14) || a == ARFE || a == AUNDEF){ 170 return; 171 } 172 if(p->cond != P) 173 if(a != ABL && a != ABX && p->link != P) { 174 q = brchain(p->link); 175 if(a != ATEXT && a != ABCASE) 176 if(q != P && (q->mark&FOLL)) { 177 p->as = relinv(a); 178 p->link = p->cond; 179 p->cond = q; 180 } 181 xfol(p->link, last); 182 q = brchain(p->cond); 183 if(q == P) 184 q = p->cond; 185 if(q->mark&FOLL) { 186 p->cond = q; 187 return; 188 } 189 p = q; 190 goto loop; 191 } 192 p = p->link; 193 goto loop; 194 } 195 196 void 197 patch(void) 198 { 199 int32 c, vexit; 200 Prog *p, *q; 201 Sym *s; 202 int a; 203 204 if(debug['v']) 205 Bprint(&bso, "%5.2f patch\n", cputime()); 206 Bflush(&bso); 207 mkfwd(); 208 s = lookup("exit", 0); 209 vexit = s->value; 210 for(cursym = textp; cursym != nil; cursym = cursym->next) { 211 for(p = cursym->text; p != P; p = p->link) { 212 a = p->as; 213 if((a == ABL || a == ABX || a == AB || a == ARET) && 214 p->to.type != D_BRANCH && p->to.sym != S) { 215 s = p->to.sym; 216 if(s->text == nil) 217 continue; 218 switch(s->type&SMASK) { 219 default: 220 diag("undefined: %s", s->name); 221 s->type = STEXT; 222 s->value = vexit; 223 continue; // avoid more error messages 224 case STEXT: 225 p->to.offset = s->value; 226 p->to.type = D_BRANCH; 227 p->cond = s->text; 228 continue; 229 } 230 } 231 if(p->to.type != D_BRANCH) 232 continue; 233 c = p->to.offset; 234 for(q = cursym->text; q != P;) { 235 if(c == q->pc) 236 break; 237 if(q->forwd != P && c >= q->forwd->pc) 238 q = q->forwd; 239 else 240 q = q->link; 241 } 242 if(q == P) { 243 diag("branch out of range %d\n%P", c, p); 244 p->to.type = D_NONE; 245 } 246 p->cond = q; 247 } 248 } 249 250 for(cursym = textp; cursym != nil; cursym = cursym->next) { 251 for(p = cursym->text; p != P; p = p->link) { 252 if(p->cond != P) { 253 p->cond = brloop(p->cond); 254 if(p->cond != P) 255 if(p->to.type == D_BRANCH) 256 p->to.offset = p->cond->pc; 257 } 258 } 259 } 260 } 261 262 Prog* 263 brloop(Prog *p) 264 { 265 Prog *q; 266 int c; 267 268 for(c=0; p!=P;) { 269 if(p->as != AB) 270 return p; 271 q = p->cond; 272 if(q <= p) { 273 c++; 274 if(q == p || c > 5000) 275 break; 276 } 277 p = q; 278 } 279 return P; 280 } 281 282 int32 283 atolwhex(char *s) 284 { 285 int32 n; 286 int f; 287 288 n = 0; 289 f = 0; 290 while(*s == ' ' || *s == '\t') 291 s++; 292 if(*s == '-' || *s == '+') { 293 if(*s++ == '-') 294 f = 1; 295 while(*s == ' ' || *s == '\t') 296 s++; 297 } 298 if(s[0]=='0' && s[1]){ 299 if(s[1]=='x' || s[1]=='X'){ 300 s += 2; 301 for(;;){ 302 if(*s >= '0' && *s <= '9') 303 n = n*16 + *s++ - '0'; 304 else if(*s >= 'a' && *s <= 'f') 305 n = n*16 + *s++ - 'a' + 10; 306 else if(*s >= 'A' && *s <= 'F') 307 n = n*16 + *s++ - 'A' + 10; 308 else 309 break; 310 } 311 } else 312 while(*s >= '0' && *s <= '7') 313 n = n*8 + *s++ - '0'; 314 } else 315 while(*s >= '0' && *s <= '9') 316 n = n*10 + *s++ - '0'; 317 if(f) 318 n = -n; 319 return n; 320 } 321 322 int32 323 rnd(int32 v, int32 r) 324 { 325 int32 c; 326 327 if(r <= 0) 328 return v; 329 v += r - 1; 330 c = v % r; 331 if(c < 0) 332 c += r; 333 v -= c; 334 return v; 335 } 336 337 void 338 dozerostk(void) 339 { 340 Prog *p, *pl; 341 int32 autoffset; 342 343 for(cursym = textp; cursym != nil; cursym = cursym->next) { 344 if(cursym->text == nil || cursym->text->link == nil) 345 continue; 346 p = cursym->text; 347 autoffset = p->to.offset; 348 if(autoffset < 0) 349 autoffset = 0; 350 if(autoffset && !(p->reg&NOSPLIT)) { 351 // MOVW $4(R13), R1 352 p = appendp(p); 353 p->as = AMOVW; 354 p->from.type = D_CONST; 355 p->from.reg = 13; 356 p->from.offset = 4; 357 p->to.type = D_REG; 358 p->to.reg = 1; 359 360 // MOVW $n(R13), R2 361 p = appendp(p); 362 p->as = AMOVW; 363 p->from.type = D_CONST; 364 p->from.reg = 13; 365 p->from.offset = 4 + autoffset; 366 p->to.type = D_REG; 367 p->to.reg = 2; 368 369 // MOVW $0, R3 370 p = appendp(p); 371 p->as = AMOVW; 372 p->from.type = D_CONST; 373 p->from.offset = 0; 374 p->to.type = D_REG; 375 p->to.reg = 3; 376 377 // L: 378 // MOVW.P R3, 0(R1) +4 379 // CMP R1, R2 380 // BNE L 381 p = pl = appendp(p); 382 p->as = AMOVW; 383 p->from.type = D_REG; 384 p->from.reg = 3; 385 p->to.type = D_OREG; 386 p->to.reg = 1; 387 p->to.offset = 4; 388 p->scond |= C_PBIT; 389 390 p = appendp(p); 391 p->as = ACMP; 392 p->from.type = D_REG; 393 p->from.reg = 1; 394 p->reg = 2; 395 396 p = appendp(p); 397 p->as = ABNE; 398 p->to.type = D_BRANCH; 399 p->cond = pl; 400 } 401 } 402 }