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.
15 #include <sys/types.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)
39 int id
; /* for structs, functions and arrays */
43 static struct type ts
[MAXTMP
];
46 static void ts_push_bt(unsigned 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
)
60 static void ts_pop(struct type
*type
)
73 static struct name locals
[MAXLOCALS
];
75 static struct name globals
[MAXGLOBALS
];
78 static void local_add(struct name
*name
)
80 memcpy(&locals
[nlocals
++], name
, sizeof(*name
));
83 static int global_find(char *name
)
86 for (i
= 0; i
< nglobals
; i
++)
87 if (!strcmp(name
, globals
[i
].name
))
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
)
105 #define MAXENUMS (1 << 10)
107 static struct enumval
{
113 static void enum_add(char *name
, int val
)
115 struct enumval
*ev
= &enums
[nenums
++];
116 strcpy(ev
->name
, name
);
120 static int enum_find(int *val
, char *name
)
123 for (i
= nenums
- 1; i
>= 0; --i
)
124 if (!strcmp(name
, enums
[i
].name
)) {
131 #define MAXTYPEDEFS (1 << 10)
133 static struct typdefinfo
{
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
)
149 for (i
= ntypedefs
- 1; i
>= 0; --i
)
150 if (!strcmp(name
, typedefs
[i
].name
))
155 #define MAXARRAYS (1 << 10)
157 static struct array
{
163 static int array_add(struct type
*type
, int n
)
165 struct array
*a
= &arrays
[narrays
++];
166 memcpy(&a
->type
, type
, sizeof(*type
));
171 static void array2ptr(struct type
*t
)
173 if (!(t
->flags
& T_ARRAY
) || t
->ptr
)
175 memcpy(t
, &arrays
[t
->id
].type
, sizeof(*t
));
179 #define MAXTYPES (1 << 10)
180 #define MAXFIELDS (1 << 7)
182 static struct structinfo
{
184 struct name fields
[MAXFIELDS
];
191 static int struct_find(char *name
, int isunion
)
194 for (i
= nstructs
- 1; i
>= 0; --i
)
195 if (*structs
[i
].name
&& !strcmp(name
, structs
[i
].name
) &&
196 structs
[i
].isunion
== isunion
)
199 memset(&structs
[i
], 0, sizeof(structs
[i
]));
200 strcpy(structs
[i
].name
, name
);
201 structs
[i
].isunion
= isunion
;
205 static struct name
*struct_field(int id
, char *name
)
207 struct structinfo
*si
= &structs
[id
];
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
];
219 static long continues
[MAXBREAK
];
220 static int ncontinues
;
222 static void break_fill(long addr
, int till
)
225 for (i
= till
; i
< nbreaks
; i
++)
226 o_filljmp2(breaks
[i
], addr
);
230 static void continue_fill(long addr
, int till
)
233 for (i
= till
; i
< ncontinues
; i
++)
234 o_filljmp2(continues
[i
], addr
);
238 static int type_totsz(struct type
*t
)
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
);
252 return t
->ptr
> 1 ? 8 : BT_SZ(t
->bt
);
255 static int tok_jmp(int tok
)
257 if (tok_see() != tok
)
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))
282 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
285 static int shifts(int n
)
294 static void ts_binop_add(void (*o_sth
)(void))
301 if (!t1
.ptr
&& !t2
.ptr
) {
303 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
306 if (t1
.ptr
&& !t2
.ptr
) {
312 if (!t1
.ptr
&& t2
.ptr
)
313 if (type_szde(&t2
) > 1) {
314 o_num(shifts(type_szde(&t2
)), 1);
318 if (t1
.ptr
&& t2
.ptr
) {
319 o_num(shifts(type_szde(&t1
)), 1);
321 ts_push_bt(4 | BT_SIGNED
);
327 static void structdef(void *data
, struct name
*name
, unsigned flags
)
329 struct structinfo
*si
= data
;
332 if (si
->size
< type_totsz(&name
->type
))
333 si
->size
= type_totsz(&name
->type
);
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
];
348 while (tok_jmp('}')) {
349 readdefs(structdef
, si
);
355 static void readexpr(void);
357 static void enum_create(void)
361 while (tok_jmp('}')) {
363 tok_expect(TOK_NAME
);
364 strcpy(name
, tok_id());
365 if (tok_see() == '=') {
370 die("const expr expected!\n");
377 static int basetype(struct type
*type
, unsigned *flags
)
384 char name
[NAMELEN
] = "";
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
);
427 type
->id
= struct_find(name
, isunion
);
428 type
->flags
|= T_STRUCT
;
434 if (tok_see() == '{')
436 type
->bt
= 4 | BT_SIGNED
;
439 if (tok_see() == TOK_NAME
) {
440 int id
= typedef_find(tok_id());
443 memcpy(type
, &typedefs
[id
].type
,
456 type
->bt
= size
| (sign
? BT_SIGNED
: 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('*')) {
479 static void readpre(void);
481 static void readprimary(void)
484 if (!tok_jmp(TOK_NUM
)) {
485 ts_push_bt(4 | BT_SIGNED
);
486 o_num(tok_num(), 4 | BT_SIGNED
);
489 if (!tok_jmp(TOK_STR
)) {
493 t
.bt
= 1 | BT_SIGNED
;
498 o_symaddr(out_mkdat(NULL
, buf
, len
, 0), TYPE_BT(&t
));
502 if (!tok_jmp(TOK_NAME
)) {
504 char *name
= unkn
.name
;
506 strcpy(name
, tok_id());
507 /* don't search for labels here */
508 if (!ncexpr
&& tok_see() == ':')
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
));
518 if ((n
= global_find(name
)) != -1) {
519 struct type
*t
= &globals
[n
].type
;
520 o_symaddr(globals
[n
].addr
, TYPE_BT(t
));
524 if (!enum_find(&n
, name
)) {
525 ts_push_bt(4 | BT_SIGNED
);
526 o_num(n
, 4 | BT_SIGNED
);
529 if (tok_see() != '(')
530 die("unknown symbol\n");
531 unkn
.addr
= out_mkundef(unkn
.name
, 0);
534 o_symaddr(unkn
.addr
, 8);
545 if (!t
.ptr
|| !o
.ptr
)
555 void arrayderef(struct type
*t
)
557 int sz
= type_totsz(t
);
566 static void inc_post(void (*op
)(void))
568 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
582 static void readfield(void)
586 tok_expect(TOK_NAME
);
588 field
= struct_field(t
.id
, tok_id());
590 o_num(field
->addr
, 4);
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
];
605 static unsigned ret_bt
;
607 static int func_create(struct type
*ret
, struct name
*args
, int nargs
)
609 struct funcinfo
*fi
= &funcs
[nfuncs
++];
611 memcpy(&fi
->ret
, ret
, sizeof(*ret
));
612 for (i
= 0; i
< nargs
; i
++)
613 memcpy(&fi
->args
[i
], &args
[i
].type
, sizeof(*ret
));
618 static void readcall(void)
621 unsigned bt
[MAXARGS
];
625 if (tok_see() != ')') {
628 bt
[argc
++] = TYPE_BT(&t
);
630 while (!tok_jmp(',')) {
633 bt
[argc
++] = TYPE_BT(&t
);
637 if (t
.flags
& T_FUNC
&& t
.ptr
> 0)
639 fi
= t
.flags
& T_FUNC
? &funcs
[t
.id
] : NULL
;
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
);
647 ts_push_bt(4 | BT_SIGNED
);
650 static void readpost(void)
670 if (!tok_jmp(TOK2("++"))) {
674 if (!tok_jmp(TOK2("--"))) {
683 if (!tok_jmp(TOK2("->"))) {
691 static void inc_pre(void (*op
)(void))
693 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
704 static void readpre(void)
710 if (!(type
.flags
& T_FUNC
) && !type
.ptr
)
721 if (!(t
.flags
& T_FUNC
) || t
.ptr
> 0) {
723 o_deref(TYPE_BT(&t
));
733 ts_push_bt(4 | BT_SIGNED
);
746 if (!tok_jmp(TOK2("++"))) {
750 if (!tok_jmp(TOK2("--"))) {
754 if (!tok_jmp(TOK_SIZEOF
)) {
756 int op
= !tok_jmp('(');
758 int nogen
= !o_nogen();
766 o_num(type_totsz(&t
), 4);
774 static void readmul(void)
797 static void readadd(void)
815 static void shift(void (*op
)(void))
822 ts_push_bt(TYPE_BT(&t
));
825 static void readshift(void)
829 if (!tok_jmp(TOK2("<<"))) {
833 if (!tok_jmp(TOK2(">>"))) {
841 static void cmp(void (*op
)(void))
847 ts_push_bt(4 | BT_SIGNED
);
850 static void readcmp(void)
862 if (!tok_jmp(TOK2("<="))) {
866 if (!tok_jmp(TOK2(">="))) {
874 static void eq(void (*op
)(void))
880 ts_push_bt(4 | BT_SIGNED
);
883 static void readeq(void)
887 if (!tok_jmp(TOK2("=="))) {
891 if (!tok_jmp(TOK2("!="))) {
899 static void readbitand(void)
902 while (!tok_jmp('&')) {
908 static void readxor(void)
911 while (!tok_jmp('^')) {
917 static void readbitor(void)
920 while (!tok_jmp('|')) {
926 #define MAXCOND (1 << 7)
928 static void readand(void)
935 if (tok_see() != TOK2("&&"))
937 conds
[nconds
++] = o_jz(0);
939 while (!tok_jmp(TOK2("&&"))) {
941 conds
[nconds
++] = o_jz(0);
944 o_num(1, 4 | BT_SIGNED
);
947 for (i
= 0; i
< nconds
; i
++)
949 o_num(0, 4 | BT_SIGNED
);
952 ts_push_bt(4 | BT_SIGNED
);
955 static void reador(void)
962 if (tok_see() != TOK2("||"))
964 conds
[nconds
++] = o_jnz(0);
966 while (!tok_jmp(TOK2("||"))) {
968 conds
[nconds
++] = o_jnz(0);
971 o_num(0, 4 | BT_SIGNED
);
974 for (i
= 0; i
< nconds
; i
++)
976 o_num(1, 4 | BT_SIGNED
);
979 ts_push_bt(4 | BT_SIGNED
);
982 static void readcexpr(void)
991 cexpr
= !o_popnum(&c
);
1031 static void opassign(void (*bop
)(void (*op
)(void)), void (*op
)(void))
1033 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
1041 static void doassign(void)
1045 if (!t
.ptr
&& t
.flags
& T_STRUCT
)
1046 o_memcpy(type_totsz(&t
));
1048 o_assign(TYPE_BT(&ts
[nts
- 1]));
1051 static void readexpr(void)
1054 if (!tok_jmp('=')) {
1059 if (!tok_jmp(TOK2("+="))) {
1060 opassign(ts_binop_add
, o_add
);
1063 if (!tok_jmp(TOK2("-="))) {
1064 opassign(ts_binop_add
, o_sub
);
1067 if (!tok_jmp(TOK2("*="))) {
1068 opassign(ts_binop
, o_mul
);
1071 if (!tok_jmp(TOK2("/="))) {
1072 opassign(ts_binop
, o_div
);
1075 if (!tok_jmp(TOK2("%="))) {
1076 opassign(ts_binop
, o_mod
);
1079 if (!tok_jmp(TOK3("<<="))) {
1080 opassign(ts_binop
, o_shl
);
1083 if (!tok_jmp(TOK3(">>="))) {
1084 opassign(ts_binop
, o_shr
);
1087 if (!tok_jmp(TOK3("&="))) {
1088 opassign(ts_binop
, o_and
);
1091 if (!tok_jmp(TOK3("|="))) {
1092 opassign(ts_binop
, o_or
);
1095 if (!tok_jmp(TOK3("^="))) {
1096 opassign(ts_binop
, o_xor
);
1101 static void readestmt(void)
1107 } while (!tok_jmp(','));
1110 static void o_localoff(long addr
, int off
, unsigned bt
)
1121 static struct type
*innertype(struct type
*t
)
1123 if (t
->flags
& T_ARRAY
&& !t
->ptr
)
1124 return innertype(&arrays
[t
->id
].type
);
1128 static void initexpr(struct type
*t
, int off
, void *obj
,
1129 void (*set
)(void *obj
, int off
, struct type
*t
))
1135 if (!t
->ptr
&& t
->flags
& T_STRUCT
) {
1136 struct structinfo
*si
= &structs
[t
->id
];
1138 for (i
= 0; i
< si
->nfields
; i
++) {
1139 struct name
*field
= &si
->fields
[i
];
1140 if (!tok_jmp('.')) {
1141 tok_expect(TOK_NAME
);
1142 field
= struct_field(t
->id
, tok_id());
1145 initexpr(&field
->type
, off
+ field
->addr
, obj
, set
);
1146 if (tok_jmp(',') || tok_see() == '}')
1149 } else if (t
->flags
& T_ARRAY
) {
1150 struct type
*t_de
= &arrays
[t
->id
].type
;
1152 for (i
= 0; ; i
++) {
1154 struct type
*it
= t_de
;
1155 if (!tok_jmp('[')) {
1162 if (tok_see() != '{')
1163 it
= innertype(t_de
);
1164 initexpr(it
, off
+ type_totsz(it
) * idx
, obj
, set
);
1165 if (tok_jmp(',') || tok_see() == '}')
1172 static void jumpbrace(void)
1175 while (tok_see() != '}' || depth
--)
1176 if (tok_get() == '{')
1181 static int initsize(void)
1183 long addr
= tok_addr();
1185 if (!tok_jmp(TOK_STR
)) {
1192 while (tok_jmp('}')) {
1194 if (!tok_jmp('[')) {
1203 while (tok_see() != '}' && tok_see() != ',')
1204 if (tok_get() == '{')
1213 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1215 static void globalinit(void *obj
, int off
, struct type
*t
)
1217 long addr
= *(long *) obj
;
1218 if (t
->flags
& T_ARRAY
&& tok_see() == TOK_STR
) {
1219 struct type
*t_de
= &arrays
[t
->id
].type
;
1220 if (!t_de
->ptr
&& !t_de
->flags
&& TYPE_SZ(t_de
) == 1) {
1223 tok_expect(TOK_STR
);
1225 out_datcpy(addr
, off
, buf
, len
);
1230 o_datset(addr
, off
, TYPE_BT(t
));
1234 static void globaldef(void *data
, struct name
*name
, unsigned flags
)
1236 struct type
*t
= &name
->type
;
1237 char *varname
= flags
& F_STATIC
? NULL
: name
->name
;
1239 if (t
->flags
& T_ARRAY
&& !t
->ptr
&& !arrays
[t
->id
].n
)
1240 arrays
[t
->id
].n
= initsize();
1242 if (flags
& F_EXTERN
)
1243 name
->addr
= out_mkundef(varname
, sz
);
1244 else if (flags
& F_INIT
)
1245 name
->addr
= out_mkdat(varname
, NULL
, sz
, F_GLOBAL(flags
));
1247 name
->addr
= out_mkvar(varname
, sz
, F_GLOBAL(flags
));
1250 initexpr(t
, 0, &name
->addr
, globalinit
);
1253 static void localinit(void *obj
, int off
, struct type
*t
)
1255 long addr
= *(long *) obj
;
1256 if (t
->flags
& T_ARRAY
&& tok_see() == TOK_STR
) {
1257 struct type
*t_de
= &arrays
[t
->id
].type
;
1258 if (!t_de
->ptr
&& !t_de
->flags
&& TYPE_SZ(t_de
) == 1) {
1261 tok_expect(TOK_STR
);
1263 o_localoff(addr
, off
, TYPE_BT(t
));
1264 o_symaddr(out_mkdat(NULL
, buf
, len
, 0), TYPE_BT(t
));
1270 o_localoff(addr
, off
, TYPE_BT(t
));
1278 static void localdef(void *data
, struct name
*name
, unsigned flags
)
1280 struct type
*t
= &name
->type
;
1281 if (flags
& (F_STATIC
| F_EXTERN
)) {
1282 globaldef(data
, name
, flags
);
1285 if (t
->flags
& T_ARRAY
&& !t
->ptr
&& !arrays
[t
->id
].n
)
1286 arrays
[t
->id
].n
= initsize();
1287 name
->addr
= o_mklocal(type_totsz(&name
->type
));
1289 if (flags
& F_INIT
) {
1290 if (t
->flags
& (T_ARRAY
| T_STRUCT
) && !t
->ptr
) {
1291 o_local(name
->addr
, TYPE_BT(t
));
1292 o_memset(0, type_totsz(t
));
1295 initexpr(t
, 0, &name
->addr
, localinit
);
1299 static void funcdef(char *name
, struct type
*type
, struct name
*args
,
1300 int nargs
, unsigned flags
)
1304 strcpy(global
.name
, name
);
1305 memcpy(&global
.type
, type
, sizeof(*type
));
1306 global
.addr
= o_func_beg(name
, F_GLOBAL(flags
));
1307 global_add(&global
);
1308 ret_bt
= TYPE_BT(&funcs
[type
->id
].ret
);
1309 for (i
= 0; i
< nargs
; i
++) {
1310 args
[i
].addr
= o_arg(i
, type_totsz(&args
[i
].type
));
1311 local_add(&args
[i
]);
1315 static int readargs(struct name
*args
)
1319 while (tok_see() != ')') {
1320 if (!tok_jmp(TOK3("...")))
1322 readname(&args
[nargs
].type
, args
[nargs
].name
, NULL
, 0);
1323 array2ptr(&args
[nargs
].type
);
1329 if (nargs
== 1 && !TYPE_BT(&args
[0].type
))
1334 static int readname(struct type
*main
, char *name
,
1335 struct type
*base
, unsigned flags
)
1337 struct type tpool
[3];
1339 struct type
*type
= &tpool
[npool
++];
1340 struct type
*func
= NULL
;
1341 struct type
*ret
= NULL
;
1342 memset(tpool
, 0, sizeof(tpool
));
1346 if (basetype(type
, &flags
))
1349 memcpy(type
, base
, sizeof(*base
));
1352 if (!tok_jmp('(')) {
1354 type
= &tpool
[npool
++];
1358 if (!tok_jmp(TOK_NAME
) && name
)
1359 strcpy(name
, tok_id());
1360 while (!tok_jmp('[')) {
1366 die("const expr expected\n");
1369 type
->id
= array_add(type
, n
);
1370 if (type
->flags
& T_FUNC
)
1371 func
= &arrays
[type
->id
].type
;
1372 type
->flags
= T_ARRAY
;
1378 if (tok_see() == '(') {
1379 struct name args
[MAXARGS
];
1380 int nargs
= readargs(args
);
1384 type
= &tpool
[npool
++];
1387 func
->flags
= T_FUNC
;
1389 func
->id
= func_create(ret
, args
, nargs
);
1390 if (fdef
&& tok_see() == '{') {
1391 funcdef(name
, func
, args
, nargs
, flags
);
1395 memcpy(main
, type
, sizeof(*type
));
1399 static int readdefs(void (*def
)(void *data
, struct name
*name
, unsigned flags
),
1404 if (basetype(&base
, &flags
))
1406 while (tok_see() != ';' && tok_see() != '{') {
1408 if (readname(&name
.type
, name
.name
, &base
, flags
))
1412 def(data
, &name
, flags
);
1418 static void typedefdef(void *data
, struct name
*name
, unsigned flags
)
1420 typedef_add(name
->name
, &name
->type
);
1423 static void readstmt(void);
1425 #define MAXCASES (1 << 7)
1427 static void readswitch(void)
1429 int break_beg
= nbreaks
;
1430 long val_addr
= o_mklocal(8);
1431 long matched
[MAXCASES
];
1440 o_local(val_addr
, TYPE_BT(&t
));
1442 o_assign(TYPE_BT(&t
));
1446 while (tok_jmp('}')) {
1448 while (tok_see() == TOK_CASE
|| tok_see() == TOK_DEFAULT
) {
1450 matched
[nmatched
++] = o_jmp(0);
1453 if (!tok_jmp(TOK_CASE
)) {
1455 o_local(val_addr
, TYPE_BT(&t
));
1464 if (!tok_jmp(TOK_DEFAULT
)) {
1469 for (i
= 0; i
< nmatched
; i
++)
1470 o_filljmp(matched
[i
]);
1474 o_rmlocal(val_addr
, 8);
1477 break_fill(o_mklabel(), break_beg
);
1480 #define MAXGOTO (1 << 10)
1482 static struct gotoinfo
{
1488 static struct labelinfo
{
1494 static void goto_add(char *name
)
1496 strcpy(gotos
[ngotos
].name
, name
);
1497 gotos
[ngotos
++].addr
= o_jmp(0);
1500 static void label_add(char *name
)
1502 strcpy(labels
[nlabels
].name
, name
);
1503 labels
[nlabels
++].addr
= o_mklabel();
1506 static void goto_fill(void)
1509 for (i
= 0; i
< ngotos
; i
++)
1510 for (j
= 0; j
< nlabels
; j
++)
1511 if (!strcmp(gotos
[i
].name
, labels
[j
].name
)) {
1512 o_filljmp2(gotos
[i
].addr
, labels
[j
].addr
);
1517 static void readstmt(void)
1521 if (!tok_jmp('{')) {
1522 int _nlocals
= nlocals
;
1523 int _nglobals
= nglobals
;
1524 int _nenums
= nenums
;
1525 int _ntypedefs
= ntypedefs
;
1526 int _nstructs
= nstructs
;
1527 int _nfuncs
= nfuncs
;
1528 int _narrays
= narrays
;
1529 while (tok_jmp('}'))
1533 ntypedefs
= _ntypedefs
;
1534 nstructs
= _nstructs
;
1537 nglobals
= _nglobals
;
1540 if (!readdefs(localdef
, NULL
)) {
1544 if (!tok_jmp(TOK_TYPEDEF
)) {
1545 readdefs(typedefdef
, NULL
);
1549 if (!tok_jmp(TOK_IF
)) {
1556 if (!tok_jmp(TOK_ELSE
)) {
1566 if (!tok_jmp(TOK_WHILE
)) {
1568 int break_beg
= nbreaks
;
1569 int continue_beg
= ncontinues
;
1578 break_fill(o_mklabel(), break_beg
);
1579 continue_fill(l1
, continue_beg
);
1582 if (!tok_jmp(TOK_DO
)) {
1584 int break_beg
= nbreaks
;
1585 int continue_beg
= ncontinues
;
1588 tok_expect(TOK_WHILE
);
1594 break_fill(o_mklabel(), break_beg
);
1595 continue_fill(l2
, continue_beg
);
1598 if (!tok_jmp(TOK_FOR
)) {
1599 long check
, jump
, end
, body
;
1600 int break_beg
= nbreaks
;
1601 int continue_beg
= ncontinues
;
1603 if (tok_see() != ';')
1606 check
= o_mklabel();
1607 if (tok_see() != ';')
1613 if (tok_see() != ')')
1621 break_fill(o_mklabel(), break_beg
);
1622 continue_fill(jump
, continue_beg
);
1625 if (!tok_jmp(TOK_SWITCH
)) {
1629 if (!tok_jmp(TOK_RETURN
)) {
1630 int ret
= tok_see() != ';';
1637 if (!tok_jmp(TOK_BREAK
)) {
1639 breaks
[nbreaks
++] = o_jmp(0);
1642 if (!tok_jmp(TOK_CONTINUE
)) {
1644 continues
[ncontinues
++] = o_jmp(0);
1647 if (!tok_jmp(TOK_GOTO
)) {
1648 tok_expect(TOK_NAME
);
1655 if (!tok_jmp(':')) {
1656 label_add(tok_id());
1662 static void readdecl(void)
1664 if (!tok_jmp(TOK_TYPEDEF
)) {
1665 readdefs(typedefdef
, NULL
);
1669 readdefs(globaldef
, NULL
);
1670 if (tok_see() == '{') {
1682 static void parse(void)
1684 while (tok_see() != TOK_EOF
)
1688 int main(int argc
, char *argv
[])
1693 while (i
< argc
&& argv
[i
][0] == '-')
1696 die("no file given\n");
1697 ifd
= open(argv
[i
], O_RDONLY
);
1702 strcpy(obj
, argv
[i
]);
1703 obj
[strlen(obj
) - 1] = 'o';
1704 ofd
= open(obj
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0600);