increased hash table sizes - added cdecl and stdcall attributes - #elif fix - empty args in macro fix - benchmark option
This commit is contained in:
parent
d2c9157388
commit
6e2d1a809a
1 changed files with 132 additions and 46 deletions
176
tcc.c
176
tcc.c
|
@ -52,9 +52,9 @@
|
||||||
#define STRING_MAX_SIZE 1024
|
#define STRING_MAX_SIZE 1024
|
||||||
#define INCLUDE_PATHS_MAX 32
|
#define INCLUDE_PATHS_MAX 32
|
||||||
|
|
||||||
#define TOK_HASH_SIZE 521
|
#define TOK_HASH_SIZE 2048 /* must be a power of two */
|
||||||
#define TOK_ALLOC_INCR 256 /* must be a power of two */
|
#define TOK_ALLOC_INCR 512 /* must be a power of two */
|
||||||
#define SYM_HASH_SIZE 263
|
#define SYM_HASH_SIZE 1031
|
||||||
|
|
||||||
/* token symbol management */
|
/* token symbol management */
|
||||||
typedef struct TokenSym {
|
typedef struct TokenSym {
|
||||||
|
@ -131,16 +131,22 @@ typedef struct Section {
|
||||||
typedef struct AttributeDef {
|
typedef struct AttributeDef {
|
||||||
int aligned;
|
int aligned;
|
||||||
Section *section;
|
Section *section;
|
||||||
|
unsigned char func_call; /* FUNC_CDECL or FUNC_STDCALL */
|
||||||
} AttributeDef;
|
} AttributeDef;
|
||||||
|
|
||||||
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
||||||
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
|
||||||
#define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
|
#define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
|
||||||
|
|
||||||
|
/* stored in 'Sym.c' field */
|
||||||
#define FUNC_NEW 1 /* ansi function prototype */
|
#define FUNC_NEW 1 /* ansi function prototype */
|
||||||
#define FUNC_OLD 2 /* old function prototype */
|
#define FUNC_OLD 2 /* old function prototype */
|
||||||
#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
|
#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
|
||||||
|
|
||||||
|
/* stored in 'Sym.r' field */
|
||||||
|
#define FUNC_CDECL 0 /* standard c call */
|
||||||
|
#define FUNC_STDCALL 1 /* pascal c call */
|
||||||
|
|
||||||
/* field 'Sym.t' for macros */
|
/* field 'Sym.t' for macros */
|
||||||
#define MACRO_OBJ 0 /* object like macro */
|
#define MACRO_OBJ 0 /* object like macro */
|
||||||
#define MACRO_FUNC 1 /* function like macro */
|
#define MACRO_FUNC 1 /* function like macro */
|
||||||
|
@ -215,6 +221,11 @@ int do_debug = 0;
|
||||||
/* compile with built-in memory and bounds checker */
|
/* compile with built-in memory and bounds checker */
|
||||||
int do_bounds_check = 0;
|
int do_bounds_check = 0;
|
||||||
|
|
||||||
|
/* display benchmark infos */
|
||||||
|
int do_bench = 0;
|
||||||
|
int total_lines;
|
||||||
|
int total_bytes;
|
||||||
|
|
||||||
/* use GNU C extensions */
|
/* use GNU C extensions */
|
||||||
int gnu_ext = 1;
|
int gnu_ext = 1;
|
||||||
|
|
||||||
|
@ -405,8 +416,33 @@ enum {
|
||||||
TOK___ALIGNED__,
|
TOK___ALIGNED__,
|
||||||
TOK_UNUSED,
|
TOK_UNUSED,
|
||||||
TOK___UNUSED__,
|
TOK___UNUSED__,
|
||||||
|
TOK_CDECL,
|
||||||
|
TOK___CDECL,
|
||||||
|
TOK___CDECL__,
|
||||||
|
TOK_STDCALL,
|
||||||
|
TOK___STDCALL,
|
||||||
|
TOK___STDCALL__,
|
||||||
|
TOK_NORETURN,
|
||||||
|
TOK___NORETURN__,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *tcc_keywords =
|
||||||
|
"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0"
|
||||||
|
"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0"
|
||||||
|
"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0"
|
||||||
|
"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0"
|
||||||
|
"sizeof\0__attribute__\0"
|
||||||
|
/* the following are not keywords. They are included to ease parsing */
|
||||||
|
"define\0include\0ifdef\0ifndef\0elif\0endif\0"
|
||||||
|
"defined\0undef\0error\0line\0"
|
||||||
|
"__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0"
|
||||||
|
"__func__\0main\0"
|
||||||
|
/* attributes */
|
||||||
|
"section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0"
|
||||||
|
"cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0"
|
||||||
|
"noreturn\0__noreturn__\0"
|
||||||
|
;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
/* currently incorrect */
|
/* currently incorrect */
|
||||||
|
@ -459,7 +495,7 @@ int pointed_type(int t);
|
||||||
int pointed_size(int t);
|
int pointed_size(int t);
|
||||||
int is_compatible_types(int t1, int t2);
|
int is_compatible_types(int t1, int t2);
|
||||||
int parse_btype(int *type_ptr, AttributeDef *ad);
|
int parse_btype(int *type_ptr, AttributeDef *ad);
|
||||||
int type_decl(int *v, int t, int td);
|
int type_decl(AttributeDef *ad, int *v, int t, int td);
|
||||||
|
|
||||||
void error(const char *fmt, ...);
|
void error(const char *fmt, ...);
|
||||||
void rt_error(unsigned long pc, const char *fmt, ...);
|
void rt_error(unsigned long pc, const char *fmt, ...);
|
||||||
|
@ -800,7 +836,7 @@ TokenSym *tok_alloc(const char *str, int len)
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
h = 1;
|
h = 1;
|
||||||
for(i=0;i<len;i++)
|
for(i=0;i<len;i++)
|
||||||
h = ((h << 8) | (str[i] & 0xff)) % TOK_HASH_SIZE;
|
h = (h * 263 + ((unsigned char *)str)[i]) & (TOK_HASH_SIZE - 1);
|
||||||
|
|
||||||
pts = &hash_ident[h];
|
pts = &hash_ident[h];
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -1034,11 +1070,13 @@ BufferedFile *tcc_open(const char *filename)
|
||||||
bf->buffer[0] = CH_EOB; /* put eob symbol */
|
bf->buffer[0] = CH_EOB; /* put eob symbol */
|
||||||
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
||||||
bf->line_num = 1;
|
bf->line_num = 1;
|
||||||
|
// printf("opening '%s'\n", filename);
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcc_close(BufferedFile *bf)
|
void tcc_close(BufferedFile *bf)
|
||||||
{
|
{
|
||||||
|
total_lines += bf->line_num;
|
||||||
close(bf->fd);
|
close(bf->fd);
|
||||||
free(bf);
|
free(bf);
|
||||||
}
|
}
|
||||||
|
@ -1059,6 +1097,7 @@ int tcc_getc_slow(BufferedFile *bf)
|
||||||
} else {
|
} else {
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
total_bytes += len;
|
||||||
bf->buf_ptr = bf->buffer;
|
bf->buf_ptr = bf->buffer;
|
||||||
bf->buf_end = bf->buffer + len;
|
bf->buf_end = bf->buffer + len;
|
||||||
*bf->buf_end = CH_EOB;
|
*bf->buf_end = CH_EOB;
|
||||||
|
@ -1290,7 +1329,7 @@ int expr_preprocess(void)
|
||||||
return c != 0;
|
return c != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG) || defined(PP_DEBUG)
|
||||||
void tok_print(int *str)
|
void tok_print(int *str)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
@ -1454,25 +1493,32 @@ void preprocess(void)
|
||||||
*ifdef_stack_ptr++ = c;
|
*ifdef_stack_ptr++ = c;
|
||||||
goto test_skip;
|
goto test_skip;
|
||||||
} else if (tok == TOK_ELSE) {
|
} else if (tok == TOK_ELSE) {
|
||||||
if (ifdef_stack_ptr == ifdef_stack ||
|
if (ifdef_stack_ptr == ifdef_stack)
|
||||||
(ifdef_stack_ptr[-1] & 2))
|
error("#else without matching #if");
|
||||||
|
if (ifdef_stack_ptr[-1] & 2)
|
||||||
error("#else after #else");
|
error("#else after #else");
|
||||||
c = (ifdef_stack_ptr[-1] ^= 3);
|
c = (ifdef_stack_ptr[-1] ^= 3);
|
||||||
goto test_skip;
|
goto test_skip;
|
||||||
} else if (tok == TOK_ELIF) {
|
} else if (tok == TOK_ELIF) {
|
||||||
if (ifdef_stack_ptr == ifdef_stack ||
|
if (ifdef_stack_ptr == ifdef_stack)
|
||||||
ifdef_stack_ptr[-1] > 1)
|
error("#elif without matching #if");
|
||||||
|
c = ifdef_stack_ptr[-1];
|
||||||
|
if (c > 1)
|
||||||
error("#elif after #else");
|
error("#elif after #else");
|
||||||
|
/* last #if/#elif expression was true: we skip */
|
||||||
|
if (c == 1)
|
||||||
|
goto skip;
|
||||||
c = expr_preprocess();
|
c = expr_preprocess();
|
||||||
ifdef_stack_ptr[-1] = c;
|
ifdef_stack_ptr[-1] = c;
|
||||||
test_skip:
|
test_skip:
|
||||||
if (!(c & 1)) {
|
if (!(c & 1)) {
|
||||||
|
skip:
|
||||||
preprocess_skip();
|
preprocess_skip();
|
||||||
goto redo;
|
goto redo;
|
||||||
}
|
}
|
||||||
} else if (tok == TOK_ENDIF) {
|
} else if (tok == TOK_ENDIF) {
|
||||||
if (ifdef_stack_ptr == ifdef_stack)
|
if (ifdef_stack_ptr == ifdef_stack)
|
||||||
expect("#if");
|
error("#endif without matching #if");
|
||||||
ifdef_stack_ptr--;
|
ifdef_stack_ptr--;
|
||||||
} else if (tok == TOK_LINE) {
|
} else if (tok == TOK_LINE) {
|
||||||
next();
|
next();
|
||||||
|
@ -1876,7 +1922,7 @@ void next_nomacro1(void)
|
||||||
while(1) {
|
while(1) {
|
||||||
while (ch == '\n') {
|
while (ch == '\n') {
|
||||||
cinp();
|
cinp();
|
||||||
while (ch == ' ' || ch == 9)
|
while (ch == ' ' || ch == '\t')
|
||||||
cinp();
|
cinp();
|
||||||
if (ch == '#') {
|
if (ch == '#') {
|
||||||
/* preprocessor command if # at start of line after
|
/* preprocessor command if # at start of line after
|
||||||
|
@ -2157,7 +2203,14 @@ void macro_subst(int **tok_str, int *tok_len,
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
args = NULL;
|
args = NULL;
|
||||||
sa = s->next;
|
sa = s->next;
|
||||||
while (tok != ')' && sa) {
|
/* NOTE: empty args are allowed, except if no args */
|
||||||
|
for(;;) {
|
||||||
|
/* handle '()' case */
|
||||||
|
if (!args && tok == ')')
|
||||||
|
break;
|
||||||
|
if (!sa)
|
||||||
|
error("macro '%s' used with too many args",
|
||||||
|
get_tok_str(s->v, 0));
|
||||||
len = 0;
|
len = 0;
|
||||||
str = NULL;
|
str = NULL;
|
||||||
parlevel = 0;
|
parlevel = 0;
|
||||||
|
@ -2175,13 +2228,17 @@ void macro_subst(int **tok_str, int *tok_len,
|
||||||
}
|
}
|
||||||
tok_add(&str, &len, 0);
|
tok_add(&str, &len, 0);
|
||||||
sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
|
sym_push2(&args, sa->v & ~SYM_FIELD, 0, (int)str);
|
||||||
if (tok != ',')
|
if (tok == ')')
|
||||||
break;
|
break;
|
||||||
|
if (tok != ',')
|
||||||
|
expect(",");
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
sa = sa->next;
|
sa = sa->next;
|
||||||
}
|
}
|
||||||
if (tok != ')')
|
if (sa->next)
|
||||||
expect(")");
|
error("macro '%s' used with too few args",
|
||||||
|
get_tok_str(s->v, 0));
|
||||||
|
|
||||||
/* now subst each arg */
|
/* now subst each arg */
|
||||||
mstr = macro_arg_subst(nested_list, mstr, args);
|
mstr = macro_arg_subst(nested_list, mstr, args);
|
||||||
/* free memory */
|
/* free memory */
|
||||||
|
@ -2232,7 +2289,7 @@ void next(void)
|
||||||
} else {
|
} else {
|
||||||
redo:
|
redo:
|
||||||
if (!macro_ptr) {
|
if (!macro_ptr) {
|
||||||
/* if not reading from macro substuted string, then try to substitute */
|
/* if not reading from macro substituted string, then try to substitute */
|
||||||
len = 0;
|
len = 0;
|
||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
nested_list = NULL;
|
nested_list = NULL;
|
||||||
|
@ -2338,7 +2395,8 @@ void save_reg(int r)
|
||||||
if (!saved) {
|
if (!saved) {
|
||||||
/* store register in the stack */
|
/* store register in the stack */
|
||||||
t = p->t;
|
t = p->t;
|
||||||
if (!is_float(t) && (t & VT_BTYPE) != VT_LLONG)
|
if ((p->r & VT_LVAL) ||
|
||||||
|
(!is_float(t) && (t & VT_BTYPE) != VT_LLONG))
|
||||||
t = VT_INT;
|
t = VT_INT;
|
||||||
size = type_size(t, &align);
|
size = type_size(t, &align);
|
||||||
loc = (loc - size) & -align;
|
loc = (loc - size) & -align;
|
||||||
|
@ -2690,7 +2748,7 @@ void gen_opl(int op)
|
||||||
func = __modull;
|
func = __modull;
|
||||||
gen_func:
|
gen_func:
|
||||||
/* call generic long long function */
|
/* call generic long long function */
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
gfunc_param(&gf);
|
gfunc_param(&gf);
|
||||||
gfunc_param(&gf);
|
gfunc_param(&gf);
|
||||||
vpushi((int)func);
|
vpushi((int)func);
|
||||||
|
@ -3139,7 +3197,7 @@ void gen_cvt_itof1(int t)
|
||||||
if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
|
if ((vtop->t & (VT_BTYPE | VT_UNSIGNED)) ==
|
||||||
(VT_LLONG | VT_UNSIGNED)) {
|
(VT_LLONG | VT_UNSIGNED)) {
|
||||||
|
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
gfunc_param(&gf);
|
gfunc_param(&gf);
|
||||||
if (t == VT_FLOAT)
|
if (t == VT_FLOAT)
|
||||||
vpushi((int)&__ulltof);
|
vpushi((int)&__ulltof);
|
||||||
|
@ -3163,7 +3221,7 @@ void gen_cvt_ftoi1(int t)
|
||||||
|
|
||||||
if (t == (VT_LLONG | VT_UNSIGNED)) {
|
if (t == (VT_LLONG | VT_UNSIGNED)) {
|
||||||
/* not handled natively */
|
/* not handled natively */
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
st = vtop->t & VT_BTYPE;
|
st = vtop->t & VT_BTYPE;
|
||||||
gfunc_param(&gf);
|
gfunc_param(&gf);
|
||||||
if (st == VT_FLOAT)
|
if (st == VT_FLOAT)
|
||||||
|
@ -3346,6 +3404,8 @@ void gen_cast(int t)
|
||||||
/* from long long: just take low order word */
|
/* from long long: just take low order word */
|
||||||
lexpand();
|
lexpand();
|
||||||
vpop();
|
vpop();
|
||||||
|
} else if (sbt == VT_PTR) {
|
||||||
|
/* ok to cast */
|
||||||
} else if (vtop->r & VT_LVAL) {
|
} else if (vtop->r & VT_LVAL) {
|
||||||
/* if lvalue and single word type, nothing to do (XXX:
|
/* if lvalue and single word type, nothing to do (XXX:
|
||||||
maybe incorrect for sizeof op) */
|
maybe incorrect for sizeof op) */
|
||||||
|
@ -3616,7 +3676,7 @@ void vstore(void)
|
||||||
/* XXX: optimize if small size */
|
/* XXX: optimize if small size */
|
||||||
|
|
||||||
vdup();
|
vdup();
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
/* type size */
|
/* type size */
|
||||||
size = type_size(vtop->t, &align);
|
size = type_size(vtop->t, &align);
|
||||||
vpushi(size);
|
vpushi(size);
|
||||||
|
@ -3759,6 +3819,21 @@ void parse_attribute(AttributeDef *ad)
|
||||||
/* currently, no need to handle it because tcc does not
|
/* currently, no need to handle it because tcc does not
|
||||||
track unused objects */
|
track unused objects */
|
||||||
break;
|
break;
|
||||||
|
case TOK_NORETURN:
|
||||||
|
case TOK___NORETURN__:
|
||||||
|
/* currently, no need to handle it because tcc does not
|
||||||
|
track unused objects */
|
||||||
|
break;
|
||||||
|
case TOK_CDECL:
|
||||||
|
case TOK___CDECL:
|
||||||
|
case TOK___CDECL__:
|
||||||
|
ad->func_call = FUNC_CDECL;
|
||||||
|
break;
|
||||||
|
case TOK_STDCALL:
|
||||||
|
case TOK___STDCALL:
|
||||||
|
case TOK___STDCALL__:
|
||||||
|
ad->func_call = FUNC_STDCALL;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
warning("'%s' attribute ignored", get_tok_str(t, NULL));
|
||||||
/* skip parameters */
|
/* skip parameters */
|
||||||
|
@ -3837,7 +3912,7 @@ int struct_decl(int u)
|
||||||
bit_size = -1;
|
bit_size = -1;
|
||||||
v = 0;
|
v = 0;
|
||||||
if (tok != ':') {
|
if (tok != ':') {
|
||||||
t = type_decl(&v, b, TYPE_DIRECT);
|
t = type_decl(&ad, &v, b, TYPE_DIRECT);
|
||||||
if ((t & VT_BTYPE) == VT_FUNC ||
|
if ((t & VT_BTYPE) == VT_FUNC ||
|
||||||
(t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
|
(t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
|
||||||
error("invalid type for '%s'",
|
error("invalid type for '%s'",
|
||||||
|
@ -4055,11 +4130,11 @@ the_end:
|
||||||
return type_found;
|
return type_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
int post_type(int t)
|
int post_type(int t, AttributeDef *ad)
|
||||||
{
|
{
|
||||||
int p, n, pt, l, t1;
|
int p, n, pt, l, t1;
|
||||||
Sym **plast, *s, *first;
|
Sym **plast, *s, *first;
|
||||||
AttributeDef ad;
|
AttributeDef ad1;
|
||||||
|
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
/* function declaration */
|
/* function declaration */
|
||||||
|
@ -4070,7 +4145,7 @@ int post_type(int t)
|
||||||
while (tok != ')') {
|
while (tok != ')') {
|
||||||
/* read param name and compute offset */
|
/* read param name and compute offset */
|
||||||
if (l != FUNC_OLD) {
|
if (l != FUNC_OLD) {
|
||||||
if (!parse_btype(&pt, &ad)) {
|
if (!parse_btype(&pt, &ad1)) {
|
||||||
if (l) {
|
if (l) {
|
||||||
error("invalid type");
|
error("invalid type");
|
||||||
} else {
|
} else {
|
||||||
|
@ -4081,7 +4156,7 @@ int post_type(int t)
|
||||||
l = FUNC_NEW;
|
l = FUNC_NEW;
|
||||||
if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
|
if ((pt & VT_BTYPE) == VT_VOID && tok == ')')
|
||||||
break;
|
break;
|
||||||
pt = type_decl(&n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
|
pt = type_decl(&ad1, &n, pt, TYPE_DIRECT | TYPE_ABSTRACT);
|
||||||
if ((pt & VT_BTYPE) == VT_VOID)
|
if ((pt & VT_BTYPE) == VT_VOID)
|
||||||
error("parameter declared as void");
|
error("parameter declared as void");
|
||||||
} else {
|
} else {
|
||||||
|
@ -4109,10 +4184,10 @@ int post_type(int t)
|
||||||
l = FUNC_OLD;
|
l = FUNC_OLD;
|
||||||
skip(')');
|
skip(')');
|
||||||
t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
|
t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
|
||||||
t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
|
t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
|
||||||
/* we push a anonymous symbol which will contain the function prototype */
|
/* we push a anonymous symbol which will contain the function prototype */
|
||||||
p = anon_sym++;
|
p = anon_sym++;
|
||||||
s = sym_push(p, t, 0, l);
|
s = sym_push(p, t, ad->func_call, l);
|
||||||
s->next = first;
|
s->next = first;
|
||||||
t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
|
t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT);
|
||||||
} else if (tok == '[') {
|
} else if (tok == '[') {
|
||||||
|
@ -4127,7 +4202,7 @@ int post_type(int t)
|
||||||
skip(']');
|
skip(']');
|
||||||
/* parse next post type */
|
/* parse next post type */
|
||||||
t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
|
t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
|
||||||
t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
|
t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN), ad);
|
||||||
|
|
||||||
/* we push a anonymous symbol which will contain the array
|
/* we push a anonymous symbol which will contain the array
|
||||||
element type */
|
element type */
|
||||||
|
@ -4139,8 +4214,10 @@ int post_type(int t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a type declaration (except basic type), and return the
|
/* Read a type declaration (except basic type), and return the
|
||||||
type. If v is true, then also put variable name in 'vtop->c' */
|
type. 'td' is a bitmask indicating which kind of type decl is
|
||||||
int type_decl(int *v, int t, int td)
|
expected. 't' should contain the basic type. 'ad' is the attribute
|
||||||
|
definition of the basic type. It can be modified by type_decl(). */
|
||||||
|
int type_decl(AttributeDef *ad, int *v, int t, int td)
|
||||||
{
|
{
|
||||||
int u, p;
|
int u, p;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
@ -4156,7 +4233,11 @@ int type_decl(int *v, int t, int td)
|
||||||
/* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
|
/* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
next();
|
next();
|
||||||
u = type_decl(v, 0, td);
|
/* XXX: this is not correct to modify 'ad' at this point, but
|
||||||
|
the syntax is not clear */
|
||||||
|
if (tok == TOK___ATTRIBUTE__)
|
||||||
|
parse_attribute(ad);
|
||||||
|
u = type_decl(ad, v, 0, td);
|
||||||
skip(')');
|
skip(')');
|
||||||
} else {
|
} else {
|
||||||
u = 0;
|
u = 0;
|
||||||
|
@ -4171,7 +4252,9 @@ int type_decl(int *v, int t, int td)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* append t at the end of u */
|
/* append t at the end of u */
|
||||||
t = post_type(t);
|
t = post_type(t, ad);
|
||||||
|
if (tok == TOK___ATTRIBUTE__)
|
||||||
|
parse_attribute(ad);
|
||||||
if (!u)
|
if (!u)
|
||||||
return t;
|
return t;
|
||||||
p = u;
|
p = u;
|
||||||
|
@ -4295,7 +4378,7 @@ void unary(void)
|
||||||
if (t == '(') {
|
if (t == '(') {
|
||||||
/* cast ? */
|
/* cast ? */
|
||||||
if (parse_btype(&t, &ad)) {
|
if (parse_btype(&t, &ad)) {
|
||||||
ft = type_decl(&n, t, TYPE_ABSTRACT);
|
ft = type_decl(&ad, &n, t, TYPE_ABSTRACT);
|
||||||
skip(')');
|
skip(')');
|
||||||
/* check ISOC99 compound literal */
|
/* check ISOC99 compound literal */
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
|
@ -4353,7 +4436,7 @@ void unary(void)
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
next();
|
next();
|
||||||
if (parse_btype(&t, &ad)) {
|
if (parse_btype(&t, &ad)) {
|
||||||
t = type_decl(&n, t, TYPE_ABSTRACT);
|
t = type_decl(&ad, &n, t, TYPE_ABSTRACT);
|
||||||
} else {
|
} else {
|
||||||
/* XXX: some code could be generated: add eval
|
/* XXX: some code could be generated: add eval
|
||||||
flag */
|
flag */
|
||||||
|
@ -4457,7 +4540,7 @@ void unary(void)
|
||||||
/* get return type */
|
/* get return type */
|
||||||
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
|
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
|
||||||
save_regs(); /* save used temporary registers */
|
save_regs(); /* save used temporary registers */
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, s->r);
|
||||||
next();
|
next();
|
||||||
sa = s->next; /* first parameter */
|
sa = s->next; /* first parameter */
|
||||||
#ifdef INVERT_FUNC_PARAMS
|
#ifdef INVERT_FUNC_PARAMS
|
||||||
|
@ -4682,7 +4765,7 @@ void expr_eq(void)
|
||||||
if (is_float(vtop->t))
|
if (is_float(vtop->t))
|
||||||
rc = RC_FLOAT;
|
rc = RC_FLOAT;
|
||||||
r1 = gv(rc);
|
r1 = gv(rc);
|
||||||
vpop();
|
vtop--; /* no vpop so that FP stack is not flushed */
|
||||||
skip(':');
|
skip(':');
|
||||||
u = gjmp(0);
|
u = gjmp(0);
|
||||||
|
|
||||||
|
@ -5143,7 +5226,7 @@ void init_putz(int t, int r, int c, int size)
|
||||||
if ((r & VT_VALMASK) == VT_CONST) {
|
if ((r & VT_VALMASK) == VT_CONST) {
|
||||||
/* nothing to do because globals are already set to zero */
|
/* nothing to do because globals are already set to zero */
|
||||||
} else {
|
} else {
|
||||||
gfunc_start(&gf);
|
gfunc_start(&gf, FUNC_CDECL);
|
||||||
vpushi(size);
|
vpushi(size);
|
||||||
gfunc_param(&gf);
|
gfunc_param(&gf);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
|
@ -5472,11 +5555,7 @@ void decl(int l)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while (1) { /* iterate thru each declaration */
|
while (1) { /* iterate thru each declaration */
|
||||||
t = type_decl(&v, b, TYPE_DIRECT);
|
t = type_decl(&ad, &v, b, TYPE_DIRECT);
|
||||||
/* currently, we do not parse attribute in
|
|
||||||
type_decl(). May change if needed */
|
|
||||||
if (tok == TOK___ATTRIBUTE__)
|
|
||||||
parse_attribute(&ad);
|
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
char buf[500];
|
char buf[500];
|
||||||
|
@ -6204,7 +6283,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* add all tokens */
|
/* add all tokens */
|
||||||
tok_ident = TOK_IDENT;
|
tok_ident = TOK_IDENT;
|
||||||
p = "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0__attribute__\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0";
|
p = tcc_keywords;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
r = p;
|
r = p;
|
||||||
while (*r++);
|
while (*r++);
|
||||||
|
@ -6252,6 +6331,8 @@ int main(int argc, char **argv)
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
goto show_help;
|
goto show_help;
|
||||||
tcc_compile_file(argv[optind++]);
|
tcc_compile_file(argv[optind++]);
|
||||||
|
} else if (!strcmp(r + 1, "bench")) {
|
||||||
|
do_bench = 1;
|
||||||
} else if (r[1] == 'b') {
|
} else if (r[1] == 'b') {
|
||||||
if (!do_bounds_check) {
|
if (!do_bounds_check) {
|
||||||
do_bounds_check = 1;
|
do_bounds_check = 1;
|
||||||
|
@ -6300,6 +6381,11 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
tcc_compile_file(argv[optind]);
|
tcc_compile_file(argv[optind]);
|
||||||
|
|
||||||
|
if (do_bench) {
|
||||||
|
printf("total: %d idents, %d lines, %d bytes\n",
|
||||||
|
tok_ident - TOK_IDENT, total_lines, total_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
resolve_extern_syms();
|
resolve_extern_syms();
|
||||||
|
|
||||||
if (outfile) {
|
if (outfile) {
|
||||||
|
|
Loading…
Reference in a new issue