From 0ec3a40dfd9513f3e803450eaa1ed7833f89568c Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 12 Mar 2023 11:16:27 +0100 Subject: [PATCH] about CONST_WANTED & VT_NONCONST - integrate CONST_WANTED with nocode_wanted - expr_const() checks VT_NONCONST --- tcc.h | 1 - tccgen.c | 64 +++++++++++++++++++++++++++++++++++----------------------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/tcc.h b/tcc.h index 4bc5f508..00d80879 100644 --- a/tcc.h +++ b/tcc.h @@ -1421,7 +1421,6 @@ ST_DATA SValue *vtop; ST_DATA int rsym, anon_sym, ind, loc; ST_DATA char debug_modes; -ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ diff --git a/tccgen.c b/tccgen.c index d5c01670..af4ea899 100644 --- a/tccgen.c +++ b/tccgen.c @@ -51,15 +51,24 @@ ST_DATA SValue *vtop; static SValue _vstack[1 + VSTACK_SIZE]; #define vstack (_vstack + 1) -ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* no code generation wanted */ -#define unevalmask 0xffff /* unevaluated subexpression */ #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ #define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */ + +/* no code output after unconditional jumps such as with if (0) ... */ #define CODE_OFF_BIT 0x20000000 #define CODE_OFF() if(!nocode_wanted)(nocode_wanted |= CODE_OFF_BIT) #define CODE_ON() (nocode_wanted &= ~CODE_OFF_BIT) +/* no code output when parsing sizeof()/typeof() etc. (using nocode_wanted++/--) */ +#define NOEVAL_MASK 0x0000FFFF +#define NOEVAL_WANTED (nocode_wanted & NOEVAL_MASK) + +/* no code output when parsing constant expressions */ +#define CONST_WANTED_BIT 0x00010000 +#define CONST_WANTED_MASK 0x0FFF0000 +#define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK) + ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ @@ -375,7 +384,6 @@ ST_FUNC int tccgen_compile(TCCState *s1) funcname = ""; func_ind = -1; anon_sym = SYM_FIRST_ANOM; - const_wanted = 0; nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */ local_scope = 0; debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1; @@ -2274,10 +2282,10 @@ static void gen_opic(int op) int t2 = v2->type.t & VT_BTYPE; int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; - int nonconst = (v1->r | v2->r) & VT_NONCONST; uint64_t l1 = c1 ? v1->c.i : 0; uint64_t l2 = c2 ? v2->c.i : 0; int shm = (t1 == VT_LLONG) ? 63 : 31; + int r; if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) l1 = ((uint32_t)l1 | @@ -2302,7 +2310,7 @@ static void gen_opic(int op) case TOK_UMOD: /* if division by zero, generate explicit division */ if (l2 == 0) { - if (const_wanted && !(nocode_wanted & unevalmask)) + if (CONST_WANTED && !NOEVAL_WANTED) tcc_error("division by zero in constant"); goto general_case; } @@ -2339,9 +2347,9 @@ static void gen_opic(int op) l1 = ((uint32_t)l1 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); v1->c.i = l1; + v1->r |= v2->r & VT_NONCONST; vtop--; } else { - nonconst = VT_NONCONST; /* if commutative ops, put c2 as constant */ if (c1 && (op == '+' || op == '&' || op == '^' || op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) { @@ -2349,14 +2357,12 @@ static void gen_opic(int op) c2 = c1; //c = c1, c1 = c2, c2 = c; l2 = l1; //l = l1, l1 = l2, l2 = l; } - if (!const_wanted && - c1 && ((l1 == 0 && + if (c1 && ((l1 == 0 && (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) || (l1 == -1 && op == TOK_SAR))) { /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */ - vtop--; - } else if (!const_wanted && - c2 && ((l2 == 0 && (op == '&' || op == '*')) || + vpop(); + } else if (c2 && ((l2 == 0 && (op == '&' || op == '*')) || (op == '|' && (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) || (l2 == 1 && (op == '%' || op == TOK_UMOD)))) { @@ -2393,8 +2399,8 @@ static void gen_opic(int op) } goto general_case; } else if (c2 && (op == '+' || op == '-') && - (((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM)) - || (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) { + (r = vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM), + r == (VT_CONST | VT_SYM) || r == VT_LOCAL)) { /* symbol + constant case */ if (op == '-') l2 = -l2; @@ -2414,9 +2420,9 @@ static void gen_opic(int op) else gen_opi(op); } + if (vtop->r == VT_CONST) + vtop->r |= VT_NONCONST; /* is const, but only by optimization */ } - if (vtop->r == VT_CONST) - vtop->r |= nonconst; } #if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 @@ -2484,7 +2490,7 @@ static void gen_opif(int op) } /* NOTE: we only do constant propagation if finite number (not NaN or infinity) (ANSI spec) */ - if (!(ieee_finite(f1) || !ieee_finite(f2)) && !const_wanted) + if (!(ieee_finite(f1) || !ieee_finite(f2)) && !CONST_WANTED) goto general_case; switch(op) { case '+': f1 += f2; break; @@ -2495,7 +2501,7 @@ static void gen_opif(int op) union { float f; unsigned u; } x1, x2, y; /* If not in initializer we need to potentially generate FP exceptions at runtime, otherwise we want to fold. */ - if (!const_wanted) + if (!CONST_WANTED) goto general_case; /* the run-time result of 0.0/0.0 on x87, also of other compilers when used to compile the f1 /= f2 below, would be -nan */ @@ -2965,7 +2971,7 @@ redo: vpush_type_size(pointed_type(&vtop[-1].type), &align); gen_op('*'); #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && !const_wanted) { + if (tcc_state->do_bounds_check && !CONST_WANTED) { /* if bounded pointers, we generate a special code to test bounds */ if (op == '-') { @@ -5533,7 +5539,7 @@ ST_FUNC void unary(void) } } else if (tok == '{') { int saved_nocode_wanted = nocode_wanted; - if (const_wanted && !(nocode_wanted & unevalmask)) + if (CONST_WANTED && !NOEVAL_WANTED) expect("constant"); if (0 == local_scope) tcc_error("statement expression outside of function"); @@ -5848,17 +5854,19 @@ ST_FUNC void unary(void) int has_match = 0; int learn = 0; TokenString *str = NULL; - int saved_const_wanted = const_wanted; + int saved_nocode_wanted = nocode_wanted; + nocode_wanted &= ~CONST_WANTED_MASK; - next(); + next(); skip('('); - const_wanted = 0; expr_type(&controlling_type, expr_eq); controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY); if ((controlling_type.t & VT_BTYPE) == VT_FUNC) mk_pointer(&controlling_type); - const_wanted = saved_const_wanted; - for (;;) { + + nocode_wanted = saved_nocode_wanted; + + for (;;) { learn = 0; skip(','); if (tok == TOK_DEFAULT) { @@ -6532,11 +6540,9 @@ ST_FUNC void gexpr(void) /* parse a constant expression and return value in vtop. */ static void expr_const1(void) { - const_wanted++; - nocode_wanted += unevalmask + 1; + nocode_wanted += CONST_WANTED_BIT; expr_cond(); - nocode_wanted -= unevalmask + 1; - const_wanted--; + nocode_wanted -= CONST_WANTED_BIT; } /* parse an integer constant and return its value. */ @@ -6544,7 +6550,7 @@ static inline int64_t expr_const64(void) { int64_t c; expr_const1(); - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM | VT_NONCONST)) != VT_CONST) expect("constant expression"); c = vtop->c.i; vpop(); -- 2.11.4.GIT