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)
38 int id
; /* for structs, functions and arrays */
42 static struct type ts
[MAXTMP
];
45 static void ts_push_bt(unsigned bt
)
52 static void ts_push(struct type
*t
)
54 memcpy(&ts
[nts
++], t
, sizeof(*t
));
55 if (t
->flags
& (T_FUNC
| T_ARRAY
) && !t
->ptr
)
59 static void ts_pop(struct type
*type
)
72 static struct name locals
[MAXLOCALS
];
74 static struct name globals
[MAXGLOBALS
];
77 static void local_add(struct name
*name
)
79 memcpy(&locals
[nlocals
++], name
, sizeof(*name
));
82 static void global_add(struct name
*name
)
84 memcpy(&globals
[nglobals
++], name
, sizeof(*name
));
87 static void die(char *s
)
93 #define MAXENUMS (1 << 10)
95 static struct enumval
{
101 static void enum_add(char *name
, int val
)
103 struct enumval
*ev
= &enums
[nenums
++];
104 strcpy(ev
->name
, name
);
108 static int enum_find(int *val
, char *name
)
111 for (i
= nenums
- 1; i
>= 0; --i
)
112 if (!strcmp(name
, enums
[i
].name
)) {
119 #define MAXTYPEDEFS (1 << 5)
121 static struct typdefinfo
{
124 } typedefs
[MAXTYPEDEFS
];
125 static int ntypedefs
;
127 static void typedef_add(char *name
, struct type
*type
)
129 struct typdefinfo
*ti
= &typedefs
[ntypedefs
++];
130 strcpy(ti
->name
, name
);
131 memcpy(&ti
->type
, type
, sizeof(*type
));
134 static int typedef_find(char *name
)
137 for (i
= ntypedefs
- 1; i
>= 0; --i
)
138 if (!strcmp(name
, typedefs
[i
].name
))
143 #define MAXARRAYS (1 << 5)
145 static struct array
{
151 static int array_add(struct type
*type
, int n
)
153 struct array
*a
= &arrays
[narrays
++];
154 memcpy(&a
->type
, type
, sizeof(*type
));
159 static void array2ptr(struct type
*t
)
161 if (!(t
->flags
& T_ARRAY
) || t
->ptr
)
163 memcpy(t
, &arrays
[t
->id
].type
, sizeof(*t
));
167 #define MAXTYPES (1 << 7)
168 #define MAXFIELDS (1 << 5)
170 static struct structinfo
{
172 struct name fields
[MAXFIELDS
];
179 static int struct_find(char *name
, int isunion
)
182 for (i
= nstructs
- 1; i
>= 0; --i
)
183 if (!strcmp(name
, structs
[i
].name
) &&
184 structs
[i
].isunion
== isunion
)
186 die("struct not found\n");
189 static struct name
*struct_field(int id
, char *name
)
191 struct structinfo
*si
= &structs
[id
];
193 for (i
= 0; i
< si
->nfields
; i
++)
194 if (!strcmp(name
, si
->fields
[i
].name
))
195 return &si
->fields
[i
];
196 die("field not found\n");
199 #define MAXBREAK (1 << 7)
200 static long breaks
[MAXBREAK
];
202 static long continues
[MAXBREAK
];
203 static int ncontinues
;
205 static void break_fill(long addr
, int till
)
208 for (i
= till
; i
< nbreaks
; i
++)
209 o_filljmp2(breaks
[i
], addr
);
213 static void continue_fill(long addr
, int till
)
216 for (i
= till
; i
< ncontinues
; i
++)
217 o_filljmp2(continues
[i
], addr
);
221 static int type_totsz(struct type
*t
)
225 if (t
->flags
& T_ARRAY
)
226 return arrays
[t
->id
].n
* type_totsz(&arrays
[t
->id
].type
);
227 return t
->flags
& T_STRUCT
? structs
[t
->id
].size
: BT_SZ(t
->bt
);
230 static unsigned type_szde(struct type
*t
)
232 if (t
->flags
& T_ARRAY
)
233 return t
->ptr
> 0 ? 8 : TYPE_SZ(&arrays
[t
->id
].type
);
235 return t
->ptr
> 1 ? 8 : BT_SZ(t
->bt
);
238 static int tok_jmp(int tok
)
240 if (tok_see() != tok
)
246 static void tok_expect(int tok
)
248 if (tok_get() != tok
)
249 die("syntax error\n");
252 static unsigned bt_op(unsigned bt1
, unsigned bt2
)
254 unsigned s1
= BT_SZ(bt1
);
255 unsigned s2
= BT_SZ(bt2
);
256 return (bt1
| bt2
) & BT_SIGNED
| (s1
> s2
? s1
: s2
);
259 static void ts_binop(void (*o_sth
)(void))
265 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
268 static int shifts(int n
)
277 static void ts_binop_add(void (*o_sth
)(void))
284 if (!t1
.ptr
&& !t2
.ptr
) {
286 ts_push_bt(bt_op(TYPE_BT(&t1
), TYPE_BT(&t2
)));
289 if (t1
.ptr
&& !t2
.ptr
) {
295 if (!t1
.ptr
&& t2
.ptr
)
296 if (type_szde(&t2
) > 1) {
297 o_num(shifts(type_szde(&t2
)), 1);
301 if (t1
.ptr
&& t2
.ptr
) {
302 o_num(shifts(type_szde(&t1
)), 1);
304 ts_push_bt(4 | BT_SIGNED
);
310 static void structdef(void *data
, struct name
*name
, unsigned flags
)
312 struct structinfo
*si
= data
;
315 if (si
->size
< type_totsz(&name
->type
))
316 si
->size
= type_totsz(&name
->type
);
318 name
->addr
= si
->size
;
319 si
->size
+= type_totsz(&name
->type
);
321 memcpy(&si
->fields
[si
->nfields
++], name
, sizeof(*name
));
324 static int readdefs(void (*def
)(void *, struct name
*, unsigned f
), void *data
);
326 static int struct_create(char *name
, int isunion
)
329 struct structinfo
*si
= &structs
[id
];
330 strcpy(si
->name
, name
);
331 si
->isunion
= isunion
;
333 while (tok_jmp('}')) {
334 readdefs(structdef
, si
);
340 static void readexpr(void);
342 static void enum_create(void)
346 while (tok_jmp('}')) {
348 tok_expect(TOK_NAME
);
349 strcpy(name
, tok_id());
350 if (tok_see() == '=') {
355 die("const expr expected!\n");
362 static int basetype(struct type
*type
, unsigned *flags
)
401 isunion
= tok_get() == TOK_UNION
;
402 tok_expect(TOK_NAME
);
403 strcpy(name
, tok_id());
404 if (tok_see() == '{')
405 type
->id
= struct_create(name
, isunion
);
407 type
->id
= struct_find(name
, isunion
);
408 type
->flags
|= T_STRUCT
;
413 tok_expect(TOK_NAME
);
414 if (tok_see() == '{')
416 type
->bt
= 4 | BT_SIGNED
;
419 if (tok_see() == TOK_NAME
) {
420 int id
= typedef_find(tok_id());
423 memcpy(type
, &typedefs
[id
].type
,
436 type
->bt
= size
| (sign
? BT_SIGNED
: 0);
440 static void readptrs(struct type
*type
)
442 while (!tok_jmp('*'))
446 static int readtype(struct type
*type
)
449 if (basetype(type
, &flags
))
455 static void readpre(void);
457 static void readprimary(void)
461 if (!tok_jmp(TOK_NUM
)) {
462 ts_push_bt(4 | BT_SIGNED
);
463 o_num(tok_num(), 4 | BT_SIGNED
);
466 if (!tok_jmp(TOK_STR
)) {
470 t
.bt
= 1 | BT_SIGNED
;
475 o_symaddr(o_mkdat(NULL
, buf
, len
, 0), TYPE_BT(&t
));
479 if (!tok_jmp(TOK_NAME
)) {
481 for (i
= nlocals
- 1; i
>= 0; --i
) {
482 struct type
*t
= &locals
[i
].type
;
483 if (!strcmp(locals
[i
].name
, tok_id())) {
484 o_local(locals
[i
].addr
, TYPE_BT(t
));
489 for (i
= 0; i
< nglobals
; i
++) {
490 struct type
*t
= &globals
[i
].type
;
491 if (!strcmp(globals
[i
].name
, tok_id())) {
492 o_symaddr(globals
[i
].addr
, TYPE_BT(t
));
497 if (!enum_find(&n
, tok_id())) {
498 ts_push_bt(4 | BT_SIGNED
);
499 o_num(n
, 4 | BT_SIGNED
);
502 strcpy(name
.name
, tok_id());
503 name
.addr
= o_mkundef(name
.name
);
506 o_symaddr(name
.addr
, 8);
517 if (!t
.ptr
|| !o
.ptr
)
527 void arrayderef(struct type
*t
)
529 int sz
= type_totsz(t
);
538 static void inc_post(void (*op
)(void))
540 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
554 static void readfield(void)
558 tok_expect(TOK_NAME
);
560 field
= struct_field(t
.id
, tok_id());
562 o_num(field
->addr
, 4);
565 o_deref(TYPE_BT(&field
->type
));
566 ts_push(&field
->type
);
569 #define MAXFUNCS (1 << 10)
571 static struct funcinfo
{
572 struct type args
[MAXFIELDS
];
577 static unsigned ret_bt
;
579 static int func_create(struct type
*ret
, struct name
*args
, int nargs
)
581 struct funcinfo
*fi
= &funcs
[nfuncs
++];
583 memcpy(&fi
->ret
, ret
, sizeof(*ret
));
584 for (i
= 0; i
< nargs
; i
++)
585 memcpy(&fi
->args
[i
], &args
[i
].type
, sizeof(*ret
));
590 static void readcall(void)
593 unsigned bt
[MAXARGS
];
597 if (tok_see() != ')') {
600 bt
[argc
++] = TYPE_BT(&t
);
602 while (!tok_jmp(',')) {
605 bt
[argc
++] = TYPE_BT(&t
);
609 if (t
.flags
& T_FUNC
&& t
.ptr
> 0)
611 fi
= t
.flags
& T_FUNC
? &funcs
[t
.id
] : NULL
;
613 for (i
= 0; i
< fi
->nargs
; i
++)
614 bt
[i
] = TYPE_BT(&fi
->args
[i
]);
615 o_call(argc
, bt
, fi
? TYPE_BT(&fi
->ret
) : 4 | BT_SIGNED
);
619 ts_push_bt(4 | BT_SIGNED
);
622 static void readpost(void)
642 if (!tok_jmp(TOK2("++"))) {
646 if (!tok_jmp(TOK2("--"))) {
655 if (!tok_jmp(TOK2("->"))) {
663 static void inc_pre(void (*op
)(void))
665 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
676 static void readpre(void)
682 if (!(type
.flags
& T_FUNC
) && !type
.ptr
)
693 if (!(t
.flags
& T_FUNC
) || t
.ptr
> 0) {
695 o_deref(TYPE_BT(&t
));
705 ts_push_bt(4 | BT_SIGNED
);
718 if (!tok_jmp(TOK2("++"))) {
722 if (!tok_jmp(TOK2("--"))) {
726 if (!tok_jmp(TOK_SIZEOF
)) {
728 int op
= !tok_jmp('(');
730 int nogen
= !o_nogen();
738 o_num(type_totsz(&t
), 4);
746 static void readmul(void)
769 static void readadd(void)
787 static void shift(void (*op
)(void))
794 ts_push_bt(TYPE_BT(&t
));
797 static void readshift(void)
801 if (!tok_jmp(TOK2("<<"))) {
805 if (!tok_jmp(TOK2(">>"))) {
813 static void cmp(void (*op
)(void))
819 ts_push_bt(4 | BT_SIGNED
);
822 static void readcmp(void)
834 if (!tok_jmp(TOK2("<="))) {
838 if (!tok_jmp(TOK2(">="))) {
846 static void eq(void (*op
)(void))
852 ts_push_bt(4 | BT_SIGNED
);
855 static void readeq(void)
859 if (!tok_jmp(TOK2("=="))) {
863 if (!tok_jmp(TOK2("!="))) {
871 static void readbitand(void)
874 while (!tok_jmp('&')) {
880 static void readxor(void)
883 while (!tok_jmp('^')) {
889 static void readbitor(void)
892 while (!tok_jmp('|')) {
898 #define MAXCOND (1 << 5)
900 static void readand(void)
907 if (tok_see() != TOK2("&&"))
909 conds
[nconds
++] = o_jz(0);
911 while (!tok_jmp(TOK2("&&"))) {
913 conds
[nconds
++] = o_jz(0);
916 o_num(1, 4 | BT_SIGNED
);
919 for (i
= 0; i
< nconds
; i
++)
921 o_num(0, 4 | BT_SIGNED
);
924 ts_push_bt(4 | BT_SIGNED
);
927 static void reador(void)
934 if (tok_see() != TOK2("||"))
936 conds
[nconds
++] = o_jnz(0);
938 while (!tok_jmp(TOK2("||"))) {
940 conds
[nconds
++] = o_jnz(0);
943 o_num(0, 4 | BT_SIGNED
);
946 for (i
= 0; i
< nconds
; i
++)
948 o_num(1, 4 | BT_SIGNED
);
951 ts_push_bt(4 | BT_SIGNED
);
954 static void readcexpr(void)
962 cexpr
= !o_popnum(&c
);
1001 static void opassign(void (*bop
)(void (*op
)(void)), void (*op
)(void))
1003 unsigned bt
= TYPE_BT(&ts
[nts
- 1]);
1011 static void readexpr(void)
1014 if (!tok_jmp('=')) {
1017 o_assign(TYPE_BT(&ts
[nts
- 1]));
1020 if (!tok_jmp(TOK2("+="))) {
1021 opassign(ts_binop_add
, o_add
);
1024 if (!tok_jmp(TOK2("-="))) {
1025 opassign(ts_binop_add
, o_sub
);
1028 if (!tok_jmp(TOK2("*="))) {
1029 opassign(ts_binop
, o_mul
);
1032 if (!tok_jmp(TOK2("/="))) {
1033 opassign(ts_binop
, o_div
);
1036 if (!tok_jmp(TOK2("%="))) {
1037 opassign(ts_binop
, o_mod
);
1040 if (!tok_jmp(TOK3("<<="))) {
1041 opassign(ts_binop
, o_shl
);
1044 if (!tok_jmp(TOK3(">>="))) {
1045 opassign(ts_binop
, o_shr
);
1048 if (!tok_jmp(TOK3("&="))) {
1049 opassign(ts_binop
, o_and
);
1052 if (!tok_jmp(TOK3("|="))) {
1053 opassign(ts_binop
, o_or
);
1056 if (!tok_jmp(TOK3("^="))) {
1057 opassign(ts_binop
, o_xor
);
1062 static void readestmt(void)
1068 } while (!tok_jmp(','));
1071 #define F_GLOBAL(flags) (!((flags) & F_STATIC))
1073 static void globaldef(void *data
, struct name
*name
, unsigned flags
)
1075 char *varname
= flags
& F_STATIC
? NULL
: name
->name
;
1076 name
->addr
= o_mkvar(varname
, type_totsz(&name
->type
), F_GLOBAL(flags
));
1080 static void localdef(void *data
, struct name
*name
, unsigned flags
)
1082 if (flags
& F_STATIC
) {
1083 globaldef(data
, name
, flags
);
1086 name
->addr
= o_mklocal(type_totsz(&name
->type
));
1088 if (flags
& F_INIT
) {
1089 struct type
*t
= &name
->type
;
1090 o_local(locals
[nlocals
- 1].addr
, TYPE_BT(t
));
1092 o_assign(TYPE_BT(t
));
1096 static void funcdef(struct name
*name
, struct name
*args
,
1097 int nargs
, unsigned flags
)
1100 name
->addr
= o_func_beg(name
->name
, F_GLOBAL(flags
));
1102 ret_bt
= TYPE_BT(&funcs
[name
->addr
].ret
);
1103 for (i
= 0; i
< nargs
; i
++) {
1104 args
[i
].addr
= o_arg(i
, type_totsz(&args
[i
].type
));
1105 local_add(&args
[i
]);
1109 static int readargs(struct name
*args
)
1113 while (tok_see() != ')') {
1114 readtype(&args
[nargs
].type
);
1115 if (!tok_jmp(TOK_NAME
))
1116 strcpy(args
[nargs
++].name
, tok_id());
1124 static int readdefs(void (*def
)(void *data
, struct name
*name
, unsigned flags
),
1129 if (basetype(&base
, &flags
))
1131 while (tok_see() != ';' && tok_see() != '{') {
1132 struct type tpool
[3];
1135 struct type
*type
= &tpool
[npool
++];
1136 struct type
*func
= NULL
;
1137 struct type
*ret
= NULL
;
1138 memset(tpool
, 0, sizeof(tpool
));
1139 memcpy(type
, &base
, sizeof(base
));
1141 if (!tok_jmp('(')) {
1143 type
= &tpool
[npool
++];
1147 tok_expect(TOK_NAME
);
1148 strcpy(name
.name
, tok_id());
1149 while (!tok_jmp('[')) {
1154 die("const expr expected\n");
1155 type
->id
= array_add(type
, n
);
1156 if (type
->flags
& T_FUNC
)
1157 func
= &arrays
[type
->id
].type
;
1158 type
->flags
= T_ARRAY
;
1165 if (tok_see() == '(') {
1166 struct name args
[MAXARGS
];
1167 int nargs
= readargs(args
);
1171 type
= &tpool
[npool
++];
1174 func
->flags
= T_FUNC
;
1176 func
->id
= func_create(ret
, args
, nargs
);
1178 if (tok_see() != '{')
1180 memcpy(&name
.type
, func
, sizeof(*func
));
1181 funcdef(&name
, args
, nargs
, flags
);
1185 memcpy(&name
.type
, type
, sizeof(*type
));
1188 def(data
, &name
, flags
);
1194 static void typedefdef(void *data
, struct name
*name
, unsigned flags
)
1196 typedef_add(name
->name
, &name
->type
);
1199 #define MAXCASES (1 << 7)
1201 static void readstmt(void);
1203 static void readswitch(void)
1205 int break_beg
= nbreaks
;
1206 long val_addr
= o_mklocal(8);
1207 long matched
[MAXCASES
];
1216 o_local(val_addr
, TYPE_BT(&t
));
1218 o_assign(TYPE_BT(&t
));
1222 while (tok_jmp('}')) {
1224 while (tok_see() == TOK_CASE
|| tok_see() == TOK_DEFAULT
) {
1226 matched
[nmatched
++] = o_jmp(0);
1229 if (!tok_jmp(TOK_CASE
)) {
1231 o_local(val_addr
, TYPE_BT(&t
));
1240 if (!tok_jmp(TOK_DEFAULT
)) {
1245 for (i
= 0; i
< nmatched
; i
++)
1246 o_filljmp(matched
[i
]);
1250 o_rmlocal(val_addr
, 8);
1253 break_fill(o_mklabel(), break_beg
);
1256 static void readstmt(void)
1260 if (!tok_jmp('{')) {
1261 int _nlocals
= nlocals
;
1262 int _nglobals
= nglobals
;
1263 int _nenums
= nenums
;
1264 int _ntypedefs
= ntypedefs
;
1265 int _nstructs
= nstructs
;
1266 int _nfuncs
= nfuncs
;
1267 int _narrays
= narrays
;
1268 while (tok_jmp('}'))
1272 ntypedefs
= _ntypedefs
;
1273 nstructs
= _nstructs
;
1276 nglobals
= _nglobals
;
1279 if (!readdefs(localdef
, NULL
)) {
1283 if (!tok_jmp(TOK_TYPEDEF
)) {
1284 readdefs(typedefdef
, NULL
);
1288 if (!tok_jmp(TOK_IF
)) {
1295 if (!tok_jmp(TOK_ELSE
)) {
1305 if (!tok_jmp(TOK_WHILE
)) {
1307 int break_beg
= nbreaks
;
1308 int continue_beg
= ncontinues
;
1317 break_fill(o_mklabel(), break_beg
);
1318 continue_fill(l1
, continue_beg
);
1321 if (!tok_jmp(TOK_DO
)) {
1323 int break_beg
= nbreaks
;
1324 int continue_beg
= ncontinues
;
1327 tok_expect(TOK_WHILE
);
1333 break_fill(o_mklabel(), break_beg
);
1334 continue_fill(l2
, continue_beg
);
1337 if (!tok_jmp(TOK_FOR
)) {
1338 long check
, jump
, end
, body
;
1339 int break_beg
= nbreaks
;
1340 int continue_beg
= ncontinues
;
1342 if (tok_see() != ';')
1345 check
= o_mklabel();
1346 if (tok_see() != ';')
1352 if (tok_see() != ')')
1360 break_fill(o_mklabel(), break_beg
);
1361 continue_fill(jump
, continue_beg
);
1364 if (!tok_jmp(TOK_SWITCH
)) {
1368 if (!tok_jmp(TOK_RETURN
)) {
1369 int ret
= tok_see() != ';';
1376 if (!tok_jmp(TOK_BREAK
)) {
1378 breaks
[nbreaks
++] = o_jmp(0);
1381 if (!tok_jmp(TOK_CONTINUE
)) {
1383 continues
[ncontinues
++] = o_jmp(0);
1390 static void readdecl(void)
1392 if (!tok_jmp(TOK_TYPEDEF
)) {
1393 readdefs(typedefdef
, NULL
);
1397 readdefs(globaldef
, NULL
);
1398 if (tok_see() == '{') {
1407 static void parse(void)
1409 while (tok_see() != TOK_EOF
)
1413 int main(int argc
, char *argv
[])
1418 while (i
< argc
&& argv
[i
][0] == '-')
1421 die("no file given\n");
1422 ifd
= open(argv
[i
], O_RDONLY
);
1427 strcpy(obj
, argv
[i
]);
1428 obj
[strlen(obj
) - 1] = 'o';
1429 ofd
= open(obj
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0600);