handle struct assignment
[neatcc.git] / ncc.c
blob8f01bd5a7860a78e58348a6fc25ae3e4a220a8e5
1 /*
2 * neatcc - A small and simple x86_64 C compiler
4 * Copyright (C) 2010 Ali Gholami Rudi
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License, as published by the
8 * Free Software Foundation.
9 */
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include "gen.h"
17 #include "tok.h"
19 #define MAXLOCALS (1 << 10)
20 #define MAXGLOBALS (1 << 10)
21 #define MAXARGS (1 << 5)
22 #define print(s) write(2, (s), strlen(s));
24 #define TYPE_BT(t) ((t)->ptr ? 8 : (t)->bt)
25 #define TYPE_SZ(t) ((t)->ptr ? 8 : (t)->bt & BT_SZMASK)
27 #define T_ARRAY 0x01
28 #define T_STRUCT 0x02
29 #define T_FUNC 0x04
31 #define F_INIT 0x01
32 #define F_STATIC 0x02
34 struct type {
35 unsigned bt;
36 unsigned flags;
37 int ptr;
38 int id; /* for structs, functions and arrays */
41 /* type stack */
42 static struct type ts[MAXTMP];
43 static int nts;
45 static void ts_push_bt(unsigned bt)
47 ts[nts].ptr = 0;
48 ts[nts].flags = 0;
49 ts[nts++].bt = bt;
52 static void ts_push(struct type *t)
54 memcpy(&ts[nts++], t, sizeof(*t));
55 if (t->flags & (T_FUNC | T_ARRAY) && !t->ptr)
56 o_addr();
59 static void ts_pop(struct type *type)
61 nts--;
62 if (type)
63 *type = ts[nts];
66 struct name {
67 char name[NAMELEN];
68 struct type type;
69 long addr;
72 static struct name locals[MAXLOCALS];
73 static int nlocals;
74 static struct name globals[MAXGLOBALS];
75 static int nglobals;
77 static void local_add(struct name *name)
79 memcpy(&locals[nlocals++], name, sizeof(*name));
82 static int global_find(char *name)
84 int i;
85 for (i = 0; i < nglobals; i++)
86 if (!strcmp(name, globals[i].name))
87 return i;
88 return -1;
91 static void global_add(struct name *name)
93 int found = global_find(name->name);
94 int i = found == -1 ? nglobals++ : found;
95 memcpy(&globals[i], name, sizeof(*name));
98 static void die(char *s)
100 print(s);
101 exit(1);
104 #define MAXENUMS (1 << 10)
106 static struct enumval {
107 char name[NAMELEN];
108 int n;
109 } enums[MAXENUMS];
110 static int nenums;
112 static void enum_add(char *name, int val)
114 struct enumval *ev = &enums[nenums++];
115 strcpy(ev->name, name);
116 ev->n = val;
119 static int enum_find(int *val, char *name)
121 int i;
122 for (i = nenums - 1; i >= 0; --i)
123 if (!strcmp(name, enums[i].name)) {
124 *val = enums[i].n;
125 return 0;
127 return 1;
130 #define MAXTYPEDEFS (1 << 5)
132 static struct typdefinfo {
133 char name[NAMELEN];
134 struct type type;
135 } typedefs[MAXTYPEDEFS];
136 static int ntypedefs;
138 static void typedef_add(char *name, struct type *type)
140 struct typdefinfo *ti = &typedefs[ntypedefs++];
141 strcpy(ti->name, name);
142 memcpy(&ti->type, type, sizeof(*type));
145 static int typedef_find(char *name)
147 int i;
148 for (i = ntypedefs - 1; i >= 0; --i)
149 if (!strcmp(name, typedefs[i].name))
150 return i;
151 return -1;
154 #define MAXARRAYS (1 << 5)
156 static struct array {
157 struct type type;
158 int n;
159 } arrays[MAXARRAYS];
160 static int narrays;
162 static int array_add(struct type *type, int n)
164 struct array *a = &arrays[narrays++];
165 memcpy(&a->type, type, sizeof(*type));
166 a->n = n;
167 return a - arrays;
170 static void array2ptr(struct type *t)
172 if (!(t->flags & T_ARRAY) || t->ptr)
173 return;
174 memcpy(t, &arrays[t->id].type, sizeof(*t));
175 t->ptr++;
178 #define MAXTYPES (1 << 7)
179 #define MAXFIELDS (1 << 5)
181 static struct structinfo {
182 char name[NAMELEN];
183 struct name fields[MAXFIELDS];
184 int nfields;
185 int isunion;
186 int size;
187 } structs[MAXTYPES];
188 static int nstructs;
190 static int struct_find(char *name, int isunion)
192 int i;
193 for (i = nstructs - 1; i >= 0; --i)
194 if (!strcmp(name, structs[i].name) &&
195 structs[i].isunion == isunion)
196 return i;
197 die("struct not found\n");
200 static struct name *struct_field(int id, char *name)
202 struct structinfo *si = &structs[id];
203 int i;
204 for (i = 0; i < si->nfields; i++)
205 if (!strcmp(name, si->fields[i].name))
206 return &si->fields[i];
207 die("field not found\n");
210 #define MAXBREAK (1 << 7)
211 static long breaks[MAXBREAK];
212 static int nbreaks;
213 static long continues[MAXBREAK];
214 static int ncontinues;
216 static void break_fill(long addr, int till)
218 int i;
219 for (i = till; i < nbreaks; i++)
220 o_filljmp2(breaks[i], addr);
221 nbreaks = till;
224 static void continue_fill(long addr, int till)
226 int i;
227 for (i = till; i < ncontinues; i++)
228 o_filljmp2(continues[i], addr);
229 ncontinues = till;
232 static int type_totsz(struct type *t)
234 if (t->ptr)
235 return 8;
236 if (t->flags & T_ARRAY)
237 return arrays[t->id].n * type_totsz(&arrays[t->id].type);
238 return t->flags & T_STRUCT ? structs[t->id].size : BT_SZ(t->bt);
241 static unsigned type_szde(struct type *t)
243 if (t->flags & T_ARRAY)
244 return t->ptr > 0 ? 8 : TYPE_SZ(&arrays[t->id].type);
245 else
246 return t->ptr > 1 ? 8 : BT_SZ(t->bt);
249 static int tok_jmp(int tok)
251 if (tok_see() != tok)
252 return 1;
253 tok_get();
254 return 0;
257 static void tok_expect(int tok)
259 if (tok_get() != tok)
260 die("syntax error\n");
263 static unsigned bt_op(unsigned bt1, unsigned bt2)
265 unsigned s1 = BT_SZ(bt1);
266 unsigned s2 = BT_SZ(bt2);
267 return (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
270 static void ts_binop(void (*o_sth)(void))
272 struct type t1, t2;
273 ts_pop(&t1);
274 ts_pop(&t2);
275 o_sth();
276 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
279 static int shifts(int n)
281 int i = -1;
282 while (i++ < 16)
283 if (n == 1 << i)
284 break;
285 return i;
288 static void ts_binop_add(void (*o_sth)(void))
290 struct type t1, t2;
291 ts_pop(&t1);
292 ts_pop(&t2);
293 array2ptr(&t1);
294 array2ptr(&t2);
295 if (!t1.ptr && !t2.ptr) {
296 o_sth();
297 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
298 return;
300 if (t1.ptr && !t2.ptr) {
301 struct type t = t2;
302 t2 = t1;
303 t1 = t;
304 o_tmpswap();
306 if (!t1.ptr && t2.ptr)
307 if (type_szde(&t2) > 1) {
308 o_num(shifts(type_szde(&t2)), 1);
309 o_shl();
311 o_sth();
312 if (t1.ptr && t2.ptr) {
313 o_num(shifts(type_szde(&t1)), 1);
314 o_shr();
315 ts_push_bt(4 | BT_SIGNED);
316 } else {
317 ts_push(&t2);
321 static void structdef(void *data, struct name *name, unsigned flags)
323 struct structinfo *si = data;
324 if (si->isunion) {
325 name->addr = 0;
326 if (si->size < type_totsz(&name->type))
327 si->size = type_totsz(&name->type);
328 } else {
329 name->addr = si->size;
330 si->size += type_totsz(&name->type);
332 memcpy(&si->fields[si->nfields++], name, sizeof(*name));
335 static int readdefs(void (*def)(void *, struct name *, unsigned f), void *data);
337 static int struct_create(char *name, int isunion)
339 int id = nstructs++;
340 struct structinfo *si = &structs[id];
341 strcpy(si->name, name);
342 si->isunion = isunion;
343 tok_expect('{');
344 while (tok_jmp('}')) {
345 readdefs(structdef, si);
346 tok_expect(';');
348 return id;
351 static void readexpr(void);
353 static void enum_create(void)
355 long n = 0;
356 tok_expect('{');
357 while (tok_jmp('}')) {
358 char name[NAMELEN];
359 tok_expect(TOK_NAME);
360 strcpy(name, tok_id());
361 if (tok_see() == '=') {
362 tok_get();
363 readexpr();
364 ts_pop(NULL);
365 if (o_popnum(&n))
366 die("const expr expected!\n");
368 enum_add(name, n++);
369 tok_jmp(',');
373 static int basetype(struct type *type, unsigned *flags)
375 int sign = 1;
376 int size = 4;
377 int done = 0;
378 int i = 0;
379 int isunion;
380 char name[NAMELEN];
381 *flags = 0;
382 type->flags = 0;
383 type->ptr = 0;
384 while (!done) {
385 switch (tok_see()) {
386 case TOK_STATIC:
387 *flags |= F_STATIC;
388 break;
389 case TOK_VOID:
390 sign = 0;
391 size = 0;
392 done = 1;
393 break;
394 case TOK_INT:
395 done = 1;
396 break;
397 case TOK_CHAR:
398 size = 1;
399 done = 1;
400 break;
401 case TOK_SHORT:
402 size = 2;
403 break;
404 case TOK_LONG:
405 size = 8;
406 break;
407 case TOK_UNSIGNED:
408 sign = 0;
409 break;
410 case TOK_UNION:
411 case TOK_STRUCT:
412 isunion = tok_get() == TOK_UNION;
413 tok_expect(TOK_NAME);
414 strcpy(name, tok_id());
415 if (tok_see() == '{')
416 type->id = struct_create(name, isunion);
417 else
418 type->id = struct_find(name, isunion);
419 type->flags |= T_STRUCT;
420 type->bt = 8;
421 return 0;
422 case TOK_ENUM:
423 tok_get();
424 tok_expect(TOK_NAME);
425 if (tok_see() == '{')
426 enum_create();
427 type->bt = 4 | BT_SIGNED;
428 return 0;
429 default:
430 if (tok_see() == TOK_NAME) {
431 int id = typedef_find(tok_id());
432 if (id != -1) {
433 tok_get();
434 memcpy(type, &typedefs[id].type,
435 sizeof(*type));
436 return 0;
439 if (!i)
440 return 1;
441 done = 1;
442 continue;
444 i++;
445 tok_get();
447 type->bt = size | (sign ? BT_SIGNED : 0);
448 return 0;
451 static void readptrs(struct type *type)
453 while (!tok_jmp('*'))
454 type->ptr++;
457 static int readtype(struct type *type)
459 unsigned flags;
460 if (basetype(type, &flags))
461 return 1;
462 readptrs(type);
463 return 0;
466 static void readpre(void);
468 static void readprimary(void)
470 struct name name;
471 int i;
472 if (!tok_jmp(TOK_NUM)) {
473 ts_push_bt(4 | BT_SIGNED);
474 o_num(tok_num(), 4 | BT_SIGNED);
475 return;
477 if (!tok_jmp(TOK_STR)) {
478 struct type t;
479 char buf[BUFSIZE];
480 int len;
481 t.bt = 1 | BT_SIGNED;
482 t.ptr = 1;
483 t.flags = 0;
484 ts_push(&t);
485 len = tok_str(buf);
486 o_symaddr(o_mkdat(NULL, buf, len, 0), TYPE_BT(&t));
487 o_addr();
488 return;
490 if (!tok_jmp(TOK_NAME)) {
491 int n;
492 for (i = nlocals - 1; i >= 0; --i) {
493 struct type *t = &locals[i].type;
494 if (!strcmp(locals[i].name, tok_id())) {
495 o_local(locals[i].addr, TYPE_BT(t));
496 ts_push(t);
497 return;
500 if ((n = global_find(tok_id())) != -1) {
501 struct type *t = &globals[n].type;
502 o_symaddr(globals[n].addr, TYPE_BT(t));
503 ts_push(t);
504 return;
506 if (!enum_find(&n, tok_id())) {
507 ts_push_bt(4 | BT_SIGNED);
508 o_num(n, 4 | BT_SIGNED);
509 return;
511 strcpy(name.name, tok_id());
512 name.addr = o_mkundef(name.name);
513 global_add(&name);
514 ts_push_bt(8);
515 o_symaddr(name.addr, 8);
516 return;
518 if (!tok_jmp('(')) {
519 struct type t;
520 if (!readtype(&t)) {
521 struct type o;
522 tok_expect(')');
523 readpre();
524 ts_pop(&o);
525 ts_push(&t);
526 if (!t.ptr || !o.ptr)
527 o_cast(TYPE_BT(&t));
528 } else {
529 readexpr();
530 tok_expect(')');
532 return;
536 void arrayderef(struct type *t)
538 int sz = type_totsz(t);
539 if (sz > 1) {
540 o_num(sz, 4);
541 o_mul();
543 o_add();
544 o_deref(TYPE_BT(t));
547 static void inc_post(void (*op)(void))
549 unsigned bt = TYPE_BT(&ts[nts - 1]);
550 o_tmpcopy();
551 o_load();
552 o_tmpswap();
553 o_tmpcopy();
554 o_num(1, 4);
555 ts_push_bt(bt);
556 ts_push_bt(bt);
557 ts_binop_add(op);
558 ts_pop(NULL);
559 o_assign(bt);
560 o_tmpdrop(1);
563 static void readfield(void)
565 struct name *field;
566 struct type t;
567 tok_expect(TOK_NAME);
568 ts_pop(&t);
569 field = struct_field(t.id, tok_id());
570 if (field->addr) {
571 o_num(field->addr, 4);
572 o_add();
574 o_deref(TYPE_BT(&field->type));
575 ts_push(&field->type);
578 #define MAXFUNCS (1 << 10)
580 static struct funcinfo {
581 struct type args[MAXFIELDS];
582 struct type ret;
583 int nargs;
584 } funcs[MAXFUNCS];
585 static int nfuncs;
586 static unsigned ret_bt;
588 static int func_create(struct type *ret, struct name *args, int nargs)
590 struct funcinfo *fi = &funcs[nfuncs++];
591 int i;
592 memcpy(&fi->ret, ret, sizeof(*ret));
593 for (i = 0; i < nargs; i++)
594 memcpy(&fi->args[i], &args[i].type, sizeof(*ret));
595 fi->nargs = nargs;
596 return fi - funcs;
599 static void readcall(void)
601 struct type t;
602 unsigned bt[MAXARGS];
603 struct funcinfo *fi;
604 int argc = 0;
605 int i;
606 if (tok_see() != ')') {
607 readexpr();
608 ts_pop(&t);
609 bt[argc++] = TYPE_BT(&t);
611 while (!tok_jmp(',')) {
612 readexpr();
613 ts_pop(&t);
614 bt[argc++] = TYPE_BT(&t);
616 tok_expect(')');
617 ts_pop(&t);
618 if (t.flags & T_FUNC && t.ptr > 0)
619 o_deref(8);
620 fi = t.flags & T_FUNC ? &funcs[t.id] : NULL;
621 if (fi)
622 for (i = 0; i < fi->nargs; i++)
623 bt[i] = TYPE_BT(&fi->args[i]);
624 o_call(argc, bt, fi ? TYPE_BT(&fi->ret) : 4 | BT_SIGNED);
625 if (fi)
626 ts_push(&fi->ret);
627 else
628 ts_push_bt(4 | BT_SIGNED);
631 static void readpost(void)
633 readprimary();
634 while (1) {
635 if (!tok_jmp('[')) {
636 struct type t;
637 ts_pop(&t);
638 readexpr();
639 ts_pop(NULL);
640 tok_expect(']');
641 array2ptr(&t);
642 t.ptr--;
643 arrayderef(&t);
644 ts_push(&t);
645 continue;
647 if (!tok_jmp('(')) {
648 readcall();
649 continue;
651 if (!tok_jmp(TOK2("++"))) {
652 inc_post(o_add);
653 continue;
655 if (!tok_jmp(TOK2("--"))) {
656 inc_post(o_sub);
657 continue;
659 if (!tok_jmp('.')) {
660 o_addr();
661 readfield();
662 continue;
664 if (!tok_jmp(TOK2("->"))) {
665 readfield();
666 continue;
668 break;
672 static void inc_pre(void (*op)(void))
674 unsigned bt = TYPE_BT(&ts[nts - 1]);
675 readpre();
676 o_tmpcopy();
677 o_num(1, 4);
678 ts_push_bt(bt);
679 ts_push_bt(bt);
680 ts_binop_add(op);
681 ts_pop(NULL);
682 o_assign(bt);
685 static void readpre(void)
687 if (!tok_jmp('&')) {
688 struct type type;
689 readpre();
690 ts_pop(&type);
691 if (!(type.flags & T_FUNC) && !type.ptr)
692 type.ptr++;
693 ts_push(&type);
694 o_addr();
695 return;
697 if (!tok_jmp('*')) {
698 struct type t;
699 readpre();
700 ts_pop(&t);
701 array2ptr(&t);
702 if (!(t.flags & T_FUNC) || t.ptr > 0) {
703 t.ptr--;
704 o_deref(TYPE_BT(&t));
706 ts_push(&t);
707 return;
709 if (!tok_jmp('!')) {
710 struct type type;
711 readpre();
712 ts_pop(&type);
713 o_lnot();
714 ts_push_bt(4 | BT_SIGNED);
715 return;
717 if (!tok_jmp('-')) {
718 readpre();
719 o_neg();
720 return;
722 if (!tok_jmp('~')) {
723 readpre();
724 o_not();
725 return;
727 if (!tok_jmp(TOK2("++"))) {
728 inc_pre(o_add);
729 return;
731 if (!tok_jmp(TOK2("--"))) {
732 inc_pre(o_sub);
733 return;
735 if (!tok_jmp(TOK_SIZEOF)) {
736 struct type t;
737 int op = !tok_jmp('(');
738 if (readtype(&t)) {
739 int nogen = !o_nogen();
740 readexpr();
741 if (nogen)
742 o_dogen();
743 ts_pop(&t);
744 o_tmpdrop(1);
746 ts_push_bt(4);
747 o_num(type_totsz(&t), 4);
748 if (op)
749 tok_expect(')');
750 return;
752 readpost();
755 static void readmul(void)
757 readpre();
758 while (1) {
759 if (!tok_jmp('*')) {
760 readpre();
761 ts_binop(o_mul);
762 continue;
764 if (!tok_jmp('/')) {
765 readpre();
766 ts_binop(o_div);
767 continue;
769 if (!tok_jmp('%')) {
770 readpre();
771 ts_binop(o_mod);
772 continue;
774 break;
778 static void readadd(void)
780 readmul();
781 while (1) {
782 if (!tok_jmp('+')) {
783 readmul();
784 ts_binop_add(o_add);
785 continue;
787 if (!tok_jmp('-')) {
788 readmul();
789 ts_binop_add(o_sub);
790 continue;
792 break;
796 static void shift(void (*op)(void))
798 struct type t;
799 readadd();
800 ts_pop(NULL);
801 ts_pop(&t);
802 op();
803 ts_push_bt(TYPE_BT(&t));
806 static void readshift(void)
808 readadd();
809 while (1) {
810 if (!tok_jmp(TOK2("<<"))) {
811 shift(o_shl);
812 continue;
814 if (!tok_jmp(TOK2(">>"))) {
815 shift(o_shr);
816 continue;
818 break;
822 static void cmp(void (*op)(void))
824 readshift();
825 ts_pop(NULL);
826 ts_pop(NULL);
827 op();
828 ts_push_bt(4 | BT_SIGNED);
831 static void readcmp(void)
833 readshift();
834 while (1) {
835 if (!tok_jmp('<')) {
836 cmp(o_lt);
837 continue;
839 if (!tok_jmp('>')) {
840 cmp(o_gt);
841 continue;
843 if (!tok_jmp(TOK2("<="))) {
844 cmp(o_le);
845 continue;
847 if (!tok_jmp(TOK2(">="))) {
848 cmp(o_ge);
849 continue;
851 break;
855 static void eq(void (*op)(void))
857 readcmp();
858 ts_pop(NULL);
859 ts_pop(NULL);
860 op();
861 ts_push_bt(4 | BT_SIGNED);
864 static void readeq(void)
866 readcmp();
867 while (1) {
868 if (!tok_jmp(TOK2("=="))) {
869 eq(o_eq);
870 continue;
872 if (!tok_jmp(TOK2("!="))) {
873 eq(o_neq);
874 continue;
876 break;
880 static void readbitand(void)
882 readeq();
883 while (!tok_jmp('&')) {
884 readeq();
885 ts_binop(o_and);
889 static void readxor(void)
891 readbitand();
892 while (!tok_jmp('^')) {
893 readbitand();
894 ts_binop(o_xor);
898 static void readbitor(void)
900 readxor();
901 while (!tok_jmp('|')) {
902 readxor();
903 ts_binop(o_or);
907 #define MAXCOND (1 << 5)
909 static void readand(void)
911 long conds[MAXCOND];
912 int nconds = 0;
913 long passed;
914 int i;
915 readbitor();
916 if (tok_see() != TOK2("&&"))
917 return;
918 conds[nconds++] = o_jz(0);
919 ts_pop(NULL);
920 while (!tok_jmp(TOK2("&&"))) {
921 readbitor();
922 conds[nconds++] = o_jz(0);
923 ts_pop(NULL);
925 o_num(1, 4 | BT_SIGNED);
926 o_tmpfork();
927 passed = o_jmp(0);
928 for (i = 0; i < nconds; i++)
929 o_filljmp(conds[i]);
930 o_num(0, 4 | BT_SIGNED);
931 o_tmpjoin();
932 o_filljmp(passed);
933 ts_push_bt(4 | BT_SIGNED);
936 static void reador(void)
938 long conds[MAXCOND];
939 int nconds = 0;
940 long failed;
941 int i;
942 readand();
943 if (tok_see() != TOK2("||"))
944 return;
945 conds[nconds++] = o_jnz(0);
946 ts_pop(NULL);
947 while (!tok_jmp(TOK2("||"))) {
948 readand();
949 conds[nconds++] = o_jnz(0);
950 ts_pop(NULL);
952 o_num(0, 4 | BT_SIGNED);
953 o_tmpfork();
954 failed = o_jmp(0);
955 for (i = 0; i < nconds; i++)
956 o_filljmp(conds[i]);
957 o_num(1, 4 | BT_SIGNED);
958 o_tmpjoin();
959 o_filljmp(failed);
960 ts_push_bt(4 | BT_SIGNED);
963 static void readcexpr(void)
965 long l1, l2;
966 long c;
967 int cexpr, nogen;
968 reador();
969 if (tok_jmp('?'))
970 return;
971 cexpr = !o_popnum(&c);
972 ts_pop(NULL);
973 if (cexpr) {
974 if (!c)
975 nogen = !o_nogen();
976 } else {
977 l1 = o_jz(0);
979 reador();
980 if (!cexpr) {
981 o_tmpfork();
982 l2 = o_jmp(0);
984 ts_pop(NULL);
985 tok_expect(':');
986 if (cexpr) {
987 if (c) {
988 nogen = !o_nogen();
989 } else {
990 if (nogen)
991 o_dogen();
992 o_tmpdrop(1);
994 } else {
995 o_filljmp(l1);
997 reador();
998 if (cexpr) {
999 if (c) {
1000 if (nogen)
1001 o_dogen();
1002 o_tmpdrop(1);
1004 } else {
1005 o_tmpjoin();
1006 o_filljmp(l2);
1010 static void opassign(void (*bop)(void (*op)(void)), void (*op)(void))
1012 unsigned bt = TYPE_BT(&ts[nts - 1]);
1013 o_tmpcopy();
1014 readexpr();
1015 bop(op);
1016 ts_pop(NULL);
1017 o_assign(bt);
1020 static void readexpr(void)
1022 readcexpr();
1023 if (!tok_jmp('=')) {
1024 struct type t;
1025 readexpr();
1026 ts_pop(&t);
1027 if (t.flags & (T_STRUCT))
1028 o_memcpy(type_totsz(&t));
1029 else
1030 o_assign(TYPE_BT(&ts[nts - 1]));
1031 return;
1033 if (!tok_jmp(TOK2("+="))) {
1034 opassign(ts_binop_add, o_add);
1035 return;
1037 if (!tok_jmp(TOK2("-="))) {
1038 opassign(ts_binop_add, o_sub);
1039 return;
1041 if (!tok_jmp(TOK2("*="))) {
1042 opassign(ts_binop, o_mul);
1043 return;
1045 if (!tok_jmp(TOK2("/="))) {
1046 opassign(ts_binop, o_div);
1047 return;
1049 if (!tok_jmp(TOK2("%="))) {
1050 opassign(ts_binop, o_mod);
1051 return;
1053 if (!tok_jmp(TOK3("<<="))) {
1054 opassign(ts_binop, o_shl);
1055 return;
1057 if (!tok_jmp(TOK3(">>="))) {
1058 opassign(ts_binop, o_shr);
1059 return;
1061 if (!tok_jmp(TOK3("&="))) {
1062 opassign(ts_binop, o_and);
1063 return;
1065 if (!tok_jmp(TOK3("|="))) {
1066 opassign(ts_binop, o_or);
1067 return;
1069 if (!tok_jmp(TOK3("^="))) {
1070 opassign(ts_binop, o_xor);
1071 return;
1075 static void readestmt(void)
1077 do {
1078 o_tmpdrop(-1);
1079 nts = 0;
1080 readexpr();
1081 } while (!tok_jmp(','));
1084 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1086 static void globaldef(void *data, struct name *name, unsigned flags)
1088 char *varname = flags & F_STATIC ? NULL : name->name;
1089 name->addr = o_mkvar(varname, type_totsz(&name->type), F_GLOBAL(flags));
1090 global_add(name);
1093 static void localdef(void *data, struct name *name, unsigned flags)
1095 if (flags & F_STATIC) {
1096 globaldef(data, name, flags);
1097 return;
1099 name->addr = o_mklocal(type_totsz(&name->type));
1100 local_add(name);
1101 if (flags & F_INIT) {
1102 struct type *t = &name->type;
1103 o_local(locals[nlocals - 1].addr, TYPE_BT(t));
1104 readexpr();
1105 o_assign(TYPE_BT(t));
1109 static void funcdef(struct name *name, struct name *args,
1110 int nargs, unsigned flags)
1112 int i;
1113 name->addr = o_func_beg(name->name, F_GLOBAL(flags));
1114 global_add(name);
1115 ret_bt = TYPE_BT(&funcs[name->type.id].ret);
1116 for (i = 0; i < nargs; i++) {
1117 args[i].addr = o_arg(i, type_totsz(&args[i].type));
1118 local_add(&args[i]);
1122 static int readargs(struct name *args)
1124 int nargs = 0;
1125 tok_expect('(');
1126 while (tok_see() != ')') {
1127 readtype(&args[nargs].type);
1128 if (!tok_jmp(TOK_NAME))
1129 strcpy(args[nargs++].name, tok_id());
1130 if (tok_jmp(','))
1131 break;
1133 tok_expect(')');
1134 return nargs;
1137 static int readdefs(void (*def)(void *data, struct name *name, unsigned flags),
1138 void *data)
1140 struct type base;
1141 unsigned flags;
1142 if (basetype(&base, &flags))
1143 return 1;
1144 while (tok_see() != ';' && tok_see() != '{') {
1145 struct type tpool[3];
1146 struct name name;
1147 int npool = 0;
1148 struct type *type = &tpool[npool++];
1149 struct type *func = NULL;
1150 struct type *ret = NULL;
1151 memset(tpool, 0, sizeof(tpool));
1152 memcpy(type, &base, sizeof(base));
1153 readptrs(type);
1154 if (!tok_jmp('(')) {
1155 ret = type;
1156 type = &tpool[npool++];
1157 func = type;
1158 readptrs(type);
1160 tok_expect(TOK_NAME);
1161 strcpy(name.name, tok_id());
1162 while (!tok_jmp('[')) {
1163 long n;
1164 readexpr();
1165 ts_pop(NULL);
1166 if (o_popnum(&n))
1167 die("const expr expected\n");
1168 type->id = array_add(type, n);
1169 if (type->flags & T_FUNC)
1170 func = &arrays[type->id].type;
1171 type->flags = T_ARRAY;
1172 type->bt = 8;
1173 type->ptr = 0;
1174 tok_expect(']');
1176 if (func)
1177 tok_expect(')');
1178 if (tok_see() == '(') {
1179 struct name args[MAXARGS];
1180 int nargs = readargs(args);
1181 int fdef = !func;
1182 if (!func) {
1183 ret = type;
1184 type = &tpool[npool++];
1185 func = type;
1187 func->flags = T_FUNC;
1188 func->bt = 8;
1189 func->id = func_create(ret, args, nargs);
1190 if (fdef && tok_see() == '{') {
1191 memcpy(&name.type, func, sizeof(*func));
1192 funcdef(&name, args, nargs, flags);
1193 return 0;
1196 memcpy(&name.type, type, sizeof(*type));
1197 if (!tok_jmp('='))
1198 flags |= F_INIT;
1199 def(data, &name, flags);
1200 tok_jmp(',');
1202 return 0;
1205 static void typedefdef(void *data, struct name *name, unsigned flags)
1207 typedef_add(name->name, &name->type);
1210 #define MAXCASES (1 << 7)
1212 static void readstmt(void);
1214 static void readswitch(void)
1216 int break_beg = nbreaks;
1217 long val_addr = o_mklocal(8);
1218 long matched[MAXCASES];
1219 int nmatched = 0;
1220 struct type t;
1221 long next;
1222 int ref = 1;
1223 int i;
1224 tok_expect('(');
1225 readexpr();
1226 ts_pop(&t);
1227 o_local(val_addr, TYPE_BT(&t));
1228 o_tmpswap();
1229 o_assign(TYPE_BT(&t));
1230 o_tmpdrop(1);
1231 tok_expect(')');
1232 tok_expect('{');
1233 while (tok_jmp('}')) {
1234 int n = 0;
1235 while (tok_see() == TOK_CASE || tok_see() == TOK_DEFAULT) {
1236 if (n++ > 0)
1237 matched[nmatched++] = o_jmp(0);
1238 if (!ref++)
1239 o_filljmp(next);
1240 if (!tok_jmp(TOK_CASE)) {
1241 readexpr();
1242 o_local(val_addr, TYPE_BT(&t));
1243 o_eq();
1244 next = o_jz(0);
1245 ref = 0;
1246 tok_expect(':');
1247 o_tmpdrop(1);
1248 ts_pop(NULL);
1249 continue;
1251 if (!tok_jmp(TOK_DEFAULT)) {
1252 tok_expect(':');
1253 continue;
1256 for (i = 0; i < nmatched; i++)
1257 o_filljmp(matched[i]);
1258 nmatched = 0;
1259 readstmt();
1261 o_rmlocal(val_addr, 8);
1262 if (!ref++)
1263 o_filljmp(next);
1264 break_fill(o_mklabel(), break_beg);
1267 static void readstmt(void)
1269 o_tmpdrop(-1);
1270 nts = 0;
1271 if (!tok_jmp('{')) {
1272 int _nlocals = nlocals;
1273 int _nglobals = nglobals;
1274 int _nenums = nenums;
1275 int _ntypedefs = ntypedefs;
1276 int _nstructs = nstructs;
1277 int _nfuncs = nfuncs;
1278 int _narrays = narrays;
1279 while (tok_jmp('}'))
1280 readstmt();
1281 nlocals = _nlocals;
1282 nenums = _nenums;
1283 ntypedefs = _ntypedefs;
1284 nstructs = _nstructs;
1285 nfuncs = _nfuncs;
1286 narrays = _narrays;
1287 nglobals = _nglobals;
1288 return;
1290 if (!readdefs(localdef, NULL)) {
1291 tok_expect(';');
1292 return;
1294 if (!tok_jmp(TOK_TYPEDEF)) {
1295 readdefs(typedefdef, NULL);
1296 tok_expect(';');
1297 return;
1299 if (!tok_jmp(TOK_IF)) {
1300 long l1, l2;
1301 tok_expect('(');
1302 readexpr();
1303 tok_expect(')');
1304 l1 = o_jz(0);
1305 readstmt();
1306 if (!tok_jmp(TOK_ELSE)) {
1307 l2 = o_jmp(0);
1308 o_filljmp(l1);
1309 readstmt();
1310 o_filljmp(l2);
1311 } else {
1312 o_filljmp(l1);
1314 return;
1316 if (!tok_jmp(TOK_WHILE)) {
1317 long l1, l2;
1318 int break_beg = nbreaks;
1319 int continue_beg = ncontinues;
1320 l1 = o_mklabel();
1321 tok_expect('(');
1322 readexpr();
1323 tok_expect(')');
1324 l2 = o_jz(0);
1325 readstmt();
1326 o_jmp(l1);
1327 o_filljmp(l2);
1328 break_fill(o_mklabel(), break_beg);
1329 continue_fill(l1, continue_beg);
1330 return;
1332 if (!tok_jmp(TOK_DO)) {
1333 long l1, l2;
1334 int break_beg = nbreaks;
1335 int continue_beg = ncontinues;
1336 l1 = o_mklabel();
1337 readstmt();
1338 tok_expect(TOK_WHILE);
1339 tok_expect('(');
1340 l2 = o_mklabel();
1341 readexpr();
1342 o_jnz(l1);
1343 tok_expect(')');
1344 break_fill(o_mklabel(), break_beg);
1345 continue_fill(l2, continue_beg);
1346 return;
1348 if (!tok_jmp(TOK_FOR)) {
1349 long check, jump, end, body;
1350 int break_beg = nbreaks;
1351 int continue_beg = ncontinues;
1352 tok_expect('(');
1353 if (tok_see() != ';')
1354 readestmt();
1355 tok_expect(';');
1356 check = o_mklabel();
1357 if (tok_see() != ';')
1358 readestmt();
1359 tok_expect(';');
1360 end = o_jz(0);
1361 body = o_jmp(0);
1362 jump = o_mklabel();
1363 if (tok_see() != ')')
1364 readestmt();
1365 tok_expect(')');
1366 o_jmp(check);
1367 o_filljmp(body);
1368 readstmt();
1369 o_jmp(jump);
1370 o_filljmp(end);
1371 break_fill(o_mklabel(), break_beg);
1372 continue_fill(jump, continue_beg);
1373 return;
1375 if (!tok_jmp(TOK_SWITCH)) {
1376 readswitch();
1377 return;
1379 if (!tok_jmp(TOK_RETURN)) {
1380 int ret = tok_see() != ';';
1381 if (ret)
1382 readexpr();
1383 tok_expect(';');
1384 o_ret(ret_bt);
1385 return;
1387 if (!tok_jmp(TOK_BREAK)) {
1388 tok_expect(';');
1389 breaks[nbreaks++] = o_jmp(0);
1390 return;
1392 if (!tok_jmp(TOK_CONTINUE)) {
1393 tok_expect(';');
1394 continues[ncontinues++] = o_jmp(0);
1395 return;
1397 readestmt();
1398 tok_expect(';');
1401 static void readdecl(void)
1403 if (!tok_jmp(TOK_TYPEDEF)) {
1404 readdefs(typedefdef, NULL);
1405 tok_expect(';');
1406 return;
1408 readdefs(globaldef, NULL);
1409 if (tok_see() == '{') {
1410 readstmt();
1411 o_func_end();
1412 nlocals = 0;
1413 return;
1415 tok_expect(';');
1418 static void parse(void)
1420 while (tok_see() != TOK_EOF)
1421 readdecl();
1424 int main(int argc, char *argv[])
1426 char obj[128];
1427 int ifd, ofd;
1428 int i = 1;
1429 while (i < argc && argv[i][0] == '-')
1430 i++;
1431 if (i == argc)
1432 die("no file given\n");
1433 ifd = open(argv[i], O_RDONLY);
1434 tok_init(ifd);
1435 close(ifd);
1436 parse();
1438 strcpy(obj, argv[i]);
1439 obj[strlen(obj) - 1] = 'o';
1440 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
1441 out_write(ofd);
1442 close(ofd);
1443 return 0;