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

View file

@ -42,8 +42,11 @@ typedef struct {
type_t *type; type_t *type;
type_t *a_cast; type_t *a_cast;
type_t *b_cast; type_t *b_cast;
expr_t *(*process)(int op, expr_t *e1, expr_t *e2);
} expr_type_t; } expr_type_t;
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
static expr_type_t string_string[] = { static expr_type_t string_string[] = {
{'+', &type_string}, {'+', &type_string},
{EQ, &type_integer}, {EQ, &type_integer},
@ -157,8 +160,8 @@ static expr_type_t pointer_pointer[] = {
}; };
static expr_type_t pointer_integer[] = { static expr_type_t pointer_integer[] = {
{'+', &type_pointer}, {'+', 0, 0, 0, pointer_arithmetic},
{'-', &type_pointer}, {'-', 0, 0, 0, pointer_arithmetic},
{0, 0} {0, 0}
}; };
#define pointer_uinteger pointer_integer #define pointer_uinteger pointer_integer
@ -218,7 +221,7 @@ static expr_type_t integer_vector[] = {
}; };
static expr_type_t integer_pointer[] = { static expr_type_t integer_pointer[] = {
{'+', &type_pointer}, {'+', &type_pointer, 0, &type_integer},
{0, 0} {0, 0}
}; };
@ -579,6 +582,25 @@ static expr_type_t **binary_expr_types[] = {
short_x, 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 * static expr_t *
invalid_binary_expr (int op, expr_t *e1, expr_t *e2) 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); e1 = cast_expr (expr_type->a_cast, e1);
if (expr_type->b_cast) if (expr_type->b_cast)
e2 = cast_expr (expr_type->b_cast, e2); 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))) if ((e = reimplement_binary_expr (op, e1, e2)))
return e; return fold_constants (e);
e = new_binary_expr (op, e1, e2); e = new_binary_expr (op, e1, e2);
e->e.expr.type = expr_type->type; 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) if (options.code.progsversion == PROG_ID_VERSION)
e->e.expr.type = &type_float; 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 <symbol> methoddef
%type <expr> opt_initializer var_initializer local_def %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> optional_state_expr texpr vector_expr
%type <expr> statement statements compound_statement %type <expr> statement statements compound_statement
%type <expr> else label break_label continue_label %type <expr> else label break_label continue_label
@ -577,7 +577,7 @@ enumerator_list
enumerator enumerator
: identifier { add_enum ($<symbol>0, $1, 0); } : 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 struct_specifier
@ -846,9 +846,8 @@ abs_decl
; ;
array_decl array_decl
: '[' fexpr ']' : '[' expr ']'
{ {
$2 = fold_constants ($2);
if (!is_integer_val ($2) || expr_integer ($2) < 1) { if (!is_integer_val ($2) || expr_integer ($2) < 1) {
error (0, "invalid array size"); error (0, "invalid array size");
$$ = 0; $$ = 0;
@ -971,11 +970,11 @@ overloaded_identifier
; ;
non_code_func non_code_func
: '=' '#' fexpr : '=' '#' expr
{ {
build_builtin_function ($<symbol>0, $3, 0); build_builtin_function ($<symbol>0, $3, 0);
} }
| '=' fexpr | '=' expr
{ {
symbol_t *sym = $<symbol>0; symbol_t *sym = $<symbol>0;
specifier_t spec = $<spec>-1; specifier_t spec = $<spec>-1;
@ -1023,7 +1022,7 @@ opt_initializer
; ;
var_initializer var_initializer
: '=' fexpr { $$ = $2; } : '=' expr { $$ = $2; }
| '=' '{' element_list optional_comma '}' { $$ = $3; } | '=' '{' element_list optional_comma '}' { $$ = $3; }
; ;
@ -1046,7 +1045,7 @@ element_list
element element
: '{' element_list optional_comma '}' { $$ = $2; } : '{' element_list optional_comma '}' { $$ = $2; }
| fexpr { $$ = $1; } | expr { $$ = $1; }
; ;
optional_comma optional_comma
@ -1128,7 +1127,7 @@ statement
else else
error (0, "continue outside of loop"); error (0, "continue outside of loop");
} }
| CASE fexpr ':' | CASE expr ':'
{ {
$$ = case_label_expr (switch_block, $2); $$ = case_label_expr (switch_block, $2);
} }
@ -1136,7 +1135,7 @@ statement
{ {
$$ = case_label_expr (switch_block, 0); $$ = 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_expr (switch_block, break_label, $7);
switch_block = $5; switch_block = $5;
@ -1295,7 +1294,7 @@ unary_expr
; ;
vector_expr vector_expr
: '[' fexpr ',' arg_list ']' : '[' expr ',' arg_list ']'
{ {
expr_t *t = $4; expr_t *t = $4;
while (t->next) while (t->next)
@ -1338,12 +1337,8 @@ expr
| expr '%' expr { $$ = binary_expr ('%', $1, $3); } | expr '%' expr { $$ = binary_expr ('%', $1, $3); }
; ;
fexpr
: expr { $$ = fold_constants ($1); }
;
texpr texpr
: fexpr { $$ = convert_bool ($1, 1); } : expr { $$ = convert_bool ($1, 1); }
; ;
cexpr cexpr
@ -1364,8 +1359,8 @@ opt_arg_list
; ;
arg_list arg_list
: fexpr : expr
| arg_list ',' fexpr | arg_list ',' expr
{ {
$3->next = $1; $3->next = $1;
$$ = $3; $$ = $3;
@ -1874,7 +1869,7 @@ obj_messageexpr
; ;
receiver receiver
: fexpr : expr
| CLASS_NAME | CLASS_NAME
{ {
$$ = new_symbol_expr ($1); $$ = 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; int i;
expr_t *range = binary_expr ('-', tree->high, tree->low); expr_t *range = binary_expr ('-', tree->high, tree->low);
range = fold_constants (range);
table_init = new_block_expr (); table_init = new_block_expr ();
for (i = 0; i <= high - low; i++) { for (i = 0; i <= high - low; i++) {
tree->labels[i]->e.label.used++; tree->labels[i]->e.label.used++;