added do while continue - simplify break/continue handling

tcc-xref
bellard 2001-10-30 20:27:54 +00:00
parent 704d61357c
commit 4e92bac070
1 changed files with 63 additions and 30 deletions

93
tcc.c
View File

@ -11,12 +11,11 @@
glo : global variable index glo : global variable index
parm : parameter variable index parm : parameter variable index
ind : output code ptr ind : output code ptr
lsym: loop symbol stack
rsym: return symbol rsym: return symbol
prog: output code prog: output code
astk: arg position stack astk: arg position stack
*/ */
int tok, *vac, *vat, *lsym, rsym, int tok, *vac, *vat, rsym,
prog, ind, loc, glo, file, vt, prog, ind, loc, glo, file, vt,
vc, *macro_stack, *macro_stack_ptr, line_num; vc, *macro_stack, *macro_stack_ptr, line_num;
char *idtable, *idptr, *filename; char *idtable, *idptr, *filename;
@ -87,17 +86,21 @@ char *idtable, *idptr, *filename;
#define TOK_CASE 274 #define TOK_CASE 274
/* ignored types Must have contiguous values */ /* ignored types Must have contiguous values */
#define TOK_CONST 271 #define TOK_CONST 275
#define TOK_LONG 276 #define TOK_VOLATILE 276
#define TOK_REGISTER 277 #define TOK_LONG 277
#define TOK_SIGNED 278 #define TOK_REGISTER 278
#define TOK_SIGNED 279
/* unsupported types. Must have contiguous values */ /* unsupported types. Must have contiguous values */
#define TOK_FLOAT 279 #define TOK_FLOAT 280
#define TOK_DOUBLE 280 #define TOK_DOUBLE 281
#define TOK_STRUCT 281 #define TOK_STRUCT 282
#define TOK_UNION 282 #define TOK_UNION 283
#define TOK_TYPEDEF 283 #define TOK_TYPEDEF 284
#define TOK_DEFAULT 285
#define TOK_ENUM 286
#define TOK_EQ 0x94 /* warning: depend on asm code */ #define TOK_EQ 0x94 /* warning: depend on asm code */
#define TOK_NE 0x95 /* warning: depend on asm code */ #define TOK_NE 0x95 /* warning: depend on asm code */
@ -336,16 +339,21 @@ void o(c)
} }
/* output a symbol and patch all calls to it */ /* output a symbol and patch all calls to it */
void gsym(t) void gsym_addr(t, a)
{ {
int n; int n;
while (t) { while (t) {
n = *(int *)t; /* next value */ n = *(int *)t; /* next value */
*(int *)t = ind - t - 4; *(int *)t = a - t - 4;
t = n; t = n;
} }
} }
void gsym(t)
{
gsym_addr(t, ind);
}
/* psym is used to put an instruction with a data field which is a /* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */ reference to a symbol. It is in fact the same as oad ! */
#define psym oad #define psym oad
@ -1022,9 +1030,9 @@ void expr()
#endif #endif
void block() void block(int *bsym, int *csym)
{ {
int a, c, d; int a, b, c, d;
if (tok == TOK_IF) { if (tok == TOK_IF) {
/* if test */ /* if test */
@ -1033,13 +1041,13 @@ void block()
expr(); expr();
skip(')'); skip(')');
a = gtst(1, 0); a = gtst(1, 0);
block(); block(bsym, csym);
c = tok; c = tok;
if (c == TOK_ELSE) { if (c == TOK_ELSE) {
next(); next();
d = psym(0xe9, 0); /* jmp */ d = psym(0xe9, 0); /* jmp */
gsym(a); gsym(a);
block(); block(bsym, csym);
gsym(d); /* patch else jmp */ gsym(d); /* patch else jmp */
} else } else
gsym(a); gsym(a);
@ -1049,16 +1057,18 @@ void block()
skip('('); skip('(');
expr(); expr();
skip(')'); skip(')');
*++lsym = gtst(1, 0); a = gtst(1, 0);
block(); b = 0;
block(&a, &b);
oad(0xe9, d - ind - 5); /* jmp */ oad(0xe9, d - ind - 5); /* jmp */
gsym(*lsym--); gsym(a);
gsym_addr(b, d);
} else if (tok == '{') { } else if (tok == '{') {
next(); next();
/* declarations */ /* declarations */
decl(VT_LOCAL); decl(VT_LOCAL);
while (tok != '}') while (tok != '}')
block(); block(bsym, csym);
next(); next();
} else if (tok == TOK_RETURN) { } else if (tok == TOK_RETURN) {
next(); next();
@ -1070,7 +1080,16 @@ void block()
rsym = psym(0xe9, rsym); /* jmp */ rsym = psym(0xe9, rsym); /* jmp */
} else if (tok == TOK_BREAK) { } else if (tok == TOK_BREAK) {
/* compute jump */ /* compute jump */
*lsym = psym(0xe9, *lsym); if (!bsym)
error("cannot break");
*bsym = psym(0xe9, *bsym);
next();
skip(';');
} else if (tok == TOK_CONTINUE) {
/* compute jump */
if (!csym)
error("cannot continue");
*csym = psym(0xe9, *csym);
next(); next();
skip(';'); skip(';');
} else } else
@ -1085,11 +1104,11 @@ void block()
d = ind; d = ind;
c = ind; c = ind;
a = 0; a = 0;
b = 0;
if (tok != ';') { if (tok != ';') {
expr(); expr();
a = gtst(1, 0); a = gtst(1, 0);
} }
*++lsym = a;
skip(';'); skip(';');
if (tok != ')') { if (tok != ')') {
e = psym(0xe9, 0); e = psym(0xe9, 0);
@ -1099,10 +1118,26 @@ void block()
gsym(e); gsym(e);
} }
skip(')'); skip(')');
block(); block(&a, &b);
oad(0xe9, c - ind - 5); /* jmp */ oad(0xe9, c - ind - 5); /* jmp */
gsym(*lsym--); gsym(a);
gsym_addr(b, c);
} else } else
if (tok == TOK_DO) {
next();
a = 0;
b = 0;
d = ind;
block(&a, &b);
skip(TOK_WHILE);
skip('(');
gsym(b);
expr();
c = gtst(0, 0);
gsym_addr(c, d);
skip(')');
gsym(a);
} else
#endif #endif
{ {
if (tok != ';') if (tok != ';')
@ -1131,7 +1166,7 @@ void decl(l)
o(0xe58955); /* push %ebp, mov %esp, %ebp */ o(0xe58955); /* push %ebp, mov %esp, %ebp */
a = oad(0xec81, 0); /* sub $xxx, %esp */ a = oad(0xec81, 0); /* sub $xxx, %esp */
rsym = 0; rsym = 0;
block(); block(0, 0);
gsym(rsym); gsym(rsym);
o(0xc3c9); /* leave, ret */ o(0xc3c9); /* leave, ret */
*a = (-loc + 3) & -4; /* align local size to word & *a = (-loc + 3) & -4; /* align local size to word &
@ -1207,15 +1242,13 @@ int main(int c, char **v)
idptr = idtable + 53; idptr = idtable + 53;
#else #else
memcpy(idtable, memcpy(idtable,
"int\0void\0char\0if\0else\0while\0break\0return\0define\0main\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0long\0register\0signed\0float\0double\0struct\0union\0typedef", 170); "int\0void\0char\0if\0else\0while\0break\0return\0define\0main\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0float\0double\0struct\0union\0typedef\0default\0enum", 192);
idptr = idtable + 192;
idptr = idtable + 170;
#endif #endif
glo = malloc(DATA_SIZE); glo = malloc(DATA_SIZE);
prog = malloc(TEXT_SIZE); prog = malloc(TEXT_SIZE);
vac = malloc(VAR_TABLE_SIZE); vac = malloc(VAR_TABLE_SIZE);
vat = malloc(VAR_TABLE_SIZE); vat = malloc(VAR_TABLE_SIZE);
lsym = malloc(256);
macro_stack = malloc(256); macro_stack = malloc(256);
macro_stack_ptr = macro_stack; macro_stack_ptr = macro_stack;
ind = prog; ind = prog;