* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / lcc / src / .svn / text-base / stmt.c.svn-base
blob9c3bdbe9b10b198ee5eabe8313a1ab9639eb70a8
1 #include "c.h"
4 #define SWSIZE 512
6 #define den(i,j) ((j-buckets[i]+1.0)/(v[j]-v[buckets[i]]+1))
8 struct code codehead = { Start };
9 Code codelist = &codehead;
10 float density = 0.5;
11 Table stmtlabs;
13 static int foldcond(Tree e1, Tree e2);
14 static void caselabel(Swtch, long, int);
15 static void cmp(int, Symbol, long, int);
16 static Tree conditional(int);
17 static void dostmt(int, Swtch, int);
18 static int equal(Symbol, Symbol);
19 static void forstmt(int, Swtch, int);
20 static void ifstmt(int, int, Swtch, int);
21 static Symbol localaddr(Tree);
22 static void stmtlabel(void);
23 static void swstmt(int, int, int);
24 static void whilestmt(int, Swtch, int);
25 Code code(int kind) {
26         Code cp;
28         if (!reachable(kind))
29                 warning("unreachable code\n");
31         NEW(cp, FUNC);
32         cp->kind = kind;
33         cp->prev = codelist;
34         cp->next = NULL;
35         codelist->next = cp;
36         codelist = cp;
37         return cp;
39 int reachable(int kind) {
41         if (kind > Start) {
42                 Code cp;
43                 for (cp = codelist; cp->kind < Label; )
44                         cp = cp->prev;
45                 if (cp->kind == Jump || cp->kind == Switch)
46                         return 0;
47         }
48         return 1;
50 void addlocal(Symbol p) {
51         if (!p->defined) {
52                 code(Local)->u.var = p;
53                 p->defined = 1;
54                 p->scope = level;
55         }
57 void definept(Coordinate *p) {
58         Code cp = code(Defpoint);
60         cp->u.point.src = p ? *p : src;
61         cp->u.point.point = npoints;
62         if (ncalled > 0) {
63                 int n = findcount(cp->u.point.src.file,
64                         cp->u.point.src.x, cp->u.point.src.y);
65                 if (n > 0)
66                         refinc = (float)n/ncalled;
67         }
68         if (glevel > 2) locus(identifiers, &cp->u.point.src);
69         if (events.points && reachable(Gen))
70                 {
71                         Tree e = NULL;
72                         apply(events.points, &cp->u.point.src, &e);
73                         if (e)
74                                 listnodes(e, 0, 0);
75                 }
77 void statement(int loop, Swtch swp, int lev) {
78         float ref = refinc;
80         if (Aflag >= 2 && lev == 15)
81                 warning("more than 15 levels of nested statements\n");
82         switch (t) {
83         case IF:       ifstmt(genlabel(2), loop, swp, lev + 1);
84  break;
85         case WHILE:    whilestmt(genlabel(3), swp, lev + 1); break;
86         case DO:       dostmt(genlabel(3), swp, lev + 1); expect(';');
87                                         break;
89         case FOR:      forstmt(genlabel(4), swp, lev + 1);
90  break;
91         case BREAK:    walk(NULL, 0, 0);
92                        definept(NULL);
93                        if (swp && swp->lab > loop)
94                         branch(swp->lab + 1);
95                        else if (loop)
96                         branch(loop + 2);
97                        else
98                         error("illegal break statement\n");
99                        t = gettok(); expect(';');
100                                            break;
102         case CONTINUE: walk(NULL, 0, 0);
103                        definept(NULL);
104                        if (loop)
105                         branch(loop + 1);
106                        else
107                         error("illegal continue statement\n");
108                        t = gettok(); expect(';');
109                                               break;
111         case SWITCH:   swstmt(loop, genlabel(2), lev + 1);
112  break;
113         case CASE:     {
114                         int lab = genlabel(1);
115                         if (swp == NULL)
116                                 error("illegal case label\n");
117                         definelab(lab);
118                         while (t == CASE) {
119                                 static char stop[] = { IF, ID, 0 };
120                                 Tree p;
121                                 t = gettok();
122                                 p = constexpr(0);
123                                 if (generic(p->op) == CNST && isint(p->type)) {
124                                         if (swp) {
125                                                 needconst++;
126                                                 p = cast(p, swp->sym->type);
127                                                 if (p->type->op == UNSIGNED)
128                                                         p->u.v.i = extend(p->u.v.u, p->type);
129                                                 needconst--;
130                                                 caselabel(swp, p->u.v.i, lab);
131                                         }
132                                 } else
133                                         error("case label must be a constant integer expression\n");
135                                 test(':', stop);
136                         }
137                         statement(loop, swp, lev);
138                        } break;
139         case DEFAULT:  if (swp == NULL)
140                         error("illegal default label\n");
141                        else if (swp->deflab)
142                         error("extra default label\n");
143                        else {
144                         swp->deflab = findlabel(swp->lab);
145                         definelab(swp->deflab->u.l.label);
146                        }
147                        t = gettok();
148                        expect(':');
149                        statement(loop, swp, lev); break;
150         case RETURN:   {
151                         Type rty = freturn(cfunc->type);
152                         t = gettok();
153                         definept(NULL);
154                         if (t != ';')
155                                 if (rty == voidtype) {
156                                         error("extraneous return value\n");
157                                         expr(0);
158                                         retcode(NULL);
159                                 } else
160                                         retcode(expr(0));
161                         else {
162                                 if (rty != voidtype)
163                                         warning("missing return value\n");
164                                 retcode(NULL);
165                         }
166                         branch(cfunc->u.f.label);
167                        } expect(';');
168                                             break;
170         case '{':      compound(loop, swp, lev + 1); break;
171         case ';':      definept(NULL); t = gettok(); break;
172         case GOTO:     walk(NULL, 0, 0);
173                        definept(NULL);
174                        t = gettok();
175                        if (t == ID) {
176                         Symbol p = lookup(token, stmtlabs);
177                         if (p == NULL) {
178                                 p = install(token, &stmtlabs, 0, FUNC);
179                                 p->scope = LABELS;
180                                 p->u.l.label = genlabel(1);
181                                 p->src = src;
182                         }
183                         use(p, src);
184                         branch(p->u.l.label);
185                         t = gettok();
186                        } else
187                         error("missing label in goto\n"); expect(';');
188                                           break;
190         case ID:       if (getchr() == ':') {
191                         stmtlabel();
192                         statement(loop, swp, lev);
193                         break;
194                        }
195         default:       definept(NULL);
196                        if (kind[t] != ID) {
197                         error("unrecognized statement\n");
198                         t = gettok();
199                        } else {
200                         Tree e = expr0(0);
201                         listnodes(e, 0, 0);
202                         if (nodecount == 0 || nodecount > 200)
203                                 walk(NULL, 0, 0);
204                         else if (glevel) walk(NULL, 0, 0);
205                         deallocate(STMT);
206                        } expect(';');
207                                                 break;
209         }
210         if (kind[t] != IF && kind[t] != ID
211         && t != '}' && t != EOI) {
212                 static char stop[] = { IF, ID, '}', 0 };
213                 error("illegal statement termination\n");
214                 skipto(0, stop);
215         }
216         refinc = ref;
219 static void ifstmt(int lab, int loop, Swtch swp, int lev) {
220         t = gettok();
221         expect('(');
222         definept(NULL);
223         walk(conditional(')'), 0, lab);
224         refinc /= 2.0;
225         statement(loop, swp, lev);
226         if (t == ELSE) {
227                 branch(lab + 1);
228                 t = gettok();
229                 definelab(lab);
230                 statement(loop, swp, lev);
231                 if (findlabel(lab + 1)->ref)
232                         definelab(lab + 1);
233         } else
234                 definelab(lab);
236 static Tree conditional(int tok) {
237         Tree p = expr(tok);
239         if (Aflag > 1 && isfunc(p->type))
240                 warning("%s used in a conditional expression\n",
241                         funcname(p));
242         return cond(p);
244 static void stmtlabel(void) {
245         Symbol p = lookup(token, stmtlabs);
247         if (p == NULL) {
248                 p = install(token, &stmtlabs, 0, FUNC);
249                 p->scope = LABELS;
250                 p->u.l.label = genlabel(1);
251                 p->src = src;
252         }
253         if (p->defined)
254                 error("redefinition of label `%s' previously defined at %w\n", p->name, &p->src);
256         p->defined = 1;
257         definelab(p->u.l.label);
258         t = gettok();
259         expect(':');
261 static void forstmt(int lab, Swtch swp, int lev) {
262         int once = 0;
263         Tree e1 = NULL, e2 = NULL, e3 = NULL;
264         Coordinate pt2, pt3;
265         
266         t = gettok();
267         expect('(');
268         definept(NULL);
269         if (kind[t] == ID)
270                 e1 = texpr(expr0, ';', FUNC);
271         else
272                 expect(';');
273         walk(e1, 0, 0);
274         pt2 = src;
275         refinc *= 10.0;
276         if (kind[t] == ID)
277                 e2 = texpr(conditional, ';', FUNC);
278         else
279                 expect(';');
280         pt3 = src;
281         if (kind[t] == ID)
282                 e3 = texpr(expr0, ')', FUNC);
283         else {
284                 static char stop[] = { IF, ID, '}', 0 };
285                 test(')', stop);
286         }
287         if (e2) {
288                 once = foldcond(e1, e2);
289                 if (!once)
290                         branch(lab + 3);
291         }
292         definelab(lab);
293         statement(lab, swp, lev);
294         definelab(lab + 1);
295         definept(&pt3);
296         if (e3)
297                 walk(e3, 0, 0);
298         if (e2) {
299                 if (!once)
300                         definelab(lab + 3);
301                 definept(&pt2);
302                 walk(e2, lab, 0);
303         } else {
304                 definept(&pt2);
305                 branch(lab);
306         }
307         if (findlabel(lab + 2)->ref)
308                 definelab(lab + 2);
310 static void swstmt(int loop, int lab, int lev) {
311         Tree e;
312         struct swtch sw;
313         Code head, tail;
315         t = gettok();
316         expect('(');
317         definept(NULL);
318         e = expr(')');
319         if (!isint(e->type)) {
320                 error("illegal type `%t' in switch expression\n",
321                         e->type);
322                 e = retype(e, inttype);
323         }
324         e = cast(e, promote(e->type));
325         if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op)
326         && e->kids[0]->u.sym->type == e->type
327         && !isvolatile(e->kids[0]->u.sym->type)) {
328                 sw.sym = e->kids[0]->u.sym;
329                 walk(NULL, 0, 0);
330         } else {
331                 sw.sym = genident(REGISTER, e->type, level);
332                 addlocal(sw.sym);
333                 walk(asgn(sw.sym, e), 0, 0);
334         }
335         head = code(Switch);
336         sw.lab = lab;
337         sw.deflab = NULL;
338         sw.ncases = 0;
339         sw.size = SWSIZE;
340         sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC);
341         sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC);
342         refinc /= 10.0;
343         statement(loop, &sw, lev);
344         if (sw.deflab == NULL) {
345                 sw.deflab = findlabel(lab);
346                 definelab(lab);
347                 if (sw.ncases == 0)
348                         warning("switch statement with no cases\n");
349         }
350         if (findlabel(lab + 1)->ref)
351                 definelab(lab + 1);
352         tail = codelist;
353         codelist = head->prev;
354         codelist->next = head->prev = NULL;
355         if (sw.ncases > 0)
356                 swgen(&sw);
357         branch(lab);
358         head->next->prev = codelist;
359         codelist->next = head->next;
360         codelist = tail;
362 static void caselabel(Swtch swp, long val, int lab) {
363         int k;
365         if (swp->ncases >= swp->size)
366                 {
367                 long   *vals = swp->values;
368                 Symbol *labs = swp->labels;
369                 swp->size *= 2;
370                 swp->values = newarray(swp->size, sizeof *swp->values, FUNC);
371                 swp->labels = newarray(swp->size, sizeof *swp->labels, FUNC);
372                 for (k = 0; k < swp->ncases; k++) {
373                         swp->values[k] = vals[k];
374                         swp->labels[k] = labs[k];
375                 }
376                 }
377         k = swp->ncases;
378         for ( ; k > 0 && swp->values[k-1] >= val; k--) {
379                 swp->values[k] = swp->values[k-1];
380                 swp->labels[k] = swp->labels[k-1];
381         }
382         if (k < swp->ncases && swp->values[k] == val)
383                 error("duplicate case label `%d'\n", val);
384         swp->values[k] = val;
385         swp->labels[k] = findlabel(lab);
386         ++swp->ncases;
387         if (Aflag >= 2 && swp->ncases == 258)
388                 warning("more than 257 cases in a switch\n");
390 void swgen(Swtch swp) {
391         int *buckets, k, n;
392         long *v = swp->values;
394         buckets = newarray(swp->ncases + 1,
395                 sizeof *buckets, FUNC);
396         for (n = k = 0; k < swp->ncases; k++, n++) {
397                 buckets[n] = k;
398                 while (n > 0 && den(n-1, k) >= density)
399                         n--;
400         }
401         buckets[n] = swp->ncases;
402         swcode(swp, buckets, 0, n - 1);
404 void swcode(Swtch swp, int b[], int lb, int ub) {
405         int hilab, lolab, l, u, k = (lb + ub)/2;
406         long *v = swp->values;
408         if (k > lb && k < ub) {
409                 lolab = genlabel(1);
410                 hilab = genlabel(1);
411         } else if (k > lb) {
412                 lolab = genlabel(1);
413                 hilab = swp->deflab->u.l.label;
414         } else if (k < ub) {
415                 lolab = swp->deflab->u.l.label;
416                 hilab = genlabel(1);
417         } else
418                 lolab = hilab = swp->deflab->u.l.label;
419         l = b[k];
420         u = b[k+1] - 1;
421         if (u - l + 1 <= 3)
422                 {
423                         int i;
424                         for (i = l; i <= u; i++)
425                                 cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label);
426                         if (k > lb && k < ub)
427                                 cmp(GT, swp->sym, v[u], hilab);
428                         else if (k > lb)
429                                 cmp(GT, swp->sym, v[u], hilab);
430                         else if (k < ub)
431                                 cmp(LT, swp->sym, v[l], lolab);
432                         else
433                                 assert(lolab == hilab),
434                                 branch(lolab);
435                         walk(NULL, 0, 0);
436                 }
437         else {
438                 Tree e;
439                 Type ty = signedint(swp->sym->type);
440                 Symbol table = genident(STATIC,
441                         array(voidptype, u - l + 1, 0), GLOBAL);
442                 (*IR->defsymbol)(table);
443                 if (!isunsigned(swp->sym->type) || v[l] != 0)
444                         cmp(LT, swp->sym, v[l], lolab);
445                 cmp(GT, swp->sym, v[u], hilab);
446                 e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l]));
447                 if (e->type->size < unsignedptr->size)
448                         e = cast(e, unsignedlong);
449                 walk(tree(JUMP, voidtype,
450                         rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), NULL),
451                         0, 0);
452                 code(Switch);
453                 codelist->u.swtch.table = table;
454                 codelist->u.swtch.sym = swp->sym;
455                 codelist->u.swtch.deflab = swp->deflab;
456                 codelist->u.swtch.size = u - l + 1;
457                 codelist->u.swtch.values = &v[l];
458                 codelist->u.swtch.labels = &swp->labels[l];
459                 if (v[u] - v[l] + 1 >= 10000)
460                         warning("switch generates a huge table\n");
461         }
462         if (k > lb) {
463                 assert(lolab != swp->deflab->u.l.label);
464                 definelab(lolab);
465                 swcode(swp, b, lb, k - 1);
466         }
467         if (k < ub) {
468                 assert(hilab != swp->deflab->u.l.label);
469                 definelab(hilab);
470                 swcode(swp, b, k + 1, ub);
471         }
473 static void cmp(int op, Symbol p, long n, int lab) {
474         Type ty = signedint(p->type);
476         listnodes(eqtree(op,
477                         cast(idtree(p), ty),
478                         cnsttree(ty, n)),
479                 lab, 0);
481 void retcode(Tree p) {
482         Type ty;
484         if (p == NULL) {
485                 if (events.returns)
486                         apply(events.returns, cfunc, NULL);
487                 return;
488         }
489         p = pointer(p);
490         ty = assign(freturn(cfunc->type), p);
491         if (ty == NULL) {
492                 error("illegal return type; found `%t' expected `%t'\n",
493                         p->type, freturn(cfunc->type));
494                 return;
495         }
496         p = cast(p, ty);
497         if (retv)
498                 {
499                         if (iscallb(p))
500                                 p = tree(RIGHT, p->type,
501                                         tree(CALL+B, p->type,
502                                                 p->kids[0]->kids[0], idtree(retv)),
503                                         rvalue(idtree(retv)));
504                         else
505                                 p = asgntree(ASGN, rvalue(idtree(retv)), p);
506                         walk(p, 0, 0);
507                         if (events.returns)
508                                 apply(events.returns, cfunc, rvalue(idtree(retv)));
509                         return;
510                 }
511         if (events.returns)
512                 {
513                         Symbol t1 = genident(AUTO, p->type, level);
514                         addlocal(t1);
515                         walk(asgn(t1, p), 0, 0);
516                         apply(events.returns, cfunc, idtree(t1));
517                         p = idtree(t1);
518                 }
519         if (!isfloat(p->type))
520                 p = cast(p, promote(p->type));
521         if (isptr(p->type))
522                 {
523                         Symbol q = localaddr(p);
524                         if (q && (q->computed || q->generated))
525                                 warning("pointer to a %s is an illegal return value\n",
526                                         q->scope == PARAM ? "parameter" : "local");
527                         else if (q)
528                                 warning("pointer to %s `%s' is an illegal return value\n",
529                                         q->scope == PARAM ? "parameter" : "local", q->name);
530                 }
531         walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0);
533 void definelab(int lab) {
534         Code cp;
535         Symbol p = findlabel(lab);
537         assert(lab);
538         walk(NULL, 0, 0);
539         code(Label)->u.forest = newnode(LABEL+V, NULL, NULL, p);
540         for (cp = codelist->prev; cp->kind <= Label; )
541                 cp = cp->prev;
542         while (   cp->kind == Jump
543                && cp->u.forest->kids[0]
544                && specific(cp->u.forest->kids[0]->op) == ADDRG+P
545                && cp->u.forest->kids[0]->syms[0] == p) {
546                 assert(cp->u.forest->kids[0]->syms[0]->u.l.label == lab);
547                 p->ref--;
548                 assert(cp->next);
549                 assert(cp->prev);
550                 cp->prev->next = cp->next;
551                 cp->next->prev = cp->prev;
552                 cp = cp->prev;
553                 while (cp->kind <= Label)
554                         cp = cp->prev;
555         }
557 Node jump(int lab) {
558         Symbol p = findlabel(lab);
560         p->ref++;
561         return newnode(JUMP+V, newnode(ADDRG+ttob(voidptype), NULL, NULL, p),
562                 NULL, NULL);
564 void branch(int lab) {
565         Code cp;
566         Symbol p = findlabel(lab);
568         assert(lab);
569         walk(NULL, 0, 0);
570         code(Label)->u.forest = jump(lab);
571         for (cp = codelist->prev; cp->kind < Label; )
572                 cp = cp->prev;
573         while (   cp->kind == Label
574                && cp->u.forest->op == LABEL+V
575                && !equal(cp->u.forest->syms[0], p)) {
576                 equatelab(cp->u.forest->syms[0], p);
577                 assert(cp->next);
578                 assert(cp->prev);
579                 cp->prev->next = cp->next;
580                 cp->next->prev = cp->prev;
581                 cp = cp->prev;
582                 while (cp->kind < Label)
583                         cp = cp->prev;
584         }
585         if (cp->kind == Jump || cp->kind == Switch) {
586                 p->ref--;
587                 codelist->prev->next = NULL;
588                 codelist = codelist->prev;
589         } else {
590                 codelist->kind = Jump;
591                 if (cp->kind == Label
592                 &&  cp->u.forest->op == LABEL+V
593                 &&  equal(cp->u.forest->syms[0], p))
594                         warning("source code specifies an infinite loop");
595         }
597 void equatelab(Symbol old, Symbol new) {
598         assert(old->u.l.equatedto == NULL);
599         old->u.l.equatedto = new;
600         new->ref++;
602 static int equal(Symbol lprime, Symbol dst) {
603         assert(dst && lprime);
604         for ( ; dst; dst = dst->u.l.equatedto)
605                 if (lprime == dst)
606                         return 1;
607         return 0;
609 /* dostmt - do statement while ( expression ) */
610 static void dostmt(int lab, Swtch swp, int lev) {
611         refinc *= 10.0;
612         t = gettok();
613         definelab(lab);
614         statement(lab, swp, lev);
615         definelab(lab + 1);
616         expect(WHILE);
617         expect('(');
618         definept(NULL);
619         walk(conditional(')'), lab, 0);
620         if (findlabel(lab + 2)->ref)
621                 definelab(lab + 2);
624 /* foldcond - check if initial test in for(e1;e2;e3) S is necessary */
625 static int foldcond(Tree e1, Tree e2) {
626         int op = generic(e2->op);
627         Symbol v;
629         if (e1 == 0 || e2 == 0)
630                 return 0;
631         if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op)
632         && generic(e1->kids[1]->op) == CNST) {
633                 v = e1->kids[0]->u.sym;
634                 e1 = e1->kids[1];
635         } else
636                 return 0;
637         if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE)
638         && generic(e2->kids[0]->op) == INDIR
639         && e2->kids[0]->kids[0]->u.sym == v
640         && e2->kids[1]->op == e1->op) {
641                 e1 = simplify(op, e2->type, e1, e2->kids[1]);
642                 if (e1->op == CNST+I)
643                         return e1->u.v.i;
644         }
645         return 0;
648 /* localaddr - returns q if p yields the address of local/parameter q; otherwise returns 0 */
649 static Symbol localaddr(Tree p) {
650         if (p == NULL)
651                 return NULL;
652         switch (generic(p->op)) {
653         case INDIR: case CALL: case ARG:
654                 return NULL;
655         case ADDRL: case ADDRF:
656                 return p->u.sym;
657         case RIGHT: case ASGN:
658                 if (p->kids[1])
659                         return localaddr(p->kids[1]);
660                 return localaddr(p->kids[0]);
661         case COND: {
662                 Symbol q;
663                 assert(p->kids[1] && p->kids[1]->op == RIGHT);
664                 if ((q = localaddr(p->kids[1]->kids[0])) != NULL)
665                         return q;
666                 return localaddr(p->kids[1]->kids[1]);
667                 }
668         default: {
669                 Symbol q;
670                 if (p->kids[0] && (q = localaddr(p->kids[0])) != NULL)
671                         return q;
672                 return localaddr(p->kids[1]);
673                 }
674         }
677 /* whilestmt - while ( expression ) statement */
678 static void whilestmt(int lab, Swtch swp, int lev) {
679         Coordinate pt;
680         Tree e;
682         refinc *= 10.0;
683         t = gettok();
684         expect('(');
685         walk(NULL, 0, 0);
686         pt = src;
687         e = texpr(conditional, ')', FUNC);
688         branch(lab + 1);
689         definelab(lab);
690         statement(lab, swp, lev);
691         definelab(lab + 1);
692         definept(&pt);
693         walk(e, lab, 0);
694         if (findlabel(lab + 2)->ref)
695                 definelab(lab + 2);