handle array args
[neatcc.git] / ncc.c
blob6ba3a62839ea674d2d1b539437f07a96eaa84608
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
33 #define F_EXTERN 0x04
35 struct type {
36 unsigned bt;
37 unsigned flags;
38 int ptr;
39 int id; /* for structs, functions and arrays */
42 /* type stack */
43 static struct type ts[MAXTMP];
44 static int nts;
46 static void ts_push_bt(unsigned bt)
48 ts[nts].ptr = 0;
49 ts[nts].flags = 0;
50 ts[nts++].bt = bt;
53 static void ts_push(struct type *t)
55 memcpy(&ts[nts++], t, sizeof(*t));
56 if (t->flags & (T_FUNC | T_ARRAY) && !t->ptr)
57 o_addr();
60 static void ts_pop(struct type *type)
62 nts--;
63 if (type)
64 *type = ts[nts];
67 struct name {
68 char name[NAMELEN];
69 struct type type;
70 long addr;
73 static struct name locals[MAXLOCALS];
74 static int nlocals;
75 static struct name globals[MAXGLOBALS];
76 static int nglobals;
78 static void local_add(struct name *name)
80 memcpy(&locals[nlocals++], name, sizeof(*name));
83 static int global_find(char *name)
85 int i;
86 for (i = 0; i < nglobals; i++)
87 if (!strcmp(name, globals[i].name))
88 return i;
89 return -1;
92 static void global_add(struct name *name)
94 int found = global_find(name->name);
95 int i = found == -1 ? nglobals++ : found;
96 memcpy(&globals[i], name, sizeof(*name));
99 static void die(char *s)
101 print(s);
102 exit(1);
105 #define MAXENUMS (1 << 10)
107 static struct enumval {
108 char name[NAMELEN];
109 int n;
110 } enums[MAXENUMS];
111 static int nenums;
113 static void enum_add(char *name, int val)
115 struct enumval *ev = &enums[nenums++];
116 strcpy(ev->name, name);
117 ev->n = val;
120 static int enum_find(int *val, char *name)
122 int i;
123 for (i = nenums - 1; i >= 0; --i)
124 if (!strcmp(name, enums[i].name)) {
125 *val = enums[i].n;
126 return 0;
128 return 1;
131 #define MAXTYPEDEFS (1 << 10)
133 static struct typdefinfo {
134 char name[NAMELEN];
135 struct type type;
136 } typedefs[MAXTYPEDEFS];
137 static int ntypedefs;
139 static void typedef_add(char *name, struct type *type)
141 struct typdefinfo *ti = &typedefs[ntypedefs++];
142 strcpy(ti->name, name);
143 memcpy(&ti->type, type, sizeof(*type));
146 static int typedef_find(char *name)
148 int i;
149 for (i = ntypedefs - 1; i >= 0; --i)
150 if (!strcmp(name, typedefs[i].name))
151 return i;
152 return -1;
155 #define MAXARRAYS (1 << 10)
157 static struct array {
158 struct type type;
159 int n;
160 } arrays[MAXARRAYS];
161 static int narrays;
163 static int array_add(struct type *type, int n)
165 struct array *a = &arrays[narrays++];
166 memcpy(&a->type, type, sizeof(*type));
167 a->n = n;
168 return a - arrays;
171 static void array2ptr(struct type *t)
173 if (!(t->flags & T_ARRAY) || t->ptr)
174 return;
175 memcpy(t, &arrays[t->id].type, sizeof(*t));
176 t->ptr++;
179 #define MAXTYPES (1 << 10)
180 #define MAXFIELDS (1 << 7)
182 static struct structinfo {
183 char name[NAMELEN];
184 struct name fields[MAXFIELDS];
185 int nfields;
186 int isunion;
187 int size;
188 } structs[MAXTYPES];
189 static int nstructs;
191 static int struct_find(char *name, int isunion)
193 int i;
194 for (i = nstructs - 1; i >= 0; --i)
195 if (*structs[i].name && !strcmp(name, structs[i].name) &&
196 structs[i].isunion == isunion)
197 return i;
198 i = nstructs++;
199 memset(&structs[i], 0, sizeof(structs[i]));
200 strcpy(structs[i].name, name);
201 structs[i].isunion = isunion;
202 return i;
205 static struct name *struct_field(int id, char *name)
207 struct structinfo *si = &structs[id];
208 int i;
209 for (i = 0; i < si->nfields; i++)
210 if (!strcmp(name, si->fields[i].name))
211 return &si->fields[i];
212 die("field not found\n");
215 #define MAXBREAK (1 << 7)
217 static long breaks[MAXBREAK];
218 static int nbreaks;
219 static long continues[MAXBREAK];
220 static int ncontinues;
222 static void break_fill(long addr, int till)
224 int i;
225 for (i = till; i < nbreaks; i++)
226 o_filljmp2(breaks[i], addr);
227 nbreaks = till;
230 static void continue_fill(long addr, int till)
232 int i;
233 for (i = till; i < ncontinues; i++)
234 o_filljmp2(continues[i], addr);
235 ncontinues = till;
238 static int type_totsz(struct type *t)
240 if (t->ptr)
241 return 8;
242 if (t->flags & T_ARRAY)
243 return arrays[t->id].n * type_totsz(&arrays[t->id].type);
244 return t->flags & T_STRUCT ? structs[t->id].size : BT_SZ(t->bt);
247 static unsigned type_szde(struct type *t)
249 if (t->flags & T_ARRAY)
250 return t->ptr > 0 ? 8 : TYPE_SZ(&arrays[t->id].type);
251 else
252 return t->ptr > 1 ? 8 : BT_SZ(t->bt);
255 static int tok_jmp(int tok)
257 if (tok_see() != tok)
258 return 1;
259 tok_get();
260 return 0;
263 static void tok_expect(int tok)
265 if (tok_get() != tok)
266 die("syntax error\n");
269 static unsigned bt_op(unsigned bt1, unsigned bt2)
271 unsigned s1 = BT_SZ(bt1);
272 unsigned s2 = BT_SZ(bt2);
273 return (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
276 static void ts_binop(void (*o_sth)(void))
278 struct type t1, t2;
279 ts_pop(&t1);
280 ts_pop(&t2);
281 o_sth();
282 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
285 static int shifts(int n)
287 int i = -1;
288 while (i++ < 16)
289 if (n == 1 << i)
290 break;
291 return i;
294 static void ts_binop_add(void (*o_sth)(void))
296 struct type t1, t2;
297 ts_pop(&t1);
298 ts_pop(&t2);
299 array2ptr(&t1);
300 array2ptr(&t2);
301 if (!t1.ptr && !t2.ptr) {
302 o_sth();
303 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
304 return;
306 if (t1.ptr && !t2.ptr) {
307 struct type t = t2;
308 t2 = t1;
309 t1 = t;
310 o_tmpswap();
312 if (!t1.ptr && t2.ptr)
313 if (type_szde(&t2) > 1) {
314 o_num(shifts(type_szde(&t2)), 1);
315 o_shl();
317 o_sth();
318 if (t1.ptr && t2.ptr) {
319 o_num(shifts(type_szde(&t1)), 1);
320 o_shr();
321 ts_push_bt(4 | BT_SIGNED);
322 } else {
323 ts_push(&t2);
327 static void structdef(void *data, struct name *name, unsigned flags)
329 struct structinfo *si = data;
330 if (si->isunion) {
331 name->addr = 0;
332 if (si->size < type_totsz(&name->type))
333 si->size = type_totsz(&name->type);
334 } else {
335 name->addr = si->size;
336 si->size += type_totsz(&name->type);
338 memcpy(&si->fields[si->nfields++], name, sizeof(*name));
341 static int readdefs(void (*def)(void *, struct name *, unsigned f), void *data);
343 static int struct_create(char *name, int isunion)
345 int id = struct_find(name, isunion);
346 struct structinfo *si = &structs[id];
347 tok_expect('{');
348 while (tok_jmp('}')) {
349 readdefs(structdef, si);
350 tok_expect(';');
352 return id;
355 static void readexpr(void);
357 static void enum_create(void)
359 long n = 0;
360 tok_expect('{');
361 while (tok_jmp('}')) {
362 char name[NAMELEN];
363 tok_expect(TOK_NAME);
364 strcpy(name, tok_id());
365 if (tok_see() == '=') {
366 tok_get();
367 readexpr();
368 ts_pop(NULL);
369 if (o_popnum(&n))
370 die("const expr expected!\n");
372 enum_add(name, n++);
373 tok_jmp(',');
377 static int basetype(struct type *type, unsigned *flags)
379 int sign = 1;
380 int size = 4;
381 int done = 0;
382 int i = 0;
383 int isunion;
384 char name[NAMELEN] = "";
385 *flags = 0;
386 type->flags = 0;
387 type->ptr = 0;
388 while (!done) {
389 switch (tok_see()) {
390 case TOK_STATIC:
391 *flags |= F_STATIC;
392 break;
393 case TOK_EXTERN:
394 *flags |= F_EXTERN;
395 break;
396 case TOK_VOID:
397 sign = 0;
398 size = 0;
399 done = 1;
400 break;
401 case TOK_INT:
402 done = 1;
403 break;
404 case TOK_CHAR:
405 size = 1;
406 done = 1;
407 break;
408 case TOK_SHORT:
409 size = 2;
410 break;
411 case TOK_LONG:
412 size = 8;
413 break;
414 case TOK_SIGNED:
415 break;
416 case TOK_UNSIGNED:
417 sign = 0;
418 break;
419 case TOK_UNION:
420 case TOK_STRUCT:
421 isunion = tok_get() == TOK_UNION;
422 if (!tok_jmp(TOK_NAME))
423 strcpy(name, tok_id());
424 if (tok_see() == '{')
425 type->id = struct_create(name, isunion);
426 else
427 type->id = struct_find(name, isunion);
428 type->flags |= T_STRUCT;
429 type->bt = 8;
430 return 0;
431 case TOK_ENUM:
432 tok_get();
433 tok_jmp(TOK_NAME);
434 if (tok_see() == '{')
435 enum_create();
436 type->bt = 4 | BT_SIGNED;
437 return 0;
438 default:
439 if (tok_see() == TOK_NAME) {
440 int id = typedef_find(tok_id());
441 if (id != -1) {
442 tok_get();
443 memcpy(type, &typedefs[id].type,
444 sizeof(*type));
445 return 0;
448 if (!i)
449 return 1;
450 done = 1;
451 continue;
453 i++;
454 tok_get();
456 type->bt = size | (sign ? BT_SIGNED : 0);
457 return 0;
460 static int readname(struct type *main, char *name,
461 struct type *base, unsigned flags);
463 static int readtype(struct type *type)
465 return readname(type, NULL, NULL, 0);
468 static void readptrs(struct type *type)
470 while (!tok_jmp('*')) {
471 type->ptr++;
472 if (!type->bt)
473 type->bt = 1;
477 static int ncexpr;
479 static void readpre(void);
481 static void readprimary(void)
483 int i;
484 if (!tok_jmp(TOK_NUM)) {
485 ts_push_bt(4 | BT_SIGNED);
486 o_num(tok_num(), 4 | BT_SIGNED);
487 return;
489 if (!tok_jmp(TOK_STR)) {
490 struct type t;
491 char buf[BUFSIZE];
492 int len;
493 t.bt = 1 | BT_SIGNED;
494 t.ptr = 1;
495 t.flags = 0;
496 ts_push(&t);
497 len = tok_str(buf);
498 o_symaddr(o_mkdat(NULL, buf, len, 0), TYPE_BT(&t));
499 o_addr();
500 return;
502 if (!tok_jmp(TOK_NAME)) {
503 struct name unkn;
504 char *name = unkn.name;
505 int n;
506 strcpy(name, tok_id());
507 /* don't search for labels here */
508 if (!ncexpr && tok_see() == ':')
509 return;
510 for (i = nlocals - 1; i >= 0; --i) {
511 struct type *t = &locals[i].type;
512 if (!strcmp(locals[i].name, name)) {
513 o_local(locals[i].addr, TYPE_BT(t));
514 ts_push(t);
515 return;
518 if ((n = global_find(name)) != -1) {
519 struct type *t = &globals[n].type;
520 o_symaddr(globals[n].addr, TYPE_BT(t));
521 ts_push(t);
522 return;
524 if (!enum_find(&n, name)) {
525 ts_push_bt(4 | BT_SIGNED);
526 o_num(n, 4 | BT_SIGNED);
527 return;
529 if (tok_see() != '(')
530 die("unknown symbol\n");
531 unkn.addr = o_mkundef(unkn.name, 0);
532 global_add(&unkn);
533 ts_push_bt(8);
534 o_symaddr(unkn.addr, 8);
535 return;
537 if (!tok_jmp('(')) {
538 struct type t;
539 if (!readtype(&t)) {
540 struct type o;
541 tok_expect(')');
542 readpre();
543 ts_pop(&o);
544 ts_push(&t);
545 if (!t.ptr || !o.ptr)
546 o_cast(TYPE_BT(&t));
547 } else {
548 readexpr();
549 tok_expect(')');
551 return;
555 void arrayderef(struct type *t)
557 int sz = type_totsz(t);
558 if (sz > 1) {
559 o_num(sz, 4);
560 o_mul();
562 o_add();
563 o_deref(TYPE_BT(t));
566 static void inc_post(void (*op)(void))
568 unsigned bt = TYPE_BT(&ts[nts - 1]);
569 o_tmpcopy();
570 o_load();
571 o_tmpswap();
572 o_tmpcopy();
573 o_num(1, 4);
574 ts_push_bt(bt);
575 ts_push_bt(bt);
576 ts_binop_add(op);
577 ts_pop(NULL);
578 o_assign(bt);
579 o_tmpdrop(1);
582 static void readfield(void)
584 struct name *field;
585 struct type t;
586 tok_expect(TOK_NAME);
587 ts_pop(&t);
588 field = struct_field(t.id, tok_id());
589 if (field->addr) {
590 o_num(field->addr, 4);
591 o_add();
593 o_deref(TYPE_BT(&field->type));
594 ts_push(&field->type);
597 #define MAXFUNCS (1 << 10)
599 static struct funcinfo {
600 struct type args[MAXFIELDS];
601 struct type ret;
602 int nargs;
603 } funcs[MAXFUNCS];
604 static int nfuncs;
605 static unsigned ret_bt;
607 static int func_create(struct type *ret, struct name *args, int nargs)
609 struct funcinfo *fi = &funcs[nfuncs++];
610 int i;
611 memcpy(&fi->ret, ret, sizeof(*ret));
612 for (i = 0; i < nargs; i++)
613 memcpy(&fi->args[i], &args[i].type, sizeof(*ret));
614 fi->nargs = nargs;
615 return fi - funcs;
618 static void readcall(void)
620 struct type t;
621 unsigned bt[MAXARGS];
622 struct funcinfo *fi;
623 int argc = 0;
624 int i;
625 if (tok_see() != ')') {
626 readexpr();
627 ts_pop(&t);
628 bt[argc++] = TYPE_BT(&t);
630 while (!tok_jmp(',')) {
631 readexpr();
632 ts_pop(&t);
633 bt[argc++] = TYPE_BT(&t);
635 tok_expect(')');
636 ts_pop(&t);
637 if (t.flags & T_FUNC && t.ptr > 0)
638 o_deref(8);
639 fi = t.flags & T_FUNC ? &funcs[t.id] : NULL;
640 if (fi)
641 for (i = 0; i < fi->nargs; i++)
642 bt[i] = TYPE_BT(&fi->args[i]);
643 o_call(argc, bt, fi ? TYPE_BT(&fi->ret) : 4 | BT_SIGNED);
644 if (fi)
645 ts_push(&fi->ret);
646 else
647 ts_push_bt(4 | BT_SIGNED);
650 static void readpost(void)
652 readprimary();
653 while (1) {
654 if (!tok_jmp('[')) {
655 struct type t;
656 ts_pop(&t);
657 readexpr();
658 ts_pop(NULL);
659 tok_expect(']');
660 array2ptr(&t);
661 t.ptr--;
662 arrayderef(&t);
663 ts_push(&t);
664 continue;
666 if (!tok_jmp('(')) {
667 readcall();
668 continue;
670 if (!tok_jmp(TOK2("++"))) {
671 inc_post(o_add);
672 continue;
674 if (!tok_jmp(TOK2("--"))) {
675 inc_post(o_sub);
676 continue;
678 if (!tok_jmp('.')) {
679 o_addr();
680 readfield();
681 continue;
683 if (!tok_jmp(TOK2("->"))) {
684 readfield();
685 continue;
687 break;
691 static void inc_pre(void (*op)(void))
693 unsigned bt = TYPE_BT(&ts[nts - 1]);
694 readpre();
695 o_tmpcopy();
696 o_num(1, 4);
697 ts_push_bt(bt);
698 ts_push_bt(bt);
699 ts_binop_add(op);
700 ts_pop(NULL);
701 o_assign(bt);
704 static void readpre(void)
706 if (!tok_jmp('&')) {
707 struct type type;
708 readpre();
709 ts_pop(&type);
710 if (!(type.flags & T_FUNC) && !type.ptr)
711 type.ptr++;
712 ts_push(&type);
713 o_addr();
714 return;
716 if (!tok_jmp('*')) {
717 struct type t;
718 readpre();
719 ts_pop(&t);
720 array2ptr(&t);
721 if (!(t.flags & T_FUNC) || t.ptr > 0) {
722 t.ptr--;
723 o_deref(TYPE_BT(&t));
725 ts_push(&t);
726 return;
728 if (!tok_jmp('!')) {
729 struct type type;
730 readpre();
731 ts_pop(&type);
732 o_lnot();
733 ts_push_bt(4 | BT_SIGNED);
734 return;
736 if (!tok_jmp('-')) {
737 readpre();
738 o_neg();
739 return;
741 if (!tok_jmp('~')) {
742 readpre();
743 o_not();
744 return;
746 if (!tok_jmp(TOK2("++"))) {
747 inc_pre(o_add);
748 return;
750 if (!tok_jmp(TOK2("--"))) {
751 inc_pre(o_sub);
752 return;
754 if (!tok_jmp(TOK_SIZEOF)) {
755 struct type t;
756 int op = !tok_jmp('(');
757 if (readtype(&t)) {
758 int nogen = !o_nogen();
759 readexpr();
760 if (nogen)
761 o_dogen();
762 ts_pop(&t);
763 o_tmpdrop(1);
765 ts_push_bt(4);
766 o_num(type_totsz(&t), 4);
767 if (op)
768 tok_expect(')');
769 return;
771 readpost();
774 static void readmul(void)
776 readpre();
777 while (1) {
778 if (!tok_jmp('*')) {
779 readpre();
780 ts_binop(o_mul);
781 continue;
783 if (!tok_jmp('/')) {
784 readpre();
785 ts_binop(o_div);
786 continue;
788 if (!tok_jmp('%')) {
789 readpre();
790 ts_binop(o_mod);
791 continue;
793 break;
797 static void readadd(void)
799 readmul();
800 while (1) {
801 if (!tok_jmp('+')) {
802 readmul();
803 ts_binop_add(o_add);
804 continue;
806 if (!tok_jmp('-')) {
807 readmul();
808 ts_binop_add(o_sub);
809 continue;
811 break;
815 static void shift(void (*op)(void))
817 struct type t;
818 readadd();
819 ts_pop(NULL);
820 ts_pop(&t);
821 op();
822 ts_push_bt(TYPE_BT(&t));
825 static void readshift(void)
827 readadd();
828 while (1) {
829 if (!tok_jmp(TOK2("<<"))) {
830 shift(o_shl);
831 continue;
833 if (!tok_jmp(TOK2(">>"))) {
834 shift(o_shr);
835 continue;
837 break;
841 static void cmp(void (*op)(void))
843 readshift();
844 ts_pop(NULL);
845 ts_pop(NULL);
846 op();
847 ts_push_bt(4 | BT_SIGNED);
850 static void readcmp(void)
852 readshift();
853 while (1) {
854 if (!tok_jmp('<')) {
855 cmp(o_lt);
856 continue;
858 if (!tok_jmp('>')) {
859 cmp(o_gt);
860 continue;
862 if (!tok_jmp(TOK2("<="))) {
863 cmp(o_le);
864 continue;
866 if (!tok_jmp(TOK2(">="))) {
867 cmp(o_ge);
868 continue;
870 break;
874 static void eq(void (*op)(void))
876 readcmp();
877 ts_pop(NULL);
878 ts_pop(NULL);
879 op();
880 ts_push_bt(4 | BT_SIGNED);
883 static void readeq(void)
885 readcmp();
886 while (1) {
887 if (!tok_jmp(TOK2("=="))) {
888 eq(o_eq);
889 continue;
891 if (!tok_jmp(TOK2("!="))) {
892 eq(o_neq);
893 continue;
895 break;
899 static void readbitand(void)
901 readeq();
902 while (!tok_jmp('&')) {
903 readeq();
904 ts_binop(o_and);
908 static void readxor(void)
910 readbitand();
911 while (!tok_jmp('^')) {
912 readbitand();
913 ts_binop(o_xor);
917 static void readbitor(void)
919 readxor();
920 while (!tok_jmp('|')) {
921 readxor();
922 ts_binop(o_or);
926 #define MAXCOND (1 << 7)
928 static void readand(void)
930 long conds[MAXCOND];
931 int nconds = 0;
932 long passed;
933 int i;
934 readbitor();
935 if (tok_see() != TOK2("&&"))
936 return;
937 conds[nconds++] = o_jz(0);
938 ts_pop(NULL);
939 while (!tok_jmp(TOK2("&&"))) {
940 readbitor();
941 conds[nconds++] = o_jz(0);
942 ts_pop(NULL);
944 o_num(1, 4 | BT_SIGNED);
945 o_tmpfork();
946 passed = o_jmp(0);
947 for (i = 0; i < nconds; i++)
948 o_filljmp(conds[i]);
949 o_num(0, 4 | BT_SIGNED);
950 o_tmpjoin();
951 o_filljmp(passed);
952 ts_push_bt(4 | BT_SIGNED);
955 static void reador(void)
957 long conds[MAXCOND];
958 int nconds = 0;
959 long failed;
960 int i;
961 readand();
962 if (tok_see() != TOK2("||"))
963 return;
964 conds[nconds++] = o_jnz(0);
965 ts_pop(NULL);
966 while (!tok_jmp(TOK2("||"))) {
967 readand();
968 conds[nconds++] = o_jnz(0);
969 ts_pop(NULL);
971 o_num(0, 4 | BT_SIGNED);
972 o_tmpfork();
973 failed = o_jmp(0);
974 for (i = 0; i < nconds; i++)
975 o_filljmp(conds[i]);
976 o_num(1, 4 | BT_SIGNED);
977 o_tmpjoin();
978 o_filljmp(failed);
979 ts_push_bt(4 | BT_SIGNED);
982 static void readcexpr(void)
984 long l1, l2;
985 long c;
986 int cexpr, nogen;
987 reador();
988 if (tok_jmp('?'))
989 return;
990 ncexpr++;
991 cexpr = !o_popnum(&c);
992 ts_pop(NULL);
993 if (cexpr) {
994 if (!c)
995 nogen = !o_nogen();
996 } else {
997 l1 = o_jz(0);
999 reador();
1000 if (!cexpr) {
1001 o_tmpfork();
1002 l2 = o_jmp(0);
1004 ts_pop(NULL);
1005 tok_expect(':');
1006 if (cexpr) {
1007 if (c) {
1008 nogen = !o_nogen();
1009 } else {
1010 if (nogen)
1011 o_dogen();
1012 o_tmpdrop(1);
1014 } else {
1015 o_filljmp(l1);
1017 reador();
1018 if (cexpr) {
1019 if (c) {
1020 if (nogen)
1021 o_dogen();
1022 o_tmpdrop(1);
1024 } else {
1025 o_tmpjoin();
1026 o_filljmp(l2);
1028 ncexpr--;
1031 static void opassign(void (*bop)(void (*op)(void)), void (*op)(void))
1033 unsigned bt = TYPE_BT(&ts[nts - 1]);
1034 o_tmpcopy();
1035 readexpr();
1036 bop(op);
1037 ts_pop(NULL);
1038 o_assign(bt);
1041 static void doassign(void)
1043 struct type t;
1044 ts_pop(&t);
1045 if (!t.ptr && t.flags & T_STRUCT)
1046 o_memcpy(type_totsz(&t));
1047 else
1048 o_assign(TYPE_BT(&ts[nts - 1]));
1051 static void readexpr(void)
1053 readcexpr();
1054 if (!tok_jmp('=')) {
1055 readexpr();
1056 doassign();
1057 return;
1059 if (!tok_jmp(TOK2("+="))) {
1060 opassign(ts_binop_add, o_add);
1061 return;
1063 if (!tok_jmp(TOK2("-="))) {
1064 opassign(ts_binop_add, o_sub);
1065 return;
1067 if (!tok_jmp(TOK2("*="))) {
1068 opassign(ts_binop, o_mul);
1069 return;
1071 if (!tok_jmp(TOK2("/="))) {
1072 opassign(ts_binop, o_div);
1073 return;
1075 if (!tok_jmp(TOK2("%="))) {
1076 opassign(ts_binop, o_mod);
1077 return;
1079 if (!tok_jmp(TOK3("<<="))) {
1080 opassign(ts_binop, o_shl);
1081 return;
1083 if (!tok_jmp(TOK3(">>="))) {
1084 opassign(ts_binop, o_shr);
1085 return;
1087 if (!tok_jmp(TOK3("&="))) {
1088 opassign(ts_binop, o_and);
1089 return;
1091 if (!tok_jmp(TOK3("|="))) {
1092 opassign(ts_binop, o_or);
1093 return;
1095 if (!tok_jmp(TOK3("^="))) {
1096 opassign(ts_binop, o_xor);
1097 return;
1101 static void readestmt(void)
1103 do {
1104 o_tmpdrop(-1);
1105 nts = 0;
1106 readexpr();
1107 } while (!tok_jmp(','));
1110 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1112 static void globaldef(void *data, struct name *name, unsigned flags)
1114 char *varname = flags & F_STATIC ? NULL : name->name;
1115 int sz = type_totsz(&name->type);
1116 if (flags & F_EXTERN)
1117 name->addr = o_mkundef(varname, sz);
1118 else
1119 name->addr = o_mkvar(varname, sz, F_GLOBAL(flags));
1120 global_add(name);
1123 static void o_localoff(long addr, int off, unsigned bt)
1125 o_local(addr, bt);
1126 if (off) {
1127 o_addr();
1128 o_num(off, 4);
1129 o_add();
1130 o_deref(bt);
1134 static struct type *innertype(struct type *t)
1136 if (t->flags & T_ARRAY && !t->ptr)
1137 return innertype(&arrays[t->id].type);
1138 return t;
1141 static void initexpr(struct type *t, long addr, int off)
1143 if (t->flags & T_ARRAY && tok_see() == TOK_STR) {
1144 struct type *t_de = &arrays[t->id].type;
1145 if (!t_de->ptr && !t_de->flags && TYPE_SZ(t_de) == 1) {
1146 char buf[BUFSIZE];
1147 int len;
1148 tok_expect(TOK_STR);
1149 len = tok_str(buf);
1150 o_localoff(addr, off, TYPE_BT(t));
1151 o_symaddr(o_mkdat(NULL, buf, len, 0), TYPE_BT(t));
1152 o_memcpy(len);
1153 o_tmpdrop(1);
1154 o_localoff(addr, off + len, TYPE_BT(t));
1155 o_memset(0, arrays[t->id].n - len);
1156 o_tmpdrop(1);
1157 return;
1160 if (tok_jmp('{')) {
1161 o_localoff(addr, off, TYPE_BT(t));
1162 ts_push(t);
1163 readexpr();
1164 doassign();
1165 ts_pop(NULL);
1166 o_tmpdrop(1);
1167 return;
1169 if (!t->ptr && t->flags & T_STRUCT) {
1170 struct structinfo *si = &structs[t->id];
1171 int i;
1172 for (i = 0; i < si->nfields; i++) {
1173 struct name *field = &si->fields[i];
1174 if (!tok_jmp('.')) {
1175 tok_expect(TOK_NAME);
1176 field = struct_field(t->id, tok_id());
1177 tok_expect('=');
1179 initexpr(&field->type, addr, off + field->addr);
1180 if (tok_jmp(',') || tok_see() == '}')
1181 break;
1183 } else if (t->flags & T_ARRAY) {
1184 struct type *t_de = &arrays[t->id].type;
1185 int i;
1186 for (i = 0; ; i++) {
1187 long idx = i;
1188 struct type *it = t_de;
1189 if (!tok_jmp('[')) {
1190 readexpr();
1191 o_popnum(&idx);
1192 ts_pop(NULL);
1193 tok_expect(']');
1194 tok_expect('=');
1196 if (tok_see() != '{')
1197 it = innertype(t_de);
1198 initexpr(it, addr, off + type_totsz(it) * idx);
1199 if (tok_jmp(',') || tok_see() == '}')
1200 break;
1203 tok_expect('}');
1206 static void localdef(void *data, struct name *name, unsigned flags)
1208 if (flags & (F_STATIC | F_EXTERN)) {
1209 globaldef(data, name, flags);
1210 return;
1212 name->addr = o_mklocal(type_totsz(&name->type));
1213 local_add(name);
1214 if (flags & F_INIT) {
1215 struct type *t = &name->type;
1216 if (tok_see() == '{') {
1217 o_local(name->addr, TYPE_BT(t));
1218 o_memset(0, type_totsz(t));
1219 o_tmpdrop(1);
1221 initexpr(t, name->addr, 0);
1225 static void funcdef(char *name, struct type *type, struct name *args,
1226 int nargs, unsigned flags)
1228 int i;
1229 struct name global;
1230 strcpy(global.name, name);
1231 memcpy(&global.type, type, sizeof(*type));
1232 global.addr = o_func_beg(name, F_GLOBAL(flags));
1233 global_add(&global);
1234 ret_bt = TYPE_BT(&funcs[type->id].ret);
1235 for (i = 0; i < nargs; i++) {
1236 args[i].addr = o_arg(i, type_totsz(&args[i].type));
1237 local_add(&args[i]);
1241 static int readargs(struct name *args)
1243 int nargs = 0;
1244 tok_expect('(');
1245 while (tok_see() != ')') {
1246 readname(&args[nargs].type, args[nargs].name, NULL, 0);
1247 array2ptr(&args[nargs].type);
1248 nargs++;
1249 if (tok_jmp(','))
1250 break;
1252 tok_expect(')');
1253 if (nargs == 1 && !TYPE_BT(&args[0].type))
1254 return 0;
1255 return nargs;
1258 static int readname(struct type *main, char *name,
1259 struct type *base, unsigned flags)
1261 struct type tpool[3];
1262 int npool = 0;
1263 struct type *type = &tpool[npool++];
1264 struct type *func = NULL;
1265 struct type *ret = NULL;
1266 memset(tpool, 0, sizeof(tpool));
1267 if (name)
1268 *name = '\0';
1269 if (!base) {
1270 if (basetype(type, &flags))
1271 return 1;
1272 } else {
1273 memcpy(type, base, sizeof(*base));
1275 readptrs(type);
1276 if (!tok_jmp('(')) {
1277 ret = type;
1278 type = &tpool[npool++];
1279 func = type;
1280 readptrs(type);
1282 if (!tok_jmp(TOK_NAME) && name)
1283 strcpy(name, tok_id());
1284 while (!tok_jmp('[')) {
1285 long n;
1286 if (tok_jmp(']')) {
1287 readexpr();
1288 ts_pop(NULL);
1289 if (o_popnum(&n))
1290 die("const expr expected\n");
1291 tok_expect(']');
1293 type->id = array_add(type, n);
1294 if (type->flags & T_FUNC)
1295 func = &arrays[type->id].type;
1296 type->flags = T_ARRAY;
1297 type->bt = 8;
1298 type->ptr = 0;
1300 if (func)
1301 tok_expect(')');
1302 if (tok_see() == '(') {
1303 struct name args[MAXARGS];
1304 int nargs = readargs(args);
1305 int fdef = !func;
1306 if (!func) {
1307 ret = type;
1308 type = &tpool[npool++];
1309 func = type;
1311 func->flags = T_FUNC;
1312 func->bt = 8;
1313 func->id = func_create(ret, args, nargs);
1314 if (fdef && tok_see() == '{') {
1315 funcdef(name, func, args, nargs, flags);
1316 return 1;
1319 memcpy(main, type, sizeof(*type));
1320 return 0;
1323 static int readdefs(void (*def)(void *data, struct name *name, unsigned flags),
1324 void *data)
1326 struct type base;
1327 unsigned flags;
1328 if (basetype(&base, &flags))
1329 return 1;
1330 while (tok_see() != ';' && tok_see() != '{') {
1331 struct name name;
1332 if (readname(&name.type, name.name, &base, flags))
1333 break;
1334 if (!tok_jmp('='))
1335 flags |= F_INIT;
1336 def(data, &name, flags);
1337 tok_jmp(',');
1339 return 0;
1342 static void typedefdef(void *data, struct name *name, unsigned flags)
1344 typedef_add(name->name, &name->type);
1347 static void readstmt(void);
1349 #define MAXCASES (1 << 7)
1351 static void readswitch(void)
1353 int break_beg = nbreaks;
1354 long val_addr = o_mklocal(8);
1355 long matched[MAXCASES];
1356 int nmatched = 0;
1357 struct type t;
1358 long next;
1359 int ref = 1;
1360 int i;
1361 tok_expect('(');
1362 readexpr();
1363 ts_pop(&t);
1364 o_local(val_addr, TYPE_BT(&t));
1365 o_tmpswap();
1366 o_assign(TYPE_BT(&t));
1367 o_tmpdrop(1);
1368 tok_expect(')');
1369 tok_expect('{');
1370 while (tok_jmp('}')) {
1371 int n = 0;
1372 while (tok_see() == TOK_CASE || tok_see() == TOK_DEFAULT) {
1373 if (n++ > 0)
1374 matched[nmatched++] = o_jmp(0);
1375 if (!ref++)
1376 o_filljmp(next);
1377 if (!tok_jmp(TOK_CASE)) {
1378 readexpr();
1379 o_local(val_addr, TYPE_BT(&t));
1380 o_eq();
1381 next = o_jz(0);
1382 ref = 0;
1383 tok_expect(':');
1384 o_tmpdrop(1);
1385 ts_pop(NULL);
1386 continue;
1388 if (!tok_jmp(TOK_DEFAULT)) {
1389 tok_expect(':');
1390 continue;
1393 for (i = 0; i < nmatched; i++)
1394 o_filljmp(matched[i]);
1395 nmatched = 0;
1396 readstmt();
1398 o_rmlocal(val_addr, 8);
1399 if (!ref++)
1400 o_filljmp(next);
1401 break_fill(o_mklabel(), break_beg);
1404 #define MAXGOTO (1 << 10)
1406 static struct gotoinfo {
1407 char name[NAMELEN];
1408 long addr;
1409 } gotos[MAXGOTO];
1410 static int ngotos;
1412 static struct labelinfo {
1413 char name[NAMELEN];
1414 long addr;
1415 } labels[MAXGOTO];
1416 static int nlabels;
1418 static void goto_add(char *name)
1420 strcpy(gotos[ngotos].name, name);
1421 gotos[ngotos++].addr = o_jmp(0);
1424 static void label_add(char *name)
1426 strcpy(labels[nlabels].name, name);
1427 labels[nlabels++].addr = o_mklabel();
1430 static void goto_fill(void)
1432 int i, j;
1433 for (i = 0; i < ngotos; i++)
1434 for (j = 0; j < nlabels; j++)
1435 if (!strcmp(gotos[i].name, labels[j].name)) {
1436 o_filljmp2(gotos[i].addr, labels[j].addr);
1437 break;
1441 static void readstmt(void)
1443 o_tmpdrop(-1);
1444 nts = 0;
1445 if (!tok_jmp('{')) {
1446 int _nlocals = nlocals;
1447 int _nglobals = nglobals;
1448 int _nenums = nenums;
1449 int _ntypedefs = ntypedefs;
1450 int _nstructs = nstructs;
1451 int _nfuncs = nfuncs;
1452 int _narrays = narrays;
1453 while (tok_jmp('}'))
1454 readstmt();
1455 nlocals = _nlocals;
1456 nenums = _nenums;
1457 ntypedefs = _ntypedefs;
1458 nstructs = _nstructs;
1459 nfuncs = _nfuncs;
1460 narrays = _narrays;
1461 nglobals = _nglobals;
1462 return;
1464 if (!readdefs(localdef, NULL)) {
1465 tok_expect(';');
1466 return;
1468 if (!tok_jmp(TOK_TYPEDEF)) {
1469 readdefs(typedefdef, NULL);
1470 tok_expect(';');
1471 return;
1473 if (!tok_jmp(TOK_IF)) {
1474 long l1, l2;
1475 tok_expect('(');
1476 readexpr();
1477 tok_expect(')');
1478 l1 = o_jz(0);
1479 readstmt();
1480 if (!tok_jmp(TOK_ELSE)) {
1481 l2 = o_jmp(0);
1482 o_filljmp(l1);
1483 readstmt();
1484 o_filljmp(l2);
1485 } else {
1486 o_filljmp(l1);
1488 return;
1490 if (!tok_jmp(TOK_WHILE)) {
1491 long l1, l2;
1492 int break_beg = nbreaks;
1493 int continue_beg = ncontinues;
1494 l1 = o_mklabel();
1495 tok_expect('(');
1496 readexpr();
1497 tok_expect(')');
1498 l2 = o_jz(0);
1499 readstmt();
1500 o_jmp(l1);
1501 o_filljmp(l2);
1502 break_fill(o_mklabel(), break_beg);
1503 continue_fill(l1, continue_beg);
1504 return;
1506 if (!tok_jmp(TOK_DO)) {
1507 long l1, l2;
1508 int break_beg = nbreaks;
1509 int continue_beg = ncontinues;
1510 l1 = o_mklabel();
1511 readstmt();
1512 tok_expect(TOK_WHILE);
1513 tok_expect('(');
1514 l2 = o_mklabel();
1515 readexpr();
1516 o_jnz(l1);
1517 tok_expect(')');
1518 break_fill(o_mklabel(), break_beg);
1519 continue_fill(l2, continue_beg);
1520 return;
1522 if (!tok_jmp(TOK_FOR)) {
1523 long check, jump, end, body;
1524 int break_beg = nbreaks;
1525 int continue_beg = ncontinues;
1526 tok_expect('(');
1527 if (tok_see() != ';')
1528 readestmt();
1529 tok_expect(';');
1530 check = o_mklabel();
1531 if (tok_see() != ';')
1532 readestmt();
1533 tok_expect(';');
1534 end = o_jz(0);
1535 body = o_jmp(0);
1536 jump = o_mklabel();
1537 if (tok_see() != ')')
1538 readestmt();
1539 tok_expect(')');
1540 o_jmp(check);
1541 o_filljmp(body);
1542 readstmt();
1543 o_jmp(jump);
1544 o_filljmp(end);
1545 break_fill(o_mklabel(), break_beg);
1546 continue_fill(jump, continue_beg);
1547 return;
1549 if (!tok_jmp(TOK_SWITCH)) {
1550 readswitch();
1551 return;
1553 if (!tok_jmp(TOK_RETURN)) {
1554 int ret = tok_see() != ';';
1555 if (ret)
1556 readexpr();
1557 tok_expect(';');
1558 o_ret(ret_bt);
1559 return;
1561 if (!tok_jmp(TOK_BREAK)) {
1562 tok_expect(';');
1563 breaks[nbreaks++] = o_jmp(0);
1564 return;
1566 if (!tok_jmp(TOK_CONTINUE)) {
1567 tok_expect(';');
1568 continues[ncontinues++] = o_jmp(0);
1569 return;
1571 if (!tok_jmp(TOK_GOTO)) {
1572 tok_expect(TOK_NAME);
1573 goto_add(tok_id());
1574 tok_expect(';');
1575 return;
1577 readestmt();
1578 /* labels */
1579 if (!tok_jmp(':')) {
1580 label_add(tok_id());
1581 return;
1583 tok_expect(';');
1586 static void readdecl(void)
1588 if (!tok_jmp(TOK_TYPEDEF)) {
1589 readdefs(typedefdef, NULL);
1590 tok_expect(';');
1591 return;
1593 readdefs(globaldef, NULL);
1594 if (tok_see() == '{') {
1595 readstmt();
1596 goto_fill();
1597 o_func_end();
1598 nlocals = 0;
1599 ngotos = 0;
1600 nlabels = 0;
1601 return;
1603 tok_expect(';');
1606 static void parse(void)
1608 while (tok_see() != TOK_EOF)
1609 readdecl();
1612 int main(int argc, char *argv[])
1614 char obj[128];
1615 int ifd, ofd;
1616 int i = 1;
1617 while (i < argc && argv[i][0] == '-')
1618 i++;
1619 if (i == argc)
1620 die("no file given\n");
1621 ifd = open(argv[i], O_RDONLY);
1622 tok_init(ifd);
1623 close(ifd);
1624 parse();
1626 strcpy(obj, argv[i]);
1627 obj[strlen(obj) - 1] = 'o';
1628 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
1629 out_write(ofd);
1630 close(ofd);
1631 return 0;