with certain combinations.
(2nd half of #83)
This also hides some internals of yasm_expr_level_tree.
svn path=/trunk/yasm/; revision=1655
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);
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 */
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;
}
}
/*@=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 */
}
}
+ /* 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);
}
}
+ 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) {
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.
*/
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
(/*@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
* \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.
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
--- /dev/null
+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
--- /dev/null
+90
+83
+fb
+42
+83
+fb
+42
+83
+fb
+42
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())
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
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);
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:
/* 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,
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)