mirror of
https://github.com/frida/tinycc
synced 2025-01-17 00:39:37 +03:00
optimisations: hash table for include file search, pool for symbol allocation - sympler token string allocation - '-b' fix with '-run' option
This commit is contained in:
parent
398e22c541
commit
48c85f1b15
185
tcc.c
185
tcc.c
@ -289,10 +289,13 @@ typedef struct TokenString {
|
|||||||
inclusion if the include file is protected by #ifndef ... #endif */
|
inclusion if the include file is protected by #ifndef ... #endif */
|
||||||
typedef struct CachedInclude {
|
typedef struct CachedInclude {
|
||||||
int ifndef_macro;
|
int ifndef_macro;
|
||||||
|
int hash_next; /* -1 if none */
|
||||||
char type; /* '"' or '>' to give include type */
|
char type; /* '"' or '>' to give include type */
|
||||||
char filename[1]; /* path specified in #include */
|
char filename[1]; /* path specified in #include */
|
||||||
} CachedInclude;
|
} CachedInclude;
|
||||||
|
|
||||||
|
#define CACHED_INCLUDES_HASH_SIZE 512
|
||||||
|
|
||||||
/* parser */
|
/* parser */
|
||||||
static struct BufferedFile *file;
|
static struct BufferedFile *file;
|
||||||
static int ch, tok;
|
static int ch, tok;
|
||||||
@ -319,7 +322,9 @@ static int parse_flags;
|
|||||||
static Section *text_section, *data_section, *bss_section; /* predefined sections */
|
static Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||||
static Section *cur_text_section; /* current section where function code is
|
static Section *cur_text_section; /* current section where function code is
|
||||||
generated */
|
generated */
|
||||||
|
#ifdef CONFIG_TCC_ASM
|
||||||
static Section *last_text_section; /* to handle .previous asm directive */
|
static Section *last_text_section; /* to handle .previous asm directive */
|
||||||
|
#endif
|
||||||
/* bound check related sections */
|
/* bound check related sections */
|
||||||
static Section *bounds_section; /* contains global data bound description */
|
static Section *bounds_section; /* contains global data bound description */
|
||||||
static Section *lbounds_section; /* contains local data bound description */
|
static Section *lbounds_section; /* contains local data bound description */
|
||||||
@ -352,6 +357,9 @@ static char *funcname;
|
|||||||
static Sym *global_stack, *local_stack;
|
static Sym *global_stack, *local_stack;
|
||||||
static Sym *define_stack;
|
static Sym *define_stack;
|
||||||
static Sym *global_label_stack, *local_label_stack;
|
static Sym *global_label_stack, *local_label_stack;
|
||||||
|
/* symbol allocator */
|
||||||
|
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
||||||
|
static Sym *sym_free_first;
|
||||||
|
|
||||||
static SValue vstack[VSTACK_SIZE], *vtop;
|
static SValue vstack[VSTACK_SIZE], *vtop;
|
||||||
/* some predefined types */
|
/* some predefined types */
|
||||||
@ -473,6 +481,9 @@ struct TCCState {
|
|||||||
|
|
||||||
/* see ifdef_stack_ptr */
|
/* see ifdef_stack_ptr */
|
||||||
int ifdef_stack[IFDEF_STACK_SIZE];
|
int ifdef_stack[IFDEF_STACK_SIZE];
|
||||||
|
|
||||||
|
/* see cached_includes */
|
||||||
|
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The current value can be: */
|
/* The current value can be: */
|
||||||
@ -1048,6 +1059,41 @@ static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
|
|||||||
*nb_ptr = nb;
|
*nb_ptr = nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* symbol allocator */
|
||||||
|
static Sym *__sym_malloc(void)
|
||||||
|
{
|
||||||
|
Sym *sym_pool, *sym, *last_sym;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
|
||||||
|
|
||||||
|
last_sym = sym_free_first;
|
||||||
|
sym = sym_pool;
|
||||||
|
for(i = 0; i < SYM_POOL_NB; i++) {
|
||||||
|
sym->next = last_sym;
|
||||||
|
last_sym = sym;
|
||||||
|
sym++;
|
||||||
|
}
|
||||||
|
sym_free_first = last_sym;
|
||||||
|
return last_sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Sym *sym_malloc(void)
|
||||||
|
{
|
||||||
|
Sym *sym;
|
||||||
|
sym = sym_free_first;
|
||||||
|
if (!sym)
|
||||||
|
sym = __sym_malloc();
|
||||||
|
sym_free_first = sym->next;
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sym_free(Sym *sym)
|
||||||
|
{
|
||||||
|
sym->next = sym_free_first;
|
||||||
|
sym_free_first = sym;
|
||||||
|
}
|
||||||
|
|
||||||
Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
|
Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
|
||||||
{
|
{
|
||||||
Section *sec;
|
Section *sec;
|
||||||
@ -1433,7 +1479,7 @@ static void cstr_realloc(CString *cstr, int new_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add a byte */
|
/* add a byte */
|
||||||
static void cstr_ccat(CString *cstr, int ch)
|
static inline void cstr_ccat(CString *cstr, int ch)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
size = cstr->size + 1;
|
size = cstr->size + 1;
|
||||||
@ -1480,21 +1526,6 @@ static void cstr_free(CString *cstr)
|
|||||||
|
|
||||||
#define cstr_reset(cstr) cstr_free(cstr)
|
#define cstr_reset(cstr) cstr_free(cstr)
|
||||||
|
|
||||||
static CString *cstr_dup(CString *cstr1)
|
|
||||||
{
|
|
||||||
CString *cstr;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
cstr = tcc_malloc(sizeof(CString));
|
|
||||||
size = cstr1->size;
|
|
||||||
cstr->size = size;
|
|
||||||
cstr->size_allocated = size;
|
|
||||||
cstr->data_allocated = tcc_malloc(size);
|
|
||||||
cstr->data = cstr->data_allocated;
|
|
||||||
memcpy(cstr->data_allocated, cstr1->data_allocated, size);
|
|
||||||
return cstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: unicode ? */
|
/* XXX: unicode ? */
|
||||||
static void add_char(CString *cstr, int c)
|
static void add_char(CString *cstr, int c)
|
||||||
{
|
{
|
||||||
@ -1618,7 +1649,7 @@ char *get_tok_str(int v, CValue *cv)
|
|||||||
static Sym *sym_push2(Sym **ps, int v, int t, int c)
|
static Sym *sym_push2(Sym **ps, int v, int t, int c)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
s = tcc_malloc(sizeof(Sym));
|
s = sym_malloc();
|
||||||
s->v = v;
|
s->v = v;
|
||||||
s->type.t = t;
|
s->type.t = t;
|
||||||
s->c = c;
|
s->c = c;
|
||||||
@ -1726,7 +1757,7 @@ static void sym_pop(Sym **ptop, Sym *b)
|
|||||||
ps = &ts->sym_identifier;
|
ps = &ts->sym_identifier;
|
||||||
*ps = s->prev_tok;
|
*ps = s->prev_tok;
|
||||||
}
|
}
|
||||||
tcc_free(s);
|
sym_free(s);
|
||||||
s = ss;
|
s = ss;
|
||||||
}
|
}
|
||||||
*ptop = b;
|
*ptop = b;
|
||||||
@ -2194,11 +2225,13 @@ static inline int tok_ext_size(int t)
|
|||||||
case TOK_CUINT:
|
case TOK_CUINT:
|
||||||
case TOK_CCHAR:
|
case TOK_CCHAR:
|
||||||
case TOK_LCHAR:
|
case TOK_LCHAR:
|
||||||
case TOK_STR:
|
|
||||||
case TOK_LSTR:
|
|
||||||
case TOK_CFLOAT:
|
case TOK_CFLOAT:
|
||||||
case TOK_LINENUM:
|
case TOK_LINENUM:
|
||||||
|
return 1;
|
||||||
|
case TOK_STR:
|
||||||
|
case TOK_LSTR:
|
||||||
case TOK_PPNUM:
|
case TOK_PPNUM:
|
||||||
|
error("unsupported token");
|
||||||
return 1;
|
return 1;
|
||||||
case TOK_CDOUBLE:
|
case TOK_CDOUBLE:
|
||||||
case TOK_CLLONG:
|
case TOK_CLLONG:
|
||||||
@ -2223,48 +2256,6 @@ static inline void tok_str_new(TokenString *s)
|
|||||||
|
|
||||||
static void tok_str_free(int *str)
|
static void tok_str_free(int *str)
|
||||||
{
|
{
|
||||||
const int *p;
|
|
||||||
CString *cstr;
|
|
||||||
int t;
|
|
||||||
|
|
||||||
p = str;
|
|
||||||
for(;;) {
|
|
||||||
t = *p;
|
|
||||||
/* NOTE: we test zero separately so that GCC can generate a
|
|
||||||
table for the following switch */
|
|
||||||
if (t == 0)
|
|
||||||
break;
|
|
||||||
switch(t) {
|
|
||||||
case TOK_CINT:
|
|
||||||
case TOK_CUINT:
|
|
||||||
case TOK_CCHAR:
|
|
||||||
case TOK_LCHAR:
|
|
||||||
case TOK_CFLOAT:
|
|
||||||
case TOK_LINENUM:
|
|
||||||
p += 2;
|
|
||||||
break;
|
|
||||||
case TOK_PPNUM:
|
|
||||||
case TOK_STR:
|
|
||||||
case TOK_LSTR:
|
|
||||||
/* XXX: use a macro to be portable on 64 bit ? */
|
|
||||||
cstr = (CString *)p[1];
|
|
||||||
cstr_free(cstr);
|
|
||||||
tcc_free(cstr);
|
|
||||||
p += 2;
|
|
||||||
break;
|
|
||||||
case TOK_CDOUBLE:
|
|
||||||
case TOK_CLLONG:
|
|
||||||
case TOK_CULLONG:
|
|
||||||
p += 3;
|
|
||||||
break;
|
|
||||||
case TOK_CLDOUBLE:
|
|
||||||
p += 1 + (LDOUBLE_SIZE / 4);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
p++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tcc_free(str);
|
tcc_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2320,7 +2311,22 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
|||||||
case TOK_PPNUM:
|
case TOK_PPNUM:
|
||||||
case TOK_STR:
|
case TOK_STR:
|
||||||
case TOK_LSTR:
|
case TOK_LSTR:
|
||||||
str[len++] = (int)cstr_dup(cv->cstr);
|
{
|
||||||
|
int nb_words;
|
||||||
|
CString *cstr;
|
||||||
|
|
||||||
|
nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
|
||||||
|
while ((len + nb_words) > s->allocated_len)
|
||||||
|
str = tok_str_realloc(s);
|
||||||
|
cstr = (CString *)(str + len);
|
||||||
|
cstr->data = NULL;
|
||||||
|
cstr->size = cv->cstr->size;
|
||||||
|
cstr->data_allocated = NULL;
|
||||||
|
cstr->size_allocated = cstr->size;
|
||||||
|
memcpy((char *)cstr + sizeof(CString),
|
||||||
|
cv->cstr->data, cstr->size);
|
||||||
|
len += nb_words;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_CDOUBLE:
|
case TOK_CDOUBLE:
|
||||||
case TOK_CLLONG:
|
case TOK_CLLONG:
|
||||||
@ -2386,10 +2392,14 @@ static void tok_str_add_tok(TokenString *s)
|
|||||||
case TOK_LCHAR: \
|
case TOK_LCHAR: \
|
||||||
case TOK_CFLOAT: \
|
case TOK_CFLOAT: \
|
||||||
case TOK_LINENUM: \
|
case TOK_LINENUM: \
|
||||||
|
cv.tab[0] = *p++; \
|
||||||
|
break; \
|
||||||
case TOK_STR: \
|
case TOK_STR: \
|
||||||
case TOK_LSTR: \
|
case TOK_LSTR: \
|
||||||
case TOK_PPNUM: \
|
case TOK_PPNUM: \
|
||||||
cv.tab[0] = *p++; \
|
cv.cstr = (CString *)p; \
|
||||||
|
cv.cstr->data = (char *)p + sizeof(CString);\
|
||||||
|
p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
|
||||||
break; \
|
break; \
|
||||||
case TOK_CDOUBLE: \
|
case TOK_CDOUBLE: \
|
||||||
case TOK_CLLONG: \
|
case TOK_CLLONG: \
|
||||||
@ -2450,7 +2460,7 @@ static void free_defines(Sym *b)
|
|||||||
v = top->v;
|
v = top->v;
|
||||||
if (v >= TOK_IDENT && v < tok_ident)
|
if (v >= TOK_IDENT && v < tok_ident)
|
||||||
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
table_ident[v - TOK_IDENT]->sym_define = NULL;
|
||||||
tcc_free(top);
|
sym_free(top);
|
||||||
top = top1;
|
top = top1;
|
||||||
}
|
}
|
||||||
define_stack = b;
|
define_stack = b;
|
||||||
@ -2503,7 +2513,7 @@ static void label_pop(Sym **ptop, Sym *slast)
|
|||||||
}
|
}
|
||||||
/* remove label */
|
/* remove label */
|
||||||
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
|
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
|
||||||
tcc_free(s);
|
sym_free(s);
|
||||||
}
|
}
|
||||||
*ptop = slast;
|
*ptop = slast;
|
||||||
}
|
}
|
||||||
@ -2619,17 +2629,37 @@ static void parse_define(void)
|
|||||||
define_push(v, t, str.str, first);
|
define_push(v, t, str.str, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hash_cached_include(int type, const char *filename)
|
||||||
|
{
|
||||||
|
const unsigned char *s;
|
||||||
|
unsigned int h;
|
||||||
|
|
||||||
|
h = TOK_HASH_INIT;
|
||||||
|
h = TOK_HASH_FUNC(h, type);
|
||||||
|
s = filename;
|
||||||
|
while (*s) {
|
||||||
|
h = TOK_HASH_FUNC(h, *s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
h &= (CACHED_INCLUDES_HASH_SIZE - 1);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: use a token or a hash table to accelerate matching ? */
|
/* XXX: use a token or a hash table to accelerate matching ? */
|
||||||
static CachedInclude *search_cached_include(TCCState *s1,
|
static CachedInclude *search_cached_include(TCCState *s1,
|
||||||
int type, const char *filename)
|
int type, const char *filename)
|
||||||
{
|
{
|
||||||
CachedInclude *e;
|
CachedInclude *e;
|
||||||
int i;
|
int i, h;
|
||||||
|
h = hash_cached_include(type, filename);
|
||||||
for(i = 0;i < s1->nb_cached_includes; i++) {
|
i = s1->cached_includes_hash[h];
|
||||||
e = s1->cached_includes[i];
|
for(;;) {
|
||||||
|
if (i == 0)
|
||||||
|
break;
|
||||||
|
e = s1->cached_includes[i - 1];
|
||||||
if (e->type == type && !strcmp(e->filename, filename))
|
if (e->type == type && !strcmp(e->filename, filename))
|
||||||
return e;
|
return e;
|
||||||
|
i = e->hash_next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -2638,6 +2668,7 @@ static inline void add_cached_include(TCCState *s1, int type,
|
|||||||
const char *filename, int ifndef_macro)
|
const char *filename, int ifndef_macro)
|
||||||
{
|
{
|
||||||
CachedInclude *e;
|
CachedInclude *e;
|
||||||
|
int h;
|
||||||
|
|
||||||
if (search_cached_include(s1, type, filename))
|
if (search_cached_include(s1, type, filename))
|
||||||
return;
|
return;
|
||||||
@ -2651,6 +2682,10 @@ static inline void add_cached_include(TCCState *s1, int type,
|
|||||||
strcpy(e->filename, filename);
|
strcpy(e->filename, filename);
|
||||||
e->ifndef_macro = ifndef_macro;
|
e->ifndef_macro = ifndef_macro;
|
||||||
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
|
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
|
||||||
|
/* add in hash table */
|
||||||
|
h = hash_cached_include(type, filename);
|
||||||
|
e->hash_next = s1->cached_includes_hash[h];
|
||||||
|
s1->cached_includes_hash[h] = s1->nb_cached_includes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is_bof is true if first non space token at beginning of file */
|
/* is_bof is true if first non space token at beginning of file */
|
||||||
@ -3989,7 +4024,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
while (sa) {
|
while (sa) {
|
||||||
sa1 = sa->prev;
|
sa1 = sa->prev;
|
||||||
tok_str_free((int *)sa->c);
|
tok_str_free((int *)sa->c);
|
||||||
tcc_free(sa);
|
sym_free(sa);
|
||||||
sa = sa1;
|
sa = sa1;
|
||||||
}
|
}
|
||||||
mstr_allocated = 1;
|
mstr_allocated = 1;
|
||||||
@ -3999,7 +4034,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
/* pop nested defined symbol */
|
/* pop nested defined symbol */
|
||||||
sa1 = *nested_list;
|
sa1 = *nested_list;
|
||||||
*nested_list = sa1->prev;
|
*nested_list = sa1->prev;
|
||||||
tcc_free(sa1);
|
sym_free(sa1);
|
||||||
if (mstr_allocated)
|
if (mstr_allocated)
|
||||||
tok_str_free(mstr);
|
tok_str_free(mstr);
|
||||||
}
|
}
|
||||||
@ -9409,10 +9444,12 @@ int tcc_relocate(TCCState *s1)
|
|||||||
|
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
|
|
||||||
build_got_entries(s1);
|
|
||||||
|
|
||||||
relocate_common_syms();
|
relocate_common_syms();
|
||||||
|
|
||||||
|
tcc_add_linker_symbols(s1);
|
||||||
|
|
||||||
|
build_got_entries(s1);
|
||||||
|
|
||||||
/* compute relocation address : section are relocated in place. We
|
/* compute relocation address : section are relocated in place. We
|
||||||
also alloc the bss space */
|
also alloc the bss space */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user