invalidate last_cmp if tmps are changed
[neatcc.git] / ncc.c
blobf17b53ff92b45a5694a2f40ebcd957145d819e34
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 void die(char *s)
69 print(s);
70 exit(1);
73 struct name {
74 char name[NAMELEN];
75 struct type type;
76 long addr;
77 int unused; /* unreferenced external symbols */
80 static struct name locals[MAXLOCALS];
81 static int nlocals;
82 static struct name globals[MAXGLOBALS];
83 static int nglobals;
85 static void local_add(struct name *name)
87 if (nlocals >= MAXLOCALS)
88 die("nomem: MAXLOCALS reached!\n");
89 memcpy(&locals[nlocals++], name, sizeof(*name));
92 static int global_find(char *name)
94 int i;
95 for (i = 0; i < nglobals; i++)
96 if (!strcmp(name, globals[i].name))
97 return i;
98 return -1;
101 static void global_add(struct name *name)
103 int found = global_find(name->name);
104 int i = found == -1 ? nglobals++ : found;
105 if (nglobals >= MAXGLOBALS)
106 die("nomem: MAXGLOBALS reached!\n");
107 memcpy(&globals[i], name, sizeof(*name));
110 #define MAXENUMS (1 << 10)
112 static struct enumval {
113 char name[NAMELEN];
114 int n;
115 } enums[MAXENUMS];
116 static int nenums;
118 static void enum_add(char *name, int val)
120 struct enumval *ev = &enums[nenums++];
121 if (nenums >= MAXENUMS)
122 die("nomem: MAXENUMS reached!\n");
123 strcpy(ev->name, name);
124 ev->n = val;
127 static int enum_find(int *val, char *name)
129 int i;
130 for (i = nenums - 1; i >= 0; --i)
131 if (!strcmp(name, enums[i].name)) {
132 *val = enums[i].n;
133 return 0;
135 return 1;
138 #define MAXTYPEDEFS (1 << 10)
140 static struct typdefinfo {
141 char name[NAMELEN];
142 struct type type;
143 } typedefs[MAXTYPEDEFS];
144 static int ntypedefs;
146 static void typedef_add(char *name, struct type *type)
148 struct typdefinfo *ti = &typedefs[ntypedefs++];
149 if (ntypedefs >= MAXTYPEDEFS)
150 die("nomem: MAXTYPEDEFS reached!\n");
151 strcpy(ti->name, name);
152 memcpy(&ti->type, type, sizeof(*type));
155 static int typedef_find(char *name)
157 int i;
158 for (i = ntypedefs - 1; i >= 0; --i)
159 if (!strcmp(name, typedefs[i].name))
160 return i;
161 return -1;
164 #define MAXARRAYS (1 << 10)
166 static struct array {
167 struct type type;
168 int n;
169 } arrays[MAXARRAYS];
170 static int narrays;
172 static int array_add(struct type *type, int n)
174 struct array *a = &arrays[narrays++];
175 if (narrays >= MAXARRAYS)
176 die("nomem: MAXARRAYS reached!\n");
177 memcpy(&a->type, type, sizeof(*type));
178 a->n = n;
179 return a - arrays;
182 static void array2ptr(struct type *t)
184 if (!(t->flags & T_ARRAY) || t->ptr)
185 return;
186 memcpy(t, &arrays[t->id].type, sizeof(*t));
187 t->ptr++;
190 #define MAXSTRUCTS (1 << 10)
191 #define MAXFIELDS (1 << 7)
193 static struct structinfo {
194 char name[NAMELEN];
195 struct name fields[MAXFIELDS];
196 int nfields;
197 int isunion;
198 int size;
199 } structs[MAXSTRUCTS];
200 static int nstructs;
202 static int struct_find(char *name, int isunion)
204 int i;
205 for (i = nstructs - 1; i >= 0; --i)
206 if (*structs[i].name && !strcmp(name, structs[i].name) &&
207 structs[i].isunion == isunion)
208 return i;
209 i = nstructs++;
210 if (nstructs >= MAXSTRUCTS)
211 die("nomem: MAXTYPES reached!\n");
212 memset(&structs[i], 0, sizeof(structs[i]));
213 strcpy(structs[i].name, name);
214 structs[i].isunion = isunion;
215 return i;
218 static struct name *struct_field(int id, char *name)
220 struct structinfo *si = &structs[id];
221 int i;
222 for (i = 0; i < si->nfields; i++)
223 if (!strcmp(name, si->fields[i].name))
224 return &si->fields[i];
225 die("field not found\n");
228 #define MAXBREAK (1 << 7)
230 static long breaks[MAXBREAK];
231 static int nbreaks;
232 static long continues[MAXBREAK];
233 static int ncontinues;
235 static void break_fill(long addr, int till)
237 int i;
238 for (i = till; i < nbreaks; i++)
239 o_filljmp2(breaks[i], addr);
240 nbreaks = till;
243 static void continue_fill(long addr, int till)
245 int i;
246 for (i = till; i < ncontinues; i++)
247 o_filljmp2(continues[i], addr);
248 ncontinues = till;
251 static int type_totsz(struct type *t)
253 if (t->ptr)
254 return 8;
255 if (t->flags & T_ARRAY)
256 return arrays[t->id].n * type_totsz(&arrays[t->id].type);
257 return t->flags & T_STRUCT ? structs[t->id].size : BT_SZ(t->bt);
260 static unsigned type_szde(struct type *t)
262 if (t->flags & T_ARRAY)
263 return t->ptr > 0 ? 8 : TYPE_SZ(&arrays[t->id].type);
264 else
265 return t->ptr > 1 ? 8 : BT_SZ(t->bt);
268 static int tok_jmp(int tok)
270 if (tok_see() != tok)
271 return 1;
272 tok_get();
273 return 0;
276 static void tok_expect(int tok)
278 if (tok_get() != tok)
279 die("syntax error\n");
282 static unsigned bt_op(unsigned bt1, unsigned bt2)
284 unsigned s1 = BT_SZ(bt1);
285 unsigned s2 = BT_SZ(bt2);
286 return (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
289 static void ts_binop(void (*o_sth)(void))
291 struct type t1, t2;
292 ts_pop(&t1);
293 ts_pop(&t2);
294 o_sth();
295 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
298 static int shifts(int n)
300 int i = -1;
301 while (i++ < 16)
302 if (n == 1 << i)
303 break;
304 return i;
307 static void ts_binop_add(void (*o_sth)(void))
309 struct type t1, t2;
310 ts_pop(&t1);
311 ts_pop(&t2);
312 array2ptr(&t1);
313 array2ptr(&t2);
314 if (!t1.ptr && !t2.ptr) {
315 o_sth();
316 ts_push_bt(bt_op(TYPE_BT(&t1), TYPE_BT(&t2)));
317 return;
319 if (t1.ptr && !t2.ptr) {
320 struct type t = t2;
321 t2 = t1;
322 t1 = t;
323 o_tmpswap();
325 if (!t1.ptr && t2.ptr)
326 if (type_szde(&t2) > 1) {
327 o_num(shifts(type_szde(&t2)), 1);
328 o_shl();
330 o_sth();
331 if (t1.ptr && t2.ptr) {
332 o_num(shifts(type_szde(&t1)), 1);
333 o_shr();
334 ts_push_bt(4 | BT_SIGNED);
335 } else {
336 ts_push(&t2);
340 static void structdef(void *data, struct name *name, unsigned flags)
342 struct structinfo *si = data;
343 if (si->isunion) {
344 name->addr = 0;
345 if (si->size < type_totsz(&name->type))
346 si->size = type_totsz(&name->type);
347 } else {
348 name->addr = si->size;
349 si->size += type_totsz(&name->type);
351 memcpy(&si->fields[si->nfields++], name, sizeof(*name));
354 static int readdefs(void (*def)(void *, struct name *, unsigned f), void *data);
356 static int struct_create(char *name, int isunion)
358 int id = struct_find(name, isunion);
359 struct structinfo *si = &structs[id];
360 tok_expect('{');
361 while (tok_jmp('}')) {
362 readdefs(structdef, si);
363 tok_expect(';');
365 return id;
368 static void readexpr(void);
370 static void enum_create(void)
372 long n = 0;
373 tok_expect('{');
374 while (tok_jmp('}')) {
375 char name[NAMELEN];
376 tok_expect(TOK_NAME);
377 strcpy(name, tok_id());
378 if (tok_see() == '=') {
379 tok_get();
380 readexpr();
381 ts_pop(NULL);
382 if (o_popnum(&n))
383 die("const expr expected!\n");
385 enum_add(name, n++);
386 tok_jmp(',');
390 static int basetype(struct type *type, unsigned *flags)
392 int sign = 1;
393 int size = 4;
394 int done = 0;
395 int i = 0;
396 int isunion;
397 char name[NAMELEN] = "";
398 *flags = 0;
399 type->flags = 0;
400 type->ptr = 0;
401 while (!done) {
402 switch (tok_see()) {
403 case TOK_STATIC:
404 *flags |= F_STATIC;
405 break;
406 case TOK_EXTERN:
407 *flags |= F_EXTERN;
408 break;
409 case TOK_VOID:
410 sign = 0;
411 size = 0;
412 done = 1;
413 break;
414 case TOK_INT:
415 done = 1;
416 break;
417 case TOK_CHAR:
418 size = 1;
419 done = 1;
420 break;
421 case TOK_SHORT:
422 size = 2;
423 break;
424 case TOK_LONG:
425 size = 8;
426 break;
427 case TOK_SIGNED:
428 break;
429 case TOK_UNSIGNED:
430 sign = 0;
431 break;
432 case TOK_UNION:
433 case TOK_STRUCT:
434 isunion = tok_get() == TOK_UNION;
435 if (!tok_jmp(TOK_NAME))
436 strcpy(name, tok_id());
437 if (tok_see() == '{')
438 type->id = struct_create(name, isunion);
439 else
440 type->id = struct_find(name, isunion);
441 type->flags |= T_STRUCT;
442 type->bt = 8;
443 return 0;
444 case TOK_ENUM:
445 tok_get();
446 tok_jmp(TOK_NAME);
447 if (tok_see() == '{')
448 enum_create();
449 type->bt = 4 | BT_SIGNED;
450 return 0;
451 default:
452 if (tok_see() == TOK_NAME) {
453 int id = typedef_find(tok_id());
454 if (id != -1) {
455 tok_get();
456 memcpy(type, &typedefs[id].type,
457 sizeof(*type));
458 return 0;
461 if (!i)
462 return 1;
463 done = 1;
464 continue;
466 i++;
467 tok_get();
469 type->bt = size | (sign ? BT_SIGNED : 0);
470 return 0;
473 static int readname(struct type *main, char *name,
474 struct type *base, unsigned flags);
476 static int readtype(struct type *type)
478 return readname(type, NULL, NULL, 0);
481 static void readptrs(struct type *type)
483 while (!tok_jmp('*')) {
484 type->ptr++;
485 if (!type->bt)
486 type->bt = 1;
490 static int ncexpr;
492 static void readpre(void);
494 static void readprimary(void)
496 int i;
497 if (!tok_jmp(TOK_NUM)) {
498 ts_push_bt(4 | BT_SIGNED);
499 o_num(tok_num(), 4 | BT_SIGNED);
500 return;
502 if (!tok_jmp(TOK_STR)) {
503 struct type t;
504 char buf[BUFSIZE];
505 int len;
506 t.bt = 1 | BT_SIGNED;
507 t.ptr = 1;
508 t.flags = 0;
509 ts_push(&t);
510 len = tok_str(buf);
511 o_symaddr(out_mkdat(NULL, buf, len, 0), TYPE_BT(&t));
512 o_addr();
513 return;
515 if (!tok_jmp(TOK_NAME)) {
516 struct name unkn;
517 char *name = unkn.name;
518 int n;
519 strcpy(name, tok_id());
520 /* don't search for labels here */
521 if (!ncexpr && tok_see() == ':')
522 return;
523 for (i = nlocals - 1; i >= 0; --i) {
524 struct type *t = &locals[i].type;
525 if (!strcmp(locals[i].name, name)) {
526 o_local(locals[i].addr, TYPE_BT(t));
527 ts_push(t);
528 return;
531 if ((n = global_find(name)) != -1) {
532 struct name *g = &globals[n];
533 struct type *t = &g->type;
534 if (g->unused) {
535 g->unused = 0;
536 if (t->flags & T_FUNC && !t->ptr)
537 g->addr = out_mkundef(name, 0);
538 else
539 g->addr = out_mkundef(name, type_totsz(t));
541 o_symaddr(g->addr, TYPE_BT(t));
542 ts_push(t);
543 return;
545 if (!enum_find(&n, name)) {
546 ts_push_bt(4 | BT_SIGNED);
547 o_num(n, 4 | BT_SIGNED);
548 return;
550 if (tok_see() != '(')
551 die("unknown symbol\n");
552 unkn.addr = out_mkundef(unkn.name, 0);
553 global_add(&unkn);
554 ts_push_bt(8);
555 o_symaddr(unkn.addr, 8);
556 return;
558 if (!tok_jmp('(')) {
559 struct type t;
560 if (!readtype(&t)) {
561 struct type o;
562 tok_expect(')');
563 readpre();
564 ts_pop(&o);
565 ts_push(&t);
566 if (!t.ptr || !o.ptr)
567 o_cast(TYPE_BT(&t));
568 } else {
569 readexpr();
570 tok_expect(')');
572 return;
576 void arrayderef(struct type *t)
578 int sz = type_totsz(t);
579 if (sz > 1) {
580 o_num(sz, 4);
581 o_mul();
583 o_add();
584 o_deref(TYPE_BT(t));
587 static void inc_post(void (*op)(void))
589 unsigned bt = TYPE_BT(&ts[nts - 1]);
590 o_tmpcopy();
591 o_load();
592 o_tmpswap();
593 o_tmpcopy();
594 o_num(1, 4);
595 ts_push_bt(bt);
596 ts_push_bt(bt);
597 ts_binop_add(op);
598 ts_pop(NULL);
599 o_assign(bt);
600 o_tmpdrop(1);
603 static void readfield(void)
605 struct name *field;
606 struct type t;
607 tok_expect(TOK_NAME);
608 ts_pop(&t);
609 array2ptr(&t);
610 field = struct_field(t.id, tok_id());
611 if (field->addr) {
612 o_num(field->addr, 4);
613 o_add();
615 o_deref(TYPE_BT(&field->type));
616 ts_push(&field->type);
619 #define MAXFUNCS (1 << 10)
621 static struct funcinfo {
622 struct type args[MAXFIELDS];
623 struct type ret;
624 int nargs;
625 } funcs[MAXFUNCS];
626 static int nfuncs;
627 static unsigned ret_bt;
629 static int func_create(struct type *ret, struct name *args, int nargs)
631 struct funcinfo *fi = &funcs[nfuncs++];
632 int i;
633 if (nfuncs >= MAXFUNCS)
634 die("nomem: MAXFUNCS reached!\n");
635 memcpy(&fi->ret, ret, sizeof(*ret));
636 for (i = 0; i < nargs; i++)
637 memcpy(&fi->args[i], &args[i].type, sizeof(*ret));
638 fi->nargs = nargs;
639 return fi - funcs;
642 static void readcall(void)
644 struct type t;
645 unsigned bt[MAXARGS];
646 struct funcinfo *fi;
647 int argc = 0;
648 int i;
649 if (tok_see() != ')') {
650 readexpr();
651 ts_pop(&t);
652 bt[argc++] = TYPE_BT(&t);
654 while (!tok_jmp(',')) {
655 readexpr();
656 ts_pop(&t);
657 bt[argc++] = TYPE_BT(&t);
659 tok_expect(')');
660 ts_pop(&t);
661 if (t.flags & T_FUNC && t.ptr > 0)
662 o_deref(8);
663 fi = t.flags & T_FUNC ? &funcs[t.id] : NULL;
664 if (fi)
665 for (i = 0; i < fi->nargs; i++)
666 bt[i] = TYPE_BT(&fi->args[i]);
667 o_call(argc, bt, fi ? TYPE_BT(&fi->ret) : 4 | BT_SIGNED);
668 if (fi)
669 ts_push(&fi->ret);
670 else
671 ts_push_bt(4 | BT_SIGNED);
674 static void readpost(void)
676 readprimary();
677 while (1) {
678 if (!tok_jmp('[')) {
679 struct type t;
680 ts_pop(&t);
681 readexpr();
682 ts_pop(NULL);
683 tok_expect(']');
684 array2ptr(&t);
685 t.ptr--;
686 arrayderef(&t);
687 ts_push(&t);
688 continue;
690 if (!tok_jmp('(')) {
691 readcall();
692 continue;
694 if (!tok_jmp(TOK2("++"))) {
695 inc_post(o_add);
696 continue;
698 if (!tok_jmp(TOK2("--"))) {
699 inc_post(o_sub);
700 continue;
702 if (!tok_jmp('.')) {
703 o_addr();
704 readfield();
705 continue;
707 if (!tok_jmp(TOK2("->"))) {
708 readfield();
709 continue;
711 break;
715 static void inc_pre(void (*op)(void))
717 unsigned bt = TYPE_BT(&ts[nts - 1]);
718 readpre();
719 o_tmpcopy();
720 o_num(1, 4);
721 ts_push_bt(bt);
722 ts_push_bt(bt);
723 ts_binop_add(op);
724 ts_pop(NULL);
725 o_assign(bt);
728 static void readpre(void)
730 if (!tok_jmp('&')) {
731 struct type type;
732 readpre();
733 ts_pop(&type);
734 if (!(type.flags & T_FUNC) && !type.ptr)
735 type.ptr++;
736 ts_push(&type);
737 o_addr();
738 return;
740 if (!tok_jmp('*')) {
741 struct type t;
742 readpre();
743 ts_pop(&t);
744 array2ptr(&t);
745 if (!(t.flags & T_FUNC) || t.ptr > 0) {
746 t.ptr--;
747 o_deref(TYPE_BT(&t));
749 ts_push(&t);
750 return;
752 if (!tok_jmp('!')) {
753 struct type type;
754 readpre();
755 ts_pop(&type);
756 o_lnot();
757 ts_push_bt(4 | BT_SIGNED);
758 return;
760 if (!tok_jmp('-')) {
761 readpre();
762 o_neg();
763 return;
765 if (!tok_jmp('~')) {
766 readpre();
767 o_not();
768 return;
770 if (!tok_jmp(TOK2("++"))) {
771 inc_pre(o_add);
772 return;
774 if (!tok_jmp(TOK2("--"))) {
775 inc_pre(o_sub);
776 return;
778 if (!tok_jmp(TOK_SIZEOF)) {
779 struct type t;
780 int op = !tok_jmp('(');
781 if (readtype(&t)) {
782 int nogen = !o_nogen();
783 readexpr();
784 if (nogen)
785 o_dogen();
786 ts_pop(&t);
787 o_tmpdrop(1);
789 ts_push_bt(4);
790 o_num(type_totsz(&t), 4);
791 if (op)
792 tok_expect(')');
793 return;
795 readpost();
798 static void readmul(void)
800 readpre();
801 while (1) {
802 if (!tok_jmp('*')) {
803 readpre();
804 ts_binop(o_mul);
805 continue;
807 if (!tok_jmp('/')) {
808 readpre();
809 ts_binop(o_div);
810 continue;
812 if (!tok_jmp('%')) {
813 readpre();
814 ts_binop(o_mod);
815 continue;
817 break;
821 static void readadd(void)
823 readmul();
824 while (1) {
825 if (!tok_jmp('+')) {
826 readmul();
827 ts_binop_add(o_add);
828 continue;
830 if (!tok_jmp('-')) {
831 readmul();
832 ts_binop_add(o_sub);
833 continue;
835 break;
839 static void shift(void (*op)(void))
841 struct type t;
842 readadd();
843 ts_pop(NULL);
844 ts_pop(&t);
845 op();
846 ts_push_bt(TYPE_BT(&t));
849 static void readshift(void)
851 readadd();
852 while (1) {
853 if (!tok_jmp(TOK2("<<"))) {
854 shift(o_shl);
855 continue;
857 if (!tok_jmp(TOK2(">>"))) {
858 shift(o_shr);
859 continue;
861 break;
865 static void cmp(void (*op)(void))
867 readshift();
868 ts_pop(NULL);
869 ts_pop(NULL);
870 op();
871 ts_push_bt(4 | BT_SIGNED);
874 static void readcmp(void)
876 readshift();
877 while (1) {
878 if (!tok_jmp('<')) {
879 cmp(o_lt);
880 continue;
882 if (!tok_jmp('>')) {
883 cmp(o_gt);
884 continue;
886 if (!tok_jmp(TOK2("<="))) {
887 cmp(o_le);
888 continue;
890 if (!tok_jmp(TOK2(">="))) {
891 cmp(o_ge);
892 continue;
894 break;
898 static void eq(void (*op)(void))
900 readcmp();
901 ts_pop(NULL);
902 ts_pop(NULL);
903 op();
904 ts_push_bt(4 | BT_SIGNED);
907 static void readeq(void)
909 readcmp();
910 while (1) {
911 if (!tok_jmp(TOK2("=="))) {
912 eq(o_eq);
913 continue;
915 if (!tok_jmp(TOK2("!="))) {
916 eq(o_neq);
917 continue;
919 break;
923 static void readbitand(void)
925 readeq();
926 while (!tok_jmp('&')) {
927 readeq();
928 ts_binop(o_and);
932 static void readxor(void)
934 readbitand();
935 while (!tok_jmp('^')) {
936 readbitand();
937 ts_binop(o_xor);
941 static void readbitor(void)
943 readxor();
944 while (!tok_jmp('|')) {
945 readxor();
946 ts_binop(o_or);
950 #define MAXCOND (1 << 7)
952 static void readand(void)
954 long conds[MAXCOND];
955 int nconds = 0;
956 long passed;
957 int i;
958 readbitor();
959 if (tok_see() != TOK2("&&"))
960 return;
961 conds[nconds++] = o_jz(0);
962 ts_pop(NULL);
963 while (!tok_jmp(TOK2("&&"))) {
964 readbitor();
965 conds[nconds++] = o_jz(0);
966 ts_pop(NULL);
968 o_num(1, 4 | BT_SIGNED);
969 o_tmpfork();
970 passed = o_jmp(0);
971 for (i = 0; i < nconds; i++)
972 o_filljmp(conds[i]);
973 o_num(0, 4 | BT_SIGNED);
974 o_tmpjoin();
975 o_filljmp(passed);
976 ts_push_bt(4 | BT_SIGNED);
979 static void reador(void)
981 long conds[MAXCOND];
982 int nconds = 0;
983 long failed;
984 int i;
985 readand();
986 if (tok_see() != TOK2("||"))
987 return;
988 conds[nconds++] = o_jnz(0);
989 ts_pop(NULL);
990 while (!tok_jmp(TOK2("||"))) {
991 readand();
992 conds[nconds++] = o_jnz(0);
993 ts_pop(NULL);
995 o_num(0, 4 | BT_SIGNED);
996 o_tmpfork();
997 failed = o_jmp(0);
998 for (i = 0; i < nconds; i++)
999 o_filljmp(conds[i]);
1000 o_num(1, 4 | BT_SIGNED);
1001 o_tmpjoin();
1002 o_filljmp(failed);
1003 ts_push_bt(4 | BT_SIGNED);
1006 static void readcexpr(void)
1008 long l1, l2;
1009 long c;
1010 int cexpr, nogen;
1011 reador();
1012 if (tok_jmp('?'))
1013 return;
1014 ncexpr++;
1015 cexpr = !o_popnum(&c);
1016 ts_pop(NULL);
1017 if (cexpr) {
1018 if (!c)
1019 nogen = !o_nogen();
1020 } else {
1021 l1 = o_jz(0);
1023 reador();
1024 if (!cexpr) {
1025 o_tmpfork();
1026 l2 = o_jmp(0);
1028 ts_pop(NULL);
1029 tok_expect(':');
1030 if (cexpr) {
1031 if (c) {
1032 nogen = !o_nogen();
1033 } else {
1034 if (nogen)
1035 o_dogen();
1036 o_tmpdrop(1);
1038 } else {
1039 o_filljmp(l1);
1041 reador();
1042 if (cexpr) {
1043 if (c) {
1044 if (nogen)
1045 o_dogen();
1046 o_tmpdrop(1);
1048 } else {
1049 o_tmpjoin();
1050 o_filljmp(l2);
1052 ncexpr--;
1055 static void opassign(void (*bop)(void (*op)(void)), void (*op)(void))
1057 unsigned bt = TYPE_BT(&ts[nts - 1]);
1058 o_tmpcopy();
1059 readexpr();
1060 bop(op);
1061 ts_pop(NULL);
1062 o_assign(bt);
1065 static void doassign(void)
1067 struct type t;
1068 ts_pop(&t);
1069 if (!t.ptr && t.flags & T_STRUCT)
1070 o_memcpy(type_totsz(&t));
1071 else
1072 o_assign(TYPE_BT(&ts[nts - 1]));
1075 static void readexpr(void)
1077 readcexpr();
1078 if (!tok_jmp('=')) {
1079 readexpr();
1080 doassign();
1081 return;
1083 if (!tok_jmp(TOK2("+="))) {
1084 opassign(ts_binop_add, o_add);
1085 return;
1087 if (!tok_jmp(TOK2("-="))) {
1088 opassign(ts_binop_add, o_sub);
1089 return;
1091 if (!tok_jmp(TOK2("*="))) {
1092 opassign(ts_binop, o_mul);
1093 return;
1095 if (!tok_jmp(TOK2("/="))) {
1096 opassign(ts_binop, o_div);
1097 return;
1099 if (!tok_jmp(TOK2("%="))) {
1100 opassign(ts_binop, o_mod);
1101 return;
1103 if (!tok_jmp(TOK3("<<="))) {
1104 opassign(ts_binop, o_shl);
1105 return;
1107 if (!tok_jmp(TOK3(">>="))) {
1108 opassign(ts_binop, o_shr);
1109 return;
1111 if (!tok_jmp(TOK3("&="))) {
1112 opassign(ts_binop, o_and);
1113 return;
1115 if (!tok_jmp(TOK3("|="))) {
1116 opassign(ts_binop, o_or);
1117 return;
1119 if (!tok_jmp(TOK3("^="))) {
1120 opassign(ts_binop, o_xor);
1121 return;
1125 static void readestmt(void)
1127 do {
1128 o_tmpdrop(-1);
1129 nts = 0;
1130 readexpr();
1131 } while (!tok_jmp(','));
1134 static void o_localoff(long addr, int off, unsigned bt)
1136 o_local(addr, bt);
1137 if (off) {
1138 o_addr();
1139 o_num(off, 4);
1140 o_add();
1141 o_deref(bt);
1145 static struct type *innertype(struct type *t)
1147 if (t->flags & T_ARRAY && !t->ptr)
1148 return innertype(&arrays[t->id].type);
1149 return t;
1152 static void initexpr(struct type *t, int off, void *obj,
1153 void (*set)(void *obj, int off, struct type *t))
1155 if (tok_jmp('{')) {
1156 set(obj, off, t);
1157 return;
1159 if (!t->ptr && t->flags & T_STRUCT) {
1160 struct structinfo *si = &structs[t->id];
1161 int i;
1162 for (i = 0; i < si->nfields; i++) {
1163 struct name *field = &si->fields[i];
1164 if (!tok_jmp('.')) {
1165 tok_expect(TOK_NAME);
1166 field = struct_field(t->id, tok_id());
1167 tok_expect('=');
1169 initexpr(&field->type, off + field->addr, obj, set);
1170 if (tok_jmp(',') || tok_see() == '}')
1171 break;
1173 } else if (t->flags & T_ARRAY) {
1174 struct type *t_de = &arrays[t->id].type;
1175 int i;
1176 for (i = 0; ; i++) {
1177 long idx = i;
1178 struct type *it = t_de;
1179 if (!tok_jmp('[')) {
1180 readexpr();
1181 o_popnum(&idx);
1182 ts_pop(NULL);
1183 tok_expect(']');
1184 tok_expect('=');
1186 if (tok_see() != '{')
1187 it = innertype(t_de);
1188 initexpr(it, off + type_totsz(it) * idx, obj, set);
1189 if (tok_jmp(',') || tok_see() == '}')
1190 break;
1193 tok_expect('}');
1196 static void jumpbrace(void)
1198 int depth = 0;
1199 while (tok_see() != '}' || depth--)
1200 if (tok_get() == '{')
1201 depth++;
1202 tok_expect('}');
1205 static int initsize(void)
1207 long addr = tok_addr();
1208 int n = 0;
1209 if (!tok_jmp(TOK_STR)) {
1210 n = tok_str(NULL);
1211 tok_jump(addr);
1212 return n;
1214 o_nogen();
1215 tok_expect('{');
1216 while (tok_jmp('}')) {
1217 long idx = n;
1218 if (!tok_jmp('[')) {
1219 readexpr();
1220 o_popnum(&idx);
1221 ts_pop(NULL);
1222 tok_expect(']');
1223 tok_expect('=');
1225 if (n < idx + 1)
1226 n = idx + 1;
1227 while (tok_see() != '}' && tok_see() != ',')
1228 if (tok_get() == '{')
1229 jumpbrace();
1230 tok_jmp(',');
1232 o_dogen();
1233 tok_jump(addr);
1234 return n;
1237 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1239 static void globalinit(void *obj, int off, struct type *t)
1241 long addr = *(long *) obj;
1242 if (t->flags & T_ARRAY && tok_see() == TOK_STR) {
1243 struct type *t_de = &arrays[t->id].type;
1244 if (!t_de->ptr && !t_de->flags && TYPE_SZ(t_de) == 1) {
1245 char buf[BUFSIZE];
1246 int len;
1247 tok_expect(TOK_STR);
1248 len = tok_str(buf);
1249 out_datcpy(addr, off, buf, len);
1250 return;
1253 readexpr();
1254 o_datset(addr, off, TYPE_BT(t));
1255 ts_pop(NULL);
1258 static void globaldef(void *data, struct name *name, unsigned flags)
1260 struct type *t = &name->type;
1261 char *varname = flags & F_STATIC ? NULL : name->name;
1262 int sz;
1263 if (t->flags & T_ARRAY && !t->ptr && !arrays[t->id].n)
1264 arrays[t->id].n = initsize();
1265 sz = type_totsz(t);
1266 if (flags & F_EXTERN || t->flags & T_FUNC && !t->ptr)
1267 name->unused = 1;
1268 else if (flags & F_INIT)
1269 name->addr = out_mkdat(varname, NULL, sz, F_GLOBAL(flags));
1270 else
1271 name->addr = out_mkvar(varname, sz, F_GLOBAL(flags));
1272 global_add(name);
1273 if (flags & F_INIT)
1274 initexpr(t, 0, &name->addr, globalinit);
1277 static void localinit(void *obj, int off, struct type *t)
1279 long addr = *(long *) obj;
1280 if (t->flags & T_ARRAY && tok_see() == TOK_STR) {
1281 struct type *t_de = &arrays[t->id].type;
1282 if (!t_de->ptr && !t_de->flags && TYPE_SZ(t_de) == 1) {
1283 char buf[BUFSIZE];
1284 int len;
1285 tok_expect(TOK_STR);
1286 len = tok_str(buf);
1287 o_localoff(addr, off, TYPE_BT(t));
1288 o_symaddr(out_mkdat(NULL, buf, len, 0), TYPE_BT(t));
1289 o_memcpy(len);
1290 o_tmpdrop(1);
1291 return;
1294 o_localoff(addr, off, TYPE_BT(t));
1295 ts_push(t);
1296 readexpr();
1297 doassign();
1298 ts_pop(NULL);
1299 o_tmpdrop(1);
1302 static void localdef(void *data, struct name *name, unsigned flags)
1304 struct type *t = &name->type;
1305 if (flags & (F_STATIC | F_EXTERN)) {
1306 globaldef(data, name, flags);
1307 return;
1309 if (t->flags & T_ARRAY && !t->ptr && !arrays[t->id].n)
1310 arrays[t->id].n = initsize();
1311 name->addr = o_mklocal(type_totsz(&name->type));
1312 local_add(name);
1313 if (flags & F_INIT) {
1314 if (t->flags & (T_ARRAY | T_STRUCT) && !t->ptr) {
1315 o_local(name->addr, TYPE_BT(t));
1316 o_memset(0, type_totsz(t));
1317 o_tmpdrop(1);
1319 initexpr(t, 0, &name->addr, localinit);
1323 static void funcdef(char *name, struct type *type, struct name *args,
1324 int nargs, unsigned flags)
1326 struct name global;
1327 int i;
1328 strcpy(global.name, name);
1329 memcpy(&global.type, type, sizeof(*type));
1330 global.addr = o_func_beg(name, F_GLOBAL(flags));
1331 global.unused = 0;
1332 global_add(&global);
1333 ret_bt = TYPE_BT(&funcs[type->id].ret);
1334 for (i = 0; i < nargs; i++) {
1335 args[i].addr = o_arg(i, type_totsz(&args[i].type));
1336 local_add(&args[i]);
1340 static int readargs(struct name *args)
1342 int nargs = 0;
1343 tok_expect('(');
1344 while (tok_see() != ')') {
1345 if (!tok_jmp(TOK3("...")))
1346 break;
1347 readname(&args[nargs].type, args[nargs].name, NULL, 0);
1348 array2ptr(&args[nargs].type);
1349 nargs++;
1350 if (tok_jmp(','))
1351 break;
1353 tok_expect(')');
1354 if (nargs == 1 && !TYPE_BT(&args[0].type))
1355 return 0;
1356 return nargs;
1359 static int readname(struct type *main, char *name,
1360 struct type *base, unsigned flags)
1362 struct type tpool[3];
1363 int npool = 0;
1364 struct type *type = &tpool[npool++];
1365 struct type *func = NULL;
1366 struct type *ret = NULL;
1367 memset(tpool, 0, sizeof(tpool));
1368 if (name)
1369 *name = '\0';
1370 if (!base) {
1371 if (basetype(type, &flags))
1372 return 1;
1373 } else {
1374 memcpy(type, base, sizeof(*base));
1376 readptrs(type);
1377 if (!tok_jmp('(')) {
1378 ret = type;
1379 type = &tpool[npool++];
1380 func = type;
1381 readptrs(type);
1383 if (!tok_jmp(TOK_NAME) && name)
1384 strcpy(name, tok_id());
1385 while (!tok_jmp('[')) {
1386 long n = 0;
1387 if (tok_jmp(']')) {
1388 readexpr();
1389 ts_pop(NULL);
1390 if (o_popnum(&n))
1391 die("const expr expected\n");
1392 tok_expect(']');
1394 type->id = array_add(type, n);
1395 if (type->flags & T_FUNC)
1396 func = &arrays[type->id].type;
1397 type->flags = T_ARRAY;
1398 type->bt = 8;
1399 type->ptr = 0;
1401 if (func)
1402 tok_expect(')');
1403 if (tok_see() == '(') {
1404 struct name args[MAXARGS];
1405 int nargs = readargs(args);
1406 int fdef = !func;
1407 if (!func) {
1408 ret = type;
1409 type = &tpool[npool++];
1410 func = type;
1412 func->flags = T_FUNC;
1413 func->bt = 8;
1414 func->id = func_create(ret, args, nargs);
1415 if (fdef && tok_see() == '{') {
1416 funcdef(name, func, args, nargs, flags);
1417 return 1;
1420 memcpy(main, type, sizeof(*type));
1421 return 0;
1424 static int readdefs(void (*def)(void *data, struct name *name, unsigned flags),
1425 void *data)
1427 struct type base;
1428 unsigned flags;
1429 if (basetype(&base, &flags))
1430 return 1;
1431 while (tok_see() != ';' && tok_see() != '{') {
1432 struct name name;
1433 name.unused = 0;
1434 if (readname(&name.type, name.name, &base, flags))
1435 break;
1436 if (!tok_jmp('='))
1437 flags |= F_INIT;
1438 def(data, &name, flags);
1439 tok_jmp(',');
1441 return 0;
1444 static void typedefdef(void *data, struct name *name, unsigned flags)
1446 typedef_add(name->name, &name->type);
1449 static void readstmt(void);
1451 #define MAXCASES (1 << 7)
1453 static void readswitch(void)
1455 int break_beg = nbreaks;
1456 long val_addr = o_mklocal(8);
1457 long matched[MAXCASES];
1458 int nmatched = 0;
1459 struct type t;
1460 long next;
1461 int ref = 1;
1462 int i;
1463 tok_expect('(');
1464 readexpr();
1465 ts_pop(&t);
1466 o_local(val_addr, TYPE_BT(&t));
1467 o_tmpswap();
1468 o_assign(TYPE_BT(&t));
1469 o_tmpdrop(1);
1470 tok_expect(')');
1471 tok_expect('{');
1472 while (tok_jmp('}')) {
1473 int n = 0;
1474 while (tok_see() == TOK_CASE || tok_see() == TOK_DEFAULT) {
1475 if (n++ > 0)
1476 matched[nmatched++] = o_jmp(0);
1477 if (!ref++)
1478 o_filljmp(next);
1479 if (!tok_jmp(TOK_CASE)) {
1480 readexpr();
1481 o_local(val_addr, TYPE_BT(&t));
1482 o_eq();
1483 next = o_jz(0);
1484 ref = 0;
1485 tok_expect(':');
1486 o_tmpdrop(1);
1487 ts_pop(NULL);
1488 continue;
1490 if (!tok_jmp(TOK_DEFAULT)) {
1491 tok_expect(':');
1492 continue;
1495 for (i = 0; i < nmatched; i++)
1496 o_filljmp(matched[i]);
1497 nmatched = 0;
1498 readstmt();
1500 o_rmlocal(val_addr, 8);
1501 if (!ref++)
1502 o_filljmp(next);
1503 break_fill(o_mklabel(), break_beg);
1506 #define MAXGOTO (1 << 10)
1508 static struct gotoinfo {
1509 char name[NAMELEN];
1510 long addr;
1511 } gotos[MAXGOTO];
1512 static int ngotos;
1514 static struct labelinfo {
1515 char name[NAMELEN];
1516 long addr;
1517 } labels[MAXGOTO];
1518 static int nlabels;
1520 static void goto_add(char *name)
1522 strcpy(gotos[ngotos].name, name);
1523 gotos[ngotos++].addr = o_jmp(0);
1526 static void label_add(char *name)
1528 strcpy(labels[nlabels].name, name);
1529 labels[nlabels++].addr = o_mklabel();
1532 static void goto_fill(void)
1534 int i, j;
1535 for (i = 0; i < ngotos; i++)
1536 for (j = 0; j < nlabels; j++)
1537 if (!strcmp(gotos[i].name, labels[j].name)) {
1538 o_filljmp2(gotos[i].addr, labels[j].addr);
1539 break;
1543 static void readstmt(void)
1545 o_tmpdrop(-1);
1546 nts = 0;
1547 if (!tok_jmp('{')) {
1548 int _nlocals = nlocals;
1549 int _nglobals = nglobals;
1550 int _nenums = nenums;
1551 int _ntypedefs = ntypedefs;
1552 int _nstructs = nstructs;
1553 int _nfuncs = nfuncs;
1554 int _narrays = narrays;
1555 while (tok_jmp('}'))
1556 readstmt();
1557 nlocals = _nlocals;
1558 nenums = _nenums;
1559 ntypedefs = _ntypedefs;
1560 nstructs = _nstructs;
1561 nfuncs = _nfuncs;
1562 narrays = _narrays;
1563 nglobals = _nglobals;
1564 return;
1566 if (!readdefs(localdef, NULL)) {
1567 tok_expect(';');
1568 return;
1570 if (!tok_jmp(TOK_TYPEDEF)) {
1571 readdefs(typedefdef, NULL);
1572 tok_expect(';');
1573 return;
1575 if (!tok_jmp(TOK_IF)) {
1576 long l1, l2;
1577 tok_expect('(');
1578 readexpr();
1579 tok_expect(')');
1580 l1 = o_jz(0);
1581 readstmt();
1582 if (!tok_jmp(TOK_ELSE)) {
1583 l2 = o_jmp(0);
1584 o_filljmp(l1);
1585 readstmt();
1586 o_filljmp(l2);
1587 } else {
1588 o_filljmp(l1);
1590 return;
1592 if (!tok_jmp(TOK_WHILE)) {
1593 long l1, l2;
1594 int break_beg = nbreaks;
1595 int continue_beg = ncontinues;
1596 l1 = o_mklabel();
1597 tok_expect('(');
1598 readexpr();
1599 tok_expect(')');
1600 l2 = o_jz(0);
1601 readstmt();
1602 o_jmp(l1);
1603 o_filljmp(l2);
1604 break_fill(o_mklabel(), break_beg);
1605 continue_fill(l1, continue_beg);
1606 return;
1608 if (!tok_jmp(TOK_DO)) {
1609 long l1, l2;
1610 int break_beg = nbreaks;
1611 int continue_beg = ncontinues;
1612 l1 = o_mklabel();
1613 readstmt();
1614 tok_expect(TOK_WHILE);
1615 tok_expect('(');
1616 l2 = o_mklabel();
1617 readexpr();
1618 o_jnz(l1);
1619 tok_expect(')');
1620 break_fill(o_mklabel(), break_beg);
1621 continue_fill(l2, continue_beg);
1622 return;
1624 if (!tok_jmp(TOK_FOR)) {
1625 long l_check, l_jump, j_fail, j_pass;
1626 int break_beg = nbreaks;
1627 int continue_beg = ncontinues;
1628 int has_cond = 0;
1629 tok_expect('(');
1630 if (tok_see() != ';')
1631 readestmt();
1632 tok_expect(';');
1633 l_check = o_mklabel();
1634 if (tok_see() != ';') {
1635 readestmt();
1636 j_fail = o_jz(0);
1637 has_cond = 1;
1639 tok_expect(';');
1640 j_pass = o_jmp(0);
1641 l_jump = o_mklabel();
1642 if (tok_see() != ')')
1643 readestmt();
1644 tok_expect(')');
1645 o_jmp(l_check);
1646 o_filljmp(j_pass);
1647 readstmt();
1648 o_jmp(l_jump);
1649 if (has_cond)
1650 o_filljmp(j_fail);
1651 break_fill(o_mklabel(), break_beg);
1652 continue_fill(l_jump, continue_beg);
1653 return;
1655 if (!tok_jmp(TOK_SWITCH)) {
1656 readswitch();
1657 return;
1659 if (!tok_jmp(TOK_RETURN)) {
1660 int ret = tok_see() != ';';
1661 if (ret)
1662 readexpr();
1663 tok_expect(';');
1664 o_ret(ret_bt);
1665 return;
1667 if (!tok_jmp(TOK_BREAK)) {
1668 tok_expect(';');
1669 breaks[nbreaks++] = o_jmp(0);
1670 return;
1672 if (!tok_jmp(TOK_CONTINUE)) {
1673 tok_expect(';');
1674 continues[ncontinues++] = o_jmp(0);
1675 return;
1677 if (!tok_jmp(TOK_GOTO)) {
1678 tok_expect(TOK_NAME);
1679 goto_add(tok_id());
1680 tok_expect(';');
1681 return;
1683 readestmt();
1684 /* labels */
1685 if (!tok_jmp(':')) {
1686 label_add(tok_id());
1687 return;
1689 tok_expect(';');
1692 static void readdecl(void)
1694 if (!tok_jmp(TOK_TYPEDEF)) {
1695 readdefs(typedefdef, NULL);
1696 tok_expect(';');
1697 return;
1699 readdefs(globaldef, NULL);
1700 if (tok_see() == '{') {
1701 readstmt();
1702 goto_fill();
1703 o_func_end();
1704 nlocals = 0;
1705 ngotos = 0;
1706 nlabels = 0;
1707 return;
1709 tok_expect(';');
1712 static void parse(void)
1714 while (tok_see() != TOK_EOF)
1715 readdecl();
1718 int main(int argc, char *argv[])
1720 char obj[128];
1721 int ifd, ofd;
1722 int i = 1;
1723 while (i < argc && argv[i][0] == '-') {
1724 if (argv[i][1] == 'I')
1725 cpp_addpath(argv[i][2] ? argv[i] + 2 : argv[++i]);
1726 if (argv[i][1] == 'D') {
1727 char *name = argv[i] + 2;
1728 char *def = "";
1729 char *eq = strchr(name, '=');
1730 if (eq) {
1731 *eq = '\0';
1732 def = eq + 1;
1734 cpp_define(name, def);
1736 i++;
1738 if (i == argc)
1739 die("no file given\n");
1740 ifd = open(argv[i], O_RDONLY);
1741 tok_init(ifd);
1742 close(ifd);
1743 parse();
1745 strcpy(obj, argv[i]);
1746 obj[strlen(obj) - 1] = 'o';
1747 ofd = open(obj, O_WRONLY | O_TRUNC | O_CREAT, 0600);
1748 out_write(ofd);
1749 close(ofd);
1750 return 0;