Don't mix EQU expansion with other expr leveling; we could get confused

with certain combinations.
(2nd half of #83)

This also hides some internals of yasm_expr_level_tree.

svn path=/trunk/yasm/; revision=1655
This commit is contained in:
Peter Johnson 2006-10-18 05:36:51 +00:00
parent d1823e2e17
commit fd04b1aef6
10 changed files with 81 additions and 41 deletions

View file

@ -205,7 +205,7 @@ bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
if (op->data.ea)
op->data.ea->disp.abs =
yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
0, NULL, NULL, NULL);
0, NULL, NULL);
if (yasm_error_occurred()) {
/* Add a pointer to where it was used to the error */
yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
@ -222,7 +222,7 @@ bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
break;
case YASM_INSN__OPERAND_IMM:
op->data.val =
yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL, NULL,
yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
NULL);
if (yasm_error_occurred()) {
/* Add a pointer to where it was used to the error */

View file

@ -357,7 +357,7 @@ yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
my_cbd.cbd = cbd;
my_cbd.subst = 0;
*ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
&my_cbd, NULL);
&my_cbd);
return my_cbd.subst;
}
@ -799,32 +799,24 @@ expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
}
/*@=mustfree@*/
typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
typedef struct yasm__exprentry {
/*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
/*@null@*/ const yasm_expr *e;
} yasm__exprentry;
/* Level an entire expn tree, expanding equ's as we go */
yasm_expr *
yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
int simplify_reg_mul, int calc_bc_dist,
yasm_expr_xform_func expr_xform_extra,
void *expr_xform_extra_data, yasm__exprhead *eh)
static yasm_expr *
expr_expand_equ(yasm_expr *e, yasm__exprhead *eh)
{
int i;
yasm__exprhead eh_local;
yasm__exprentry ee;
if (!e)
return 0;
if (!eh) {
eh = &eh_local;
SLIST_INIT(eh);
}
e = expr_xform_neg(e);
ee.e = NULL;
/* traverse terms */
@ -853,12 +845,9 @@ yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
}
}
/* Recurse */
if (e->terms[i].type == YASM_EXPR_EXPR)
e->terms[i].data.expn =
yasm_expr__level_tree(e->terms[i].data.expn, fold_const,
simplify_ident, simplify_reg_mul,
calc_bc_dist, expr_xform_extra,
expr_xform_extra_data, eh);
e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
if (ee.e) {
SLIST_REMOVE_HEAD(eh, next);
@ -866,6 +855,29 @@ yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
}
}
return e;
}
static yasm_expr *
expr_level_tree(yasm_expr *e, int fold_const, int simplify_ident,
int simplify_reg_mul, int calc_bc_dist,
yasm_expr_xform_func expr_xform_extra,
void *expr_xform_extra_data)
{
int i;
e = expr_xform_neg(e);
/* traverse terms */
for (i=0; i<e->numterms; i++) {
/* Recurse */
if (e->terms[i].type == YASM_EXPR_EXPR)
e->terms[i].data.expn =
expr_level_tree(e->terms[i].data.expn, fold_const,
simplify_ident, simplify_reg_mul, calc_bc_dist,
expr_xform_extra, expr_xform_extra_data);
}
/* Check for SEG of SEG:OFF, if we match, simplify to just the segment */
if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR &&
e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) {
@ -882,12 +894,29 @@ yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
e = expr_xform_bc_dist(e);
if (expr_xform_extra)
e = expr_xform_extra(e, expr_xform_extra_data);
e = yasm_expr__level_tree(e, fold_const, simplify_ident,
simplify_reg_mul, 0, NULL, NULL, NULL);
e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
0, NULL, NULL);
}
return e;
}
/* Level an entire expn tree, expanding equ's as we go */
yasm_expr *
yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
int simplify_reg_mul, int calc_bc_dist,
yasm_expr_xform_func expr_xform_extra,
void *expr_xform_extra_data)
{
if (!e)
return 0;
e = expr_expand_equ(e, NULL);
e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
calc_bc_dist, expr_xform_extra, expr_xform_extra_data);
return e;
}
/* Comparison function for expr_order_terms().
* Assumes ExprType enum is in canonical order.
*/

View file

@ -139,15 +139,6 @@ int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op);
typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func)
(/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d);
/** Linked list of expression entries.
* \internal
* Used internally by yasm_expr__level_tree().
*/
typedef struct yasm__exprhead yasm__exprhead;
#ifdef YASM_LIB_INTERNAL
SLIST_HEAD(yasm__exprhead, yasm__exprentry);
#endif
/** Level an entire expression tree.
* \internal
* \param e expression
@ -165,7 +156,7 @@ SLIST_HEAD(yasm__exprhead, yasm__exprentry);
(/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
/*@null@*/ yasm_expr_xform_func expr_xform_extra,
/*@null@*/ void *expr_xform_extra_data, /*@null@*/ yasm__exprhead *eh);
/*@null@*/ void *expr_xform_extra_data);
/** Simplify an expression as much as possible. Eliminates extraneous
* branches and simplifies integer-only subexpressions. Simplified version
@ -175,7 +166,7 @@ SLIST_HEAD(yasm__exprhead, yasm__exprentry);
* \return Simplified expression.
*/
#define yasm_expr_simplify(e, cbd) \
yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL, NULL)
yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL)
/** Extract the segment portion of an expression containing SEG:OFF, leaving
* the offset.

View file

@ -18,6 +18,8 @@ EXTRA_DIST += libyasm/tests/duplabel-err.asm
EXTRA_DIST += libyasm/tests/duplabel-err.errwarn
EXTRA_DIST += libyasm/tests/emptydata.asm
EXTRA_DIST += libyasm/tests/emptydata.hex
EXTRA_DIST += libyasm/tests/equ-expand.asm
EXTRA_DIST += libyasm/tests/equ-expand.hex
EXTRA_DIST += libyasm/tests/expr-wide-ident.asm
EXTRA_DIST += libyasm/tests/expr-wide-ident.hex
EXTRA_DIST += libyasm/tests/externdef.asm

View file

@ -0,0 +1,9 @@
nop
end1:
line_out equ end1+258 ;length = 1 + 263
real_end equ end1+258+264
cmp bx,(real_end-line_out)/4
cmp bx,((end1+258+264)-(end1+258))/4
cmp bx,(end1+258+264-end1-258)/4

View file

@ -0,0 +1,10 @@
90
83
fb
42
83
fb
42
83
fb
42

View file

@ -431,8 +431,9 @@ yasm_value_finalize_expr(yasm_value *value, yasm_expr *e, unsigned int size)
return 0;
}
yasm_value_initialize(value, yasm_expr__level_tree
(e, 1, 1, 0, 0, NULL, NULL, NULL), size);
yasm_value_initialize(value,
yasm_expr__level_tree(e, 1, 1, 0, 0, NULL, NULL),
size);
/* quit early if there was an issue in simplify() */
if (yasm_error_occurred())
@ -473,8 +474,7 @@ yasm_value_finalize_expr(yasm_value *value, yasm_expr *e, unsigned int size)
if (value_finalize_scan(value, value->abs, 0))
return 1;
value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL,
NULL);
value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
/* Simplify 0 in abs to NULL */
if (value->abs->op == YASM_EXPR_IDENT

View file

@ -259,7 +259,7 @@ x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
yasm_expr *e, *wrt;
/*@-unqualifiedtrans@*/
*ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL, NULL, NULL);
*ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL, NULL);
/* Check for WRT rip first */
wrt = yasm_expr_extract_wrt(ep);
@ -295,7 +295,7 @@ x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
case 2:
/* Need to simplify again */
*ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL,
NULL, NULL);
NULL);
e = *ep;
break;
default:

View file

@ -157,7 +157,7 @@ bin_objfmt_output_value(yasm_value *value, unsigned char *buf, size_t destsize,
/* Simplify absolute portion of value, transforming symrecs */
if (value->abs)
value->abs = yasm_expr__level_tree
(value->abs, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL, NULL);
(value->abs, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL);
/* Output */
switch (yasm_value_output_basic(value, buf, destsize, bc, warn,

View file

@ -43,11 +43,10 @@ cdef extern from "libyasm/expr.h":
cdef int yasm_expr_is_op(yasm_expr *e, yasm_expr_op op)
ctypedef yasm_expr * (*yasm_expr_xform_func) (yasm_expr *e, void *d)
cdef struct yasm__exprhead
cdef yasm_expr *yasm_expr__level_tree(yasm_expr *e, int fold_const,
int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
yasm_expr_xform_func expr_xform_extra,
void *expr_xform_extra_data, yasm__exprhead *eh, int *error)
void *expr_xform_extra_data)
cdef yasm_expr *yasm_expr_simplify(yasm_expr *e, int calc_bc_dist)
cdef yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep)
cdef yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep)