Make binary_expr fold constants

This is where constant folding should have happened all along. While
unary_expr should fold constants too, it seems to already try to do so
and it's a bit much of a mess to clean up right now.
This commit is contained in:
Bill Currie 2019-06-10 00:36:13 +09:00
parent bf0543f7fb
commit ef4ad52239
4 changed files with 48 additions and 30 deletions

View file

@ -1280,7 +1280,7 @@ test_expr (expr_t *e)
new = binary_expr (NE, e, new);
new->line = e->line;
new->file = e->file;
return fold_constants (new);
return new;
}
void
@ -2130,10 +2130,10 @@ array_expr (expr_t *array, expr_t *index)
|| ind - array_type->t.array.base >= array_type->t.array.size))
return error (index, "array index out of bounds");
scale = new_integer_expr (type_size (array_type->t.array.type));
index = fold_constants (binary_expr ('*', index, scale));
index = binary_expr ('*', index, scale);
base = new_integer_expr (array_type->t.array.base);
offset = fold_constants (binary_expr ('*', base, scale));
index = fold_constants (binary_expr ('-', index, offset));
offset = binary_expr ('*', base, scale);
index = binary_expr ('-', index, offset);
if (is_short_val (index))
ind = expr_short (index);
if (is_integer_val (index))

View file

@ -42,8 +42,11 @@ typedef struct {
type_t *type;
type_t *a_cast;
type_t *b_cast;
expr_t *(*process)(int op, expr_t *e1, expr_t *e2);
} expr_type_t;
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
static expr_type_t string_string[] = {
{'+', &type_string},
{EQ, &type_integer},
@ -157,8 +160,8 @@ static expr_type_t pointer_pointer[] = {
};
static expr_type_t pointer_integer[] = {
{'+', &type_pointer},
{'-', &type_pointer},
{'+', 0, 0, 0, pointer_arithmetic},
{'-', 0, 0, 0, pointer_arithmetic},
{0, 0}
};
#define pointer_uinteger pointer_integer
@ -218,7 +221,7 @@ static expr_type_t integer_vector[] = {
};
static expr_type_t integer_pointer[] = {
{'+', &type_pointer},
{'+', &type_pointer, 0, &type_integer},
{0, 0}
};
@ -579,6 +582,25 @@ static expr_type_t **binary_expr_types[] = {
short_x,
};
static expr_t *
pointer_arithmetic (int op, expr_t *e1, expr_t *e2)
{
expr_t *e;
type_t *ptype = get_type (e1);
if (!is_pointer (ptype)) {
ptype = get_type (e2);
}
if (!is_pointer (ptype)) {
internal_error (e1, "pointer arithmetic on non-pointers");
}
e1 = cast_expr (&type_integer, e1);
e2 = cast_expr (&type_integer, e2);
e = binary_expr (op, e1, e2);
return cast_expr (ptype, e);
}
static expr_t *
invalid_binary_expr (int op, expr_t *e1, expr_t *e2)
{
@ -780,9 +802,12 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
e1 = cast_expr (expr_type->a_cast, e1);
if (expr_type->b_cast)
e2 = cast_expr (expr_type->b_cast, e2);
if (expr_type->process) {
return fold_constants (expr_type->process (op, e1, e2));
}
if ((e = reimplement_binary_expr (op, e1, e2)))
return e;
return fold_constants (e);
e = new_binary_expr (op, e1, e2);
e->e.expr.type = expr_type->type;
@ -790,5 +815,5 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
if (options.code.progsversion == PROG_ID_VERSION)
e->e.expr.type = &type_float;
}
return e;
return fold_constants (e);
}

View file

@ -180,7 +180,7 @@ int yylex (void);
%type <symbol> methoddef
%type <expr> opt_initializer var_initializer local_def
%type <expr> opt_init opt_expr cexpr fexpr expr element_list element
%type <expr> opt_init opt_expr cexpr expr element_list element
%type <expr> optional_state_expr texpr vector_expr
%type <expr> statement statements compound_statement
%type <expr> else label break_label continue_label
@ -577,7 +577,7 @@ enumerator_list
enumerator
: identifier { add_enum ($<symbol>0, $1, 0); }
| identifier '=' fexpr { add_enum ($<symbol>0, $1, $3); }
| identifier '=' expr { add_enum ($<symbol>0, $1, $3); }
;
struct_specifier
@ -846,9 +846,8 @@ abs_decl
;
array_decl
: '[' fexpr ']'
: '[' expr ']'
{
$2 = fold_constants ($2);
if (!is_integer_val ($2) || expr_integer ($2) < 1) {
error (0, "invalid array size");
$$ = 0;
@ -971,11 +970,11 @@ overloaded_identifier
;
non_code_func
: '=' '#' fexpr
: '=' '#' expr
{
build_builtin_function ($<symbol>0, $3, 0);
}
| '=' fexpr
| '=' expr
{
symbol_t *sym = $<symbol>0;
specifier_t spec = $<spec>-1;
@ -1023,7 +1022,7 @@ opt_initializer
;
var_initializer
: '=' fexpr { $$ = $2; }
: '=' expr { $$ = $2; }
| '=' '{' element_list optional_comma '}' { $$ = $3; }
;
@ -1046,7 +1045,7 @@ element_list
element
: '{' element_list optional_comma '}' { $$ = $2; }
| fexpr { $$ = $1; }
| expr { $$ = $1; }
;
optional_comma
@ -1128,7 +1127,7 @@ statement
else
error (0, "continue outside of loop");
}
| CASE fexpr ':'
| CASE expr ':'
{
$$ = case_label_expr (switch_block, $2);
}
@ -1136,7 +1135,7 @@ statement
{
$$ = case_label_expr (switch_block, 0);
}
| SWITCH break_label '(' fexpr switch_block ')' compound_statement
| SWITCH break_label '(' expr switch_block ')' compound_statement
{
$$ = switch_expr (switch_block, break_label, $7);
switch_block = $5;
@ -1295,7 +1294,7 @@ unary_expr
;
vector_expr
: '[' fexpr ',' arg_list ']'
: '[' expr ',' arg_list ']'
{
expr_t *t = $4;
while (t->next)
@ -1338,12 +1337,8 @@ expr
| expr '%' expr { $$ = binary_expr ('%', $1, $3); }
;
fexpr
: expr { $$ = fold_constants ($1); }
;
texpr
: fexpr { $$ = convert_bool ($1, 1); }
: expr { $$ = convert_bool ($1, 1); }
;
cexpr
@ -1364,8 +1359,8 @@ opt_arg_list
;
arg_list
: fexpr
| arg_list ',' fexpr
: expr
| arg_list ',' expr
{
$3->next = $1;
$$ = $3;
@ -1874,7 +1869,7 @@ obj_messageexpr
;
receiver
: fexpr
: expr
| CLASS_NAME
{
$$ = new_symbol_expr ($1);

View file

@ -338,8 +338,6 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
int i;
expr_t *range = binary_expr ('-', tree->high, tree->low);
range = fold_constants (range);
table_init = new_block_expr ();
for (i = 0; i <= high - low; i++) {
tree->labels[i]->e.label.used++;