function pointer arguments
[neatcc.git] / ncc.c
blob1e3b05554aae05749265e1393460c4eb9876f9d7
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 << 10)
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 << 10)
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 << 10)
179 #define MAXFIELDS (1 << 7)
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 (*structs[i].name && !strcmp(name, structs[i].name) &&
195 structs[i].isunion == isunion)
196 return i;
197 i = nstructs++;
198 memset(&structs[i], 0, sizeof(structs[i]));
199 strcpy(structs[i].name, name);
200 structs[i].isunion = isunion;
201 return i;
204 static struct name *struct_field(int id, char *name)
206 struct structinfo *si = &structs[id];
207 int i;
208 for (i = 0; i < si->nfields; i++)
209 if (!strcmp(name, si->fields[i].name))
210 return &si->fields[i];
211 die("field not found\n");
214 #define MAXBREAK (1 << 7)
216 static long breaks[MAXBREAK];
217 static int nbreaks;
218 static long continues[MAXBREAK];
219 static int ncontinues;
221 static void break_fill(long addr, int till)
223 int i;
224 for (i = till; i < nbreaks; i++)
225 o_filljmp2(breaks[i], addr);
226 nbreaks = till;
229 static void continue_fill(long addr, int till)
231 int i;
232 for (i = till; i < ncontinues; i++)
233 o_filljmp2(continues[i], addr);
234 ncontinues = till;
237 static int type_totsz(struct type *t)
239 if (t->ptr)
240 return 8;
241 if (t->flags & T_ARRAY)
242 return arrays[t->id].n * type_totsz(&arrays[t->id].type);
243 return t->flags & T_STRUCT ? structs[t->id].size : BT_SZ(t->bt);
246 static unsigned type_szde(struct type *t)
248 if (t->flags & T_ARRAY)
249 return t->ptr > 0 ? 8 : TYPE_SZ(&arrays[t->id].type);
250 else
251 return t->ptr > 1 ? 8 : BT_SZ(t->bt);
254 static int tok_jmp(int tok)
256 if (tok_see() != tok)
257 return 1;
258 tok_get();
259 return 0;
262 static void tok_expect(int tok)
264 if (tok_get() != tok)
265 die("syntax error\n");
268 static unsigned bt_op(unsigned bt1, unsigned bt2)
270 unsigned s1 = BT_SZ(bt1);
271 unsigned s2 = BT_SZ(bt2);
272 return (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
275 static void ts_binop(void (*o_sth)(void))
277 struct type t1, t2;
278 ts_pop(&t1);
279 ts_pop(&t2);
280 o_sth();
281 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
284 static int shifts(int n)
286 int i = -1;
287 while (i++ < 16)
288 if (n == 1 << i)
289 break;
290 return i;
293 static void ts_binop_add(void (*o_sth)(void))
295 struct type t1, t2;
296 ts_pop(&t1);
297 ts_pop(&t2);
298 array2ptr(&t1);
299 array2ptr(&t2);
300 if (!t1.ptr && !t2.ptr) {
301 o_sth();
302 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
303 return;
305 if (t1.ptr && !t2.ptr) {
306 struct type t = t2;
307 t2 = t1;
308 t1 = t;
309 o_tmpswap();
311 if (!t1.ptr && t2.ptr)
312 if (type_szde(&t2) > 1) {
313 o_num(shifts(type_szde(&t2)), 1);
314 o_shl();
316 o_sth();
317 if (t1.ptr && t2.ptr) {
318 o_num(shifts(type_szde(&t1)), 1);
319 o_shr();
320 ts_push_bt(4 | BT_SIGNED);
321 } else {
322 ts_push(&t2);
326 static void structdef(void *data, struct name *name, unsigned flags)
328 struct structinfo *si = data;
329 if (si->isunion) {
330 name->addr = 0;
331 if (si->size < type_totsz(&name->type))
332 si->size = type_totsz(&name->type);
333 } else {
334 name->addr = si->size;
335 si->size += type_totsz(&name->type);
337 memcpy(&si->fields[si->nfields++], name, sizeof(*name));
340 static int readdefs(void (*def)(void *, struct name *, unsigned f), void *data);
342 static int struct_create(char *name, int isunion)
344 int id = struct_find(name, isunion);
345 struct structinfo *si = &structs[id];
346 tok_expect('{');
347 while (tok_jmp('}')) {
348 readdefs(structdef, si);
349 tok_expect(';');
351 return id;
354 static void readexpr(void);
356 static void enum_create(void)
358 long n = 0;
359 tok_expect('{');
360 while (tok_jmp('}')) {
361 char name[NAMELEN];
362 tok_expect(TOK_NAME);
363 strcpy(name, tok_id());
364 if (tok_see() == '=') {
365 tok_get();
366 readexpr();
367 ts_pop(NULL);
368 if (o_popnum(&n))
369 die("const expr expected!\n");
371 enum_add(name, n++);
372 tok_jmp(',');
376 static int basetype(struct type *type, unsigned *flags)
378 int sign = 1;
379 int size = 4;
380 int done = 0;
381 int i = 0;
382 int isunion;
383 char name[NAMELEN] = "";
384 *flags = 0;
385 type->flags = 0;
386 type->ptr = 0;
387 while (!done) {
388 switch (tok_see()) {
389 case TOK_STATIC:
390 *flags |= F_STATIC;
391 break;
392 case TOK_VOID:
393 sign = 0;
394 size = 0;
395 done = 1;
396 break;
397 case TOK_INT:
398 done = 1;
399 break;
400 case TOK_CHAR:
401 size = 1;
402 done = 1;
403 break;
404 case TOK_SHORT:
405 size = 2;
406 break;
407 case TOK_LONG:
408 size = 8;
409 break;
410 case TOK_SIGNED:
411 break;
412 case TOK_UNSIGNED:
413 sign = 0;
414 break;
415 case TOK_UNION:
416 case TOK_STRUCT:
417 isunion = tok_get() == TOK_UNION;
418 if (!tok_jmp(TOK_NAME))
419 strcpy(name, tok_id());
420 if (tok_see() == '{')
421 type->id = struct_create(name, isunion);
422 else
423 type->id = struct_find(name, isunion);
424 type->flags |= T_STRUCT;
425 type->bt = 8;
426 return 0;
427 case TOK_ENUM:
428 tok_get();
429 tok_jmp(TOK_NAME);
430 if (tok_see() == '{')
431 enum_create();
432 type->bt = 4 | BT_SIGNED;
433 return 0;
434 default:
435 if (tok_see() == TOK_NAME) {
436 int id = typedef_find(tok_id());
437 if (id != -1) {
438 tok_get();
439 memcpy(type, &typedefs[id].type,
440 sizeof(*type));
441 return 0;
444 if (!i)
445 return 1;
446 done = 1;
447 continue;
449 i++;
450 tok_get();
452 type->bt = size | (sign ? BT_SIGNED : 0);
453 return 0;
456 static int readname(struct type *main, char *name,
457 struct type *base, unsigned flags);
459 static int readtype(struct type *type)
461 return readname(type, NULL, NULL, 0);
464 static void readptrs(struct type *type)
466 while (!tok_jmp('*')) {
467 type->ptr++;
468 if (!type->bt)
469 type->bt = 1;
473 static void readpre(void);
475 static void readprimary(void)
477 struct name name;
478 int i;
479 if (!tok_jmp(TOK_NUM)) {
480 ts_push_bt(4 | BT_SIGNED);
481 o_num(tok_num(), 4 | BT_SIGNED);
482 return;
484 if (!tok_jmp(TOK_STR)) {
485 struct type t;
486 char buf[BUFSIZE];
487 int len;
488 t.bt = 1 | BT_SIGNED;
489 t.ptr = 1;
490 t.flags = 0;
491 ts_push(&t);
492 len = tok_str(buf);
493 o_symaddr(o_mkdat(NULL, buf, len, 0), TYPE_BT(&t));
494 o_addr();
495 return;
497 if (!tok_jmp(TOK_NAME)) {
498 int n;
499 for (i = nlocals - 1; i >= 0; --i) {
500 struct type *t = &locals[i].type;
501 if (!strcmp(locals[i].name, tok_id())) {
502 o_local(locals[i].addr, TYPE_BT(t));
503 ts_push(t);
504 return;
507 if ((n = global_find(tok_id())) != -1) {
508 struct type *t = &globals[n].type;
509 o_symaddr(globals[n].addr, TYPE_BT(t));
510 ts_push(t);
511 return;
513 if (!enum_find(&n, tok_id())) {
514 ts_push_bt(4 | BT_SIGNED);
515 o_num(n, 4 | BT_SIGNED);
516 return;
518 strcpy(name.name, tok_id());
519 name.addr = o_mkundef(name.name);
520 global_add(&name);
521 ts_push_bt(8);
522 o_symaddr(name.addr, 8);
523 return;
525 if (!tok_jmp('(')) {
526 struct type t;
527 if (!readtype(&t)) {
528 struct type o;
529 tok_expect(')');
530 readpre();
531 ts_pop(&o);
532 ts_push(&t);
533 if (!t.ptr || !o.ptr)
534 o_cast(TYPE_BT(&t));
535 } else {
536 readexpr();
537 tok_expect(')');
539 return;
543 void arrayderef(struct type *t)
545 int sz = type_totsz(t);
546 if (sz > 1) {
547 o_num(sz, 4);
548 o_mul();
550 o_add();
551 o_deref(TYPE_BT(t));
554 static void inc_post(void (*op)(void))
556 unsigned bt = TYPE_BT(&ts[nts - 1]);
557 o_tmpcopy();
558 o_load();
559 o_tmpswap();
560 o_tmpcopy();
561 o_num(1, 4);
562 ts_push_bt(bt);
563 ts_push_bt(bt);
564 ts_binop_add(op);
565 ts_pop(NULL);
566 o_assign(bt);
567 o_tmpdrop(1);
570 static void readfield(void)
572 struct name *field;
573 struct type t;
574 tok_expect(TOK_NAME);
575 ts_pop(&t);
576 field = struct_field(t.id, tok_id());
577 if (field->addr) {
578 o_num(field->addr, 4);
579 o_add();
581 o_deref(TYPE_BT(&field->type));
582 ts_push(&field->type);
585 #define MAXFUNCS (1 << 10)
587 static struct funcinfo {
588 struct type args[MAXFIELDS];
589 struct type ret;
590 int nargs;
591 } funcs[MAXFUNCS];
592 static int nfuncs;
593 static unsigned ret_bt;
595 static int func_create(struct type *ret, struct name *args, int nargs)
597 struct funcinfo *fi = &funcs[nfuncs++];
598 int i;
599 memcpy(&fi->ret, ret, sizeof(*ret));
600 for (i = 0; i < nargs; i++)
601 memcpy(&fi->args[i], &args[i].type, sizeof(*ret));
602 fi->nargs = nargs;
603 return fi - funcs;
606 static void readcall(void)
608 struct type t;
609 unsigned bt[MAXARGS];
610 struct funcinfo *fi;
611 int argc = 0;
612 int i;
613 if (tok_see() != ')') {
614 readexpr();
615 ts_pop(&t);
616 bt[argc++] = TYPE_BT(&t);
618 while (!tok_jmp(',')) {
619 readexpr();
620 ts_pop(&t);
621 bt[argc++] = TYPE_BT(&t);
623 tok_expect(')');
624 ts_pop(&t);
625 if (t.flags & T_FUNC && t.ptr > 0)
626 o_deref(8);
627 fi = t.flags & T_FUNC ? &funcs[t.id] : NULL;
628 if (fi)
629 for (i = 0; i < fi->nargs; i++)
630 bt[i] = TYPE_BT(&fi->args[i]);
631 o_call(argc, bt, fi ? TYPE_BT(&fi->ret) : 4 | BT_SIGNED);
632 if (fi)
633 ts_push(&fi->ret);
634 else
635 ts_push_bt(4 | BT_SIGNED);
638 static void readpost(void)
640 readprimary();
641 while (1) {
642 if (!tok_jmp('[')) {
643 struct type t;
644 ts_pop(&t);
645 readexpr();
646 ts_pop(NULL);
647 tok_expect(']');
648 array2ptr(&t);
649 t.ptr--;
650 arrayderef(&t);
651 ts_push(&t);
652 continue;
654 if (!tok_jmp('(')) {
655 readcall();
656 continue;
658 if (!tok_jmp(TOK2("++"))) {
659 inc_post(o_add);
660 continue;
662 if (!tok_jmp(TOK2("--"))) {
663 inc_post(o_sub);
664 continue;
666 if (!tok_jmp('.')) {
667 o_addr();
668 readfield();
669 continue;
671 if (!tok_jmp(TOK2("->"))) {
672 readfield();
673 continue;
675 break;
679 static void inc_pre(void (*op)(void))
681 unsigned bt = TYPE_BT(&ts[nts - 1]);
682 readpre();
683 o_tmpcopy();
684 o_num(1, 4);
685 ts_push_bt(bt);
686 ts_push_bt(bt);
687 ts_binop_add(op);
688 ts_pop(NULL);
689 o_assign(bt);
692 static void readpre(void)
694 if (!tok_jmp('&')) {
695 struct type type;
696 readpre();
697 ts_pop(&type);
698 if (!(type.flags & T_FUNC) && !type.ptr)
699 type.ptr++;
700 ts_push(&type);
701 o_addr();
702 return;
704 if (!tok_jmp('*')) {
705 struct type t;
706 readpre();
707 ts_pop(&t);
708 array2ptr(&t);
709 if (!(t.flags & T_FUNC) || t.ptr > 0) {
710 t.ptr--;
711 o_deref(TYPE_BT(&t));
713 ts_push(&t);
714 return;
716 if (!tok_jmp('!')) {
717 struct type type;
718 readpre();
719 ts_pop(&type);
720 o_lnot();
721 ts_push_bt(4 | BT_SIGNED);
722 return;
724 if (!tok_jmp('-')) {
725 readpre();
726 o_neg();
727 return;
729 if (!tok_jmp('~')) {
730 readpre();
731 o_not();
732 return;
734 if (!tok_jmp(TOK2("++"))) {
735 inc_pre(o_add);
736 return;
738 if (!tok_jmp(TOK2("--"))) {
739 inc_pre(o_sub);
740 return;
742 if (!tok_jmp(TOK_SIZEOF)) {
743 struct type t;
744 int op = !tok_jmp('(');
745 if (readtype(&t)) {
746 int nogen = !o_nogen();
747 readexpr();
748 if (nogen)
749 o_dogen();
750 ts_pop(&t);
751 o_tmpdrop(1);
753 ts_push_bt(4);
754 o_num(type_totsz(&t), 4);
755 if (op)
756 tok_expect(')');
757 return;
759 readpost();
762 static void readmul(void)
764 readpre();
765 while (1) {
766 if (!tok_jmp('*')) {
767 readpre();
768 ts_binop(o_mul);
769 continue;
771 if (!tok_jmp('/')) {
772 readpre();
773 ts_binop(o_div);
774 continue;
776 if (!tok_jmp('%')) {
777 readpre();
778 ts_binop(o_mod);
779 continue;
781 break;
785 static void readadd(void)
787 readmul();
788 while (1) {
789 if (!tok_jmp('+')) {
790 readmul();
791 ts_binop_add(o_add);
792 continue;
794 if (!tok_jmp('-')) {
795 readmul();
796 ts_binop_add(o_sub);
797 continue;
799 break;
803 static void shift(void (*op)(void))
805 struct type t;
806 readadd();
807 ts_pop(NULL);
808 ts_pop(&t);
809 op();
810 ts_push_bt(TYPE_BT(&t));
813 static void readshift(void)
815 readadd();
816 while (1) {
817 if (!tok_jmp(TOK2("<<"))) {
818 shift(o_shl);
819 continue;
821 if (!tok_jmp(TOK2(">>"))) {
822 shift(o_shr);
823 continue;
825 break;
829 static void cmp(void (*op)(void))
831 readshift();
832 ts_pop(NULL);
833 ts_pop(NULL);
834 op();
835 ts_push_bt(4 | BT_SIGNED);
838 static void readcmp(void)
840 readshift();
841 while (1) {
842 if (!tok_jmp('<')) {
843 cmp(o_lt);
844 continue;
846 if (!tok_jmp('>')) {
847 cmp(o_gt);
848 continue;
850 if (!tok_jmp(TOK2("<="))) {
851 cmp(o_le);
852 continue;
854 if (!tok_jmp(TOK2(">="))) {
855 cmp(o_ge);
856 continue;
858 break;
862 static void eq(void (*op)(void))
864 readcmp();
865 ts_pop(NULL);
866 ts_pop(NULL);
867 op();
868 ts_push_bt(4 | BT_SIGNED);
871 static void readeq(void)
873 readcmp();
874 while (1) {
875 if (!tok_jmp(TOK2("=="))) {
876 eq(o_eq);
877 continue;
879 if (!tok_jmp(TOK2("!="))) {
880 eq(o_neq);
881 continue;
883 break;
887 static void readbitand(void)
889 readeq();
890 while (!tok_jmp('&')) {
891 readeq();
892 ts_binop(o_and);
896 static void readxor(void)
898 readbitand();
899 while (!tok_jmp('^')) {
900 readbitand();
901 ts_binop(o_xor);
905 static void readbitor(void)
907 readxor();
908 while (!tok_jmp('|')) {
909 readxor();
910 ts_binop(o_or);
914 #define MAXCOND (1 << 7)
916 static void readand(void)
918 long conds[MAXCOND];
919 int nconds = 0;
920 long passed;
921 int i;
922 readbitor();
923 if (tok_see() != TOK2("&&"))
924 return;
925 conds[nconds++] = o_jz(0);
926 ts_pop(NULL);
927 while (!tok_jmp(TOK2("&&"))) {
928 readbitor();
929 conds[nconds++] = o_jz(0);
930 ts_pop(NULL);
932 o_num(1, 4 | BT_SIGNED);
933 o_tmpfork();
934 passed = o_jmp(0);
935 for (i = 0; i < nconds; i++)
936 o_filljmp(conds[i]);
937 o_num(0, 4 | BT_SIGNED);
938 o_tmpjoin();
939 o_filljmp(passed);
940 ts_push_bt(4 | BT_SIGNED);
943 static void reador(void)
945 long conds[MAXCOND];
946 int nconds = 0;
947 long failed;
948 int i;
949 readand();
950 if (tok_see() != TOK2("||"))
951 return;
952 conds[nconds++] = o_jnz(0);
953 ts_pop(NULL);
954 while (!tok_jmp(TOK2("||"))) {
955 readand();
956 conds[nconds++] = o_jnz(0);
957 ts_pop(NULL);
959 o_num(0, 4 | BT_SIGNED);
960 o_tmpfork();
961 failed = o_jmp(0);
962 for (i = 0; i < nconds; i++)
963 o_filljmp(conds[i]);
964 o_num(1, 4 | BT_SIGNED);
965 o_tmpjoin();
966 o_filljmp(failed);
967 ts_push_bt(4 | BT_SIGNED);
970 static void readcexpr(void)
972 long l1, l2;
973 long c;
974 int cexpr, nogen;
975 reador();
976 if (tok_jmp('?'))
977 return;
978 cexpr = !o_popnum(&c);
979 ts_pop(NULL);
980 if (cexpr) {
981 if (!c)
982 nogen = !o_nogen();
983 } else {
984 l1 = o_jz(0);
986 reador();
987 if (!cexpr) {
988 o_tmpfork();
989 l2 = o_jmp(0);
991 ts_pop(NULL);
992 tok_expect(':');
993 if (cexpr) {
994 if (c) {
995 nogen = !o_nogen();
996 } else {
997 if (nogen)
998 o_dogen();
999 o_tmpdrop(1);
1001 } else {
1002 o_filljmp(l1);
1004 reador();
1005 if (cexpr) {
1006 if (c) {
1007 if (nogen)
1008 o_dogen();
1009 o_tmpdrop(1);
1011 } else {
1012 o_tmpjoin();
1013 o_filljmp(l2);
1017 static void opassign(void (*bop)(void (*op)(void)), void (*op)(void))
1019 unsigned bt = TYPE_BT(&ts[nts - 1]);
1020 o_tmpcopy();
1021 readexpr();
1022 bop(op);
1023 ts_pop(NULL);
1024 o_assign(bt);
1027 static void doassign(void)
1029 struct type t;
1030 ts_pop(&t);
1031 if (!t.ptr && t.flags & T_STRUCT)
1032 o_memcpy(type_totsz(&t));
1033 else
1034 o_assign(TYPE_BT(&ts[nts - 1]));
1037 static void readexpr(void)
1039 readcexpr();
1040 if (!tok_jmp('=')) {
1041 readexpr();
1042 doassign();
1043 return;
1045 if (!tok_jmp(TOK2("+="))) {
1046 opassign(ts_binop_add, o_add);
1047 return;
1049 if (!tok_jmp(TOK2("-="))) {
1050 opassign(ts_binop_add, o_sub);
1051 return;
1053 if (!tok_jmp(TOK2("*="))) {
1054 opassign(ts_binop, o_mul);
1055 return;
1057 if (!tok_jmp(TOK2("/="))) {
1058 opassign(ts_binop, o_div);
1059 return;
1061 if (!tok_jmp(TOK2("%="))) {
1062 opassign(ts_binop, o_mod);
1063 return;
1065 if (!tok_jmp(TOK3("<<="))) {
1066 opassign(ts_binop, o_shl);
1067 return;
1069 if (!tok_jmp(TOK3(">>="))) {
1070 opassign(ts_binop, o_shr);
1071 return;
1073 if (!tok_jmp(TOK3("&="))) {
1074 opassign(ts_binop, o_and);
1075 return;
1077 if (!tok_jmp(TOK3("|="))) {
1078 opassign(ts_binop, o_or);
1079 return;
1081 if (!tok_jmp(TOK3("^="))) {
1082 opassign(ts_binop, o_xor);
1083 return;
1087 static void readestmt(void)
1089 do {
1090 o_tmpdrop(-1);
1091 nts = 0;
1092 readexpr();
1093 } while (!tok_jmp(','));
1096 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1098 static void globaldef(void *data, struct name *name, unsigned flags)
1100 char *varname = flags & F_STATIC ? NULL : name->name;
1101 name->addr = o_mkvar(varname, type_totsz(&name->type), F_GLOBAL(flags));
1102 global_add(name);
1105 static void o_localoff(long addr, int off, unsigned bt)
1107 o_local(addr, bt);
1108 if (off) {
1109 o_addr();
1110 o_num(off, 4);
1111 o_add();
1112 o_deref(bt);
1116 static struct type *innertype(struct type *t)
1118 if (t->flags & T_ARRAY && !t->ptr)
1119 return innertype(&arrays[t->id].type);
1120 return t;
1123 static void initexpr(struct type *t, long addr, int off)
1125 if (t->flags & T_ARRAY && tok_see() == TOK_STR) {
1126 struct type *t_de = &arrays[t->id].type;
1127 if (!t_de->ptr && !t_de->flags && TYPE_SZ(t_de) == 1) {
1128 char buf[BUFSIZE];
1129 int len;
1130 tok_expect(TOK_STR);
1131 len = tok_str(buf);
1132 o_localoff(addr, off, TYPE_BT(t));
1133 o_symaddr(o_mkdat(NULL, buf, len, 0), TYPE_BT(t));
1134 o_memcpy(len);
1135 o_tmpdrop(1);
1136 o_localoff(addr, off + len, TYPE_BT(t));
1137 o_memset(0, arrays[t->id].n - len);
1138 o_tmpdrop(1);
1139 return;
1142 if (tok_jmp('{')) {
1143 o_localoff(addr, off, TYPE_BT(t));
1144 ts_push(t);
1145 readexpr();
1146 doassign();
1147 ts_pop(NULL);
1148 o_tmpdrop(1);
1149 return;
1151 if (!t->ptr && t->flags & T_STRUCT) {
1152 struct structinfo *si = &structs[t->id];
1153 int i;
1154 for (i = 0; i < si->nfields; i++) {
1155 struct name *field = &si->fields[i];
1156 if (!tok_jmp('.')) {
1157 tok_expect(TOK_NAME);
1158 field = struct_field(t->id, tok_id());
1159 tok_expect('=');
1161 initexpr(&field->type, addr, off + field->addr);
1162 if (tok_jmp(',') || tok_see() == '}')
1163 break;
1165 } else if (t->flags & T_ARRAY) {
1166 struct type *t_de = &arrays[t->id].type;
1167 int i;
1168 for (i = 0; ; i++) {
1169 long idx = i;
1170 struct type *it = t_de;
1171 if (!tok_jmp('[')) {
1172 readexpr();
1173 o_popnum(&idx);
1174 ts_pop(NULL);
1175 tok_expect(']');
1176 tok_expect('=');
1178 if (tok_see() != '{')
1179 it = innertype(t_de);
1180 initexpr(it, addr, off + type_totsz(it) * idx);
1181 if (tok_jmp(',') || tok_see() == '}')
1182 break;
1185 tok_expect('}');
1188 static void localdef(void *data, struct name *name, unsigned flags)
1190 if (flags & F_STATIC) {
1191 globaldef(data, name, flags);
1192 return;
1194 name->addr = o_mklocal(type_totsz(&name->type));
1195 local_add(name);
1196 if (flags & F_INIT) {
1197 struct type *t = &name->type;
1198 if (tok_see() == '{') {
1199 o_local(name->addr, TYPE_BT(t));
1200 o_memset(0, type_totsz(t));
1201 o_tmpdrop(1);
1203 initexpr(t, name->addr, 0);
1207 static void funcdef(char *name, struct type *type, struct name *args,
1208 int nargs, unsigned flags)
1210 int i;
1211 struct name global;
1212 strcpy(global.name, name);
1213 memcpy(&global.type, type, sizeof(*type));
1214 global.addr = o_func_beg(name, F_GLOBAL(flags));
1215 global_add(&global);
1216 ret_bt = TYPE_BT(&funcs[type->id].ret);
1217 for (i = 0; i < nargs; i++) {
1218 args[i].addr = o_arg(i, type_totsz(&args[i].type));
1219 local_add(&args[i]);
1223 static int readargs(struct name *args)
1225 int nargs = 0;
1226 tok_expect('(');
1227 while (tok_see() != ')') {
1228 readname(&args[nargs].type, args[nargs].name, NULL, 0);
1229 nargs++;
1230 if (tok_jmp(','))
1231 break;
1233 tok_expect(')');
1234 if (nargs == 1 && !TYPE_BT(&args[0].type))
1235 return 0;
1236 return nargs;
1239 static int readname(struct type *main, char *name,
1240 struct type *base, unsigned flags)
1242 struct type tpool[3];
1243 int npool = 0;
1244 struct type *type = &tpool[npool++];
1245 struct type *func = NULL;
1246 struct type *ret = NULL;
1247 memset(tpool, 0, sizeof(tpool));
1248 if (name)
1249 *name = '\0';
1250 if (!base) {
1251 if (basetype(type, &flags))
1252 return 1;
1253 } else {
1254 memcpy(type, base, sizeof(*base));
1256 readptrs(type);
1257 if (!tok_jmp('(')) {
1258 ret = type;
1259 type = &tpool[npool++];
1260 func = type;
1261 readptrs(type);
1263 if (!tok_jmp(TOK_NAME) && name)
1264 strcpy(name, tok_id());
1265 while (!tok_jmp('[')) {
1266 long n;
1267 readexpr();
1268 ts_pop(NULL);
1269 if (o_popnum(&n))
1270 die("const expr expected\n");
1271 type->id = array_add(type, n);
1272 if (type->flags & T_FUNC)
1273 func = &arrays[type->id].type;
1274 type->flags = T_ARRAY;
1275 type->bt = 8;
1276 type->ptr = 0;
1277 tok_expect(']');
1279 if (func)
1280 tok_expect(')');
1281 if (tok_see() == '(') {
1282 struct name args[MAXARGS];
1283 int nargs = readargs(args);
1284 int fdef = !func;
1285 if (!func) {
1286 ret = type;
1287 type = &tpool[npool++];
1288 func = type;
1290 func->flags = T_FUNC;
1291 func->bt = 8;
1292 func->id = func_create(ret, args, nargs);
1293 if (fdef && tok_see() == '{') {
1294 funcdef(name, func, args, nargs, flags);
1295 return 1;
1298 memcpy(main, type, sizeof(*type));
1299 return 0;
1302 static int readdefs(void (*def)(void *data, struct name *name, unsigned flags),
1303 void *data)
1305 struct type base;
1306 unsigned flags;
1307 if (basetype(&base, &flags))
1308 return 1;
1309 while (tok_see() != ';' && tok_see() != '{') {
1310 struct name name;
1311 if (readname(&name.type, name.name, &base, flags))
1312 break;
1313 if (!tok_jmp('='))
1314 flags |= F_INIT;
1315 def(data, &name, flags);
1316 tok_jmp(',');
1318 return 0;
1321 static void typedefdef(void *data, struct name *name, unsigned flags)
1323 typedef_add(name->name, &name->type);
1326 static void readstmt(void);
1328 #define MAXCASES (1 << 7)
1330 static void readswitch(void)
1332 int break_beg = nbreaks;
1333 long val_addr = o_mklocal(8);
1334 long matched[MAXCASES];
1335 int nmatched = 0;
1336 struct type t;
1337 long next;
1338 int ref = 1;
1339 int i;
1340 tok_expect('(');
1341 readexpr();
1342 ts_pop(&t);
1343 o_local(val_addr, TYPE_BT(&t));
1344 o_tmpswap();
1345 o_assign(TYPE_BT(&t));
1346 o_tmpdrop(1);
1347 tok_expect(')');
1348 tok_expect('{');
1349 while (tok_jmp('}')) {
1350 int n = 0;
1351 while (tok_see() == TOK_CASE || tok_see() == TOK_DEFAULT) {
1352 if (n++ > 0)
1353 matched[nmatched++] = o_jmp(0);
1354 if (!ref++)
1355 o_filljmp(next);
1356 if (!tok_jmp(TOK_CASE)) {
1357 readexpr();
1358 o_local(val_addr, TYPE_BT(&t));
1359 o_eq();
1360 next = o_jz(0);
1361 ref = 0;
1362 tok_expect(':');
1363 o_tmpdrop(1);
1364 ts_pop(NULL);
1365 continue;
1367 if (!tok_jmp(TOK_DEFAULT)) {
1368 tok_expect(':');
1369 continue;
1372 for (i = 0; i < nmatched; i++)
1373 o_filljmp(matched[i]);
1374 nmatched = 0;
1375 readstmt();
1377 o_rmlocal(val_addr, 8);
1378 if (!ref++)
1379 o_filljmp(next);
1380 break_fill(o_mklabel(), break_beg);
1383 #define MAXGOTO (1 << 10)
1385 static struct gotoinfo {
1386 char name[NAMELEN];
1387 long addr;
1388 } gotos[MAXGOTO];
1389 static int ngotos;
1391 static struct labelinfo {
1392 char name[NAMELEN];
1393 long addr;
1394 } labels[MAXGOTO];
1395 static int nlabels;
1397 static void goto_add(char *name)
1399 strcpy(gotos[ngotos].name, name);
1400 gotos[ngotos++].addr = o_jmp(0);
1403 static void label_add(char *name)
1405 strcpy(labels[nlabels].name, name);
1406 labels[nlabels++].addr = o_mklabel();
1409 static void goto_fill(void)
1411 int i, j;
1412 for (i = 0; i < ngotos; i++)
1413 for (j = 0; j < nlabels; j++)
1414 if (!strcmp(gotos[i].name, labels[j].name)) {
1415 o_filljmp2(gotos[i].addr, labels[j].addr);
1416 break;
1420 static void readstmt(void)
1422 o_tmpdrop(-1);
1423 nts = 0;
1424 if (!tok_jmp('{')) {
1425 int _nlocals = nlocals;
1426 int _nglobals = nglobals;
1427 int _nenums = nenums;
1428 int _ntypedefs = ntypedefs;
1429 int _nstructs = nstructs;
1430 int _nfuncs = nfuncs;
1431 int _narrays = narrays;
1432 while (tok_jmp('}'))
1433 readstmt();
1434 nlocals = _nlocals;
1435 nenums = _nenums;
1436 ntypedefs = _ntypedefs;
1437 nstructs = _nstructs;
1438 nfuncs = _nfuncs;
1439 narrays = _narrays;
1440 nglobals = _nglobals;
1441 return;
1443 if (!readdefs(localdef, NULL)) {
1444 tok_expect(';');
1445 return;
1447 if (!tok_jmp(TOK_TYPEDEF)) {
1448 readdefs(typedefdef, NULL);
1449 tok_expect(';');
1450 return;
1452 if (!tok_jmp(TOK_IF)) {
1453 long l1, l2;
1454 tok_expect('(');
1455 readexpr();
1456 tok_expect(')');
1457 l1 = o_jz(0);
1458 readstmt();
1459 if (!tok_jmp(TOK_ELSE)) {
1460 l2 = o_jmp(0);
1461 o_filljmp(l1);
1462 readstmt();
1463 o_filljmp(l2);
1464 } else {
1465 o_filljmp(l1);
1467 return;
1469 if (!tok_jmp(TOK_WHILE)) {
1470 long l1, l2;
1471 int break_beg = nbreaks;
1472 int continue_beg = ncontinues;
1473 l1 = o_mklabel();
1474 tok_expect('(');
1475 readexpr();
1476 tok_expect(')');
1477 l2 = o_jz(0);
1478 readstmt();
1479 o_jmp(l1);
1480 o_filljmp(l2);
1481 break_fill(o_mklabel(), break_beg);
1482 continue_fill(l1, continue_beg);
1483 return;
1485 if (!tok_jmp(TOK_DO)) {
1486 long l1, l2;
1487 int break_beg = nbreaks;
1488 int continue_beg = ncontinues;
1489 l1 = o_mklabel();
1490 readstmt();
1491 tok_expect(TOK_WHILE);
1492 tok_expect('(');
1493 l2 = o_mklabel();
1494 readexpr();
1495 o_jnz(l1);
1496 tok_expect(')');
1497 break_fill(o_mklabel(), break_beg);
1498 continue_fill(l2, continue_beg);
1499 return;
1501 if (!tok_jmp(TOK_FOR)) {
1502 long check, jump, end, body;
1503 int break_beg = nbreaks;
1504 int continue_beg = ncontinues;
1505 tok_expect('(');
1506 if (tok_see() != ';')
1507 readestmt();
1508 tok_expect(';');
1509 check = o_mklabel();
1510 if (tok_see() != ';')
1511 readestmt();
1512 tok_expect(';');
1513 end = o_jz(0);
1514 body = o_jmp(0);
1515 jump = o_mklabel();
1516 if (tok_see() != ')')
1517 readestmt();
1518 tok_expect(')');
1519 o_jmp(check);
1520 o_filljmp(body);
1521 readstmt();
1522 o_jmp(jump);
1523 o_filljmp(end);
1524 break_fill(o_mklabel(), break_beg);
1525 continue_fill(jump, continue_beg);
1526 return;
1528 if (!tok_jmp(TOK_SWITCH)) {
1529 readswitch();
1530 return;
1532 if (!tok_jmp(TOK_RETURN)) {
1533 int ret = tok_see() != ';';
1534 if (ret)
1535 readexpr();
1536 tok_expect(';');
1537 o_ret(ret_bt);
1538 return;
1540 if (!tok_jmp(TOK_BREAK)) {
1541 tok_expect(';');
1542 breaks[nbreaks++] = o_jmp(0);
1543 return;
1545 if (!tok_jmp(TOK_CONTINUE)) {
1546 tok_expect(';');
1547 continues[ncontinues++] = o_jmp(0);
1548 return;
1550 if (!tok_jmp(TOK_GOTO)) {
1551 tok_expect(TOK_NAME);
1552 goto_add(tok_id());
1553 tok_expect(';');
1554 return;
1556 readestmt();
1557 /* labels */
1558 if (!tok_jmp(':')) {
1559 label_add(tok_id());
1560 return;
1562 tok_expect(';');
1565 static void readdecl(void)
1567 if (!tok_jmp(TOK_TYPEDEF)) {
1568 readdefs(typedefdef, NULL);
1569 tok_expect(';');
1570 return;
1572 readdefs(globaldef, NULL);
1573 if (tok_see() == '{') {
1574 readstmt();
1575 goto_fill();
1576 o_func_end();
1577 nlocals = 0;
1578 ngotos = 0;
1579 nlabels = 0;
1580 return;
1582 tok_expect(';');
1585 static void parse(void)
1587 while (tok_see() != TOK_EOF)
1588 readdecl();
1591 int main(int argc, char *argv[])
1593 char obj[128];
1594 int ifd, ofd;
1595 int i = 1;
1596 while (i < argc && argv[i][0] == '-')
1597 i++;
1598 if (i == argc)
1599 die("no file given\n");
1600 ifd = open(argv[i], O_RDONLY);
1601 tok_init(ifd);
1602 close(ifd);
1603 parse();
1605 strcpy(obj, argv[i]);
1606 obj[strlen(obj) - 1] = 'o';
1607 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
1608 out_write(ofd);
1609 close(ofd);
1610 return 0;