github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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("can't 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("can't 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 if(flag_shared) { 250 s = lookup("init_array", 0); 251 s->type = SINITARR; 252 s->reachable = 1; 253 s->hide = 1; 254 addaddr(s, lookup(INITENTRY, 0)); 255 } 256 257 for(cursym = textp; cursym != nil; cursym = cursym->next) { 258 for(p = cursym->text; p != P; p = p->link) { 259 if(p->cond != P) { 260 p->cond = brloop(p->cond); 261 if(p->cond != P) 262 if(p->to.type == D_BRANCH) 263 p->to.offset = p->cond->pc; 264 } 265 } 266 } 267 } 268 269 Prog* 270 brloop(Prog *p) 271 { 272 Prog *q; 273 int c; 274 275 for(c=0; p!=P;) { 276 if(p->as != AB) 277 return p; 278 q = p->cond; 279 if(q <= p) { 280 c++; 281 if(q == p || c > 5000) 282 break; 283 } 284 p = q; 285 } 286 return P; 287 } 288 289 int32 290 atolwhex(char *s) 291 { 292 int32 n; 293 int f; 294 295 n = 0; 296 f = 0; 297 while(*s == ' ' || *s == '\t') 298 s++; 299 if(*s == '-' || *s == '+') { 300 if(*s++ == '-') 301 f = 1; 302 while(*s == ' ' || *s == '\t') 303 s++; 304 } 305 if(s[0]=='0' && s[1]){ 306 if(s[1]=='x' || s[1]=='X'){ 307 s += 2; 308 for(;;){ 309 if(*s >= '0' && *s <= '9') 310 n = n*16 + *s++ - '0'; 311 else if(*s >= 'a' && *s <= 'f') 312 n = n*16 + *s++ - 'a' + 10; 313 else if(*s >= 'A' && *s <= 'F') 314 n = n*16 + *s++ - 'A' + 10; 315 else 316 break; 317 } 318 } else 319 while(*s >= '0' && *s <= '7') 320 n = n*8 + *s++ - '0'; 321 } else 322 while(*s >= '0' && *s <= '9') 323 n = n*10 + *s++ - '0'; 324 if(f) 325 n = -n; 326 return n; 327 } 328 329 int32 330 rnd(int32 v, int32 r) 331 { 332 int32 c; 333 334 if(r <= 0) 335 return v; 336 v += r - 1; 337 c = v % r; 338 if(c < 0) 339 c += r; 340 v -= c; 341 return v; 342 } 343 344 void 345 dozerostk(void) 346 { 347 Prog *p, *pl; 348 int32 autoffset; 349 350 for(cursym = textp; cursym != nil; cursym = cursym->next) { 351 if(cursym->text == nil || cursym->text->link == nil) 352 continue; 353 p = cursym->text; 354 autoffset = p->to.offset; 355 if(autoffset < 0) 356 autoffset = 0; 357 if(autoffset && !(p->reg&NOSPLIT)) { 358 // MOVW $4(R13), R1 359 p = appendp(p); 360 p->as = AMOVW; 361 p->from.type = D_CONST; 362 p->from.reg = 13; 363 p->from.offset = 4; 364 p->to.type = D_REG; 365 p->to.reg = 1; 366 367 // MOVW $n(R13), R2 368 p = appendp(p); 369 p->as = AMOVW; 370 p->from.type = D_CONST; 371 p->from.reg = 13; 372 p->from.offset = 4 + autoffset; 373 p->to.type = D_REG; 374 p->to.reg = 2; 375 376 // MOVW $0, R3 377 p = appendp(p); 378 p->as = AMOVW; 379 p->from.type = D_CONST; 380 p->from.offset = 0; 381 p->to.type = D_REG; 382 p->to.reg = 3; 383 384 // L: 385 // MOVW.P R3, 0(R1) +4 386 // CMP R1, R2 387 // BNE L 388 p = pl = appendp(p); 389 p->as = AMOVW; 390 p->from.type = D_REG; 391 p->from.reg = 3; 392 p->to.type = D_OREG; 393 p->to.reg = 1; 394 p->to.offset = 4; 395 p->scond |= C_PBIT; 396 397 p = appendp(p); 398 p->as = ACMP; 399 p->from.type = D_REG; 400 p->from.reg = 1; 401 p->reg = 2; 402 403 p = appendp(p); 404 p->as = ABNE; 405 p->to.type = D_BRANCH; 406 p->cond = pl; 407 } 408 } 409 }