10 #define MAXLOCALS (1 << 10)
11 #define MAXARGS (1 << 5)
12 #define print(s) write(2, (s), strlen(s));
14 #define TYPE_BT(t) ((t)->ptr ? 8 : (t)->bt)
15 #define TYPE_SZ(t) ((t)->ptr ? 8 : (t)->bt & BT_SZMASK)
16 #define TYPE_DEREF_BT(t) ((t)->ptr > 1 ? 8 : (t)->bt)
17 #define TYPE_DEREF_SZ(t) ((t)->ptr > 1 ? 8 : (t)->bt & BT_SZMASK)
28 static struct type ts
[MAXTMP
];
31 static void ts_push_bt(unsigned bt
)
38 static void ts_push(struct type
*type
)
43 static void ts_pop(struct type
*type
)
57 static void local_add(char *name
, long addr
, struct type type
)
59 strcpy(locals
[nlocals
].name
, name
);
60 locals
[nlocals
].addr
= addr
;
61 locals
[nlocals
].type
= type
;
65 static void die(char *s
)
71 static int tok_jmp(int tok
)
79 static void tok_expect(int tok
)
82 die("syntax error\n");
85 static void readexpr(void);
87 static int basetype(struct type
*type
)
118 tok_expect(TOK_NAME
);
130 type
->bt
= size
| (sign
? BT_SIGNED
: 0);
135 static void readptrs(struct type
*type
)
137 while (!tok_jmp('*'))
141 static int readtype(struct type
*type
)
149 static void readprimary(void)
152 if (!tok_jmp(TOK_NUM
)) {
153 ts_push_bt(4 | BT_SIGNED
);
154 o_num(atoi(tok_id()), 4 | BT_SIGNED
);
157 if (!tok_jmp(TOK_NAME
)) {
158 for (i
= 0; i
< nlocals
; i
++) {
159 struct type
*t
= &locals
[i
].type
;
160 if (!strcmp(locals
[i
].name
, tok_id())) {
162 o_local(locals
[i
].addr
, TYPE_BT(t
));
163 if (t
->flags
& T_ARRAY
)
169 o_symaddr(tok_id(), 8);
179 void arrayderef(unsigned bt
)
189 static void inc_post(void (*op
)(void))
191 struct type
*t
= &ts
[nts
- 1];
203 static void readpost(void)
212 arrayderef(TYPE_DEREF_BT(&t1
));
219 unsigned bt
[MAXARGS
];
220 if (tok_see() != ')') {
222 bt
[argc
++] = 4 | BT_SIGNED
;
225 while (!tok_jmp(',')) {
227 bt
[argc
++] = 4 | BT_SIGNED
;
232 o_call(argc
, bt
, 4 | BT_SIGNED
);
233 ts_push_bt(4 | BT_SIGNED
);
236 if (!tok_jmp(TOK2("++"))) {
240 if (!tok_jmp(TOK2("--"))) {
246 static void inc_pre(void (*op
)(void))
248 struct type
*t
= &ts
[nts
- 1];
256 static void readpre(void)
273 o_deref(TYPE_BT(&type
));
280 o_num(0, TYPE_BT(&type
));
282 ts_push_bt(4 | BT_SIGNED
);
295 if (!tok_jmp(TOK2("++"))) {
299 if (!tok_jmp(TOK2("--"))) {
306 static int shifts(int n
)
315 static unsigned bt_op(unsigned bt1
, unsigned bt2
)
317 unsigned s1
= BT_SZ(bt1
);
318 unsigned s2
= BT_SZ(bt2
);
319 return (bt1
| bt2
) & BT_SIGNED
| (s1
> s2
? s1
: s2
);
322 static void ts_binop(void (*o_sth
)(void))
328 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
331 static void ts_binop_add(void (*o_sth
)(void))
336 if (!t1
.ptr
&& !t2
.ptr
) {
338 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
341 if (t1
.ptr
&& !t2
.ptr
) {
347 if (!t1
.ptr
&& t2
.ptr
)
348 if (TYPE_DEREF_SZ(&t2
) > 1) {
349 o_num(shifts(TYPE_DEREF_SZ(&t2
)), 1);
353 if (t1
.ptr
&& t2
.ptr
) {
354 o_num(shifts(TYPE_DEREF_SZ(&t1
)), 1);
356 ts_push_bt(4 | BT_SIGNED
);
362 static void readmul(void)
385 static void readadd(void)
403 static void shift(void (*op
)(void))
410 ts_push_bt(TYPE_BT(&t
));
413 static void readshift(void)
416 if (!tok_jmp(TOK2("<<"))) {
420 if (!tok_jmp(TOK2(">>"))) {
426 static void cmp(void (*op
)(void))
432 ts_push_bt(4 | BT_SIGNED
);
435 static void readcmp(void)
446 if (!tok_jmp(TOK2("<="))) {
450 if (!tok_jmp(TOK2(">="))) {
456 static void eq(void (*op
)(void))
462 ts_push_bt(4 | BT_SIGNED
);
465 static void readeq(void)
468 if (!tok_jmp(TOK2("=="))) {
472 if (!tok_jmp(TOK2("!="))) {
478 static void readbitand(void)
481 while (!tok_jmp('&')) {
487 static void readxor(void)
490 while (!tok_jmp('^')) {
496 static void readbitor(void)
499 while (!tok_jmp('|')) {
505 #define MAXCOND (1 << 5)
507 static void readand(void)
514 if (tok_see() != TOK2("&&"))
516 conds
[nconds
++] = o_jz(0);
518 while (!tok_jmp(TOK2("&&"))) {
520 conds
[nconds
++] = o_jz(0);
523 o_num(1, 4 | BT_SIGNED
);
526 for (i
= 0; i
< nconds
; i
++)
528 o_num(0, 4 | BT_SIGNED
);
531 ts_push_bt(4 | BT_SIGNED
);
534 static void reador(void)
541 if (tok_see() != TOK2("||"))
543 conds
[nconds
++] = o_jnz(0);
545 while (!tok_jmp(TOK2("||"))) {
547 conds
[nconds
++] = o_jnz(0);
550 o_num(0, 4 | BT_SIGNED
);
553 for (i
= 0; i
< nconds
; i
++)
555 o_num(1, 4 | BT_SIGNED
);
558 ts_push_bt(4 | BT_SIGNED
);
561 static void readcexpr(void)
580 static void opassign(void (*op
)(void))
586 o_assign(TYPE_BT(&ts
[nts
- 1]));
589 static void readexpr(void)
595 o_assign(TYPE_BT(&ts
[nts
- 1]));
598 if (!tok_jmp(TOK2("+="))) {
602 if (!tok_jmp(TOK2("-="))) {
606 if (!tok_jmp(TOK2("*="))) {
610 if (!tok_jmp(TOK2("/="))) {
614 if (!tok_jmp(TOK2("%="))) {
618 if (!tok_jmp(TOK3("<<="))) {
622 if (!tok_jmp(TOK3(">>="))) {
626 if (!tok_jmp(TOK3("&="))) {
630 if (!tok_jmp(TOK3("|="))) {
634 if (!tok_jmp(TOK3("^="))) {
640 static void readestmt(void)
646 } while (!tok_jmp(','));
649 static void readstmt(void)
651 struct type base
= {0};
659 if (!basetype(&base
)) {
660 struct type type
= base
;
664 tok_expect(TOK_NAME
);
665 strcpy(name
, tok_id());
670 type
.flags
= T_ARRAY
;
673 local_add(name
, o_mklocal(TYPE_SZ(&type
) * n
), type
);
676 struct type
*t
= &locals
[nlocals
- 1].type
;
677 o_local(locals
[nlocals
- 1].addr
, TYPE_BT(t
));
680 ts_push_bt(TYPE_BT(t
));
681 o_assign(TYPE_BT(t
));
686 if (!tok_jmp(TOK_IF
)) {
693 if (!tok_jmp(TOK_ELSE
)) {
703 if (!tok_jmp(TOK_WHILE
)) {
715 if (!tok_jmp(TOK_FOR
)) {
716 long check
, jump
, end
, body
;
718 if (tok_see() != ';')
722 if (tok_see() != ';')
728 if (tok_see() != ')')
738 if (!tok_jmp(TOK_RETURN
)) {
739 int ret
= tok_see() != ';';
743 o_ret(4 | BT_SIGNED
);
750 static void readdecl(void)
755 tok_expect(TOK_NAME
);
756 strcpy(name
, tok_id());
761 char args
[MAXARGS
][NAMELEN
];
762 struct type types
[MAXARGS
];
765 while (tok_see() != ')') {
766 readtype(&types
[nargs
]);
767 if (!tok_jmp(TOK_NAME
))
768 strcpy(args
[nargs
++], tok_id());
776 for (i
= 0; i
< nargs
; i
++)
777 local_add(args
[i
], o_arg(i
, TYPE_BT(&types
[i
])),
783 die("syntax error\n");
786 static void parse(void)
788 while (tok_see() != TOK_EOF
)
792 int main(int argc
, char *argv
[])
797 ifd
= open(src
, O_RDONLY
);
803 obj
[strlen(obj
) - 1] = 'o';
804 ofd
= open(obj
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0600);