mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
Add gcc attribute cleanup support
The major difficulty was to handle cleanup when a goto happen to do so, I've had a "ScopeTracker" struct. I can't use local_scope because that would not work with code like below as local_scope would be at the same level: { char * __attribute__ ((cleanup(clean_function))) str = "hej"; goto next; } { next: }
This commit is contained in:
parent
f6be0d483b
commit
0d91ba749c
31
tcc.h
31
tcc.h
@ -456,15 +456,9 @@ struct FuncAttr {
|
|||||||
func_args : 8; /* PE __stdcall args */
|
func_args : 8; /* PE __stdcall args */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* GNUC attribute definition */
|
typedef struct ScopeTacker {
|
||||||
typedef struct AttributeDef {
|
struct ScopeTacker *prev;
|
||||||
struct SymAttr a;
|
} ScopeTacker;
|
||||||
struct FuncAttr f;
|
|
||||||
struct Section *section;
|
|
||||||
int alias_target; /* token */
|
|
||||||
int asm_label; /* associated asm label */
|
|
||||||
char attr_mode; /* __attribute__((__mode__(...))) */
|
|
||||||
} AttributeDef;
|
|
||||||
|
|
||||||
/* symbol management */
|
/* symbol management */
|
||||||
typedef struct Sym {
|
typedef struct Sym {
|
||||||
@ -476,7 +470,10 @@ typedef struct Sym {
|
|||||||
int c; /* associated number or Elf symbol index */
|
int c; /* associated number or Elf symbol index */
|
||||||
union {
|
union {
|
||||||
int sym_scope; /* scope level for locals */
|
int sym_scope; /* scope level for locals */
|
||||||
int jnext; /* next jump label */
|
struct {
|
||||||
|
ScopeTacker *scope;
|
||||||
|
int jnext; /* next jump label */
|
||||||
|
};
|
||||||
struct FuncAttr f; /* function attributes */
|
struct FuncAttr f; /* function attributes */
|
||||||
int auxtype; /* bitfield access type */
|
int auxtype; /* bitfield access type */
|
||||||
};
|
};
|
||||||
@ -590,6 +587,18 @@ typedef struct TokenString {
|
|||||||
char alloc;
|
char alloc;
|
||||||
} TokenString;
|
} TokenString;
|
||||||
|
|
||||||
|
/* GNUC attribute definition */
|
||||||
|
typedef struct AttributeDef {
|
||||||
|
struct SymAttr a;
|
||||||
|
struct FuncAttr f;
|
||||||
|
struct Section *section;
|
||||||
|
Sym *cleanup_func;
|
||||||
|
int should_remember;
|
||||||
|
int alias_target; /* token */
|
||||||
|
int asm_label; /* associated asm label */
|
||||||
|
char attr_mode; /* __attribute__((__mode__(...))) */
|
||||||
|
} AttributeDef;
|
||||||
|
|
||||||
/* inline functions */
|
/* inline functions */
|
||||||
typedef struct InlineFunc {
|
typedef struct InlineFunc {
|
||||||
TokenString *func_str;
|
TokenString *func_str;
|
||||||
@ -1279,6 +1288,8 @@ ST_DATA Sym *sym_free_first;
|
|||||||
ST_DATA void **sym_pools;
|
ST_DATA void **sym_pools;
|
||||||
ST_DATA int nb_sym_pools;
|
ST_DATA int nb_sym_pools;
|
||||||
|
|
||||||
|
ST_DATA ScopeTacker *scope_tracker;
|
||||||
|
|
||||||
ST_DATA Sym *global_stack;
|
ST_DATA Sym *global_stack;
|
||||||
ST_DATA Sym *local_stack;
|
ST_DATA Sym *local_stack;
|
||||||
ST_DATA Sym *local_label_stack;
|
ST_DATA Sym *local_label_stack;
|
||||||
|
274
tccgen.c
274
tccgen.c
@ -38,7 +38,13 @@ ST_DATA Sym *local_stack;
|
|||||||
ST_DATA Sym *define_stack;
|
ST_DATA Sym *define_stack;
|
||||||
ST_DATA Sym *global_label_stack;
|
ST_DATA Sym *global_label_stack;
|
||||||
ST_DATA Sym *local_label_stack;
|
ST_DATA Sym *local_label_stack;
|
||||||
|
|
||||||
static int local_scope;
|
static int local_scope;
|
||||||
|
#define SCOPE_TCK_STORE_SIZE 1024
|
||||||
|
ST_DATA ScopeTacker *scope_tracker;
|
||||||
|
static ScopeTacker scope_tck_store[SCOPE_TCK_STORE_SIZE];
|
||||||
|
static int scope_tck_idx;
|
||||||
|
|
||||||
static int in_sizeof;
|
static int in_sizeof;
|
||||||
static int section_sym;
|
static int section_sym;
|
||||||
|
|
||||||
@ -77,7 +83,29 @@ ST_DATA struct temp_local_variable {
|
|||||||
short size;
|
short size;
|
||||||
short align;
|
short align;
|
||||||
} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
||||||
|
|
||||||
short nb_temp_local_vars;
|
short nb_temp_local_vars;
|
||||||
|
static struct cleanup {
|
||||||
|
ScopeTacker *scope;
|
||||||
|
struct {
|
||||||
|
Sym *var;
|
||||||
|
Sym *func;
|
||||||
|
} *syms;
|
||||||
|
int nb_cleanup;
|
||||||
|
} *cleanup_info;
|
||||||
|
|
||||||
|
static struct cleanup **cleanup_info_store;
|
||||||
|
static int cleanup_idx;
|
||||||
|
|
||||||
|
static struct CleanupGoto {
|
||||||
|
Sym *s;
|
||||||
|
ScopeTacker *scope;
|
||||||
|
int jnext;
|
||||||
|
int is_valide;
|
||||||
|
} **cleanup_goto_info;
|
||||||
|
|
||||||
|
static int last_cleanup_goto;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void gen_cast(CType *type);
|
static void gen_cast(CType *type);
|
||||||
@ -108,6 +136,57 @@ static void gv_dup(void);
|
|||||||
static int get_temp_local_var(int size,int align);
|
static int get_temp_local_var(int size,int align);
|
||||||
static void clear_temp_local_var_list();
|
static void clear_temp_local_var_list();
|
||||||
|
|
||||||
|
static void incr_local_scope(void)
|
||||||
|
{
|
||||||
|
ScopeTacker *tmp = scope_tracker;
|
||||||
|
|
||||||
|
++local_scope;
|
||||||
|
/* if we have more scopes that SCOPE_TCK_STORE_SIZE */
|
||||||
|
/* cleanup will not work at all, but it should be a very rare case */
|
||||||
|
/* and I don't want to add too much complexiy for handeling case */
|
||||||
|
/* that should not happen */
|
||||||
|
if (scope_tck_idx < SCOPE_TCK_STORE_SIZE) {
|
||||||
|
scope_tracker = &scope_tck_store[scope_tck_idx];
|
||||||
|
scope_tracker->prev = tmp;
|
||||||
|
++scope_tck_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decr_local_scope(void)
|
||||||
|
{
|
||||||
|
if (scope_tracker)
|
||||||
|
scope_tracker = scope_tracker->prev;
|
||||||
|
--local_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_local_scope(void)
|
||||||
|
{
|
||||||
|
if (cleanup_info) {
|
||||||
|
for (int i = 0; i < cleanup_idx; ++i) {
|
||||||
|
cleanup_info = cleanup_info_store[i];
|
||||||
|
tcc_free(cleanup_info->syms);
|
||||||
|
tcc_free(cleanup_info);
|
||||||
|
}
|
||||||
|
cleanup_info = NULL;
|
||||||
|
cleanup_idx = 0;
|
||||||
|
tcc_free(cleanup_info_store);
|
||||||
|
cleanup_info_store = NULL;
|
||||||
|
dynarray_reset(&cleanup_goto_info, &last_cleanup_goto);
|
||||||
|
}
|
||||||
|
scope_tracker = NULL;
|
||||||
|
local_scope = 0;
|
||||||
|
scope_tck_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_scope_a_parent_of(ScopeTacker *parent, ScopeTacker *child)
|
||||||
|
{
|
||||||
|
for (ScopeTacker *cur = parent->prev; cur; cur = cur->prev) {
|
||||||
|
if (cur == child)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ST_INLN int is_float(int t)
|
ST_INLN int is_float(int t)
|
||||||
{
|
{
|
||||||
int bt;
|
int bt;
|
||||||
@ -3392,6 +3471,23 @@ redo:
|
|||||||
t = tok;
|
t = tok;
|
||||||
next();
|
next();
|
||||||
switch(t) {
|
switch(t) {
|
||||||
|
case TOK_CLEANUP1:
|
||||||
|
case TOK_CLEANUP2:
|
||||||
|
{
|
||||||
|
Sym *s;
|
||||||
|
|
||||||
|
skip('(');
|
||||||
|
s = sym_find(tok);
|
||||||
|
if (!s) {
|
||||||
|
tcc_warning("implicit declaration of function '%s'",
|
||||||
|
get_tok_str(tok, &tokc));
|
||||||
|
s = external_global_sym(tok, &func_old_type, 0);
|
||||||
|
}
|
||||||
|
ad->cleanup_func = s;
|
||||||
|
next();
|
||||||
|
skip(')');
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TOK_SECTION1:
|
case TOK_SECTION1:
|
||||||
case TOK_SECTION2:
|
case TOK_SECTION2:
|
||||||
skip('(');
|
skip('(');
|
||||||
@ -4541,6 +4637,8 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
|||||||
ret = pointed_type(type);
|
ret = pointed_type(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ad->cleanup_func)
|
||||||
|
ad->should_remember = 1;
|
||||||
if (tok == '(') {
|
if (tok == '(') {
|
||||||
/* This is possibly a parameter type list for abstract declarators
|
/* This is possibly a parameter type list for abstract declarators
|
||||||
('int ()'), use post_type for testing this. */
|
('int ()'), use post_type for testing this. */
|
||||||
@ -4692,6 +4790,59 @@ static void parse_builtin_params(int nc, const char *args)
|
|||||||
nocode_wanted--;
|
nocode_wanted--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void try_call_scope_cleanup(ScopeTacker *scope)
|
||||||
|
{
|
||||||
|
if (!cleanup_info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cleanup_info->scope != scope) {
|
||||||
|
for (int i = 0; i < cleanup_idx; ++i) {
|
||||||
|
cleanup_info = cleanup_info_store[i];
|
||||||
|
if (cleanup_info->scope == scope)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
found:
|
||||||
|
for (int i = cleanup_info->nb_cleanup - 1; i >= 0; --i) {
|
||||||
|
Sym *fs = cleanup_info->syms[i].func;
|
||||||
|
Sym *vs = cleanup_info->syms[i].var;
|
||||||
|
|
||||||
|
vpushsym(&fs->type, fs);
|
||||||
|
if (is_float(vs->type.t)) {
|
||||||
|
vs->type.t = VT_INT;
|
||||||
|
}
|
||||||
|
vset(&vs->type, vs->r, vs->c);
|
||||||
|
vtop->sym = vs;
|
||||||
|
gaddrof();
|
||||||
|
gfunc_param_typed(fs, vs);
|
||||||
|
gfunc_call(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void try_call_cleanup_goto(ScopeTacker *dest_scope)
|
||||||
|
{
|
||||||
|
if (!cleanup_info)
|
||||||
|
return;
|
||||||
|
for (ScopeTacker *cur_scope_tracker = scope_tracker;
|
||||||
|
cur_scope_tracker && cur_scope_tracker != dest_scope;
|
||||||
|
cur_scope_tracker = cur_scope_tracker->prev) {
|
||||||
|
try_call_scope_cleanup(cur_scope_tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void try_call_all_cleanup(void)
|
||||||
|
{
|
||||||
|
if (!cleanup_info)
|
||||||
|
return;
|
||||||
|
for (ScopeTacker *cur_scope_tracker = scope_tracker;
|
||||||
|
cur_scope_tracker;
|
||||||
|
cur_scope_tracker = cur_scope_tracker->prev) {
|
||||||
|
try_call_scope_cleanup(cur_scope_tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
ST_FUNC void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, align, size, r, sizeof_caller;
|
int n, t, align, size, r, sizeof_caller;
|
||||||
@ -6075,11 +6226,11 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
skip(')');
|
skip(')');
|
||||||
a = gvtst(1, 0);
|
a = gvtst(1, 0);
|
||||||
b = 0;
|
b = 0;
|
||||||
++local_scope;
|
incr_local_scope();
|
||||||
saved_nocode_wanted = nocode_wanted;
|
saved_nocode_wanted = nocode_wanted;
|
||||||
block(&a, &b, 0);
|
block(&a, &b, 0);
|
||||||
nocode_wanted = saved_nocode_wanted;
|
nocode_wanted = saved_nocode_wanted;
|
||||||
--local_scope;
|
decr_local_scope();
|
||||||
gjmp_addr(d);
|
gjmp_addr(d);
|
||||||
gsym(a);
|
gsym(a);
|
||||||
gsym_addr(b, d);
|
gsym_addr(b, d);
|
||||||
@ -6091,7 +6242,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
/* record local declaration stack position */
|
/* record local declaration stack position */
|
||||||
s = local_stack;
|
s = local_stack;
|
||||||
llabel = local_label_stack;
|
llabel = local_label_stack;
|
||||||
++local_scope;
|
incr_local_scope();
|
||||||
|
|
||||||
/* handle local labels declarations */
|
/* handle local labels declarations */
|
||||||
while (tok == TOK_LABEL) {
|
while (tok == TOK_LABEL) {
|
||||||
@ -6120,10 +6271,36 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
block(bsym, csym, is_expr);
|
block(bsym, csym, is_expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cleanup_info) {
|
||||||
|
int jmp = 0;
|
||||||
|
|
||||||
|
jmp = gjmp(jmp);
|
||||||
|
|
||||||
|
for (int i = 0; i < last_cleanup_goto; ++i) {
|
||||||
|
struct CleanupGoto *cur = cleanup_goto_info[i];
|
||||||
|
|
||||||
|
if (!cur->is_valide)
|
||||||
|
continue;
|
||||||
|
if (scope_tracker == cur->scope ||
|
||||||
|
is_scope_a_parent_of(cur->scope, scope_tracker)) {
|
||||||
|
gsym(cur->jnext);
|
||||||
|
try_call_scope_cleanup(scope_tracker);
|
||||||
|
cur->jnext = 0;
|
||||||
|
cur->jnext = gjmp(cur->jnext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsym(jmp);
|
||||||
|
if (!nocode_wanted) {
|
||||||
|
try_call_scope_cleanup(scope_tracker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* pop locally defined labels */
|
/* pop locally defined labels */
|
||||||
label_pop(&local_label_stack, llabel, is_expr);
|
label_pop(&local_label_stack, llabel, is_expr);
|
||||||
/* pop locally defined symbols */
|
/* pop locally defined symbols */
|
||||||
--local_scope;
|
decr_local_scope();
|
||||||
/* In the is_expr case (a statement expression is finished here),
|
/* In the is_expr case (a statement expression is finished here),
|
||||||
vtop might refer to symbols on the local_stack. Either via the
|
vtop might refer to symbols on the local_stack. Either via the
|
||||||
type or via vtop->sym. We can't pop those nor any that in turn
|
type or via vtop->sym. We can't pop those nor any that in turn
|
||||||
@ -6146,11 +6323,14 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
if (tok != ';') {
|
if (tok != ';') {
|
||||||
gexpr();
|
gexpr();
|
||||||
gen_assign_cast(&func_vt);
|
gen_assign_cast(&func_vt);
|
||||||
|
try_call_all_cleanup();
|
||||||
if ((func_vt.t & VT_BTYPE) == VT_VOID)
|
if ((func_vt.t & VT_BTYPE) == VT_VOID)
|
||||||
vtop--;
|
vtop--;
|
||||||
else
|
else
|
||||||
gfunc_return(&func_vt);
|
gfunc_return(&func_vt);
|
||||||
}
|
} else {
|
||||||
|
try_call_all_cleanup();
|
||||||
|
}
|
||||||
skip(';');
|
skip(';');
|
||||||
/* jump unless last stmt in top-level block */
|
/* jump unless last stmt in top-level block */
|
||||||
if (tok != '}' || local_scope != 1)
|
if (tok != '}' || local_scope != 1)
|
||||||
@ -6179,7 +6359,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
next();
|
next();
|
||||||
skip('(');
|
skip('(');
|
||||||
s = local_stack;
|
s = local_stack;
|
||||||
++local_scope;
|
incr_local_scope();
|
||||||
if (tok != ';') {
|
if (tok != ';') {
|
||||||
/* c99 for-loop init decl? */
|
/* c99 for-loop init decl? */
|
||||||
if (!decl0(VT_LOCAL, 1, NULL)) {
|
if (!decl0(VT_LOCAL, 1, NULL)) {
|
||||||
@ -6215,7 +6395,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
gjmp_addr(c);
|
gjmp_addr(c);
|
||||||
gsym(a);
|
gsym(a);
|
||||||
gsym_addr(b, c);
|
gsym_addr(b, c);
|
||||||
--local_scope;
|
decr_local_scope();
|
||||||
sym_pop(&local_stack, s, 0);
|
sym_pop(&local_stack, s, 0);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
@ -6319,21 +6499,42 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
expect("pointer");
|
expect("pointer");
|
||||||
ggoto();
|
ggoto();
|
||||||
} else if (tok >= TOK_UIDENT) {
|
} else if (tok >= TOK_UIDENT) {
|
||||||
s = label_find(tok);
|
s = label_find(tok);
|
||||||
/* put forward definition if needed */
|
if (!s || s->jnext == -1) {
|
||||||
if (!s) {
|
/* put forward definition if needed */
|
||||||
s = label_push(&global_label_stack, tok, LABEL_FORWARD);
|
if (!s)
|
||||||
|
s = label_push(&global_label_stack, tok, LABEL_FORWARD);
|
||||||
|
if (cleanup_info) {
|
||||||
|
struct CleanupGoto *cur =
|
||||||
|
tcc_malloc(sizeof(struct CleanupGoto));
|
||||||
|
|
||||||
|
cur->s = s;
|
||||||
|
cur->is_valide = 1;
|
||||||
|
s->jnext = -1;
|
||||||
|
cur->jnext = 0;
|
||||||
|
cur->scope = scope_tracker;
|
||||||
|
cur->jnext = gjmp(cur->jnext);
|
||||||
|
dynarray_add(&cleanup_goto_info, &last_cleanup_goto, cur);
|
||||||
|
vla_sp_restore_root();
|
||||||
|
goto out_goto;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (cleanup_info && is_scope_a_parent_of(scope_tracker,
|
||||||
|
s->scope))
|
||||||
|
try_call_cleanup_goto(s->scope);
|
||||||
|
|
||||||
if (s->r == LABEL_DECLARED)
|
if (s->r == LABEL_DECLARED)
|
||||||
s->r = LABEL_FORWARD;
|
s->r = LABEL_FORWARD;
|
||||||
}
|
}
|
||||||
vla_sp_restore_root();
|
|
||||||
|
vla_sp_restore_root();
|
||||||
if (s->r & LABEL_FORWARD)
|
if (s->r & LABEL_FORWARD)
|
||||||
s->jnext = gjmp(s->jnext);
|
s->jnext = gjmp(s->jnext);
|
||||||
else
|
else
|
||||||
gjmp_addr(s->jnext);
|
gjmp_addr(s->jnext);
|
||||||
next();
|
out_goto:
|
||||||
} else {
|
next();
|
||||||
|
} else {
|
||||||
expect("label identifier");
|
expect("label identifier");
|
||||||
}
|
}
|
||||||
skip(';');
|
skip(';');
|
||||||
@ -6346,10 +6547,21 @@ static void block(int *bsym, int *csym, int is_expr)
|
|||||||
next();
|
next();
|
||||||
s = label_find(b);
|
s = label_find(b);
|
||||||
if (s) {
|
if (s) {
|
||||||
|
int is_gen = 0;
|
||||||
|
|
||||||
if (s->r == LABEL_DEFINED)
|
if (s->r == LABEL_DEFINED)
|
||||||
tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL));
|
tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL));
|
||||||
gsym(s->jnext);
|
for (int i = 0; i < last_cleanup_goto; ++i) {
|
||||||
|
struct CleanupGoto *cur = cleanup_goto_info[i];
|
||||||
|
if (cur->s == s) {
|
||||||
|
cur->is_valide = 0;
|
||||||
|
gsym(cur->jnext);
|
||||||
|
is_gen = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
s->r = LABEL_DEFINED;
|
s->r = LABEL_DEFINED;
|
||||||
|
if (!is_gen)
|
||||||
|
gsym(s->jnext);
|
||||||
} else {
|
} else {
|
||||||
s = label_push(&global_label_stack, b, LABEL_DEFINED);
|
s = label_push(&global_label_stack, b, LABEL_DEFINED);
|
||||||
}
|
}
|
||||||
@ -7085,6 +7297,28 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sym = sym_push(v, type, r, addr);
|
sym = sym_push(v, type, r, addr);
|
||||||
|
if (ad->cleanup_func) {
|
||||||
|
int nb_cleanup;
|
||||||
|
|
||||||
|
if (!cleanup_info || cleanup_info->scope != scope_tracker) {
|
||||||
|
cleanup_info = tcc_malloc(sizeof(struct cleanup));
|
||||||
|
dynarray_add(&cleanup_info_store, &cleanup_idx,
|
||||||
|
cleanup_info);
|
||||||
|
cleanup_info ->scope = scope_tracker;
|
||||||
|
cleanup_info->nb_cleanup = 0;
|
||||||
|
cleanup_info->syms = NULL;
|
||||||
|
}
|
||||||
|
nb_cleanup = cleanup_info->nb_cleanup + 1;
|
||||||
|
cleanup_info->syms = tcc_realloc(cleanup_info->syms,
|
||||||
|
nb_cleanup *
|
||||||
|
sizeof(*cleanup_info->syms));
|
||||||
|
cleanup_info->syms[nb_cleanup - 1].func = ad->cleanup_func;
|
||||||
|
cleanup_info->syms[nb_cleanup - 1].var = sym;
|
||||||
|
cleanup_info->nb_cleanup = nb_cleanup;
|
||||||
|
if (!ad->should_remember)
|
||||||
|
ad->cleanup_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sym->a = ad->a;
|
sym->a = ad->a;
|
||||||
} else {
|
} else {
|
||||||
/* push local reference */
|
/* push local reference */
|
||||||
@ -7226,7 +7460,7 @@ static void gen_function(Sym *sym)
|
|||||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||||
local_scope = 1; /* for function parameters */
|
local_scope = 1; /* for function parameters */
|
||||||
gfunc_prolog(&sym->type);
|
gfunc_prolog(&sym->type);
|
||||||
local_scope = 0;
|
reset_local_scope();
|
||||||
rsym = 0;
|
rsym = 0;
|
||||||
clear_temp_local_var_list();
|
clear_temp_local_var_list();
|
||||||
block(NULL, NULL, 0);
|
block(NULL, NULL, 0);
|
||||||
@ -7245,7 +7479,7 @@ static void gen_function(Sym *sym)
|
|||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
label_pop(&global_label_stack, NULL, 0);
|
label_pop(&global_label_stack, NULL, 0);
|
||||||
/* reset local stack */
|
/* reset local stack */
|
||||||
local_scope = 0;
|
reset_local_scope();
|
||||||
sym_pop(&local_stack, NULL, 0);
|
sym_pop(&local_stack, NULL, 0);
|
||||||
/* end of function */
|
/* end of function */
|
||||||
/* patch symbol size */
|
/* patch symbol size */
|
||||||
|
1
tccpp.c
1
tccpp.c
@ -1367,6 +1367,7 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
|
|||||||
Sym *s, **ps;
|
Sym *s, **ps;
|
||||||
s = sym_push2(ptop, v, 0, 0);
|
s = sym_push2(ptop, v, 0, 0);
|
||||||
s->r = flags;
|
s->r = flags;
|
||||||
|
s->scope = scope_tracker;
|
||||||
ps = &table_ident[v - TOK_IDENT]->sym_label;
|
ps = &table_ident[v - TOK_IDENT]->sym_label;
|
||||||
if (ptop == &global_label_stack) {
|
if (ptop == &global_label_stack) {
|
||||||
/* modify the top most local identifier, so that
|
/* modify the top most local identifier, so that
|
||||||
|
2
tcctok.h
2
tcctok.h
@ -123,6 +123,8 @@
|
|||||||
DEF(TOK_FASTCALL3, "__fastcall__")
|
DEF(TOK_FASTCALL3, "__fastcall__")
|
||||||
DEF(TOK_REGPARM1, "regparm")
|
DEF(TOK_REGPARM1, "regparm")
|
||||||
DEF(TOK_REGPARM2, "__regparm__")
|
DEF(TOK_REGPARM2, "__regparm__")
|
||||||
|
DEF(TOK_CLEANUP1, "cleanup")
|
||||||
|
DEF(TOK_CLEANUP2, "__cleanup__")
|
||||||
|
|
||||||
DEF(TOK_MODE, "__mode__")
|
DEF(TOK_MODE, "__mode__")
|
||||||
DEF(TOK_MODE_QI, "__QI__")
|
DEF(TOK_MODE_QI, "__QI__")
|
||||||
|
Loading…
Reference in New Issue
Block a user