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 int rsym, anon_sym, ind, loc;
|
||||||
ST_DATA char debug_modes;
|
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 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 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 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];
|
static SValue _vstack[1 + VSTACK_SIZE];
|
||||||
#define vstack (_vstack + 1)
|
#define vstack (_vstack + 1)
|
||||||
|
|
||||||
ST_DATA int const_wanted; /* true if constant wanted */
|
|
||||||
ST_DATA int nocode_wanted; /* no code generation 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 NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
|
||||||
#define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
|
#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_BIT 0x20000000
|
||||||
#define CODE_OFF() if(!nocode_wanted)(nocode_wanted |= CODE_OFF_BIT)
|
#define CODE_OFF() if(!nocode_wanted)(nocode_wanted |= CODE_OFF_BIT)
|
||||||
#define CODE_ON() (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 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 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) */
|
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 = "";
|
funcname = "";
|
||||||
func_ind = -1;
|
func_ind = -1;
|
||||||
anon_sym = SYM_FIRST_ANOM;
|
anon_sym = SYM_FIRST_ANOM;
|
||||||
const_wanted = 0;
|
|
||||||
nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
|
nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
|
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 t2 = v2->type.t & VT_BTYPE;
|
||||||
int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
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 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 l1 = c1 ? v1->c.i : 0;
|
||||||
uint64_t l2 = c2 ? v2->c.i : 0;
|
uint64_t l2 = c2 ? v2->c.i : 0;
|
||||||
int shm = (t1 == VT_LLONG) ? 63 : 31;
|
int shm = (t1 == VT_LLONG) ? 63 : 31;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
|
if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
|
||||||
l1 = ((uint32_t)l1 |
|
l1 = ((uint32_t)l1 |
|
||||||
|
@ -2302,7 +2310,7 @@ static void gen_opic(int op)
|
||||||
case TOK_UMOD:
|
case TOK_UMOD:
|
||||||
/* if division by zero, generate explicit division */
|
/* if division by zero, generate explicit division */
|
||||||
if (l2 == 0) {
|
if (l2 == 0) {
|
||||||
if (const_wanted && !(nocode_wanted & unevalmask))
|
if (CONST_WANTED && !NOEVAL_WANTED)
|
||||||
tcc_error("division by zero in constant");
|
tcc_error("division by zero in constant");
|
||||||
goto general_case;
|
goto general_case;
|
||||||
}
|
}
|
||||||
|
@ -2339,9 +2347,9 @@ static void gen_opic(int op)
|
||||||
l1 = ((uint32_t)l1 |
|
l1 = ((uint32_t)l1 |
|
||||||
(v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
|
(v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
|
||||||
v1->c.i = l1;
|
v1->c.i = l1;
|
||||||
|
v1->r |= v2->r & VT_NONCONST;
|
||||||
vtop--;
|
vtop--;
|
||||||
} else {
|
} else {
|
||||||
nonconst = VT_NONCONST;
|
|
||||||
/* if commutative ops, put c2 as constant */
|
/* if commutative ops, put c2 as constant */
|
||||||
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
if (c1 && (op == '+' || op == '&' || op == '^' ||
|
||||||
op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) {
|
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;
|
c2 = c1; //c = c1, c1 = c2, c2 = c;
|
||||||
l2 = l1; //l = l1, l1 = l2, l2 = l;
|
l2 = l1; //l = l1, l1 = l2, l2 = l;
|
||||||
}
|
}
|
||||||
if (!const_wanted &&
|
if (c1 && ((l1 == 0 &&
|
||||||
c1 && ((l1 == 0 &&
|
|
||||||
(op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) ||
|
(op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) ||
|
||||||
(l1 == -1 && op == TOK_SAR))) {
|
(l1 == -1 && op == TOK_SAR))) {
|
||||||
/* treat (0 << x), (0 >> x) and (-1 >> x) as constant */
|
/* treat (0 << x), (0 >> x) and (-1 >> x) as constant */
|
||||||
vtop--;
|
vpop();
|
||||||
} else if (!const_wanted &&
|
} else if (c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
|
||||||
c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
|
|
||||||
(op == '|' &&
|
(op == '|' &&
|
||||||
(l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) ||
|
(l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) ||
|
||||||
(l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
|
(l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
|
||||||
|
@ -2393,8 +2399,8 @@ static void gen_opic(int op)
|
||||||
}
|
}
|
||||||
goto general_case;
|
goto general_case;
|
||||||
} else if (c2 && (op == '+' || op == '-') &&
|
} else if (c2 && (op == '+' || op == '-') &&
|
||||||
(((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM))
|
(r = vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM),
|
||||||
|| (vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_LOCAL)) {
|
r == (VT_CONST | VT_SYM) || r == VT_LOCAL)) {
|
||||||
/* symbol + constant case */
|
/* symbol + constant case */
|
||||||
if (op == '-')
|
if (op == '-')
|
||||||
l2 = -l2;
|
l2 = -l2;
|
||||||
|
@ -2414,9 +2420,9 @@ static void gen_opic(int op)
|
||||||
else
|
else
|
||||||
gen_opi(op);
|
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
|
#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
|
/* NOTE: we only do constant propagation if finite number (not
|
||||||
NaN or infinity) (ANSI spec) */
|
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;
|
goto general_case;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case '+': f1 += f2; break;
|
case '+': f1 += f2; break;
|
||||||
|
@ -2495,7 +2501,7 @@ static void gen_opif(int op)
|
||||||
union { float f; unsigned u; } x1, x2, y;
|
union { float f; unsigned u; } x1, x2, y;
|
||||||
/* If not in initializer we need to potentially generate
|
/* If not in initializer we need to potentially generate
|
||||||
FP exceptions at runtime, otherwise we want to fold. */
|
FP exceptions at runtime, otherwise we want to fold. */
|
||||||
if (!const_wanted)
|
if (!CONST_WANTED)
|
||||||
goto general_case;
|
goto general_case;
|
||||||
/* the run-time result of 0.0/0.0 on x87, also of other compilers
|
/* 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 */
|
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);
|
vpush_type_size(pointed_type(&vtop[-1].type), &align);
|
||||||
gen_op('*');
|
gen_op('*');
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#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
|
/* if bounded pointers, we generate a special code to
|
||||||
test bounds */
|
test bounds */
|
||||||
if (op == '-') {
|
if (op == '-') {
|
||||||
|
@ -5533,7 +5539,7 @@ ST_FUNC void unary(void)
|
||||||
}
|
}
|
||||||
} else if (tok == '{') {
|
} else if (tok == '{') {
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
if (const_wanted && !(nocode_wanted & unevalmask))
|
if (CONST_WANTED && !NOEVAL_WANTED)
|
||||||
expect("constant");
|
expect("constant");
|
||||||
if (0 == local_scope)
|
if (0 == local_scope)
|
||||||
tcc_error("statement expression outside of function");
|
tcc_error("statement expression outside of function");
|
||||||
|
@ -5848,17 +5854,19 @@ ST_FUNC void unary(void)
|
||||||
int has_match = 0;
|
int has_match = 0;
|
||||||
int learn = 0;
|
int learn = 0;
|
||||||
TokenString *str = NULL;
|
TokenString *str = NULL;
|
||||||
int saved_const_wanted = const_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
nocode_wanted &= ~CONST_WANTED_MASK;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
skip('(');
|
skip('(');
|
||||||
const_wanted = 0;
|
|
||||||
expr_type(&controlling_type, expr_eq);
|
expr_type(&controlling_type, expr_eq);
|
||||||
controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY);
|
controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY);
|
||||||
if ((controlling_type.t & VT_BTYPE) == VT_FUNC)
|
if ((controlling_type.t & VT_BTYPE) == VT_FUNC)
|
||||||
mk_pointer(&controlling_type);
|
mk_pointer(&controlling_type);
|
||||||
const_wanted = saved_const_wanted;
|
|
||||||
for (;;) {
|
nocode_wanted = saved_nocode_wanted;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
learn = 0;
|
learn = 0;
|
||||||
skip(',');
|
skip(',');
|
||||||
if (tok == TOK_DEFAULT) {
|
if (tok == TOK_DEFAULT) {
|
||||||
|
@ -6532,11 +6540,9 @@ ST_FUNC void gexpr(void)
|
||||||
/* parse a constant expression and return value in vtop. */
|
/* parse a constant expression and return value in vtop. */
|
||||||
static void expr_const1(void)
|
static void expr_const1(void)
|
||||||
{
|
{
|
||||||
const_wanted++;
|
nocode_wanted += CONST_WANTED_BIT;
|
||||||
nocode_wanted += unevalmask + 1;
|
|
||||||
expr_cond();
|
expr_cond();
|
||||||
nocode_wanted -= unevalmask + 1;
|
nocode_wanted -= CONST_WANTED_BIT;
|
||||||
const_wanted--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse an integer constant and return its value. */
|
/* parse an integer constant and return its value. */
|
||||||
|
@ -6544,7 +6550,7 @@ static inline int64_t expr_const64(void)
|
||||||
{
|
{
|
||||||
int64_t c;
|
int64_t c;
|
||||||
expr_const1();
|
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");
|
expect("constant expression");
|
||||||
c = vtop->c.i;
|
c = vtop->c.i;
|
||||||
vpop();
|
vpop();
|
||||||
|
|
Loading…
Add table
Reference in a new issue