swt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. #include "gc.h"
  2. int
  3. swcmp(const void *a1, const void *a2)
  4. {
  5. C1 *p1, *p2;
  6. p1 = (C1*)a1;
  7. p2 = (C1*)a2;
  8. if(p1->val < p2->val)
  9. return -1;
  10. return p1->val > p2->val;
  11. }
  12. void
  13. doswit(Node *n)
  14. {
  15. Case *c;
  16. C1 *q, *iq;
  17. long def, nc, i;
  18. def = 0;
  19. nc = 0;
  20. for(c = cases; c->link != C; c = c->link) {
  21. if(c->def) {
  22. if(def)
  23. diag(n, "more than one default in switch");
  24. def = c->label;
  25. continue;
  26. }
  27. nc++;
  28. }
  29. iq = alloc(nc*sizeof(C1));
  30. q = iq;
  31. for(c = cases; c->link != C; c = c->link) {
  32. if(c->def)
  33. continue;
  34. q->label = c->label;
  35. q->val = c->val;
  36. q++;
  37. }
  38. qsort(iq, nc, sizeof(C1), swcmp);
  39. if(debug['W'])
  40. for(i=0; i<nc; i++)
  41. print("case %2ld: = %.8lux\n", i, iq[i].val);
  42. if(def == 0)
  43. def = breakpc;
  44. for(i=0; i<nc-1; i++)
  45. if(iq[i].val == iq[i+1].val)
  46. diag(n, "duplicate cases in switch %ld", iq[i].val);
  47. swit1(iq, nc, def, n);
  48. }
  49. void
  50. swit1(C1 *q, int nc, long def, Node *n)
  51. {
  52. C1 *r;
  53. int i;
  54. Prog *sp;
  55. if(nc < 5) {
  56. for(i=0; i<nc; i++) {
  57. if(debug['W'])
  58. print("case = %.8lux\n", q->val);
  59. gopcode(OEQ, n->type, n, nodconst(q->val));
  60. patch(p, q->label);
  61. q++;
  62. }
  63. gbranch(OGOTO);
  64. patch(p, def);
  65. return;
  66. }
  67. i = nc / 2;
  68. r = q+i;
  69. if(debug['W'])
  70. print("case > %.8lux\n", r->val);
  71. gopcode(OGT, n->type, n, nodconst(r->val));
  72. sp = p;
  73. gbranch(OGOTO);
  74. p->as = AJEQ;
  75. patch(p, r->label);
  76. swit1(q, i, def, n);
  77. if(debug['W'])
  78. print("case < %.8lux\n", r->val);
  79. patch(sp, pc);
  80. swit1(r+1, nc-i-1, def, n);
  81. }
  82. void
  83. cas(void)
  84. {
  85. Case *c;
  86. c = alloc(sizeof(*c));
  87. c->link = cases;
  88. cases = c;
  89. }
  90. void
  91. bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
  92. {
  93. int sh;
  94. long v;
  95. Node *l;
  96. /*
  97. * n1 gets adjusted/masked value
  98. * n2 gets address of cell
  99. * n3 gets contents of cell
  100. */
  101. l = b->left;
  102. if(n2 != Z) {
  103. regalloc(n1, l, nn);
  104. reglcgen(n2, l, Z);
  105. regalloc(n3, l, Z);
  106. gmove(n2, n3);
  107. gmove(n3, n1);
  108. } else {
  109. regalloc(n1, l, nn);
  110. cgen(l, n1);
  111. }
  112. if(b->type->shift == 0 && typeu[b->type->etype]) {
  113. v = ~0 + (1L << b->type->nbits);
  114. gopcode(OAND, types[TLONG], nodconst(v), n1);
  115. } else {
  116. sh = 32 - b->type->shift - b->type->nbits;
  117. if(sh > 0)
  118. gopcode(OASHL, types[TLONG], nodconst(sh), n1);
  119. sh += b->type->shift;
  120. if(sh > 0)
  121. if(typeu[b->type->etype])
  122. gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
  123. else
  124. gopcode(OASHR, types[TLONG], nodconst(sh), n1);
  125. }
  126. }
  127. void
  128. bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
  129. {
  130. long v;
  131. Node nod;
  132. int sh;
  133. regalloc(&nod, b->left, Z);
  134. v = ~0 + (1L << b->type->nbits);
  135. gopcode(OAND, types[TLONG], nodconst(v), n1);
  136. gmove(n1, &nod);
  137. if(nn != Z)
  138. gmove(n1, nn);
  139. sh = b->type->shift;
  140. if(sh > 0)
  141. gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
  142. v <<= sh;
  143. gopcode(OAND, types[TLONG], nodconst(~v), n3);
  144. gopcode(OOR, types[TLONG], n3, &nod);
  145. gmove(&nod, n2);
  146. regfree(&nod);
  147. regfree(n1);
  148. regfree(n2);
  149. regfree(n3);
  150. }
  151. long
  152. outstring(char *s, long n)
  153. {
  154. long r;
  155. if(suppress)
  156. return nstring;
  157. r = nstring;
  158. while(n) {
  159. string[mnstring] = *s++;
  160. mnstring++;
  161. nstring++;
  162. if(mnstring >= NSNAME) {
  163. gpseudo(ADATA, symstring, nodconst(0L));
  164. p->from.offset += nstring - NSNAME;
  165. p->from.scale = NSNAME;
  166. p->to.type = D_SCONST;
  167. memmove(p->to.sval, string, NSNAME);
  168. mnstring = 0;
  169. }
  170. n--;
  171. }
  172. return r;
  173. }
  174. long
  175. outlstring(ushort *s, long n)
  176. {
  177. char buf[2];
  178. int c;
  179. long r;
  180. if(suppress)
  181. return nstring;
  182. while(nstring & 1)
  183. outstring("", 1);
  184. r = nstring;
  185. while(n > 0) {
  186. c = *s++;
  187. if(align(0, types[TCHAR], Aarg1)) {
  188. buf[0] = c>>8;
  189. buf[1] = c;
  190. } else {
  191. buf[0] = c;
  192. buf[1] = c>>8;
  193. }
  194. outstring(buf, 2);
  195. n -= sizeof(ushort);
  196. }
  197. return r;
  198. }
  199. void
  200. nullwarn(Node *l, Node *r)
  201. {
  202. warn(Z, "result of operation not used");
  203. if(l != Z)
  204. cgen(l, Z);
  205. if(r != Z)
  206. cgen(r, Z);
  207. }
  208. void
  209. sextern(Sym *s, Node *a, long o, long w)
  210. {
  211. long e, lw;
  212. for(e=0; e<w; e+=NSNAME) {
  213. lw = NSNAME;
  214. if(w-e < lw)
  215. lw = w-e;
  216. gpseudo(ADATA, s, nodconst(0L));
  217. p->from.offset += o+e;
  218. p->from.scale = lw;
  219. p->to.type = D_SCONST;
  220. memmove(p->to.sval, a->cstring+e, lw);
  221. }
  222. }
  223. void
  224. gextern(Sym *s, Node *a, long o, long w)
  225. {
  226. if(a->op == OCONST && typev[a->type->etype]) {
  227. gpseudo(ADATA, s, lo64(a));
  228. p->from.offset += o;
  229. p->from.scale = 4;
  230. gpseudo(ADATA, s, hi64(a));
  231. p->from.offset += o + 4;
  232. p->from.scale = 4;
  233. return;
  234. }
  235. gpseudo(ADATA, s, a);
  236. p->from.offset += o;
  237. p->from.scale = w;
  238. switch(p->to.type) {
  239. default:
  240. p->to.index = p->to.type;
  241. p->to.type = D_ADDR;
  242. case D_CONST:
  243. case D_FCONST:
  244. case D_ADDR:
  245. break;
  246. }
  247. }
  248. void zname(Biobuf*, Sym*, int);
  249. void zaddr(Biobuf*, Adr*, int);
  250. void outhist(Biobuf*);
  251. void
  252. outcode(void)
  253. {
  254. struct { Sym *sym; short type; } h[NSYM];
  255. Prog *p;
  256. Sym *s;
  257. int f, sf, st, t, sym;
  258. Biobuf b;
  259. if(debug['S']) {
  260. for(p = firstp; p != P; p = p->link)
  261. if(p->as != ADATA && p->as != AGLOBL)
  262. pc--;
  263. for(p = firstp; p != P; p = p->link) {
  264. print("%P\n", p);
  265. if(p->as != ADATA && p->as != AGLOBL)
  266. pc++;
  267. }
  268. }
  269. f = open(outfile, OWRITE);
  270. if(f < 0) {
  271. diag(Z, "cannot open %s", outfile);
  272. return;
  273. }
  274. Binit(&b, f, OWRITE);
  275. Bseek(&b, 0L, 2);
  276. outhist(&b);
  277. for(sym=0; sym<NSYM; sym++) {
  278. h[sym].sym = S;
  279. h[sym].type = 0;
  280. }
  281. sym = 1;
  282. for(p = firstp; p != P; p = p->link) {
  283. jackpot:
  284. sf = 0;
  285. s = p->from.sym;
  286. while(s != S) {
  287. sf = s->sym;
  288. if(sf < 0 || sf >= NSYM)
  289. sf = 0;
  290. t = p->from.type;
  291. if(t == D_ADDR)
  292. t = p->from.index;
  293. if(h[sf].type == t)
  294. if(h[sf].sym == s)
  295. break;
  296. s->sym = sym;
  297. zname(&b, s, t);
  298. h[sym].sym = s;
  299. h[sym].type = t;
  300. sf = sym;
  301. sym++;
  302. if(sym >= NSYM)
  303. sym = 1;
  304. break;
  305. }
  306. st = 0;
  307. s = p->to.sym;
  308. while(s != S) {
  309. st = s->sym;
  310. if(st < 0 || st >= NSYM)
  311. st = 0;
  312. t = p->to.type;
  313. if(t == D_ADDR)
  314. t = p->to.index;
  315. if(h[st].type == t)
  316. if(h[st].sym == s)
  317. break;
  318. s->sym = sym;
  319. zname(&b, s, t);
  320. h[sym].sym = s;
  321. h[sym].type = t;
  322. st = sym;
  323. sym++;
  324. if(sym >= NSYM)
  325. sym = 1;
  326. if(st == sf)
  327. goto jackpot;
  328. break;
  329. }
  330. Bputc(&b, p->as);
  331. Bputc(&b, p->as>>8);
  332. Bputc(&b, p->lineno);
  333. Bputc(&b, p->lineno>>8);
  334. Bputc(&b, p->lineno>>16);
  335. Bputc(&b, p->lineno>>24);
  336. zaddr(&b, &p->from, sf);
  337. zaddr(&b, &p->to, st);
  338. }
  339. Bflush(&b);
  340. close(f);
  341. firstp = P;
  342. lastp = P;
  343. }
  344. void
  345. outhist(Biobuf *b)
  346. {
  347. Hist *h;
  348. char *p, *q, *op, c;
  349. Prog pg;
  350. int n;
  351. pg = zprog;
  352. pg.as = AHISTORY;
  353. c = pathchar();
  354. for(h = hist; h != H; h = h->link) {
  355. p = h->name;
  356. op = 0;
  357. /* on windows skip drive specifier in pathname */
  358. if(systemtype(Windows) && p && p[1] == ':'){
  359. p += 2;
  360. c = *p;
  361. }
  362. if(p && p[0] != c && h->offset == 0 && pathname){
  363. /* on windows skip drive specifier in pathname */
  364. if(systemtype(Windows) && pathname[1] == ':') {
  365. op = p;
  366. p = pathname+2;
  367. c = *p;
  368. } else if(pathname[0] == c){
  369. op = p;
  370. p = pathname;
  371. }
  372. }
  373. while(p) {
  374. q = utfrune(p, c);
  375. if(q) {
  376. n = q-p;
  377. if(n == 0){
  378. n = 1; /* leading "/" */
  379. *p = '/'; /* don't emit "\" on windows */
  380. }
  381. q++;
  382. } else {
  383. n = strlen(p);
  384. q = 0;
  385. }
  386. if(n) {
  387. Bputc(b, ANAME);
  388. Bputc(b, ANAME>>8);
  389. Bputc(b, D_FILE);
  390. Bputc(b, 1);
  391. Bputc(b, '<');
  392. Bwrite(b, p, n);
  393. Bputc(b, 0);
  394. }
  395. p = q;
  396. if(p == 0 && op) {
  397. p = op;
  398. op = 0;
  399. }
  400. }
  401. pg.lineno = h->line;
  402. pg.to.type = zprog.to.type;
  403. pg.to.offset = h->offset;
  404. if(h->offset)
  405. pg.to.type = D_CONST;
  406. Bputc(b, pg.as);
  407. Bputc(b, pg.as>>8);
  408. Bputc(b, pg.lineno);
  409. Bputc(b, pg.lineno>>8);
  410. Bputc(b, pg.lineno>>16);
  411. Bputc(b, pg.lineno>>24);
  412. zaddr(b, &pg.from, 0);
  413. zaddr(b, &pg.to, 0);
  414. }
  415. }
  416. void
  417. zname(Biobuf *b, Sym *s, int t)
  418. {
  419. char *n;
  420. ulong sig;
  421. if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
  422. sig = sign(s);
  423. Bputc(b, ASIGNAME);
  424. Bputc(b, ASIGNAME>>8);
  425. Bputc(b, sig);
  426. Bputc(b, sig>>8);
  427. Bputc(b, sig>>16);
  428. Bputc(b, sig>>24);
  429. s->sig = SIGDONE;
  430. }
  431. else{
  432. Bputc(b, ANAME); /* as */
  433. Bputc(b, ANAME>>8); /* as */
  434. }
  435. Bputc(b, t); /* type */
  436. Bputc(b, s->sym); /* sym */
  437. n = s->name;
  438. while(*n) {
  439. Bputc(b, *n);
  440. n++;
  441. }
  442. Bputc(b, 0);
  443. }
  444. void
  445. zaddr(Biobuf *b, Adr *a, int s)
  446. {
  447. long l;
  448. int i, t;
  449. char *n;
  450. Ieee e;
  451. t = 0;
  452. if(a->index != D_NONE || a->scale != 0)
  453. t |= T_INDEX;
  454. if(s != 0)
  455. t |= T_SYM;
  456. switch(a->type) {
  457. default:
  458. t |= T_TYPE;
  459. case D_NONE:
  460. if(a->offset != 0)
  461. t |= T_OFFSET;
  462. break;
  463. case D_FCONST:
  464. t |= T_FCONST;
  465. break;
  466. case D_SCONST:
  467. t |= T_SCONST;
  468. break;
  469. }
  470. Bputc(b, t);
  471. if(t & T_INDEX) { /* implies index, scale */
  472. Bputc(b, a->index);
  473. Bputc(b, a->scale);
  474. }
  475. if(t & T_OFFSET) { /* implies offset */
  476. l = a->offset;
  477. Bputc(b, l);
  478. Bputc(b, l>>8);
  479. Bputc(b, l>>16);
  480. Bputc(b, l>>24);
  481. }
  482. if(t & T_SYM) /* implies sym */
  483. Bputc(b, s);
  484. if(t & T_FCONST) {
  485. ieeedtod(&e, a->dval);
  486. l = e.l;
  487. Bputc(b, l);
  488. Bputc(b, l>>8);
  489. Bputc(b, l>>16);
  490. Bputc(b, l>>24);
  491. l = e.h;
  492. Bputc(b, l);
  493. Bputc(b, l>>8);
  494. Bputc(b, l>>16);
  495. Bputc(b, l>>24);
  496. return;
  497. }
  498. if(t & T_SCONST) {
  499. n = a->sval;
  500. for(i=0; i<NSNAME; i++) {
  501. Bputc(b, *n);
  502. n++;
  503. }
  504. return;
  505. }
  506. if(t & T_TYPE)
  507. Bputc(b, a->type);
  508. }
  509. void
  510. ieeedtod(Ieee *ieee, double native)
  511. {
  512. double fr, ho, f;
  513. int exp;
  514. if(native < 0) {
  515. ieeedtod(ieee, -native);
  516. ieee->h |= 0x80000000L;
  517. return;
  518. }
  519. if(native == 0) {
  520. ieee->l = 0;
  521. ieee->h = 0;
  522. return;
  523. }
  524. fr = frexp(native, &exp);
  525. f = 2097152L; /* shouldnt use fp constants here */
  526. fr = modf(fr*f, &ho);
  527. ieee->h = ho;
  528. ieee->h &= 0xfffffL;
  529. ieee->h |= (exp+1022L) << 20;
  530. f = 65536L;
  531. fr = modf(fr*f, &ho);
  532. ieee->l = ho;
  533. ieee->l <<= 16;
  534. ieee->l |= (long)(fr*f);
  535. }
  536. long
  537. align(long i, Type *t, int op)
  538. {
  539. long o;
  540. Type *v;
  541. int w;
  542. o = i;
  543. w = 1;
  544. switch(op) {
  545. default:
  546. diag(Z, "unknown align opcode %d", op);
  547. break;
  548. case Asu2: /* padding at end of a struct */
  549. w = SZ_LONG;
  550. if(packflg)
  551. w = packflg;
  552. break;
  553. case Ael1: /* initial allign of struct element */
  554. for(v=t; v->etype==TARRAY; v=v->link)
  555. ;
  556. w = ewidth[v->etype];
  557. if(w <= 0 || w >= SZ_LONG)
  558. w = SZ_LONG;
  559. if(packflg)
  560. w = packflg;
  561. break;
  562. case Ael2: /* width of a struct element */
  563. o += t->width;
  564. break;
  565. case Aarg0: /* initial passbyptr argument in arg list */
  566. if(typesuv[t->etype]) {
  567. o = align(o, types[TIND], Aarg1);
  568. o = align(o, types[TIND], Aarg2);
  569. }
  570. break;
  571. case Aarg1: /* initial allign of parameter */
  572. w = ewidth[t->etype];
  573. if(w <= 0 || w >= SZ_LONG) {
  574. w = SZ_LONG;
  575. break;
  576. }
  577. w = 1; /* little endian no adjustment */
  578. break;
  579. case Aarg2: /* width of a parameter */
  580. o += t->width;
  581. w = SZ_LONG;
  582. break;
  583. case Aaut3: /* total allign of automatic */
  584. o = align(o, t, Ael1);
  585. o = align(o, t, Ael2);
  586. break;
  587. }
  588. o = round(o, w);
  589. if(debug['A'])
  590. print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
  591. return o;
  592. }
  593. long
  594. maxround(long max, long v)
  595. {
  596. v += SZ_LONG-1;
  597. if(v > max)
  598. max = round(v, SZ_LONG);
  599. return max;
  600. }