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
45static /*@only@*/ yasm_expr *expr_level_op
46    (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
47     int simplify_ident, int simplify_reg_mul);
48static int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e,
49                                    /*@null@*/ void *d,
50                                    int (*func) (/*@null@*/ yasm_expr *e,
51                                                 /*@null@*/ void *d));
52static 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 */
57static unsigned long itempool_used = 0;
58static 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@*/
63yasm_expr *
64yasm_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 */
126static yasm_expr__item *
127expr_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
142yasm_expr__item *
143yasm_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
151yasm_expr__item *
152yasm_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
160yasm_expr__item *
161yasm_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
169yasm_expr__item *
170yasm_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
178yasm_expr__item *
179yasm_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
187yasm_expr__item *
188yasm_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 */
201static /*@only@*/ yasm_expr *
202expr_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
295static int
296expr_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 */
311static /*@only@*/ yasm_expr *
312expr_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
317typedef 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
324static int
325expr_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
339static yasm_expr *
340expr_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
345int
346yasm_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 */
362static void
363expr_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 */
386static /*@only@*/ yasm_expr *
387expr_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 */
459static /*@only@*/ yasm_expr *
460expr_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 */
488static int
489expr_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. */
499static int
500expr_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 */
512static int
513expr_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 */
536static int
537expr_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@*/
618static /*@only@*/ yasm_expr *
619expr_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
803typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
804typedef struct yasm__exprentry {
805    /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
806    /*@null@*/ const yasm_expr *e;
807} yasm__exprentry;
808
809static yasm_expr *
810expr_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
849static yasm_expr *
850expr_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 */
893yasm_expr *
894yasm_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 */
915static int
916expr_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 */
929void
930yasm_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
958static void
959expr_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*. */
992yasm_expr *
993yasm_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
1012static void
1013expr_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
1031static int
1032expr_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@*/
1042void
1043yasm_expr_destroy(yasm_expr *e)
1044{
1045    expr_traverse_nodes_post(e, NULL, expr_destroy_each);
1046}
1047/*@=mustfree@*/
1048
1049int
1050yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op)
1051{
1052    return (e->op == op);
1053}
1054
1055static int
1056expr_contains_callback(const yasm_expr__item *ei, void *d)
1057{
1058    yasm_expr__type *t = d;
1059    return (ei->type & *t);
1060}
1061
1062int
1063yasm_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
1068typedef struct subst_cbd {
1069    unsigned int num_items;
1070    const yasm_expr__item *items;
1071} subst_cbd;
1072
1073static int
1074expr_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
1085int
1086yasm_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 */
1101static int
1102expr_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 */
1127int
1128yasm_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 */
1154int
1155yasm_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
1175yasm_expr *
1176yasm_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
1200yasm_expr *
1201yasm_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
1229yasm_expr *
1230yasm_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@*/
1258yasm_intnum *
1259yasm_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@*/
1271const yasm_symrec *
1272yasm_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@*/
1285const uintptr_t *
1286yasm_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
1298void
1299yasm_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
1448unsigned int
1449yasm_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
1487const char *
1488yasm_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