Skip to content

Commit

Permalink
about CONST_WANTED & VT_NONCONST
Browse files Browse the repository at this point in the history
- integrate CONST_WANTED with nocode_wanted
- expr_const() checks VT_NONCONST
  • Loading branch information
grischka committed Apr 25, 2023
1 parent bb93bf8 commit 0ec3a40
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 30 deletions.
1 change: 0 additions & 1 deletion tcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
Expand Down
64 changes: 35 additions & 29 deletions tccgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 |
Expand All @@ -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;
}
Expand Down Expand Up @@ -2339,24 +2347,22 @@ 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)) {
vswap();
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)))) {
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -2965,7 +2971,7 @@ ST_FUNC void gen_op(int op)
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 == '-') {
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -6532,19 +6540,17 @@ 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. */
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();
Expand Down

0 comments on commit 0ec3a40

Please sign in to comment.