• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Expression handling
3  *
4  *  Copyright (C) 2001-2007  Michael Urman, Peter Johnson
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include "util.h"
28 
29 #include "libyasm-stdint.h"
30 #include "coretype.h"
31 #include "bitvect.h"
32 
33 #include "errwarn.h"
34 #include "intnum.h"
35 #include "floatnum.h"
36 #include "expr.h"
37 #include "symrec.h"
38 
39 #include "bytecode.h"
40 #include "section.h"
41 
42 #include "arch.h"
43 
44 
45 static /*@only@*/ yasm_expr *expr_level_op
46     (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
47      int simplify_ident, int simplify_reg_mul);
48 static int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e,
49                                     /*@null@*/ void *d,
50                                     int (*func) (/*@null@*/ yasm_expr *e,
51                                                  /*@null@*/ void *d));
52 static void expr_delete_term(yasm_expr__item *term, int recurse);
53 
54 /* Bitmap of used items.  We should really never need more than 2 at a time,
55  * so 31 is pretty much overkill.
56  */
57 static unsigned long itempool_used = 0;
58 static yasm_expr__item itempool[31];
59 
60 /* allocate a new expression node, with children as defined.
61  * If it's a unary operator, put the element in left and set right=NULL. */
62 /*@-compmempass@*/
63 yasm_expr *
yasm_expr_create(yasm_expr_op op,yasm_expr__item * left,yasm_expr__item * right,unsigned long line)64 yasm_expr_create(yasm_expr_op op, yasm_expr__item *left,
65                  yasm_expr__item *right, unsigned long line)
66 {
67     yasm_expr *ptr, *sube;
68     unsigned long z;
69     ptr = yasm_xmalloc(sizeof(yasm_expr));
70 
71     ptr->op = op;
72     ptr->numterms = 0;
73     ptr->terms[0].type = YASM_EXPR_NONE;
74     ptr->terms[1].type = YASM_EXPR_NONE;
75     if (left) {
76         ptr->terms[0] = *left;  /* structure copy */
77         z = (unsigned long)(left-itempool);
78         if (z>=31)
79             yasm_internal_error(N_("could not find expritem in pool"));
80         itempool_used &= ~(1<<z);
81         ptr->numterms++;
82 
83         /* Search downward until we find something *other* than an
84          * IDENT, then bring it up to the current level.
85          */
86         while (ptr->terms[0].type == YASM_EXPR_EXPR &&
87                ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) {
88             sube = ptr->terms[0].data.expn;
89             ptr->terms[0] = sube->terms[0];     /* structure copy */
90             /*@-usereleased@*/
91             yasm_xfree(sube);
92             /*@=usereleased@*/
93         }
94     } else {
95         yasm_internal_error(N_("Right side of expression must exist"));
96     }
97 
98     if (right) {
99         ptr->terms[1] = *right; /* structure copy */
100         z = (unsigned long)(right-itempool);
101         if (z>=31)
102             yasm_internal_error(N_("could not find expritem in pool"));
103         itempool_used &= ~(1<<z);
104         ptr->numterms++;
105 
106         /* Search downward until we find something *other* than an
107          * IDENT, then bring it up to the current level.
108          */
109         while (ptr->terms[1].type == YASM_EXPR_EXPR &&
110                ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) {
111             sube = ptr->terms[1].data.expn;
112             ptr->terms[1] = sube->terms[0];     /* structure copy */
113             /*@-usereleased@*/
114             yasm_xfree(sube);
115             /*@=usereleased@*/
116         }
117     }
118 
119     ptr->line = line;
120 
121     return expr_level_op(ptr, 1, 1, 0);
122 }
123 /*@=compmempass@*/
124 
125 /* helpers */
126 static yasm_expr__item *
expr_get_item(void)127 expr_get_item(void)
128 {
129     int z = 0;
130     unsigned long v = itempool_used & 0x7fffffff;
131 
132     while (v & 1) {
133         v >>= 1;
134         z++;
135     }
136     if (z>=31)
137         yasm_internal_error(N_("too many expritems"));
138     itempool_used |= 1<<z;
139     return &itempool[z];
140 }
141 
142 yasm_expr__item *
yasm_expr_precbc(yasm_bytecode * precbc)143 yasm_expr_precbc(yasm_bytecode *precbc)
144 {
145     yasm_expr__item *e = expr_get_item();
146     e->type = YASM_EXPR_PRECBC;
147     e->data.precbc = precbc;
148     return e;
149 }
150 
151 yasm_expr__item *
yasm_expr_sym(yasm_symrec * s)152 yasm_expr_sym(yasm_symrec *s)
153 {
154     yasm_expr__item *e = expr_get_item();
155     e->type = YASM_EXPR_SYM;
156     e->data.sym = s;
157     return e;
158 }
159 
160 yasm_expr__item *
yasm_expr_expr(yasm_expr * x)161 yasm_expr_expr(yasm_expr *x)
162 {
163     yasm_expr__item *e = expr_get_item();
164     e->type = YASM_EXPR_EXPR;
165     e->data.expn = x;
166     return e;
167 }
168 
169 yasm_expr__item *
yasm_expr_int(yasm_intnum * i)170 yasm_expr_int(yasm_intnum *i)
171 {
172     yasm_expr__item *e = expr_get_item();
173     e->type = YASM_EXPR_INT;
174     e->data.intn = i;
175     return e;
176 }
177 
178 yasm_expr__item *
yasm_expr_float(yasm_floatnum * f)179 yasm_expr_float(yasm_floatnum *f)
180 {
181     yasm_expr__item *e = expr_get_item();
182     e->type = YASM_EXPR_FLOAT;
183     e->data.flt = f;
184     return e;
185 }
186 
187 yasm_expr__item *
yasm_expr_reg(uintptr_t reg)188 yasm_expr_reg(uintptr_t reg)
189 {
190     yasm_expr__item *e = expr_get_item();
191     e->type = YASM_EXPR_REG;
192     e->data.reg = reg;
193     return e;
194 }
195 
196 /* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single
197  * expritems if possible.  Uses a simple n^2 algorithm because n is usually
198  * quite small.  Also works for precbc-precbc (or symrec-precbc,
199  * precbc-symrec).
200  */
201 static /*@only@*/ yasm_expr *
expr_xform_bc_dist_base(yasm_expr * e,void * cbd,int (* callback)(yasm_expr__item * ei,yasm_bytecode * precbc,yasm_bytecode * precbc2,void * cbd))202 expr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e,
203                         /*@null@*/ void *cbd,
204                         int (*callback) (yasm_expr__item *ei,
205                                          yasm_bytecode *precbc,
206                                          yasm_bytecode *precbc2,
207                                          void *cbd))
208 {
209     int i;
210     /*@dependent@*/ yasm_section *sect;
211     /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
212     int numterms;
213 
214     /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and
215      * symrec term pairs (where both symrecs are in the same segment).
216      */
217     if (e->op != YASM_EXPR_ADD)
218         return e;
219 
220     for (i=0; i<e->numterms; i++) {
221         int j;
222         yasm_expr *sube;
223         yasm_intnum *intn;
224         yasm_symrec *sym = NULL;
225         /*@dependent@*/ yasm_section *sect2;
226         /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
227 
228         /* First look for an (-1*symrec) term */
229         if (e->terms[i].type != YASM_EXPR_EXPR)
230             continue;
231         sube = e->terms[i].data.expn;
232         if (sube->op != YASM_EXPR_MUL || sube->numterms != 2)
233             continue;
234 
235         if (sube->terms[0].type == YASM_EXPR_INT &&
236             (sube->terms[1].type == YASM_EXPR_SYM ||
237              sube->terms[1].type == YASM_EXPR_PRECBC)) {
238             intn = sube->terms[0].data.intn;
239             if (sube->terms[1].type == YASM_EXPR_PRECBC)
240                 precbc = sube->terms[1].data.precbc;
241             else
242                 sym = sube->terms[1].data.sym;
243         } else if ((sube->terms[0].type == YASM_EXPR_SYM ||
244                     sube->terms[0].type == YASM_EXPR_PRECBC) &&
245                    sube->terms[1].type == YASM_EXPR_INT) {
246             if (sube->terms[0].type == YASM_EXPR_PRECBC)
247                 precbc = sube->terms[0].data.precbc;
248             else
249                 sym = sube->terms[0].data.sym;
250             intn = sube->terms[1].data.intn;
251         } else
252             continue;
253 
254         if (!yasm_intnum_is_neg1(intn))
255             continue;
256 
257         if (sym && !yasm_symrec_get_label(sym, &precbc))
258             continue;
259         sect2 = yasm_bc_get_section(precbc);
260 
261         /* Now look for a symrec term in the same segment */
262         for (j=0; j<e->numterms; j++) {
263             if (((e->terms[j].type == YASM_EXPR_SYM &&
264                   yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) ||
265                  (e->terms[j].type == YASM_EXPR_PRECBC &&
266                   (precbc2 = e->terms[j].data.precbc))) &&
267                 (sect = yasm_bc_get_section(precbc2)) &&
268                 sect == sect2 &&
269                 callback(&e->terms[j], precbc, precbc2, cbd)) {
270                 /* Delete the matching (-1*symrec) term */
271                 yasm_expr_destroy(sube);
272                 e->terms[i].type = YASM_EXPR_NONE;
273                 break;  /* stop looking for matching symrec term */
274             }
275         }
276     }
277 
278     /* Clean up any deleted (EXPR_NONE) terms */
279     numterms = 0;
280     for (i=0; i<e->numterms; i++) {
281         if (e->terms[i].type != YASM_EXPR_NONE)
282             e->terms[numterms++] = e->terms[i]; /* structure copy */
283     }
284     if (e->numterms != numterms) {
285         e->numterms = numterms;
286         e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 :
287                           sizeof(yasm_expr__item)*(numterms-2)));
288         if (numterms == 1)
289             e->op = YASM_EXPR_IDENT;
290     }
291 
292     return e;
293 }
294 
295 static int
expr_xform_bc_dist_cb(yasm_expr__item * ei,yasm_bytecode * precbc,yasm_bytecode * precbc2,void * d)296 expr_xform_bc_dist_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
297                       yasm_bytecode *precbc2, /*@null@*/ void *d)
298 {
299     yasm_intnum *dist = yasm_calc_bc_dist(precbc, precbc2);
300     if (!dist)
301         return 0;
302     /* Change the term to an integer */
303     ei->type = YASM_EXPR_INT;
304     ei->data.intn = dist;
305     return 1;
306 }
307 
308 /* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into integers if
309  * possible.
310  */
311 static /*@only@*/ yasm_expr *
expr_xform_bc_dist(yasm_expr * e)312 expr_xform_bc_dist(/*@returned@*/ /*@only@*/ yasm_expr *e)
313 {
314     return expr_xform_bc_dist_base(e, NULL, expr_xform_bc_dist_cb);
315 }
316 
317 typedef struct bc_dist_subst_cbd {
318     void (*callback) (unsigned int subst, yasm_bytecode *precbc,
319                       yasm_bytecode *precbc2, void *cbd);
320     void *cbd;
321     unsigned int subst;
322 } bc_dist_subst_cbd;
323 
324 static int
expr_bc_dist_subst_cb(yasm_expr__item * ei,yasm_bytecode * precbc,yasm_bytecode * precbc2,void * d)325 expr_bc_dist_subst_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
326                       yasm_bytecode *precbc2, /*@null@*/ void *d)
327 {
328     bc_dist_subst_cbd *my_cbd = d;
329     assert(my_cbd != NULL);
330     /* Call higher-level callback */
331     my_cbd->callback(my_cbd->subst, precbc, precbc2, my_cbd->cbd);
332     /* Change the term to an subst */
333     ei->type = YASM_EXPR_SUBST;
334     ei->data.subst = my_cbd->subst;
335     my_cbd->subst++;
336     return 1;
337 }
338 
339 static yasm_expr *
expr_xform_bc_dist_subst(yasm_expr * e,void * d)340 expr_xform_bc_dist_subst(yasm_expr *e, void *d)
341 {
342     return expr_xform_bc_dist_base(e, d, expr_bc_dist_subst_cb);
343 }
344 
345 int
yasm_expr__bc_dist_subst(yasm_expr ** ep,void * cbd,void (* callback)(unsigned int subst,yasm_bytecode * precbc,yasm_bytecode * precbc2,void * cbd))346 yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
347                          void (*callback) (unsigned int subst,
348                                            yasm_bytecode *precbc,
349                                            yasm_bytecode *precbc2,
350                                            void *cbd))
351 {
352     bc_dist_subst_cbd my_cbd;   /* callback info for low-level callback */
353     my_cbd.callback = callback;
354     my_cbd.cbd = cbd;
355     my_cbd.subst = 0;
356     *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
357                                 &my_cbd);
358     return my_cbd.subst;
359 }
360 
361 /* Negate just a single ExprItem by building a -1*ei subexpression */
362 static void
expr_xform_neg_item(yasm_expr * e,yasm_expr__item * ei)363 expr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei)
364 {
365     yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr));
366 
367     /* Build -1*ei subexpression */
368     sube->op = YASM_EXPR_MUL;
369     sube->line = e->line;
370     sube->numterms = 2;
371     sube->terms[0].type = YASM_EXPR_INT;
372     sube->terms[0].data.intn = yasm_intnum_create_int(-1);
373     sube->terms[1] = *ei;       /* structure copy */
374 
375     /* Replace original ExprItem with subexp */
376     ei->type = YASM_EXPR_EXPR;
377     ei->data.expn = sube;
378 }
379 
380 /* Negates e by multiplying by -1, with distribution over lower-precedence
381  * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and
382  * others.
383  *
384  * Returns a possibly reallocated e.
385  */
386 static /*@only@*/ yasm_expr *
expr_xform_neg_helper(yasm_expr * e)387 expr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e)
388 {
389     yasm_expr *ne;
390     int i;
391 
392     switch (e->op) {
393         case YASM_EXPR_ADD:
394             /* distribute (recursively if expr) over terms */
395             for (i=0; i<e->numterms; i++) {
396                 if (e->terms[i].type == YASM_EXPR_EXPR)
397                     e->terms[i].data.expn =
398                         expr_xform_neg_helper(e->terms[i].data.expn);
399                 else
400                     expr_xform_neg_item(e, &e->terms[i]);
401             }
402             break;
403         case YASM_EXPR_SUB:
404             /* change op to ADD, and recursively negate left side (if expr) */
405             e->op = YASM_EXPR_ADD;
406             if (e->terms[0].type == YASM_EXPR_EXPR)
407                 e->terms[0].data.expn =
408                     expr_xform_neg_helper(e->terms[0].data.expn);
409             else
410                 expr_xform_neg_item(e, &e->terms[0]);
411             break;
412         case YASM_EXPR_NEG:
413             /* Negating a negated value?  Make it an IDENT. */
414             e->op = YASM_EXPR_IDENT;
415             break;
416         case YASM_EXPR_IDENT:
417             /* Negating an ident?  Change it into a MUL w/ -1 if there's no
418              * floatnums present below; if there ARE floatnums, recurse.
419              */
420             if (e->terms[0].type == YASM_EXPR_FLOAT)
421                 yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL);
422             else if (e->terms[0].type == YASM_EXPR_INT)
423                 yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL);
424             else if (e->terms[0].type == YASM_EXPR_EXPR &&
425                 yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT))
426                     expr_xform_neg_helper(e->terms[0].data.expn);
427             else {
428                 e->op = YASM_EXPR_MUL;
429                 e->numterms = 2;
430                 e->terms[1].type = YASM_EXPR_INT;
431                 e->terms[1].data.intn = yasm_intnum_create_int(-1);
432             }
433             break;
434         default:
435             /* Everything else.  MUL will be combined when it's leveled.
436              * Make a new expr (to replace e) with -1*e.
437              */
438             ne = yasm_xmalloc(sizeof(yasm_expr));
439             ne->op = YASM_EXPR_MUL;
440             ne->line = e->line;
441             ne->numterms = 2;
442             ne->terms[0].type = YASM_EXPR_INT;
443             ne->terms[0].data.intn = yasm_intnum_create_int(-1);
444             ne->terms[1].type = YASM_EXPR_EXPR;
445             ne->terms[1].data.expn = e;
446             return ne;
447     }
448     return e;
449 }
450 
451 /* Transforms negatives into expressions that are easier to combine:
452  * -x -> -1*x
453  * a-b -> a+(-1*b)
454  *
455  * Call post-order on an expression tree to transform the entire tree.
456  *
457  * Returns a possibly reallocated e.
458  */
459 static /*@only@*/ yasm_expr *
expr_xform_neg(yasm_expr * e)460 expr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e)
461 {
462     switch (e->op) {
463         case YASM_EXPR_NEG:
464             /* Turn -x into -1*x */
465             e->op = YASM_EXPR_IDENT;
466             return expr_xform_neg_helper(e);
467         case YASM_EXPR_SUB:
468             /* Turn a-b into a+(-1*b) */
469 
470             /* change op to ADD, and recursively negate right side (if expr) */
471             e->op = YASM_EXPR_ADD;
472             if (e->terms[1].type == YASM_EXPR_EXPR)
473                 e->terms[1].data.expn =
474                     expr_xform_neg_helper(e->terms[1].data.expn);
475             else
476                 expr_xform_neg_item(e, &e->terms[1]);
477             break;
478         default:
479             break;
480     }
481 
482     return e;
483 }
484 
485 /* Look for simple identities that make the entire result constant:
486  * 0*&x, -1|x, etc.
487  */
488 static int
expr_is_constant(yasm_expr_op op,yasm_intnum * intn)489 expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
490 {
491     int iszero = yasm_intnum_is_zero(intn);
492     return ((iszero && op == YASM_EXPR_MUL) ||
493             (iszero && op == YASM_EXPR_AND) ||
494             (iszero && op == YASM_EXPR_LAND) ||
495             (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_OR));
496 }
497 
498 /* Look for simple "left" identities like 0+x, 1*x, etc. */
499 static int
expr_can_destroy_int_left(yasm_expr_op op,yasm_intnum * intn)500 expr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn)
501 {
502     int iszero = yasm_intnum_is_zero(intn);
503     return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) ||
504             (iszero && op == YASM_EXPR_ADD) ||
505             (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
506             (!iszero && op == YASM_EXPR_LAND) ||
507             (iszero && op == YASM_EXPR_OR) ||
508             (iszero && op == YASM_EXPR_LOR));
509 }
510 
511 /* Look for simple "right" identities like x+|-0, x*&/1 */
512 static int
expr_can_destroy_int_right(yasm_expr_op op,yasm_intnum * intn)513 expr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn)
514 {
515     int iszero = yasm_intnum_is_zero(intn);
516     int ispos1 = yasm_intnum_is_pos1(intn);
517     return ((ispos1 && op == YASM_EXPR_MUL) ||
518             (ispos1 && op == YASM_EXPR_DIV) ||
519             (iszero && op == YASM_EXPR_ADD) ||
520             (iszero && op == YASM_EXPR_SUB) ||
521             (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
522             (!iszero && op == YASM_EXPR_LAND) ||
523             (iszero && op == YASM_EXPR_OR) ||
524             (iszero && op == YASM_EXPR_LOR) ||
525             (iszero && op == YASM_EXPR_SHL) ||
526             (iszero && op == YASM_EXPR_SHR));
527 }
528 
529 /* Check for and simplify identities.  Returns new number of expr terms.
530  * Sets e->op = EXPR_IDENT if numterms ends up being 1.
531  * Uses numterms parameter instead of e->numterms for basis of "new" number
532  * of terms.
533  * Assumes int_term is *only* integer term in e.
534  * NOTE: Really designed to only be used by expr_level_op().
535  */
536 static int
expr_simplify_identity(yasm_expr * e,int numterms,int * int_term,int simplify_reg_mul)537 expr_simplify_identity(yasm_expr *e, int numterms, int *int_term,
538                        int simplify_reg_mul)
539 {
540     int i;
541     int save_numterms;
542 
543     /* Don't do this step if it's 1*REG.  Save and restore numterms so
544      * yasm_expr__contains() works correctly.
545      */
546     save_numterms = e->numterms;
547     e->numterms = numterms;
548     if (simplify_reg_mul || e->op != YASM_EXPR_MUL
549         || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn)
550         || !yasm_expr__contains(e, YASM_EXPR_REG)) {
551         /* Check for simple identities that delete the intnum.
552          * Don't delete if the intnum is the only thing in the expn.
553          */
554         if ((*int_term == 0 && numterms > 1 &&
555              expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) ||
556             (*int_term > 0 &&
557              expr_can_destroy_int_right(e->op,
558                                         e->terms[*int_term].data.intn))) {
559             /* Delete the intnum */
560             yasm_intnum_destroy(e->terms[*int_term].data.intn);
561 
562             /* Slide everything to its right over by 1 */
563             if (*int_term != numterms-1) /* if it wasn't last.. */
564                 memmove(&e->terms[*int_term], &e->terms[*int_term+1],
565                         (numterms-1-*int_term)*sizeof(yasm_expr__item));
566 
567             /* Update numterms */
568             numterms--;
569             *int_term = -1;     /* no longer an int term */
570         }
571     }
572     e->numterms = save_numterms;
573 
574     /* Check for simple identites that delete everything BUT the intnum.
575      * Don't bother if the intnum is the only thing in the expn.
576      */
577     if (numterms > 1 && *int_term != -1 &&
578         expr_is_constant(e->op, e->terms[*int_term].data.intn)) {
579         /* Loop through, deleting everything but the integer term */
580         for (i=0; i<e->numterms; i++)
581             if (i != *int_term)
582                 expr_delete_term(&e->terms[i], 1);
583 
584         /* Move integer term to the first term (if not already there) */
585         if (*int_term != 0)
586             e->terms[0] = e->terms[*int_term];  /* structure copy */
587 
588         /* Set numterms to 1 */
589         numterms = 1;
590     }
591 
592     /* Compute NOT, NEG, and LNOT on single intnum. */
593     if (numterms == 1 && *int_term == 0 &&
594         (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG ||
595          e->op == YASM_EXPR_LNOT))
596         yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL);
597 
598     /* Change expression to IDENT if possible. */
599     if (numterms == 1)
600         e->op = YASM_EXPR_IDENT;
601 
602     /* Return the updated numterms */
603     return numterms;
604 }
605 
606 /* Levels the expression tree starting at e.  Eg:
607  * a+(b+c) -> a+b+c
608  * (a+b)+(c+d) -> a+b+c+d
609  * Naturally, only levels operators that allow more than two operand terms.
610  * NOTE: only does *one* level of leveling (no recursion).  Should be called
611  *  post-order on a tree to combine deeper levels.
612  * Also brings up any IDENT values into the current level (for ALL operators).
613  * Folds (combines by evaluation) *integer* constant values if fold_const != 0.
614  *
615  * Returns a possibly reallocated e.
616  */
617 /*@-mustfree@*/
618 static /*@only@*/ yasm_expr *
expr_level_op(yasm_expr * e,int fold_const,int simplify_ident,int simplify_reg_mul)619 expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
620               int simplify_ident, int simplify_reg_mul)
621 {
622     int i, j, o, fold_numterms, level_numterms, level_fold_numterms;
623     int first_int_term = -1;
624 
625     /* Determine how many operands will need to be brought up (for leveling).
626      * Go ahead and bring up any IDENT'ed values.
627      */
628     while (e->op == YASM_EXPR_IDENT && e->terms[0].type == YASM_EXPR_EXPR) {
629         yasm_expr *sube = e->terms[0].data.expn;
630         yasm_xfree(e);
631         e = sube;
632     }
633 
634     /* If non-numeric expression, don't fold constants. */
635     if (e->op > YASM_EXPR_NONNUM)
636         fold_const = 0;
637 
638     level_numterms = e->numterms;
639     level_fold_numterms = 0;
640     for (i=0; i<e->numterms; i++) {
641         /* Search downward until we find something *other* than an
642          * IDENT, then bring it up to the current level.
643          */
644         while (e->terms[i].type == YASM_EXPR_EXPR &&
645                e->terms[i].data.expn->op == YASM_EXPR_IDENT) {
646             yasm_expr *sube = e->terms[i].data.expn;
647             e->terms[i] = sube->terms[0];
648             yasm_xfree(sube);
649         }
650 
651         if (e->terms[i].type == YASM_EXPR_EXPR &&
652             e->terms[i].data.expn->op == e->op) {
653                 /* It's an expression w/the same operator, add in its numterms.
654                  * But don't forget to subtract one for the expr itself!
655                  */
656                 level_numterms += e->terms[i].data.expn->numterms - 1;
657 
658                 /* If we're folding constants, count up the number of constants
659                  * that will be merged in.
660                  */
661                 if (fold_const)
662                     for (j=0; j<e->terms[i].data.expn->numterms; j++)
663                         if (e->terms[i].data.expn->terms[j].type ==
664                             YASM_EXPR_INT)
665                             level_fold_numterms++;
666         }
667 
668         /* Find the first integer term (if one is present) if we're folding
669          * constants.
670          */
671         if (fold_const && first_int_term == -1 &&
672             e->terms[i].type == YASM_EXPR_INT)
673             first_int_term = i;
674     }
675 
676     /* Look for other integer terms if there's one and combine.
677      * Also eliminate empty spaces when combining and adjust numterms
678      * variables.
679      */
680     fold_numterms = e->numterms;
681     if (first_int_term != -1) {
682         for (i=first_int_term+1, o=first_int_term+1; i<e->numterms; i++) {
683             if (e->terms[i].type == YASM_EXPR_INT) {
684                 yasm_intnum_calc(e->terms[first_int_term].data.intn, e->op,
685                                  e->terms[i].data.intn);
686                 fold_numterms--;
687                 level_numterms--;
688                 /* make sure to delete folded intnum */
689                 yasm_intnum_destroy(e->terms[i].data.intn);
690             } else if (o != i) {
691                 /* copy term if it changed places */
692                 e->terms[o++] = e->terms[i];
693             } else
694                 o++;
695         }
696 
697         if (simplify_ident) {
698             int new_fold_numterms;
699             /* Simplify identities and make IDENT if possible. */
700             new_fold_numterms =
701                 expr_simplify_identity(e, fold_numterms, &first_int_term,
702                                        simplify_reg_mul);
703             level_numterms -= fold_numterms-new_fold_numterms;
704             fold_numterms = new_fold_numterms;
705         }
706         if (fold_numterms == 1)
707             e->op = YASM_EXPR_IDENT;
708     }
709 
710     /* Only level operators that allow more than two operand terms.
711      * Also don't bother leveling if it's not necessary to bring up any terms.
712      */
713     if ((e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL &&
714          e->op != YASM_EXPR_OR && e->op != YASM_EXPR_AND &&
715          e->op != YASM_EXPR_LOR && e->op != YASM_EXPR_LAND &&
716          e->op != YASM_EXPR_LXOR && e->op != YASM_EXPR_XOR) ||
717         level_numterms <= fold_numterms) {
718         /* Downsize e if necessary */
719         if (fold_numterms < e->numterms && e->numterms > 2)
720             e = yasm_xrealloc(e, sizeof(yasm_expr)+((fold_numterms<2) ? 0 :
721                               sizeof(yasm_expr__item)*(fold_numterms-2)));
722         /* Update numterms */
723         e->numterms = fold_numterms;
724         return e;
725     }
726 
727     /* Adjust numterms for constant folding from terms being "pulled up".
728      * Careful: if there's no integer term in e, then save space for it.
729      */
730     if (fold_const) {
731         level_numterms -= level_fold_numterms;
732         if (first_int_term == -1 && level_fold_numterms != 0)
733             level_numterms++;
734     }
735 
736     /* Alloc more (or conceivably less, but not usually) space for e */
737     e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 :
738                       sizeof(yasm_expr__item)*(level_numterms-2)));
739 
740     /* Copy up ExprItem's.  Iterate from right to left to keep the same
741      * ordering as was present originally.
742      * Combine integer terms as necessary.
743      */
744     for (i=fold_numterms-1, o=level_numterms-1; i>=0; i--) {
745         if (e->terms[i].type == YASM_EXPR_EXPR &&
746             e->terms[i].data.expn->op == e->op) {
747             /* bring up subexpression */
748             yasm_expr *sube = e->terms[i].data.expn;
749 
750             /* copy terms right to left */
751             for (j=sube->numterms-1; j>=0; j--) {
752                 if (fold_const && sube->terms[j].type == YASM_EXPR_INT) {
753                     /* Need to fold it in.. but if there's no int term already,
754                      * just copy into a new one.
755                      */
756                     if (first_int_term == -1) {
757                         first_int_term = o--;
758                         e->terms[first_int_term] = sube->terms[j];  /* struc */
759                     } else {
760                         yasm_intnum_calc(e->terms[first_int_term].data.intn,
761                                          e->op, sube->terms[j].data.intn);
762                         /* make sure to delete folded intnum */
763                         yasm_intnum_destroy(sube->terms[j].data.intn);
764                     }
765                 } else {
766                     if (o == first_int_term)
767                         o--;
768                     e->terms[o--] = sube->terms[j];     /* structure copy */
769                 }
770             }
771 
772             /* delete subexpression, but *don't delete nodes* (as we've just
773              * copied them!)
774              */
775             yasm_xfree(sube);
776         } else if (o != i) {
777             /* copy operand if it changed places */
778             if (o == first_int_term)
779                 o--;
780             e->terms[o] = e->terms[i];
781             /* If we moved the first_int_term, change first_int_num too */
782             if (i == first_int_term)
783                 first_int_term = o;
784             o--;
785         } else
786             o--;
787     }
788 
789     /* Simplify identities, make IDENT if possible, and save to e->numterms. */
790     if (simplify_ident && first_int_term != -1) {
791         e->numterms = expr_simplify_identity(e, level_numterms,
792                                              &first_int_term, simplify_reg_mul);
793     } else {
794         e->numterms = level_numterms;
795         if (level_numterms == 1)
796             e->op = YASM_EXPR_IDENT;
797     }
798 
799     return e;
800 }
801 /*@=mustfree@*/
802 
803 typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
804 typedef struct yasm__exprentry {
805     /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
806     /*@null@*/ const yasm_expr *e;
807 } yasm__exprentry;
808 
809 static yasm_expr *
expr_expand_equ(yasm_expr * e,yasm__exprhead * eh)810 expr_expand_equ(yasm_expr *e, yasm__exprhead *eh)
811 {
812     int i;
813     yasm__exprentry ee;
814 
815     /* traverse terms */
816     for (i=0; i<e->numterms; i++) {
817         const yasm_expr *equ_expr;
818 
819         /* Expand equ's. */
820         if (e->terms[i].type == YASM_EXPR_SYM &&
821             (equ_expr = yasm_symrec_get_equ(e->terms[i].data.sym))) {
822             yasm__exprentry *np;
823 
824             /* Check for circular reference */
825             SLIST_FOREACH(np, eh, next) {
826                 if (np->e == equ_expr) {
827                     yasm_error_set(YASM_ERROR_TOO_COMPLEX,
828                                    N_("circular reference detected"));
829                     return e;
830                 }
831             }
832 
833             e->terms[i].type = YASM_EXPR_EXPR;
834             e->terms[i].data.expn = yasm_expr_copy(equ_expr);
835 
836             /* Remember we saw this equ and recurse */
837             ee.e = equ_expr;
838             SLIST_INSERT_HEAD(eh, &ee, next);
839             e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
840             SLIST_REMOVE_HEAD(eh, next);
841         } else if (e->terms[i].type == YASM_EXPR_EXPR)
842             /* Recurse */
843             e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
844     }
845 
846     return e;
847 }
848 
849 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)850 expr_level_tree(yasm_expr *e, int fold_const, int simplify_ident,
851                 int simplify_reg_mul, int calc_bc_dist,
852                 yasm_expr_xform_func expr_xform_extra,
853                 void *expr_xform_extra_data)
854 {
855     int i;
856 
857     e = expr_xform_neg(e);
858 
859     /* traverse terms */
860     for (i=0; i<e->numterms; i++) {
861         /* Recurse */
862         if (e->terms[i].type == YASM_EXPR_EXPR)
863             e->terms[i].data.expn =
864                 expr_level_tree(e->terms[i].data.expn, fold_const,
865                                 simplify_ident, simplify_reg_mul, calc_bc_dist,
866                                 expr_xform_extra, expr_xform_extra_data);
867     }
868 
869     /* Check for SEG of SEG:OFF, if we match, simplify to just the segment */
870     if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR &&
871         e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) {
872         e->op = YASM_EXPR_IDENT;
873         e->terms[0].data.expn->op = YASM_EXPR_IDENT;
874         /* Destroy the second (offset) term */
875         e->terms[0].data.expn->numterms = 1;
876         expr_delete_term(&e->terms[0].data.expn->terms[1], 1);
877     }
878 
879     /* do callback */
880     e = expr_level_op(e, fold_const, simplify_ident, simplify_reg_mul);
881     if (calc_bc_dist || expr_xform_extra) {
882         if (calc_bc_dist)
883             e = expr_xform_bc_dist(e);
884         if (expr_xform_extra)
885             e = expr_xform_extra(e, expr_xform_extra_data);
886         e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
887                             0, NULL, NULL);
888     }
889     return e;
890 }
891 
892 /* Level an entire expn tree, expanding equ's as we go */
893 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)894 yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
895                       int simplify_reg_mul, int calc_bc_dist,
896                       yasm_expr_xform_func expr_xform_extra,
897                       void *expr_xform_extra_data)
898 {
899     yasm__exprhead eh;
900     SLIST_INIT(&eh);
901 
902     if (!e)
903         return 0;
904 
905     e = expr_expand_equ(e, &eh);
906     e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
907                         calc_bc_dist, expr_xform_extra, expr_xform_extra_data);
908 
909     return e;
910 }
911 
912 /* Comparison function for expr_order_terms().
913  * Assumes ExprType enum is in canonical order.
914  */
915 static int
expr_order_terms_compare(const void * va,const void * vb)916 expr_order_terms_compare(const void *va, const void *vb)
917 {
918     const yasm_expr__item *a = va, *b = vb;
919     return (a->type - b->type);
920 }
921 
922 /* Reorder terms of e into canonical order.  Only reorders if reordering
923  * doesn't change meaning of expression.  (eg, doesn't reorder SUB).
924  * Canonical order: REG, INT, FLOAT, SYM, EXPR.
925  * Multiple terms of a single type are kept in the same order as in
926  * the original expression.
927  * NOTE: Only performs reordering on *one* level (no recursion).
928  */
929 void
yasm_expr__order_terms(yasm_expr * e)930 yasm_expr__order_terms(yasm_expr *e)
931 {
932     /* don't bother reordering if only one element */
933     if (e->numterms == 1)
934         return;
935 
936     /* only reorder some types of operations */
937     switch (e->op) {
938         case YASM_EXPR_ADD:
939         case YASM_EXPR_MUL:
940         case YASM_EXPR_OR:
941         case YASM_EXPR_AND:
942         case YASM_EXPR_XOR:
943         case YASM_EXPR_LOR:
944         case YASM_EXPR_LAND:
945         case YASM_EXPR_LXOR:
946             /* Use mergesort to sort.  It's fast on already sorted values and a
947              * stable sort (multiple terms of same type are kept in the same
948              * order).
949              */
950             yasm__mergesort(e->terms, (size_t)e->numterms,
951                             sizeof(yasm_expr__item), expr_order_terms_compare);
952             break;
953         default:
954             break;
955     }
956 }
957 
958 static void
expr_item_copy(yasm_expr__item * dest,const yasm_expr__item * src)959 expr_item_copy(yasm_expr__item *dest, const yasm_expr__item *src)
960 {
961     dest->type = src->type;
962     switch (src->type) {
963         case YASM_EXPR_SYM:
964             /* Symbols don't need to be copied */
965             dest->data.sym = src->data.sym;
966             break;
967         case YASM_EXPR_PRECBC:
968             /* Nor do direct bytecode references */
969             dest->data.precbc = src->data.precbc;
970             break;
971         case YASM_EXPR_EXPR:
972             dest->data.expn = yasm_expr__copy_except(src->data.expn, -1);
973             break;
974         case YASM_EXPR_INT:
975             dest->data.intn = yasm_intnum_copy(src->data.intn);
976             break;
977         case YASM_EXPR_FLOAT:
978             dest->data.flt = yasm_floatnum_copy(src->data.flt);
979             break;
980         case YASM_EXPR_REG:
981             dest->data.reg = src->data.reg;
982             break;
983         case YASM_EXPR_SUBST:
984             dest->data.subst = src->data.subst;
985             break;
986         default:
987             break;
988     }
989 }
990 
991 /* Copy entire expression EXCEPT for index "except" at *top level only*. */
992 yasm_expr *
yasm_expr__copy_except(const yasm_expr * e,int except)993 yasm_expr__copy_except(const yasm_expr *e, int except)
994 {
995     yasm_expr *n;
996     int i;
997 
998     n = yasm_xmalloc(sizeof(yasm_expr) +
999                      sizeof(yasm_expr__item)*(e->numterms<2?0:e->numterms-2));
1000 
1001     n->op = e->op;
1002     n->line = e->line;
1003     n->numterms = e->numterms;
1004     for (i=0; i<e->numterms; i++) {
1005         if (i != except)
1006             expr_item_copy(&n->terms[i], &e->terms[i]);
1007     }
1008 
1009     return n;
1010 }
1011 
1012 static void
expr_delete_term(yasm_expr__item * term,int recurse)1013 expr_delete_term(yasm_expr__item *term, int recurse)
1014 {
1015     switch (term->type) {
1016         case YASM_EXPR_INT:
1017             yasm_intnum_destroy(term->data.intn);
1018             break;
1019         case YASM_EXPR_FLOAT:
1020             yasm_floatnum_destroy(term->data.flt);
1021             break;
1022         case YASM_EXPR_EXPR:
1023             if (recurse)
1024                 yasm_expr_destroy(term->data.expn);
1025             break;
1026         default:
1027             break;
1028     }
1029 }
1030 
1031 static int
expr_destroy_each(yasm_expr * e,void * d)1032 expr_destroy_each(/*@only@*/ yasm_expr *e, /*@unused@*/ void *d)
1033 {
1034     int i;
1035     for (i=0; i<e->numterms; i++)
1036         expr_delete_term(&e->terms[i], 0);
1037     yasm_xfree(e);      /* free ourselves */
1038     return 0;   /* don't stop recursion */
1039 }
1040 
1041 /*@-mustfree@*/
1042 void
yasm_expr_destroy(yasm_expr * e)1043 yasm_expr_destroy(yasm_expr *e)
1044 {
1045     expr_traverse_nodes_post(e, NULL, expr_destroy_each);
1046 }
1047 /*@=mustfree@*/
1048 
1049 int
yasm_expr_is_op(const yasm_expr * e,yasm_expr_op op)1050 yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op)
1051 {
1052     return (e->op == op);
1053 }
1054 
1055 static int
expr_contains_callback(const yasm_expr__item * ei,void * d)1056 expr_contains_callback(const yasm_expr__item *ei, void *d)
1057 {
1058     yasm_expr__type *t = d;
1059     return (ei->type & *t);
1060 }
1061 
1062 int
yasm_expr__contains(const yasm_expr * e,yasm_expr__type t)1063 yasm_expr__contains(const yasm_expr *e, yasm_expr__type t)
1064 {
1065     return yasm_expr__traverse_leaves_in_const(e, &t, expr_contains_callback);
1066 }
1067 
1068 typedef struct subst_cbd {
1069     unsigned int num_items;
1070     const yasm_expr__item *items;
1071 } subst_cbd;
1072 
1073 static int
expr_subst_callback(yasm_expr__item * ei,void * d)1074 expr_subst_callback(yasm_expr__item *ei, void *d)
1075 {
1076     subst_cbd *cbd = d;
1077     if (ei->type != YASM_EXPR_SUBST)
1078         return 0;
1079     if (ei->data.subst >= cbd->num_items)
1080         return 1;   /* error */
1081     expr_item_copy(ei, &cbd->items[ei->data.subst]);
1082     return 0;
1083 }
1084 
1085 int
yasm_expr__subst(yasm_expr * e,unsigned int num_items,const yasm_expr__item * items)1086 yasm_expr__subst(yasm_expr *e, unsigned int num_items,
1087                  const yasm_expr__item *items)
1088 {
1089     subst_cbd cbd;
1090     cbd.num_items = num_items;
1091     cbd.items = items;
1092     return yasm_expr__traverse_leaves_in(e, &cbd, expr_subst_callback);
1093 }
1094 
1095 /* Traverse over expression tree, calling func for each operation AFTER the
1096  * branches (if expressions) have been traversed (eg, postorder
1097  * traversal).  The data pointer d is passed to each func call.
1098  *
1099  * Stops early (and returns 1) if func returns 1.  Otherwise returns 0.
1100  */
1101 static int
expr_traverse_nodes_post(yasm_expr * e,void * d,int (* func)(yasm_expr * e,void * d))1102 expr_traverse_nodes_post(yasm_expr *e, void *d,
1103                          int (*func) (/*@null@*/ yasm_expr *e,
1104                                       /*@null@*/ void *d))
1105 {
1106     int i;
1107 
1108     if (!e)
1109         return 0;
1110 
1111     /* traverse terms */
1112     for (i=0; i<e->numterms; i++) {
1113         if (e->terms[i].type == YASM_EXPR_EXPR &&
1114             expr_traverse_nodes_post(e->terms[i].data.expn, d, func))
1115             return 1;
1116     }
1117 
1118     /* do callback */
1119     return func(e, d);
1120 }
1121 
1122 /* Traverse over expression tree in order, calling func for each leaf
1123  * (non-operation).  The data pointer d is passed to each func call.
1124  *
1125  * Stops early (and returns 1) if func returns 1.  Otherwise returns 0.
1126  */
1127 int
yasm_expr__traverse_leaves_in_const(const yasm_expr * e,void * d,int (* func)(const yasm_expr__item * ei,void * d))1128 yasm_expr__traverse_leaves_in_const(const yasm_expr *e, void *d,
1129     int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d))
1130 {
1131     int i;
1132 
1133     if (!e)
1134         return 0;
1135 
1136     for (i=0; i<e->numterms; i++) {
1137         if (e->terms[i].type == YASM_EXPR_EXPR) {
1138             if (yasm_expr__traverse_leaves_in_const(e->terms[i].data.expn, d,
1139                                                     func))
1140                 return 1;
1141         } else {
1142             if (func(&e->terms[i], d))
1143                 return 1;
1144         }
1145     }
1146     return 0;
1147 }
1148 
1149 /* Traverse over expression tree in order, calling func for each leaf
1150  * (non-operation).  The data pointer d is passed to each func call.
1151  *
1152  * Stops early (and returns 1) if func returns 1.  Otherwise returns 0.
1153  */
1154 int
yasm_expr__traverse_leaves_in(yasm_expr * e,void * d,int (* func)(yasm_expr__item * ei,void * d))1155 yasm_expr__traverse_leaves_in(yasm_expr *e, void *d,
1156     int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d))
1157 {
1158     int i;
1159 
1160     if (!e)
1161         return 0;
1162 
1163     for (i=0; i<e->numterms; i++) {
1164         if (e->terms[i].type == YASM_EXPR_EXPR) {
1165             if (yasm_expr__traverse_leaves_in(e->terms[i].data.expn, d, func))
1166                 return 1;
1167         } else {
1168             if (func(&e->terms[i], d))
1169                 return 1;
1170         }
1171     }
1172     return 0;
1173 }
1174 
1175 yasm_expr *
yasm_expr_extract_deep_segoff(yasm_expr ** ep)1176 yasm_expr_extract_deep_segoff(yasm_expr **ep)
1177 {
1178     yasm_expr *retval;
1179     yasm_expr *e = *ep;
1180     int i;
1181 
1182     /* Try to extract at this level */
1183     retval = yasm_expr_extract_segoff(ep);
1184     if (retval)
1185         return retval;
1186 
1187     /* Not at this level?  Search any expr children. */
1188     for (i=0; i<e->numterms; i++) {
1189         if (e->terms[i].type == YASM_EXPR_EXPR) {
1190             retval = yasm_expr_extract_deep_segoff(&e->terms[i].data.expn);
1191             if (retval)
1192                 return retval;
1193         }
1194     }
1195 
1196     /* Didn't find one */
1197     return NULL;
1198 }
1199 
1200 yasm_expr *
yasm_expr_extract_segoff(yasm_expr ** ep)1201 yasm_expr_extract_segoff(yasm_expr **ep)
1202 {
1203     yasm_expr *retval;
1204     yasm_expr *e = *ep;
1205 
1206     /* If not SEG:OFF, we can't do this transformation */
1207     if (e->op != YASM_EXPR_SEGOFF)
1208         return NULL;
1209 
1210     /* Extract the SEG portion out to its own expression */
1211     if (e->terms[0].type == YASM_EXPR_EXPR)
1212         retval = e->terms[0].data.expn;
1213     else {
1214         /* Need to build IDENT expression to hold non-expression contents */
1215         retval = yasm_xmalloc(sizeof(yasm_expr));
1216         retval->op = YASM_EXPR_IDENT;
1217         retval->numterms = 1;
1218         retval->terms[0] = e->terms[0]; /* structure copy */
1219     }
1220 
1221     /* Delete the SEG: portion by changing the expression into an IDENT */
1222     e->op = YASM_EXPR_IDENT;
1223     e->numterms = 1;
1224     e->terms[0] = e->terms[1];  /* structure copy */
1225 
1226     return retval;
1227 }
1228 
1229 yasm_expr *
yasm_expr_extract_wrt(yasm_expr ** ep)1230 yasm_expr_extract_wrt(yasm_expr **ep)
1231 {
1232     yasm_expr *retval;
1233     yasm_expr *e = *ep;
1234 
1235     /* If not WRT, we can't do this transformation */
1236     if (e->op != YASM_EXPR_WRT)
1237         return NULL;
1238 
1239     /* Extract the right side portion out to its own expression */
1240     if (e->terms[1].type == YASM_EXPR_EXPR)
1241         retval = e->terms[1].data.expn;
1242     else {
1243         /* Need to build IDENT expression to hold non-expression contents */
1244         retval = yasm_xmalloc(sizeof(yasm_expr));
1245         retval->op = YASM_EXPR_IDENT;
1246         retval->numterms = 1;
1247         retval->terms[0] = e->terms[1]; /* structure copy */
1248     }
1249 
1250     /* Delete the right side portion by changing the expr into an IDENT */
1251     e->op = YASM_EXPR_IDENT;
1252     e->numterms = 1;
1253 
1254     return retval;
1255 }
1256 
1257 /*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
1258 yasm_intnum *
yasm_expr_get_intnum(yasm_expr ** ep,int calc_bc_dist)1259 yasm_expr_get_intnum(yasm_expr **ep, int calc_bc_dist)
1260 {
1261     *ep = yasm_expr_simplify(*ep, calc_bc_dist);
1262 
1263     if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_INT)
1264         return (*ep)->terms[0].data.intn;
1265     else
1266         return (yasm_intnum *)NULL;
1267 }
1268 /*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
1269 
1270 /*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
1271 const yasm_symrec *
yasm_expr_get_symrec(yasm_expr ** ep,int simplify)1272 yasm_expr_get_symrec(yasm_expr **ep, int simplify)
1273 {
1274     if (simplify)
1275         *ep = yasm_expr_simplify(*ep, 0);
1276 
1277     if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_SYM)
1278         return (*ep)->terms[0].data.sym;
1279     else
1280         return (yasm_symrec *)NULL;
1281 }
1282 /*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
1283 
1284 /*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
1285 const uintptr_t *
yasm_expr_get_reg(yasm_expr ** ep,int simplify)1286 yasm_expr_get_reg(yasm_expr **ep, int simplify)
1287 {
1288     if (simplify)
1289         *ep = yasm_expr_simplify(*ep, 0);
1290 
1291     if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_REG)
1292         return &((*ep)->terms[0].data.reg);
1293     else
1294         return NULL;
1295 }
1296 /*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
1297 
1298 void
yasm_expr_print(const yasm_expr * e,FILE * f)1299 yasm_expr_print(const yasm_expr *e, FILE *f)
1300 {
1301     char opstr[8];
1302     int i;
1303 
1304     if (!e) {
1305         fprintf(f, "(nil)");
1306         return;
1307     }
1308 
1309     switch (e->op) {
1310         case YASM_EXPR_ADD:
1311             strcpy(opstr, "+");
1312             break;
1313         case YASM_EXPR_SUB:
1314             strcpy(opstr, "-");
1315             break;
1316         case YASM_EXPR_MUL:
1317             strcpy(opstr, "*");
1318             break;
1319         case YASM_EXPR_DIV:
1320             strcpy(opstr, "/");
1321             break;
1322         case YASM_EXPR_SIGNDIV:
1323             strcpy(opstr, "//");
1324             break;
1325         case YASM_EXPR_MOD:
1326             strcpy(opstr, "%");
1327             break;
1328         case YASM_EXPR_SIGNMOD:
1329             strcpy(opstr, "%%");
1330             break;
1331         case YASM_EXPR_NEG:
1332             fprintf(f, "-");
1333             opstr[0] = 0;
1334             break;
1335         case YASM_EXPR_NOT:
1336             fprintf(f, "~");
1337             opstr[0] = 0;
1338             break;
1339         case YASM_EXPR_OR:
1340             strcpy(opstr, "|");
1341             break;
1342         case YASM_EXPR_AND:
1343             strcpy(opstr, "&");
1344             break;
1345         case YASM_EXPR_XOR:
1346             strcpy(opstr, "^");
1347             break;
1348         case YASM_EXPR_XNOR:
1349             strcpy(opstr, "XNOR");
1350             break;
1351         case YASM_EXPR_NOR:
1352             strcpy(opstr, "NOR");
1353             break;
1354         case YASM_EXPR_SHL:
1355             strcpy(opstr, "<<");
1356             break;
1357         case YASM_EXPR_SHR:
1358             strcpy(opstr, ">>");
1359             break;
1360         case YASM_EXPR_LOR:
1361             strcpy(opstr, "||");
1362             break;
1363         case YASM_EXPR_LAND:
1364             strcpy(opstr, "&&");
1365             break;
1366         case YASM_EXPR_LNOT:
1367             strcpy(opstr, "!");
1368             break;
1369         case YASM_EXPR_LXOR:
1370             strcpy(opstr, "^^");
1371             break;
1372         case YASM_EXPR_LXNOR:
1373             strcpy(opstr, "LXNOR");
1374             break;
1375         case YASM_EXPR_LNOR:
1376             strcpy(opstr, "LNOR");
1377             break;
1378         case YASM_EXPR_LT:
1379             strcpy(opstr, "<");
1380             break;
1381         case YASM_EXPR_GT:
1382             strcpy(opstr, ">");
1383             break;
1384         case YASM_EXPR_LE:
1385             strcpy(opstr, "<=");
1386             break;
1387         case YASM_EXPR_GE:
1388             strcpy(opstr, ">=");
1389             break;
1390         case YASM_EXPR_NE:
1391             strcpy(opstr, "!=");
1392             break;
1393         case YASM_EXPR_EQ:
1394             strcpy(opstr, "==");
1395             break;
1396         case YASM_EXPR_SEG:
1397             fprintf(f, "SEG ");
1398             opstr[0] = 0;
1399             break;
1400         case YASM_EXPR_WRT:
1401             strcpy(opstr, " WRT ");
1402             break;
1403         case YASM_EXPR_SEGOFF:
1404             strcpy(opstr, ":");
1405             break;
1406         case YASM_EXPR_IDENT:
1407             opstr[0] = 0;
1408             break;
1409         default:
1410             strcpy(opstr, " !UNK! ");
1411             break;
1412     }
1413     for (i=0; i<e->numterms; i++) {
1414         switch (e->terms[i].type) {
1415             case YASM_EXPR_PRECBC:
1416                 fprintf(f, "{%lx}",
1417                         yasm_bc_next_offset(e->terms[i].data.precbc));
1418                 break;
1419             case YASM_EXPR_SYM:
1420                 fprintf(f, "%s", yasm_symrec_get_name(e->terms[i].data.sym));
1421                 break;
1422             case YASM_EXPR_EXPR:
1423                 fprintf(f, "(");
1424                 yasm_expr_print(e->terms[i].data.expn, f);
1425                 fprintf(f, ")");
1426                 break;
1427             case YASM_EXPR_INT:
1428                 yasm_intnum_print(e->terms[i].data.intn, f);
1429                 break;
1430             case YASM_EXPR_FLOAT:
1431                 yasm_floatnum_print(e->terms[i].data.flt, f);
1432                 break;
1433             case YASM_EXPR_REG:
1434                 /* FIXME */
1435                 /*yasm_arch_reg_print(arch, e->terms[i].data.reg, f);*/
1436                 break;
1437             case YASM_EXPR_SUBST:
1438                 fprintf(f, "[%u]", e->terms[i].data.subst);
1439                 break;
1440             case YASM_EXPR_NONE:
1441                 break;
1442         }
1443         if (i < e->numterms-1)
1444             fprintf(f, "%s", opstr);
1445     }
1446 }
1447 
1448 unsigned int
yasm_expr_size(const yasm_expr * e)1449 yasm_expr_size(const yasm_expr *e)
1450 {
1451     int i;
1452     int seen = 0;
1453     unsigned int size = 0, newsize;
1454 
1455     if (e->op == YASM_EXPR_IDENT) {
1456         if (e->terms[0].type == YASM_EXPR_SYM)
1457             return yasm_symrec_get_size(e->terms[0].data.sym);
1458         return 0;
1459     }
1460     if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
1461         return 0;
1462 
1463     for (i=0; i<e->numterms; i++) {
1464         newsize = 0;
1465         switch (e->terms[i].type) {
1466         case YASM_EXPR_EXPR:
1467             newsize = yasm_expr_size(e->terms[i].data.expn);
1468             break;
1469         case YASM_EXPR_SYM:
1470             newsize = yasm_symrec_get_size(e->terms[i].data.sym);
1471             break;
1472         default:
1473             break;
1474         }
1475         if (newsize) {
1476             size = newsize;
1477             if (seen)
1478                 /* either sum of idents (?!) or substract of idents */
1479                 return 0;
1480             seen = 1;
1481         }
1482     }
1483     /* exactly one offset */
1484     return size;
1485 }
1486 
1487 const char *
yasm_expr_segment(const yasm_expr * e)1488 yasm_expr_segment(const yasm_expr *e)
1489 {
1490     int i;
1491     int seen = 0;
1492     const char *segment = NULL;
1493 
1494     if (e->op == YASM_EXPR_IDENT) {
1495         if (e->terms[0].type == YASM_EXPR_SYM)
1496             return yasm_symrec_get_segment(e->terms[0].data.sym);
1497         return NULL;
1498     }
1499     if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
1500         return NULL;
1501 
1502     for (i=0; i<e->numterms; i++) {
1503         if ((e->op == YASM_EXPR_ADD || !i) &&
1504                 e->terms[i].type == YASM_EXPR_EXPR) {
1505             if ((segment = yasm_expr_segment(e->terms[i].data.expn))) {
1506                 if (seen) {
1507                     /* either sum of idents (?!) or substract of idents */
1508                     return NULL;
1509                 }
1510                 seen = 1;
1511             }
1512         }
1513     }
1514     /* exactly one offset */
1515     return segment;
1516 }
1517