mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
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:
parent
d1823e2e17
commit
fd04b1aef6
10 changed files with 81 additions and 41 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
9
libyasm/tests/equ-expand.asm
Normal file
9
libyasm/tests/equ-expand.asm
Normal 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
|
||||
10
libyasm/tests/equ-expand.hex
Normal file
10
libyasm/tests/equ-expand.hex
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
90
|
||||
83
|
||||
fb
|
||||
42
|
||||
83
|
||||
fb
|
||||
42
|
||||
83
|
||||
fb
|
||||
42
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue