util.c (9196B)
1 #include "all.h" 2 #include <stdarg.h> 3 4 typedef struct Bitset Bitset; 5 typedef struct Vec Vec; 6 typedef struct Bucket Bucket; 7 8 struct Vec { 9 ulong mag; 10 Pool pool; 11 size_t esz; 12 ulong cap; 13 union { 14 long long ll; 15 long double ld; 16 void *ptr; 17 } align[]; 18 }; 19 20 struct Bucket { 21 uint nstr; 22 char **str; 23 }; 24 25 enum { 26 VMin = 2, 27 VMag = 0xcabba9e, 28 NPtr = 256, 29 IBits = 12, 30 IMask = (1<<IBits) - 1, 31 }; 32 33 Typ *typ; 34 Ins insb[NIns], *curi; 35 36 static void *ptr[NPtr]; 37 static void **pool = ptr; 38 static int nptr = 1; 39 40 static Bucket itbl[IMask+1]; /* string interning table */ 41 42 uint32_t 43 hash(char *s) 44 { 45 uint32_t h; 46 47 for (h=0; *s; ++s) 48 h = *s + 17*h; 49 return h; 50 } 51 52 void 53 die_(char *file, char *s, ...) 54 { 55 va_list ap; 56 57 fprintf(stderr, "%s: dying: ", file); 58 va_start(ap, s); 59 vfprintf(stderr, s, ap); 60 va_end(ap); 61 fputc('\n', stderr); 62 abort(); 63 } 64 65 void * 66 emalloc(size_t n) 67 { 68 void *p; 69 70 p = calloc(1, n); 71 if (!p) 72 die("emalloc, out of memory"); 73 return p; 74 } 75 76 void * 77 alloc(size_t n) 78 { 79 void **pp; 80 81 if (n == 0) 82 return 0; 83 if (nptr >= NPtr) { 84 pp = emalloc(NPtr * sizeof(void *)); 85 pp[0] = pool; 86 pool = pp; 87 nptr = 1; 88 } 89 return pool[nptr++] = emalloc(n); 90 } 91 92 void 93 freeall() 94 { 95 void **pp; 96 97 for (;;) { 98 for (pp = &pool[1]; pp < &pool[nptr]; pp++) 99 free(*pp); 100 pp = pool[0]; 101 if (!pp) 102 break; 103 free(pool); 104 pool = pp; 105 nptr = NPtr; 106 } 107 nptr = 1; 108 } 109 110 void * 111 vnew(ulong len, size_t esz, Pool pool) 112 { 113 void *(*f)(size_t); 114 ulong cap; 115 Vec *v; 116 117 for (cap=VMin; cap<len; cap*=2) 118 ; 119 f = pool == PHeap ? emalloc : alloc; 120 v = f(cap * esz + sizeof(Vec)); 121 v->mag = VMag; 122 v->cap = cap; 123 v->esz = esz; 124 v->pool = pool; 125 return v + 1; 126 } 127 128 void 129 vfree(void *p) 130 { 131 Vec *v; 132 133 v = (Vec *)p - 1; 134 assert(v->mag == VMag); 135 if (v->pool == PHeap) { 136 v->mag = 0; 137 free(v); 138 } 139 } 140 141 void 142 vgrow(void *vp, ulong len) 143 { 144 Vec *v; 145 void *v1; 146 147 v = *(Vec **)vp - 1; 148 assert(v+1 && v->mag == VMag); 149 if (v->cap >= len) 150 return; 151 v1 = vnew(len, v->esz, v->pool); 152 memcpy(v1, v+1, v->cap * v->esz); 153 vfree(v+1); 154 *(Vec **)vp = v1; 155 } 156 157 void 158 strf(char str[NString], char *s, ...) 159 { 160 va_list ap; 161 162 va_start(ap, s); 163 vsnprintf(str, NString, s, ap); 164 va_end(ap); 165 } 166 167 uint32_t 168 intern(char *s) 169 { 170 Bucket *b; 171 uint32_t h; 172 uint i, n; 173 174 h = hash(s) & IMask; 175 b = &itbl[h]; 176 n = b->nstr; 177 178 for (i=0; i<n; i++) 179 if (strcmp(s, b->str[i]) == 0) 180 return h + (i<<IBits); 181 182 if (n == 1<<(32-IBits)) 183 die("interning table overflow"); 184 if (n == 0) 185 b->str = vnew(1, sizeof b->str[0], PHeap); 186 else if ((n & (n-1)) == 0) 187 vgrow(&b->str, n+n); 188 189 b->str[n] = emalloc(strlen(s)+1); 190 b->nstr = n + 1; 191 strcpy(b->str[n], s); 192 return h + (n<<IBits); 193 } 194 195 char * 196 str(uint32_t id) 197 { 198 assert(id>>IBits < itbl[id&IMask].nstr); 199 return itbl[id&IMask].str[id>>IBits]; 200 } 201 202 int 203 isreg(Ref r) 204 { 205 return rtype(r) == RTmp && r.val < Tmp0; 206 } 207 208 int 209 iscmp(int op, int *pk, int *pc) 210 { 211 if (Ocmpw <= op && op <= Ocmpw1) { 212 *pc = op - Ocmpw; 213 *pk = Kw; 214 } 215 else if (Ocmpl <= op && op <= Ocmpl1) { 216 *pc = op - Ocmpl; 217 *pk = Kl; 218 } 219 else if (Ocmps <= op && op <= Ocmps1) { 220 *pc = NCmpI + op - Ocmps; 221 *pk = Ks; 222 } 223 else if (Ocmpd <= op && op <= Ocmpd1) { 224 *pc = NCmpI + op - Ocmpd; 225 *pk = Kd; 226 } 227 else 228 return 0; 229 return 1; 230 } 231 232 int 233 argcls(Ins *i, int n) 234 { 235 return optab[i->op].argcls[n][i->cls]; 236 } 237 238 void 239 emit(int op, int k, Ref to, Ref arg0, Ref arg1) 240 { 241 if (curi == insb) 242 die("emit, too many instructions"); 243 *--curi = (Ins){ 244 .op = op, .cls = k, 245 .to = to, .arg = {arg0, arg1} 246 }; 247 } 248 249 void 250 emiti(Ins i) 251 { 252 emit(i.op, i.cls, i.to, i.arg[0], i.arg[1]); 253 } 254 255 void 256 idup(Ins **pd, Ins *s, ulong n) 257 { 258 *pd = alloc(n * sizeof(Ins)); 259 if (n) 260 memcpy(*pd, s, n * sizeof(Ins)); 261 } 262 263 Ins * 264 icpy(Ins *d, Ins *s, ulong n) 265 { 266 if (n) 267 memcpy(d, s, n * sizeof(Ins)); 268 return d + n; 269 } 270 271 static int cmptab[][2] ={ 272 /* negation swap */ 273 [Ciule] = {Ciugt, Ciuge}, 274 [Ciult] = {Ciuge, Ciugt}, 275 [Ciugt] = {Ciule, Ciult}, 276 [Ciuge] = {Ciult, Ciule}, 277 [Cisle] = {Cisgt, Cisge}, 278 [Cislt] = {Cisge, Cisgt}, 279 [Cisgt] = {Cisle, Cislt}, 280 [Cisge] = {Cislt, Cisle}, 281 [Cieq] = {Cine, Cieq}, 282 [Cine] = {Cieq, Cine}, 283 [NCmpI+Cfle] = {NCmpI+Cfgt, NCmpI+Cfge}, 284 [NCmpI+Cflt] = {NCmpI+Cfge, NCmpI+Cfgt}, 285 [NCmpI+Cfgt] = {NCmpI+Cfle, NCmpI+Cflt}, 286 [NCmpI+Cfge] = {NCmpI+Cflt, NCmpI+Cfle}, 287 [NCmpI+Cfeq] = {NCmpI+Cfne, NCmpI+Cfeq}, 288 [NCmpI+Cfne] = {NCmpI+Cfeq, NCmpI+Cfne}, 289 [NCmpI+Cfo] = {NCmpI+Cfuo, NCmpI+Cfo}, 290 [NCmpI+Cfuo] = {NCmpI+Cfo, NCmpI+Cfuo}, 291 }; 292 293 int 294 cmpneg(int c) 295 { 296 assert(0 <= c && c < NCmp); 297 return cmptab[c][0]; 298 } 299 300 int 301 cmpop(int c) 302 { 303 assert(0 <= c && c < NCmp); 304 return cmptab[c][1]; 305 } 306 307 int 308 clsmerge(short *pk, short k) 309 { 310 short k1; 311 312 k1 = *pk; 313 if (k1 == Kx) { 314 *pk = k; 315 return 0; 316 } 317 if ((k1 == Kw && k == Kl) || (k1 == Kl && k == Kw)) { 318 *pk = Kw; 319 return 0; 320 } 321 return k1 != k; 322 } 323 324 int 325 phicls(int t, Tmp *tmp) 326 { 327 int t1; 328 329 t1 = tmp[t].phi; 330 if (!t1) 331 return t; 332 t1 = phicls(t1, tmp); 333 tmp[t].phi = t1; 334 return t1; 335 } 336 337 Ref 338 newtmp(char *prfx, int k, Fn *fn) 339 { 340 static int n; 341 int t; 342 343 t = fn->ntmp++; 344 vgrow(&fn->tmp, fn->ntmp); 345 memset(&fn->tmp[t], 0, sizeof(Tmp)); 346 if (prfx) 347 strf(fn->tmp[t].name, "%s.%d", prfx, ++n); 348 fn->tmp[t].cls = k; 349 fn->tmp[t].slot = -1; 350 fn->tmp[t].nuse = +1; 351 fn->tmp[t].ndef = +1; 352 return TMP(t); 353 } 354 355 void 356 chuse(Ref r, int du, Fn *fn) 357 { 358 if (rtype(r) == RTmp) 359 fn->tmp[r.val].nuse += du; 360 } 361 362 int 363 symeq(Sym s0, Sym s1) 364 { 365 return s0.type == s1.type && s0.id == s1.id; 366 } 367 368 Ref 369 newcon(Con *c0, Fn *fn) 370 { 371 Con *c1; 372 int i; 373 374 for (i=1; i<fn->ncon; i++) { 375 c1 = &fn->con[i]; 376 if (c0->type == c1->type 377 && symeq(c0->sym, c1->sym) 378 && c0->bits.i == c1->bits.i) 379 return CON(i); 380 } 381 vgrow(&fn->con, ++fn->ncon); 382 fn->con[i] = *c0; 383 return CON(i); 384 } 385 386 Ref 387 getcon(int64_t val, Fn *fn) 388 { 389 int c; 390 391 for (c=1; c<fn->ncon; c++) 392 if (fn->con[c].type == CBits 393 && fn->con[c].bits.i == val) 394 return CON(c); 395 vgrow(&fn->con, ++fn->ncon); 396 fn->con[c] = (Con){.type = CBits, .bits.i = val}; 397 return CON(c); 398 } 399 400 int 401 addcon(Con *c0, Con *c1) 402 { 403 if (c0->type == CUndef) 404 *c0 = *c1; 405 else { 406 if (c1->type == CAddr) { 407 if (c0->type == CAddr) 408 return 0; 409 c0->type = CAddr; 410 c0->sym = c1->sym; 411 } 412 c0->bits.i += c1->bits.i; 413 } 414 return 1; 415 } 416 417 void 418 salloc(Ref rt, Ref rs, Fn *fn) 419 { 420 Ref r0, r1; 421 int64_t sz; 422 423 /* we need to make sure 424 * the stack remains aligned 425 * (rsp = 0) mod 16 426 */ 427 fn->dynalloc = 1; 428 if (rtype(rs) == RCon) { 429 sz = fn->con[rs.val].bits.i; 430 if (sz < 0 || sz >= INT_MAX-15) 431 err("invalid alloc size %"PRId64, sz); 432 sz = (sz + 15) & -16; 433 emit(Osalloc, Kl, rt, getcon(sz, fn), R); 434 } else { 435 /* r0 = (r + 15) & -16 */ 436 r0 = newtmp("isel", Kl, fn); 437 r1 = newtmp("isel", Kl, fn); 438 emit(Osalloc, Kl, rt, r0, R); 439 emit(Oand, Kl, r0, r1, getcon(-16, fn)); 440 emit(Oadd, Kl, r1, rs, getcon(15, fn)); 441 if (fn->tmp[rs.val].slot != -1) 442 err("unlikely alloc argument %%%s for %%%s", 443 fn->tmp[rs.val].name, fn->tmp[rt.val].name); 444 } 445 } 446 447 void 448 bsinit(BSet *bs, uint n) 449 { 450 n = (n + NBit-1) / NBit; 451 bs->nt = n; 452 bs->t = alloc(n * sizeof bs->t[0]); 453 } 454 455 MAKESURE(NBit_is_64, NBit == 64); 456 inline static uint 457 popcnt(bits b) 458 { 459 b = (b & 0x5555555555555555) + ((b>>1) & 0x5555555555555555); 460 b = (b & 0x3333333333333333) + ((b>>2) & 0x3333333333333333); 461 b = (b & 0x0f0f0f0f0f0f0f0f) + ((b>>4) & 0x0f0f0f0f0f0f0f0f); 462 b += (b>>8); 463 b += (b>>16); 464 b += (b>>32); 465 return b & 0xff; 466 } 467 468 inline static int 469 firstbit(bits b) 470 { 471 int n; 472 473 n = 0; 474 if (!(b & 0xffffffff)) { 475 n += 32; 476 b >>= 32; 477 } 478 if (!(b & 0xffff)) { 479 n += 16; 480 b >>= 16; 481 } 482 if (!(b & 0xff)) { 483 n += 8; 484 b >>= 8; 485 } 486 if (!(b & 0xf)) { 487 n += 4; 488 b >>= 4; 489 } 490 n += (char[16]){4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0}[b & 0xf]; 491 return n; 492 } 493 494 uint 495 bscount(BSet *bs) 496 { 497 uint i, n; 498 499 n = 0; 500 for (i=0; i<bs->nt; i++) 501 n += popcnt(bs->t[i]); 502 return n; 503 } 504 505 static inline uint 506 bsmax(BSet *bs) 507 { 508 return bs->nt * NBit; 509 } 510 511 void 512 bsset(BSet *bs, uint elt) 513 { 514 assert(elt < bsmax(bs)); 515 bs->t[elt/NBit] |= BIT(elt%NBit); 516 } 517 518 void 519 bsclr(BSet *bs, uint elt) 520 { 521 assert(elt < bsmax(bs)); 522 bs->t[elt/NBit] &= ~BIT(elt%NBit); 523 } 524 525 #define BSOP(f, op) \ 526 void \ 527 f(BSet *a, BSet *b) \ 528 { \ 529 uint i; \ 530 \ 531 assert(a->nt == b->nt); \ 532 for (i=0; i<a->nt; i++) \ 533 a->t[i] op b->t[i]; \ 534 } 535 536 BSOP(bscopy, =) 537 BSOP(bsunion, |=) 538 BSOP(bsinter, &=) 539 BSOP(bsdiff, &= ~) 540 541 int 542 bsequal(BSet *a, BSet *b) 543 { 544 uint i; 545 546 assert(a->nt == b->nt); 547 for (i=0; i<a->nt; i++) 548 if (a->t[i] != b->t[i]) 549 return 0; 550 return 1; 551 } 552 553 void 554 bszero(BSet *bs) 555 { 556 memset(bs->t, 0, bs->nt * sizeof bs->t[0]); 557 } 558 559 /* iterates on a bitset, use as follows 560 * 561 * for (i=0; bsiter(set, &i); i++) 562 * use(i); 563 * 564 */ 565 int 566 bsiter(BSet *bs, int *elt) 567 { 568 bits b; 569 uint t, i; 570 571 i = *elt; 572 t = i/NBit; 573 if (t >= bs->nt) 574 return 0; 575 b = bs->t[t]; 576 b &= ~(BIT(i%NBit) - 1); 577 while (!b) { 578 ++t; 579 if (t >= bs->nt) 580 return 0; 581 b = bs->t[t]; 582 } 583 *elt = NBit*t + firstbit(b); 584 return 1; 585 } 586 587 void 588 dumpts(BSet *bs, Tmp *tmp, FILE *f) 589 { 590 int t; 591 592 fprintf(f, "["); 593 for (t=Tmp0; bsiter(bs, &t); t++) 594 fprintf(f, " %s", tmp[t].name); 595 fprintf(f, " ]\n"); 596 }