about CONST_WANTED & VT_NONCONST
- integrate CONST_WANTED with nocode_wanted - expr_const() checks VT_NONCONST
This commit is contained in:
parent
bb93bf8cd2
commit
0ec3a40dfd
2 changed files with 35 additions and 30 deletions
1
tcc.h
1
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) */
|
||||
|
|
64
tccgen.c
64
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();
|
||||
|
|
Loading…
Reference in a new issue