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