History

Tidy new support for cleanups

encode most things in Syms, do only as much work as necessary (e.g. pending cleanups), don't track scopes in a large structure (instead encode the scopes with cleanups directly in the cleanups tree). Removes ca. 120 lines of code.

Michael Matz committed 7 years ago

Commit 4cc802a1 parent 5d805a93 files · +95 −221Browse files

Unified · Split

3 files
  1. tcc.h +3 −11
  2. tccgen.c +92 −209
  3. tccpp.c +0 −1
tcc.h+3−11
@@ -456,10 +456,6 @@ struct FuncAttr { · 455 unmodified lines
456456 func_args : 8; /* PE __stdcall args */
457457 };
458458
459−typedef struct ScopeTacker {
460− struct ScopeTacker *prev;
461−} ScopeTacker;
462−
463459 /* symbol management */
464460 typedef struct Sym {
465461 int v; /* symbol token */
@@ -470,20 +466,19 @@ typedef struct Sym { · 4 unmodified lines
470466 int c; /* associated number or Elf symbol index */
471467 union {
472468 int sym_scope; /* scope level for locals */
473− struct {
474− ScopeTacker *scope;
475− int jnext; /* next jump label */
476− };
469+ int jnext; /* next jump label */
477470 struct FuncAttr f; /* function attributes */
478471 int auxtype; /* bitfield access type */
479472 };
480473 };
481474 long long enum_val; /* enum constant if IS_ENUM_VAL */
482475 int *d; /* define token stream */
476+ struct Sym *ncl; /* next cleanup */
483477 };
484478 CType type; /* associated type */
485479 union {
486480 struct Sym *next; /* next related symbol (for fields and anoms) */
481+ struct Sym *cleanupstate; /* in defined labels */
487482 int asm_label; /* associated asm label */
488483 };
489484 struct Sym *prev; /* prev symbol in stack */
@@ -593,7 +588,6 @@ typedef struct AttributeDef { · 103 unmodified lines
593588 struct FuncAttr f;
594589 struct Section *section;
595590 Sym *cleanup_func;
596− int should_remember;
597591 int alias_target; /* token */
598592 int asm_label; /* associated asm label */
599593 char attr_mode; /* __attribute__((__mode__(...))) */
@@ -1288,8 +1282,6 @@ ST_DATA Sym *sym_free_first; · 688 unmodified lines
12881282 ST_DATA void **sym_pools;
12891283 ST_DATA int nb_sym_pools;
12901284
1291−ST_DATA ScopeTacker *scope_tracker;
1292−
12931285 ST_DATA Sym *global_stack;
12941286 ST_DATA Sym *local_stack;
12951287 ST_DATA Sym *local_label_stack;
tccgen.c+92−209
@@ -39,15 +39,10 @@ ST_DATA Sym *define_stack; · 38 unmodified lines
3939 ST_DATA Sym *global_label_stack;
4040 ST_DATA Sym *local_label_stack;
4141
42−static int local_scope;
43−#define SCOPE_TCK_STORE_SIZE 512
44−ST_DATA ScopeTacker *scope_tracker;
45−static ScopeTacker scope_tck_store[SCOPE_TCK_STORE_SIZE];
46−static int scope_tck_store_len;
47−
48−static ScopeTacker **scope_tck_2nd_store;
49−static int scope_tck_2nd_store_len;
42+static Sym *all_cleanups, *current_cleanups, *pending_gotos;
43+static int ncleanups;
5044
45+static int local_scope;
5146 static int in_sizeof;
5247 static int section_sym;
5348
@@ -86,28 +81,7 @@ ST_DATA struct temp_local_variable { · 32 unmodified lines
8681 short size;
8782 short align;
8883 } arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
89−
9084 short nb_temp_local_vars;
91−static struct cleanup {
92− ScopeTacker *scope;
93− struct {
94− Sym *var;
95− Sym *func;
96− } *syms;
97− int nb_cleanup;
98−} *cleanup_info;
99−
100−static struct cleanup **cleanup_info_store;
101−static int cleanup_idx;
102−
103−static struct CleanupGoto {
104− Sym *s;
105− ScopeTacker *scope;
106− int jnext;
107− int is_valide;
108−} **cleanup_goto_info;
109−
110−static int last_cleanup_goto;
11185
11286 /* ------------------------------------------------------------------------- */
11387
@@ -141,59 +115,20 @@ static void clear_temp_local_var_list(); · 27 unmodified lines
141115
142116 static void incr_local_scope(void)
143117 {
144− ScopeTacker *tmp = scope_tracker;
145−
146118 ++local_scope;
147− if (scope_tck_store_len >= SCOPE_TCK_STORE_SIZE) {
148− scope_tracker = tcc_malloc(sizeof(ScopeTacker));
149− dynarray_add(&scope_tck_2nd_store,
150− &scope_tck_2nd_store_len, scope_tracker);
151− } else {
152− scope_tracker = &scope_tck_store[scope_tck_store_len];
153− ++scope_tck_store_len;
154− }
155− scope_tracker->prev = tmp;
156119 }
157120
158121 static void decr_local_scope(void)
159122 {
160− if (scope_tracker)
161− scope_tracker = scope_tracker->prev;
162123 --local_scope;
163124 }
164125
165126 static void reset_local_scope(void)
166127 {
167− if (cleanup_info) {
168− int i = 0;
169−
170− for (; i < cleanup_idx; ++i) {
171− cleanup_info = cleanup_info_store[i];
172− tcc_free(cleanup_info->syms);
173− tcc_free(cleanup_info);
174− }
175− cleanup_info = NULL;
176− cleanup_idx = 0;
177− tcc_free(cleanup_info_store);
178− cleanup_info_store = NULL;
179− dynarray_reset(&cleanup_goto_info, &last_cleanup_goto);
180− }
181− scope_tracker = NULL;
128+ if (current_cleanups)
129+ tcc_error("ICE current_cleanups");
130+ sym_pop(&all_cleanups, NULL, 0);
182131 local_scope = 0;
183− scope_tck_store_len = 0;
184− if (scope_tck_2nd_store_len)
185− dynarray_reset(&scope_tck_2nd_store, &scope_tck_2nd_store_len);
186−}
187−
188−int is_scope_a_parent_of(ScopeTacker *parent, ScopeTacker *child)
189−{
190− ScopeTacker *cur = parent->prev;
191−
192− for (; cur; cur = cur->prev) {
193− if (cur == child)
194− return 1;
195− }
196− return 0;
197132 }
198133
199134 ST_INLN int is_float(int t)
@@ -4646,8 +4581,6 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) · 4446 unmodified lines
46464581 ret = pointed_type(type);
46474582 }
46484583
4649− if (ad->cleanup_func)
4650− ad->should_remember = 1;
46514584 if (tok == '(') {
46524585 /* This is possibly a parameter type list for abstract declarators
46534586 ('int ()'), use post_type for testing this. */
@@ -4799,67 +4732,43 @@ static void parse_builtin_params(int nc, const char *args) · 145 unmodified lines
47994732 nocode_wanted--;
48004733 }
48014734
4802−static void try_call_scope_cleanup(ScopeTacker *scope)
4735+static void try_call_scope_cleanup(Sym *stop)
48034736 {
4804− int i;
4805−
4806− if (!cleanup_info)
4807− return;
4737+ Sym *cls = current_cleanups;
48084738
4809− if (cleanup_info->scope != scope) {
4810− int i = 0;
4811−
4812− for (; i < cleanup_idx; ++i) {
4813− cleanup_info = cleanup_info_store[i];
4814− if (cleanup_info->scope == scope)
4815− goto found;
4816− }
4817− return;
4818− }
4819− found:
4820− for (i = cleanup_info->nb_cleanup - 1; i >= 0; --i) {
4821− Sym *fs = cleanup_info->syms[i].func;
4822− Sym *vs = cleanup_info->syms[i].var;
4739+ for (; cls != stop; cls = cls->ncl) {
4740+ Sym *fs = cls->next;
4741+ Sym *vs = cls->prev_tok;
48234742
48244743 vpushsym(&fs->type, fs);
4825− if (is_float(vs->type.t)) {
4826− vs->type.t = VT_INT;
4827− }
48284744 vset(&vs->type, vs->r, vs->c);
48294745 vtop->sym = vs;
4746+ mk_pointer(&vtop->type);
48304747 gaddrof();
4831− gfunc_param_typed(fs, vs);
48324748 gfunc_call(1);
48334749 }
48344750 }
48354751
4836−static void try_call_cleanup_goto(ScopeTacker *dest_scope)
4752+static void try_call_cleanup_goto(Sym *cleanupstate)
48374753 {
4838− ScopeTacker *cur_scope_tracker;
4754+ Sym *oc, *cc;
4755+ int ocd, ccd;
48394756
4840− if (!cleanup_info)
4757+ if (!current_cleanups)
48414758 return;
4842− for (cur_scope_tracker = scope_tracker;
4843− cur_scope_tracker && cur_scope_tracker != dest_scope;
4844− cur_scope_tracker = cur_scope_tracker->prev) {
4845− try_call_scope_cleanup(cur_scope_tracker);
4846− }
4847−}
48484759
4849−static void try_call_all_cleanup(void)
4850−{
4851− ScopeTacker *cur_scope_tracker;
4760+ /* search NCA of both cleanup chains given parents and initial depth */
4761+ ocd = cleanupstate ? cleanupstate->v & ~SYM_FIELD : 0;
4762+ for (ccd = ncleanups, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->ncl)
4763+ ;
4764+ for (cc = current_cleanups; ccd > ocd; --ccd, cc = cc->ncl)
4765+ ;
4766+ for (; cc != oc; cc = cc->ncl, oc = oc->ncl, --ccd)
4767+ ;
48524768
4853− if (!cleanup_info)
4854− return;
4855− for (cur_scope_tracker = scope_tracker;
4856− cur_scope_tracker;
4857− cur_scope_tracker = cur_scope_tracker->prev) {
4858− try_call_scope_cleanup(cur_scope_tracker);
4859− }
4769+ try_call_scope_cleanup(cc);
48604770 }
48614771
4862−
48634772 ST_FUNC void unary(void)
48644773 {
48654774 int n, t, align, size, r, sizeof_caller;
@@ -6252,14 +6161,16 @@ static void block(int *bsym, int *csym, int is_expr) · 1386 unmodified lines
62526161 gsym(a);
62536162 gsym_addr(b, d);
62546163 } else if (tok == '{') {
6255− Sym *llabel;
6164+ Sym *llabel, *lcleanup;
62566165 int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope;
6166+ int lncleanups = ncleanups;
62576167
62586168 next();
62596169 /* record local declaration stack position */
62606170 s = local_stack;
62616171 llabel = local_label_stack;
6262− incr_local_scope();
6172+ lcleanup = current_cleanups;
6173+ incr_local_scope();
62636174
62646175 /* handle local labels declarations */
62656176 while (tok == TOK_LABEL) {
@@ -6289,32 +6200,35 @@ static void block(int *bsym, int *csym, int is_expr) · 23 unmodified lines
62896200 }
62906201 }
62916202
6292− if (cleanup_info) {
6293− int jmp = 0;
6294− int i;
6295−
6296− jmp = gjmp(jmp);
6297−
6298− for (i = 0; i < last_cleanup_goto; ++i) {
6299− struct CleanupGoto *cur = cleanup_goto_info[i];
6300−
6301− if (!cur->is_valide)
6302− continue;
6303− if (scope_tracker == cur->scope ||
6304− is_scope_a_parent_of(cur->scope, scope_tracker)) {
6305− gsym(cur->jnext);
6306− try_call_scope_cleanup(scope_tracker);
6307− cur->jnext = 0;
6308− cur->jnext = gjmp(cur->jnext);
6309− }
6310− }
6311−
6312− gsym(jmp);
6313− if (!nocode_wanted) {
6314− try_call_scope_cleanup(scope_tracker);
6315− }
6316− }
6203+ if (current_cleanups != lcleanup) {
6204+ int jmp = 0;
6205+ Sym *g, **pg;
6206+
6207+ for (pg = &pending_gotos; (g = *pg) && g->c > lncleanups;)
6208+ if (g->prev_tok->r & LABEL_FORWARD) {
6209+ Sym *pcl = g->next;
6210+ if (!jmp)
6211+ jmp = gjmp(0);
6212+ gsym(pcl->jnext);
6213+ try_call_scope_cleanup(lcleanup);
6214+ pcl->jnext = gjmp(0);
6215+ if (!lncleanups)
6216+ goto remove_pending;
6217+ g->c = lncleanups;
6218+ pg = &g->prev;
6219+ } else {
6220+ remove_pending:
6221+ *pg = g->prev;
6222+ sym_free(g);
6223+ }
6224+ gsym(jmp);
6225+ if (!nocode_wanted) {
6226+ try_call_scope_cleanup(lcleanup);
6227+ }
6228+ }
63176229
6230+ current_cleanups = lcleanup;
6231+ ncleanups = lncleanups;
63186232 /* pop locally defined labels */
63196233 label_pop(&local_label_stack, llabel, is_expr);
63206234 /* pop locally defined symbols */
@@ -6334,20 +6248,20 @@ static void block(int *bsym, int *csym, int is_expr) · 13 unmodified lines
63346248 vla_sp_restore();
63356249 }
63366250 vlas_in_scope = saved_vlas_in_scope;
6337−
6251+
63386252 next();
63396253 } else if (tok == TOK_RETURN) {
63406254 next();
63416255 if (tok != ';') {
63426256 gexpr();
63436257 gen_assign_cast(&func_vt);
6344− try_call_all_cleanup();
6258+ try_call_scope_cleanup(NULL);
63456259 if ((func_vt.t & VT_BTYPE) == VT_VOID)
63466260 vtop--;
63476261 else
63486262 gfunc_return(&func_vt);
63496263 } else {
6350− try_call_all_cleanup();
6264+ try_call_scope_cleanup(NULL);
63516265 }
63526266 skip(';');
63536267 /* jump unless last stmt in top-level block */
@@ -6518,39 +6432,26 @@ static void block(int *bsym, int *csym, int is_expr) · 164 unmodified lines
65186432 ggoto();
65196433 } else if (tok >= TOK_UIDENT) {
65206434 s = label_find(tok);
6521− if (!s || s->jnext == -1) {
6522− /* put forward definition if needed */
6523− if (!s)
6524− s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6525− if (cleanup_info) {
6526− struct CleanupGoto *cur =
6527− tcc_malloc(sizeof(struct CleanupGoto));
6528−
6529− cur->s = s;
6530− cur->is_valide = 1;
6531− s->jnext = -1;
6532− cur->jnext = 0;
6533− cur->scope = scope_tracker;
6534− cur->jnext = gjmp(cur->jnext);
6535− dynarray_add(&cleanup_goto_info, &last_cleanup_goto, cur);
6536− vla_sp_restore_root();
6537− goto out_goto;
6538− }
6539− } else {
6540− if (cleanup_info && is_scope_a_parent_of(scope_tracker,
6541− s->scope))
6542− try_call_cleanup_goto(s->scope);
6543−
6544− if (s->r == LABEL_DECLARED)
6545− s->r = LABEL_FORWARD;
6546− }
6435+ /* put forward definition if needed */
6436+ if (!s)
6437+ s = label_push(&global_label_stack, tok, LABEL_FORWARD);
6438+ else if (s->r == LABEL_DECLARED)
6439+ s->r = LABEL_FORWARD;
65476440
65486441 vla_sp_restore_root();
6549− if (s->r & LABEL_FORWARD)
6442+ if (s->r & LABEL_FORWARD) {
6443+ /* start new goto chain for cleanups, linked via label->next */
6444+ if (current_cleanups) {
6445+ sym_push2(&pending_gotos, SYM_FIELD, 0, ncleanups);
6446+ pending_gotos->prev_tok = s;
6447+ s = sym_push2(&s->next, SYM_FIELD, 0, 0);
6448+ pending_gotos->next = s;
6449+ }
65506450 s->jnext = gjmp(s->jnext);
6551− else
6451+ } else {
6452+ try_call_cleanup_goto(s->cleanupstate);
65526453 gjmp_addr(s->jnext);
6553− out_goto:
6454+ }
65546455 next();
65556456 } else {
65566457 expect("label identifier");
@@ -6565,26 +6466,21 @@ static void block(int *bsym, int *csym, int is_expr) · 8 unmodified lines
65656466 next();
65666467 s = label_find(b);
65676468 if (s) {
6568− int is_gen = 0;
6569− int i;
6570−
65716469 if (s->r == LABEL_DEFINED)
65726470 tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL));
6573− for (i = 0; i < last_cleanup_goto; ++i) {
6574− struct CleanupGoto *cur = cleanup_goto_info[i];
6575− if (cur->s == s) {
6576− cur->is_valide = 0;
6577− gsym(cur->jnext);
6578− is_gen = 1;
6579− }
6580− }
65816471 s->r = LABEL_DEFINED;
6582− if (!is_gen)
6583− gsym(s->jnext);
6472+ if (s->next) {
6473+ Sym *pcl; /* pending cleanup goto */
6474+ for (pcl = s->next; pcl; pcl = pcl->prev)
6475+ gsym(pcl->jnext);
6476+ sym_pop(&s->next, NULL, 0);
6477+ } else
6478+ gsym(s->jnext);
65846479 } else {
65856480 s = label_push(&global_label_stack, b, LABEL_DEFINED);
65866481 }
65876482 s->jnext = ind;
6483+ s->cleanupstate = current_cleanups;
65886484 vla_sp_restore();
65896485 /* we accept this, but it is a mistake */
65906486 block_after_label:
@@ -7317,25 +7213,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 726 unmodified lines
73177213 #endif
73187214 sym = sym_push(v, type, r, addr);
73197215 if (ad->cleanup_func) {
7320− int nb_cleanup;
7321−
7322− if (!cleanup_info || cleanup_info->scope != scope_tracker) {
7323− cleanup_info = tcc_malloc(sizeof(struct cleanup));
7324− dynarray_add(&cleanup_info_store, &cleanup_idx,
7325− cleanup_info);
7326− cleanup_info ->scope = scope_tracker;
7327− cleanup_info->nb_cleanup = 0;
7328− cleanup_info->syms = NULL;
7329− }
7330− nb_cleanup = cleanup_info->nb_cleanup + 1;
7331− cleanup_info->syms = tcc_realloc(cleanup_info->syms,
7332− nb_cleanup *
7333− sizeof(*cleanup_info->syms));
7334− cleanup_info->syms[nb_cleanup - 1].func = ad->cleanup_func;
7335− cleanup_info->syms[nb_cleanup - 1].var = sym;
7336− cleanup_info->nb_cleanup = nb_cleanup;
7337− if (!ad->should_remember)
7338− ad->cleanup_func = NULL;
7216+ Sym *cls = sym_push2(&all_cleanups, SYM_FIELD | ++ncleanups, 0, 0);
7217+ cls->prev_tok = sym;
7218+ cls->next = ad->cleanup_func;
7219+ cls->ncl = current_cleanups;
7220+ current_cleanups = cls;
73397221 }
73407222
73417223 sym->a = ad->a;
@@ -7567,10 +7449,10 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 225 unmodified lines
75677449 int v, has_init, r;
75687450 CType type, btype;
75697451 Sym *sym;
7570− AttributeDef ad;
7452+ AttributeDef ad, adbase;
75717453
75727454 while (1) {
7573− if (!parse_btype(&btype, &ad)) {
7455+ if (!parse_btype(&btype, &adbase)) {
75747456 if (is_for_loop_init)
75757457 return 0;
75767458 /* skip redundant ';' if not in old parameter decl scope */
@@ -7618,6 +7500,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 41 unmodified lines
76187500 if ((type.t & VT_ARRAY) && type.ref->c < 0) {
76197501 type.ref = sym_push(SYM_FIELD, &type.ref->type, 0, type.ref->c);
76207502 }
7503+ ad = adbase;
76217504 type_decl(&type, &ad, &v, TYPE_DIRECT);
76227505 #if 0
76237506 {
tccpp.c+0−1
@@ -1366,7 +1366,6 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags) · 1365 unmodified lines
13661366 Sym *s, **ps;
13671367 s = sym_push2(ptop, v, 0, 0);
13681368 s->r = flags;
1369− s->scope = scope_tracker;
13701369 ps = &table_ident[v - TOK_IDENT]->sym_label;
13711370 if (ptop == &global_label_stack) {
13721371 /* modify the top most local identifier, so that

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t