mirror of
https://github.com/frida/tinycc
synced 2025-01-16 16:29:22 +03:00
restored include file optimization - added static on all globals
This commit is contained in:
parent
2956bd85cd
commit
cdcfed9737
268
tcc.c
268
tcc.c
@ -213,7 +213,8 @@ typedef struct BufferedFile {
|
||||
unsigned char *buf_end;
|
||||
int fd;
|
||||
int line_num; /* current line number - here to simply code */
|
||||
int ifndef_macro; /*'#ifndef macro \n #define macro' search */
|
||||
int ifndef_macro; /* #ifndef macro / #endif search */
|
||||
int ifndef_macro_saved; /* saved ifndef_macro */
|
||||
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
|
||||
char inc_type; /* type of include */
|
||||
char inc_filename[512]; /* filename specified by the user */
|
||||
@ -249,73 +250,76 @@ typedef struct CachedInclude {
|
||||
} CachedInclude;
|
||||
|
||||
/* parser */
|
||||
struct BufferedFile *file;
|
||||
int ch, tok, tok1;
|
||||
CValue tokc, tok1c;
|
||||
CString tokcstr; /* current parsed string, if any */
|
||||
static struct BufferedFile *file;
|
||||
static int ch, tok, tok1;
|
||||
static CValue tokc, tok1c;
|
||||
static CString tokcstr; /* current parsed string, if any */
|
||||
/* additionnal informations about token */
|
||||
static int tok_flags;
|
||||
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
|
||||
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
|
||||
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
||||
|
||||
/* if true, line feed is returned as a token. line feed is also
|
||||
returned at eof */
|
||||
int return_linefeed;
|
||||
/* set to TRUE if eof was reached */
|
||||
int eof_seen;
|
||||
Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||
Section *cur_text_section; /* current section where function code is
|
||||
static int return_linefeed;
|
||||
static Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||
static Section *cur_text_section; /* current section where function code is
|
||||
generated */
|
||||
/* bound check related sections */
|
||||
Section *bounds_section; /* contains global data bound description */
|
||||
Section *lbounds_section; /* contains local data bound description */
|
||||
static Section *bounds_section; /* contains global data bound description */
|
||||
static Section *lbounds_section; /* contains local data bound description */
|
||||
/* symbol sections */
|
||||
Section *symtab_section, *strtab_section;
|
||||
static Section *symtab_section, *strtab_section;
|
||||
|
||||
/* debug sections */
|
||||
Section *stab_section, *stabstr_section;
|
||||
static Section *stab_section, *stabstr_section;
|
||||
|
||||
/* loc : local variable index
|
||||
ind : output code index
|
||||
rsym: return symbol
|
||||
anon_sym: anonymous symbol index
|
||||
*/
|
||||
int rsym, anon_sym,
|
||||
prog, ind, loc;
|
||||
static int rsym, anon_sym, ind, loc;
|
||||
/* expression generation modifiers */
|
||||
int const_wanted; /* true if constant wanted */
|
||||
int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
int global_expr; /* true if compound literals must be allocated
|
||||
globally (used during initializers parsing */
|
||||
CType func_vt; /* current function return type (used by return
|
||||
instruction) */
|
||||
int func_vc;
|
||||
int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
||||
int tok_ident;
|
||||
TokenSym **table_ident;
|
||||
TokenSym *hash_ident[TOK_HASH_SIZE];
|
||||
char token_buf[STRING_MAX_SIZE + 1];
|
||||
char *funcname;
|
||||
Sym *global_stack, *local_stack;
|
||||
Sym *define_stack;
|
||||
Sym *label_stack;
|
||||
static int const_wanted; /* true if constant wanted */
|
||||
static int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
static int global_expr; /* true if compound literals must be allocated
|
||||
globally (used during initializers parsing */
|
||||
static CType func_vt; /* current function return type (used by return
|
||||
instruction) */
|
||||
static int func_vc;
|
||||
static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
||||
static int tok_ident;
|
||||
static TokenSym **table_ident;
|
||||
static TokenSym *hash_ident[TOK_HASH_SIZE];
|
||||
static char token_buf[STRING_MAX_SIZE + 1];
|
||||
static char *funcname;
|
||||
static Sym *global_stack, *local_stack;
|
||||
static Sym *define_stack;
|
||||
static Sym *label_stack;
|
||||
|
||||
SValue vstack[VSTACK_SIZE], *vtop;
|
||||
int *macro_ptr, *macro_ptr_allocated;
|
||||
static SValue vstack[VSTACK_SIZE], *vtop;
|
||||
static int *macro_ptr, *macro_ptr_allocated;
|
||||
/* some predefined types */
|
||||
CType char_pointer_type, func_old_type, int_type;
|
||||
static CType char_pointer_type, func_old_type, int_type;
|
||||
|
||||
/* compile with debug symbol (and use them if error during execution) */
|
||||
int do_debug = 0;
|
||||
static int do_debug = 0;
|
||||
|
||||
/* compile with built-in memory and bounds checker */
|
||||
int do_bounds_check = 0;
|
||||
static int do_bounds_check = 0;
|
||||
|
||||
/* display benchmark infos */
|
||||
int do_bench = 0;
|
||||
int total_lines;
|
||||
int total_bytes;
|
||||
static int do_bench = 0;
|
||||
static int total_lines;
|
||||
static int total_bytes;
|
||||
|
||||
/* use GNU C extensions */
|
||||
int gnu_ext = 1;
|
||||
static int gnu_ext = 1;
|
||||
|
||||
/* use Tiny C extensions */
|
||||
int tcc_ext = 1;
|
||||
static int tcc_ext = 1;
|
||||
|
||||
/* max number of callers shown if error */
|
||||
static int num_callers = 6;
|
||||
@ -1225,6 +1229,21 @@ static void cstr_free(CString *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 ? */
|
||||
static void add_char(CString *cstr, int c)
|
||||
{
|
||||
@ -1525,32 +1544,10 @@ int tcc_getc_slow(BufferedFile *bf)
|
||||
/* no need to put that inline */
|
||||
void handle_eob(void)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
|
||||
/* no need to do anything if not at EOB */
|
||||
if (file->buf_ptr <= file->buf_end)
|
||||
return;
|
||||
|
||||
for(;;) {
|
||||
ch = tcc_getc_slow(file);
|
||||
if (ch != CH_EOF)
|
||||
return;
|
||||
eof_seen = 1;
|
||||
if (return_linefeed) {
|
||||
ch = '\n';
|
||||
return;
|
||||
}
|
||||
if (s1->include_stack_ptr == s1->include_stack)
|
||||
return;
|
||||
/* add end of include file debug info */
|
||||
if (do_debug) {
|
||||
put_stabd(N_EINCL, 0, 0);
|
||||
}
|
||||
/* pop include stack */
|
||||
tcc_close(file);
|
||||
s1->include_stack_ptr--;
|
||||
file = *s1->include_stack_ptr;
|
||||
}
|
||||
ch = tcc_getc_slow(file);
|
||||
}
|
||||
|
||||
/* read next char from current input file and handle end of input buffer */
|
||||
@ -1668,7 +1665,8 @@ void preprocess_skip(void)
|
||||
|
||||
start_of_line = 1;
|
||||
a = 0;
|
||||
while (1) {
|
||||
for(;;) {
|
||||
redo_no_start:
|
||||
switch(ch) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
@ -1676,19 +1674,18 @@ void preprocess_skip(void)
|
||||
case '\v':
|
||||
case '\r':
|
||||
inp();
|
||||
break;
|
||||
goto redo_no_start;
|
||||
case '\n':
|
||||
start_of_line = 1;
|
||||
file->line_num++;
|
||||
inp();
|
||||
break;
|
||||
goto redo_no_start;
|
||||
case '\\':
|
||||
handle_stray();
|
||||
break;
|
||||
goto redo_no_start;
|
||||
/* skip strings */
|
||||
case '\"':
|
||||
case '\'':
|
||||
start_of_line = 0;
|
||||
sep = ch;
|
||||
inp();
|
||||
while (ch != sep) {
|
||||
@ -1714,8 +1711,6 @@ void preprocess_skip(void)
|
||||
parse_comment();
|
||||
} else if (ch == '/') {
|
||||
parse_line_comment();
|
||||
} else {
|
||||
start_of_line = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1731,16 +1726,15 @@ void preprocess_skip(void)
|
||||
else if (tok == TOK_ENDIF)
|
||||
a--;
|
||||
}
|
||||
start_of_line = 0;
|
||||
break;
|
||||
case CH_EOF:
|
||||
expect("#endif");
|
||||
break;
|
||||
default:
|
||||
inp();
|
||||
start_of_line = 0;
|
||||
break;
|
||||
}
|
||||
start_of_line = 0;
|
||||
}
|
||||
the_end: ;
|
||||
}
|
||||
@ -1846,22 +1840,13 @@ static void tok_str_add(TokenString *s, int t)
|
||||
|
||||
static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
||||
{
|
||||
int n, i, size;
|
||||
CString *cstr, *cstr1;
|
||||
int n, i;
|
||||
CValue cv1;
|
||||
|
||||
tok_str_add(s, t);
|
||||
if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
|
||||
/* special case: need to duplicate string */
|
||||
cstr1 = cv->cstr;
|
||||
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);
|
||||
cv1.cstr = cstr;
|
||||
cv1.cstr = cstr_dup(cv->cstr);
|
||||
tok_str_add(s, cv1.tab[0]);
|
||||
} else {
|
||||
n = tok_ext_size(t);
|
||||
@ -2107,17 +2092,11 @@ static inline void add_cached_include(TCCState *s1, int type,
|
||||
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
|
||||
}
|
||||
|
||||
|
||||
enum IncludeState {
|
||||
INCLUDE_STATE_NONE = 0,
|
||||
INCLUDE_STATE_SEEK_IFNDEF,
|
||||
};
|
||||
|
||||
void preprocess(void)
|
||||
/* is_bof is true if first non space token at beginning of file */
|
||||
static void preprocess(int is_bof)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
int size, i, c, n, line_num;
|
||||
enum IncludeState state;
|
||||
char buf[1024], *q, *p;
|
||||
char buf1[1024];
|
||||
BufferedFile *f;
|
||||
@ -2126,9 +2105,6 @@ void preprocess(void)
|
||||
|
||||
return_linefeed = 1; /* linefeed will be returned as a
|
||||
token. EOF is also returned as line feed */
|
||||
state = INCLUDE_STATE_NONE;
|
||||
eof_seen = 0;
|
||||
redo1:
|
||||
next_nomacro();
|
||||
redo:
|
||||
switch(tok) {
|
||||
@ -2253,16 +2229,8 @@ void preprocess(void)
|
||||
if (do_debug) {
|
||||
put_stabs(file->filename, N_BINCL, 0, 0, 0);
|
||||
}
|
||||
/* we check for the construct: #ifndef IDENT \n #define IDENT */
|
||||
inp();
|
||||
/* get first non space char */
|
||||
while (is_space(ch) || ch == '\n')
|
||||
cinp();
|
||||
if (ch != '#')
|
||||
goto the_end;
|
||||
state = INCLUDE_STATE_SEEK_IFNDEF;
|
||||
cinp();
|
||||
goto redo1;
|
||||
tok_flags |= TOK_FLAG_BOF;
|
||||
goto the_end;
|
||||
}
|
||||
break;
|
||||
case TOK_IFNDEF:
|
||||
@ -2277,11 +2245,13 @@ void preprocess(void)
|
||||
next_nomacro();
|
||||
if (tok < TOK_IDENT)
|
||||
error("invalid argument for '#if%sdef'", c ? "n" : "");
|
||||
if (state == INCLUDE_STATE_SEEK_IFNDEF) {
|
||||
if (is_bof) {
|
||||
if (c) {
|
||||
#ifdef INC_DEBUG
|
||||
printf("#ifndef %s\n", get_tok_str(tok, NULL));
|
||||
#endif
|
||||
file->ifndef_macro = tok;
|
||||
}
|
||||
state = INCLUDE_STATE_NONE;
|
||||
}
|
||||
c = (define_find(tok) != 0) ^ c;
|
||||
do_if:
|
||||
@ -2311,31 +2281,27 @@ void preprocess(void)
|
||||
if (!(c & 1)) {
|
||||
skip:
|
||||
preprocess_skip();
|
||||
state = INCLUDE_STATE_NONE;
|
||||
is_bof = 0;
|
||||
goto redo;
|
||||
}
|
||||
break;
|
||||
case TOK_ENDIF:
|
||||
if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
|
||||
error("#endif without matching #if");
|
||||
s1->ifdef_stack_ptr--;
|
||||
/* '#ifndef macro' was at the start of file. Now we check if
|
||||
an '#endif' is exactly at the end of file */
|
||||
if (file->ifndef_macro &&
|
||||
s1->ifdef_stack_ptr == (file->ifdef_stack_ptr + 1)) {
|
||||
/* '#ifndef macro \n #define macro' was at the start of
|
||||
file. Now we check if an '#endif' is exactly at the end
|
||||
of file */
|
||||
s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
|
||||
file->ifndef_macro_saved = file->ifndef_macro;
|
||||
/* need to set to zero to avoid false matches if another
|
||||
#ifndef at middle of file */
|
||||
file->ifndef_macro = 0;
|
||||
while (tok != TOK_LINEFEED)
|
||||
next_nomacro();
|
||||
/* XXX: should also skip comments, but it is more complicated */
|
||||
if (eof_seen) {
|
||||
add_cached_include(s1, file->inc_type, file->inc_filename,
|
||||
file->ifndef_macro);
|
||||
} else {
|
||||
/* if not end of file, we must desactivate the ifndef
|
||||
macro search */
|
||||
file->ifndef_macro = 0;
|
||||
}
|
||||
tok_flags |= TOK_FLAG_ENDIF;
|
||||
goto the_end;
|
||||
}
|
||||
s1->ifdef_stack_ptr--;
|
||||
break;
|
||||
case TOK_LINE:
|
||||
next();
|
||||
@ -2378,7 +2344,7 @@ void preprocess(void)
|
||||
break;
|
||||
}
|
||||
/* ignore other preprocess commands or #! for C scripts */
|
||||
while (tok != TOK_LINEFEED && tok != TOK_EOF)
|
||||
while (tok != TOK_LINEFEED)
|
||||
next_nomacro();
|
||||
the_end:
|
||||
return_linefeed = 0;
|
||||
@ -2780,11 +2746,10 @@ void parse_number(const char *p)
|
||||
/* return next token without macro substitution */
|
||||
static inline void next_nomacro1(void)
|
||||
{
|
||||
int b, t, start_of_line;
|
||||
int b, t;
|
||||
char *q;
|
||||
TokenSym *ts;
|
||||
|
||||
start_of_line = 0;
|
||||
redo_no_start:
|
||||
switch(ch) {
|
||||
case ' ':
|
||||
@ -2799,13 +2764,48 @@ static inline void next_nomacro1(void)
|
||||
handle_stray();
|
||||
goto redo_no_start;
|
||||
|
||||
case CH_EOF:
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
|
||||
if (return_linefeed) {
|
||||
tok = TOK_LINEFEED;
|
||||
} else if (s1->include_stack_ptr == s1->include_stack) {
|
||||
/* no include left : end of file */
|
||||
tok = TOK_EOF;
|
||||
} else {
|
||||
/* pop include file */
|
||||
|
||||
/* test if previous '#endif' was after a #ifdef at
|
||||
start of file */
|
||||
if (tok_flags & TOK_FLAG_ENDIF) {
|
||||
#ifdef INC_DEBUG
|
||||
printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
|
||||
#endif
|
||||
add_cached_include(s1, file->inc_type, file->inc_filename,
|
||||
file->ifndef_macro_saved);
|
||||
}
|
||||
|
||||
/* add end of include file debug info */
|
||||
if (do_debug) {
|
||||
put_stabd(N_EINCL, 0, 0);
|
||||
}
|
||||
/* pop include stack */
|
||||
tcc_close(file);
|
||||
s1->include_stack_ptr--;
|
||||
file = *s1->include_stack_ptr;
|
||||
inp();
|
||||
goto redo_no_start;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
file->line_num++;
|
||||
if (return_linefeed) {
|
||||
/* XXX: should eat token ? */
|
||||
tok = TOK_LINEFEED;
|
||||
} else {
|
||||
start_of_line = 1;
|
||||
tok_flags |= TOK_FLAG_BOL;
|
||||
inp();
|
||||
goto redo_no_start;
|
||||
}
|
||||
@ -2813,8 +2813,8 @@ static inline void next_nomacro1(void)
|
||||
|
||||
case '#':
|
||||
minp();
|
||||
if (start_of_line) {
|
||||
preprocess();
|
||||
if (tok_flags & TOK_FLAG_BOL) {
|
||||
preprocess(tok_flags & TOK_FLAG_BOF);
|
||||
goto redo_no_start;
|
||||
} else {
|
||||
if (ch == '#') {
|
||||
@ -3108,13 +3108,11 @@ static inline void next_nomacro1(void)
|
||||
tok = ch;
|
||||
cinp();
|
||||
break;
|
||||
case CH_EOF:
|
||||
tok = TOK_EOF;
|
||||
break;
|
||||
default:
|
||||
error("unrecognized character \\x%02x", ch);
|
||||
break;
|
||||
}
|
||||
tok_flags = 0;
|
||||
#if defined(PARSE_DEBUG)
|
||||
printf("token = %s\n", get_tok_str(tok, &tokc));
|
||||
#endif
|
||||
@ -3386,6 +3384,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||
if (macro_ptr) {
|
||||
t = *macro_ptr;
|
||||
} else {
|
||||
/* XXX: incorrect with comments */
|
||||
while (is_space(ch) || ch == '\n')
|
||||
cinp();
|
||||
t = ch;
|
||||
@ -7642,7 +7641,8 @@ static int tcc_compile(TCCState *s1)
|
||||
s1->nb_errors = 0;
|
||||
s1->error_set_jmp_enabled = 1;
|
||||
|
||||
ch = '\n'; /* needed to parse correctly first preprocessor command */
|
||||
ch = '\n'; /* XXX: suppress that*/
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
next();
|
||||
decl(VT_CONST);
|
||||
if (tok != -1)
|
||||
|
Loading…
Reference in New Issue
Block a user