add && and || operators
[neatcc.git] / cc.c
blob571fc747eca629d1ebaa4b5ae1ed9c88d8cb6f35
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include "gen.h"
8 #include "tok.h"
10 #define MAXLOCALS (1 << 10)
11 #define MAXARGS (1 << 5)
12 #define print(s) write(2, (s), strlen(s));
14 #define TYPE_BT(t) ((t)->ptr ? 8 : (t)->bt)
15 #define TYPE_SZ(t) ((t)->ptr ? 8 : (t)->bt & BT_SZMASK)
16 #define TYPE_DEREF_BT(t) ((t)->ptr > 1 ? 8 : (t)->bt)
17 #define TYPE_DEREF_SZ(t) ((t)->ptr > 1 ? 8 : (t)->bt & BT_SZMASK)
19 #define T_ARRAY 0x01
21 struct type {
22 unsigned bt;
23 unsigned flags;
24 int ptr;
27 /* type stack */
28 static struct type ts[MAXTMP];
29 static int nts;
31 static void ts_push_bt(unsigned bt)
33 ts[nts].ptr = 0;
34 ts[nts].flags = 0;
35 ts[nts++].bt = bt;
38 static void ts_push(struct type *type)
40 ts[nts++] = *type;
43 static void ts_pop(struct type *type)
45 nts--;
46 if (type)
47 *type = ts[nts];
50 static struct local {
51 char name[NAMELEN];
52 long addr;
53 struct type type;
54 } locals[MAXLOCALS];
55 static int nlocals;
57 static void local_add(char *name, long addr, struct type type)
59 strcpy(locals[nlocals].name, name);
60 locals[nlocals].addr = addr;
61 locals[nlocals].type = type;
62 nlocals++;
65 static void die(char *s)
67 print(s);
68 exit(1);
71 static int tok_jmp(int tok)
73 if (tok_see() != tok)
74 return 1;
75 tok_get();
76 return 0;
79 static void tok_expect(int tok)
81 if (tok_get() != tok)
82 die("syntax error\n");
85 static void readexpr(void);
87 static int basetype(struct type *type)
89 int sign = 1;
90 int size = 4;
91 int done = 0;
92 int i = 0;
93 while (!done) {
94 switch (tok_see()) {
95 case TOK_VOID:
96 sign = 0;
97 size = 0;
98 done = 1;
99 break;
100 case TOK_INT:
101 done = 1;
102 break;
103 case TOK_CHAR:
104 size = 1;
105 done = 1;
106 break;
107 case TOK_SHORT:
108 size = 2;
109 break;
110 case TOK_LONG:
111 size = 8;
112 break;
113 case TOK_UNSIGNED:
114 sign = 0;
115 break;
116 case TOK_ENUM:
117 case TOK_STRUCT:
118 tok_expect(TOK_NAME);
119 done = 1;
120 break;
121 default:
122 if (!i)
123 return 1;
124 done = 1;
125 continue;
127 i++;
128 tok_get();
130 type->bt = size | (sign ? BT_SIGNED : 0);
131 type->ptr = 0;
132 return 0;
135 static void readptrs(struct type *type)
137 while (!tok_jmp('*'))
138 type->ptr++;
141 static int readtype(struct type *type)
143 if (basetype(type))
144 return 1;
145 readptrs(type);
146 return 0;
149 static void readprimary(void)
151 int i;
152 if (!tok_jmp(TOK_NUM)) {
153 ts_push_bt(4 | BT_SIGNED);
154 o_num(atoi(tok_id()), 4 | BT_SIGNED);
155 return;
157 if (!tok_jmp(TOK_NAME)) {
158 for (i = 0; i < nlocals; i++) {
159 struct type *t = &locals[i].type;
160 if (!strcmp(locals[i].name, tok_id())) {
161 ts_push(t);
162 o_local(locals[i].addr, TYPE_BT(t));
163 if (t->flags & T_ARRAY)
164 o_addr();
165 return;
168 ts_push_bt(8);
169 o_symaddr(tok_id(), 8);
170 return;
172 if (!tok_jmp('(')) {
173 readexpr();
174 tok_expect(')');
175 return;
179 void arrayderef(unsigned bt)
181 if (BT_SZ(bt) > 1) {
182 o_num(BT_SZ(bt), 4);
183 o_mul();
185 o_add();
186 o_deref(bt);
189 static void inc_post(void (*op)(void))
191 struct type *t = &ts[nts - 1];
192 o_tmpcopy();
193 o_load();
194 o_tmpswap();
195 o_tmpcopy();
196 o_num(1, 4);
197 op();
198 o_assign(t->bt);
199 o_tmpdrop(1);
200 return;
203 static void readpost(void)
205 readprimary();
206 if (!tok_jmp('[')) {
207 struct type t1;
208 ts_pop(&t1);
209 readexpr();
210 ts_pop(NULL);
211 tok_expect(']');
212 arrayderef(TYPE_DEREF_BT(&t1));
213 t1.ptr--;
214 ts_push(&t1);
215 return;
217 if (!tok_jmp('(')) {
218 int argc = 0;
219 unsigned bt[MAXARGS];
220 if (tok_see() != ')') {
221 readexpr();
222 bt[argc++] = 4 | BT_SIGNED;
223 ts_pop(NULL);
225 while (!tok_jmp(',')) {
226 readexpr();
227 bt[argc++] = 4 | BT_SIGNED;
228 ts_pop(NULL);
230 tok_expect(')');
231 ts_pop(NULL);
232 o_call(argc, bt, 4 | BT_SIGNED);
233 ts_push_bt(4 | BT_SIGNED);
234 return;
236 if (!tok_jmp(TOK2("++"))) {
237 inc_post(o_add);
238 return;
240 if (!tok_jmp(TOK2("--"))) {
241 inc_post(o_sub);
242 return;
246 static void inc_pre(void (*op)(void))
248 struct type *t = &ts[nts - 1];
249 readpost();
250 o_tmpcopy();
251 o_num(1, 4);
252 op();
253 o_assign(t->bt);
256 static void readpre(void)
258 if (!tok_jmp('&')) {
259 struct type type;
260 readpost();
261 ts_pop(&type);
262 type.ptr++;
263 ts_push(&type);
264 o_addr();
265 return;
267 if (!tok_jmp('*')) {
268 struct type type;
269 readpost();
270 ts_pop(&type);
271 type.ptr--;
272 ts_push(&type);
273 o_deref(TYPE_BT(&type));
274 return;
276 if (!tok_jmp('!')) {
277 struct type type;
278 readpost();
279 ts_pop(&type);
280 o_num(0, TYPE_BT(&type));
281 o_eq();
282 ts_push_bt(4 | BT_SIGNED);
283 return;
285 if (!tok_jmp('-')) {
286 readpost();
287 o_neg();
288 return;
290 if (!tok_jmp('~')) {
291 readpost();
292 o_not();
293 return;
295 if (!tok_jmp(TOK2("++"))) {
296 inc_pre(o_add);
297 return;
299 if (!tok_jmp(TOK2("--"))) {
300 inc_pre(o_sub);
301 return;
303 readpost();
306 static int shifts(int n)
308 int i = -1;
309 while (i++ < 16)
310 if (n == 1 << i)
311 break;
312 return i;
315 static unsigned bt_op(unsigned bt1, unsigned bt2)
317 unsigned s1 = BT_SZ(bt1);
318 unsigned s2 = BT_SZ(bt2);
319 return (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
322 static void ts_binop(void (*o_sth)(void))
324 struct type t1, t2;
325 ts_pop(&t1);
326 ts_pop(&t2);
327 o_sth();
328 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
331 static void ts_binop_add(void (*o_sth)(void))
333 struct type t1, t2;
334 ts_pop(&t1);
335 ts_pop(&t2);
336 if (!t1.ptr && !t2.ptr) {
337 o_sth();
338 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
339 return;
341 if (t1.ptr && !t2.ptr) {
342 struct type t = t2;
343 t2 = t1;
344 t1 = t;
345 o_tmpswap();
347 if (!t1.ptr && t2.ptr)
348 if (TYPE_DEREF_SZ(&t2) > 1) {
349 o_num(shifts(TYPE_DEREF_SZ(&t2)), 1);
350 o_shl();
352 o_sth();
353 if (t1.ptr && t2.ptr) {
354 o_num(shifts(TYPE_DEREF_SZ(&t1)), 1);
355 o_shr();
356 ts_push_bt(4 | BT_SIGNED);
357 } else {
358 ts_push(&t2);
362 static void readmul(void)
364 readpre();
365 while (1) {
366 if (!tok_jmp('*')) {
367 readpre();
368 ts_binop(o_mul);
369 continue;
371 if (!tok_jmp('/')) {
372 readpre();
373 ts_binop(o_div);
374 continue;
376 if (!tok_jmp('%')) {
377 readpre();
378 ts_binop(o_mod);
379 continue;
381 break;
385 static void readadd(void)
387 readmul();
388 while (1) {
389 if (!tok_jmp('+')) {
390 readmul();
391 ts_binop_add(o_add);
392 continue;
394 if (!tok_jmp('-')) {
395 readmul();
396 ts_binop_add(o_sub);
397 continue;
399 break;
403 static void shift(void (*op)(void))
405 struct type t;
406 readadd();
407 ts_pop(NULL);
408 ts_pop(&t);
409 op();
410 ts_push_bt(TYPE_BT(&t));
413 static void readshift(void)
415 readadd();
416 if (!tok_jmp(TOK2("<<"))) {
417 shift(o_shl);
418 return;
420 if (!tok_jmp(TOK2(">>"))) {
421 shift(o_shr);
422 return;
426 static void cmp(void (*op)(void))
428 readshift();
429 ts_pop(NULL);
430 ts_pop(NULL);
431 op();
432 ts_push_bt(4 | BT_SIGNED);
435 static void readcmp(void)
437 readshift();
438 if (!tok_jmp('<')) {
439 cmp(o_lt);
440 return;
442 if (!tok_jmp('>')) {
443 cmp(o_gt);
444 return;
446 if (!tok_jmp(TOK2("<="))) {
447 cmp(o_le);
448 return;
450 if (!tok_jmp(TOK2(">="))) {
451 cmp(o_ge);
452 return;
456 static void eq(void (*op)(void))
458 readcmp();
459 ts_pop(NULL);
460 ts_pop(NULL);
461 op();
462 ts_push_bt(4 | BT_SIGNED);
465 static void readeq(void)
467 readcmp();
468 if (!tok_jmp(TOK2("=="))) {
469 eq(o_eq);
470 return;
472 if (!tok_jmp(TOK2("!="))) {
473 eq(o_neq);
474 return;
478 static void readbitand(void)
480 readeq();
481 while (!tok_jmp('&')) {
482 readeq();
483 ts_binop(o_and);
487 static void readxor(void)
489 readbitand();
490 while (!tok_jmp('^')) {
491 readbitand();
492 ts_binop(o_xor);
496 static void readbitor(void)
498 readxor();
499 while (!tok_jmp('|')) {
500 readxor();
501 ts_binop(o_or);
505 #define MAXCOND (1 << 5)
507 static void readand(void)
509 long conds[MAXCOND];
510 int nconds = 0;
511 long passed;
512 int i;
513 readbitor();
514 if (tok_see() != TOK2("&&"))
515 return;
516 conds[nconds++] = o_jz(0);
517 ts_pop(NULL);
518 while (!tok_jmp(TOK2("&&"))) {
519 readbitor();
520 conds[nconds++] = o_jz(0);
521 ts_pop(NULL);
523 o_num(1, 4 | BT_SIGNED);
524 o_tmpfork();
525 passed = o_jmp(0);
526 for (i = 0; i < nconds; i++)
527 o_filljmp(conds[i]);
528 o_num(0, 4 | BT_SIGNED);
529 o_tmpjoin();
530 o_filljmp(passed);
531 ts_push_bt(4 | BT_SIGNED);
534 static void reador(void)
536 long conds[MAXCOND];
537 int nconds = 0;
538 long failed;
539 int i;
540 readand();
541 if (tok_see() != TOK2("||"))
542 return;
543 conds[nconds++] = o_jnz(0);
544 ts_pop(NULL);
545 while (!tok_jmp(TOK2("||"))) {
546 readand();
547 conds[nconds++] = o_jnz(0);
548 ts_pop(NULL);
550 o_num(0, 4 | BT_SIGNED);
551 o_tmpfork();
552 failed = o_jmp(0);
553 for (i = 0; i < nconds; i++)
554 o_filljmp(conds[i]);
555 o_num(1, 4 | BT_SIGNED);
556 o_tmpjoin();
557 o_filljmp(failed);
558 ts_push_bt(4 | BT_SIGNED);
561 static void readcexpr(void)
563 reador();
564 if (!tok_jmp('?')) {
565 long l1, l2;
566 l1 = o_jz(0);
567 ts_pop(NULL);
568 reador();
569 o_tmpfork();
570 l2 = o_jmp(0);
571 ts_pop(NULL);
572 tok_expect(':');
573 o_filljmp(l1);
574 reador();
575 o_tmpjoin();
576 o_filljmp(l2);
580 static void opassign(void (*op)(void))
582 o_tmpcopy();
583 readexpr();
584 op();
585 ts_pop(NULL);
586 o_assign(TYPE_BT(&ts[nts - 1]));
589 static void readexpr(void)
591 readcexpr();
592 if (!tok_jmp('=')) {
593 readexpr();
594 ts_pop(NULL);
595 o_assign(TYPE_BT(&ts[nts - 1]));
596 return;
598 if (!tok_jmp(TOK2("+="))) {
599 opassign(o_add);
600 return;
602 if (!tok_jmp(TOK2("-="))) {
603 opassign(o_sub);
604 return;
606 if (!tok_jmp(TOK2("*="))) {
607 opassign(o_mul);
608 return;
610 if (!tok_jmp(TOK2("/="))) {
611 opassign(o_div);
612 return;
614 if (!tok_jmp(TOK2("%="))) {
615 opassign(o_mod);
616 return;
618 if (!tok_jmp(TOK3("<<="))) {
619 opassign(o_shl);
620 return;
622 if (!tok_jmp(TOK3(">>="))) {
623 opassign(o_shr);
624 return;
626 if (!tok_jmp(TOK3("&="))) {
627 opassign(o_and);
628 return;
630 if (!tok_jmp(TOK3("|="))) {
631 opassign(o_or);
632 return;
634 if (!tok_jmp(TOK3("^="))) {
635 opassign(o_xor);
636 return;
640 static void readestmt(void)
642 do {
643 o_tmpdrop(-1);
644 nts = 0;
645 readexpr();
646 } while (!tok_jmp(','));
649 static void readstmt(void)
651 struct type base = {0};
652 o_tmpdrop(-1);
653 nts = 0;
654 if (!tok_jmp('{')) {
655 while (tok_jmp('}'))
656 readstmt();
657 return;
659 if (!basetype(&base)) {
660 struct type type = base;
661 char name[NAMELEN];
662 int n = 1;
663 readptrs(&type);
664 tok_expect(TOK_NAME);
665 strcpy(name, tok_id());
666 if (!tok_jmp('[')) {
667 tok_expect(TOK_NUM);
668 n = atoi(tok_id());
669 type.ptr++;
670 type.flags = T_ARRAY;
671 tok_expect(']');
673 local_add(name, o_mklocal(TYPE_SZ(&type) * n), type);
674 /* initializer */
675 if (!tok_jmp('=')) {
676 struct type *t = &locals[nlocals - 1].type;
677 o_local(locals[nlocals - 1].addr, TYPE_BT(t));
678 readexpr();
679 ts_pop(NULL);
680 ts_push_bt(TYPE_BT(t));
681 o_assign(TYPE_BT(t));
683 tok_expect(';');
684 return;
686 if (!tok_jmp(TOK_IF)) {
687 long l1, l2;
688 tok_expect('(');
689 readexpr();
690 tok_expect(')');
691 l1 = o_jz(0);
692 readstmt();
693 if (!tok_jmp(TOK_ELSE)) {
694 l2 = o_jmp(0);
695 o_filljmp(l1);
696 readstmt();
697 o_filljmp(l2);
698 } else {
699 o_filljmp(l1);
701 return;
703 if (!tok_jmp(TOK_WHILE)) {
704 long l1, l2;
705 l1 = o_mklabel();
706 tok_expect('(');
707 readexpr();
708 tok_expect(')');
709 l2 = o_jz(0);
710 readstmt();
711 o_jz(l1);
712 o_filljmp(l2);
713 return;
715 if (!tok_jmp(TOK_FOR)) {
716 long check, jump, end, body;
717 tok_expect('(');
718 if (tok_see() != ';')
719 readestmt();
720 tok_expect(';');
721 check = o_mklabel();
722 if (tok_see() != ';')
723 readestmt();
724 tok_expect(';');
725 end = o_jz(0);
726 body = o_jmp(0);
727 jump = o_mklabel();
728 if (tok_see() != ')')
729 readestmt();
730 tok_expect(')');
731 o_jmp(check);
732 o_filljmp(body);
733 readstmt();
734 o_jmp(jump);
735 o_filljmp(end);
736 return;
738 if (!tok_jmp(TOK_RETURN)) {
739 int ret = tok_see() != ';';
740 if (ret)
741 readexpr();
742 tok_expect(';');
743 o_ret(4 | BT_SIGNED);
744 return;
746 readestmt();
747 tok_expect(';');
750 static void readdecl(void)
752 char name[NAMELEN];
753 struct type type;
754 readtype(&type);
755 tok_expect(TOK_NAME);
756 strcpy(name, tok_id());
757 if (!tok_jmp(';'))
758 return;
759 if (!tok_jmp('(')) {
760 /* read args */
761 char args[MAXARGS][NAMELEN];
762 struct type types[MAXARGS];
763 int nargs = 0;
764 int i;
765 while (tok_see() != ')') {
766 readtype(&types[nargs]);
767 if (!tok_jmp(TOK_NAME))
768 strcpy(args[nargs++], tok_id());
769 if (tok_jmp(','))
770 break;
772 tok_expect(')');
773 if (!tok_jmp(';'))
774 return;
775 o_func_beg(name);
776 for (i = 0; i < nargs; i++)
777 local_add(args[i], o_arg(i, TYPE_BT(&types[i])),
778 types[i]);
779 readstmt();
780 o_func_end();
781 return;
783 die("syntax error\n");
786 static void parse(void)
788 while (tok_see() != TOK_EOF)
789 readdecl();
792 int main(int argc, char *argv[])
794 char obj[128];
795 char *src = argv[1];
796 int ifd, ofd;
797 ifd = open(src, O_RDONLY);
798 tok_init(ifd);
799 close(ifd);
800 parse();
802 strcpy(obj, src);
803 obj[strlen(obj) - 1] = 'o';
804 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
805 out_write(ofd);
806 close(ofd);
807 return 0;