Home | History | Annotate | Download | only in libyasm
      1 /**
      2  * \file libyasm/expr.h
      3  * \brief YASM expression interface.
      4  *
      5  * \license
      6  *  Copyright (C) 2001-2007  Michael Urman, Peter Johnson
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *  - Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  - Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  * \endlicense
     29  */
     30 #ifndef YASM_EXPR_H
     31 #define YASM_EXPR_H
     32 
     33 #ifndef YASM_LIB_DECL
     34 #define YASM_LIB_DECL
     35 #endif
     36 
     37 /** Type of an expression item.  Types are listed in canonical sorting order.
     38  * See expr_order_terms().
     39  * Note #YASM_EXPR_PRECBC must be used carefully (in a-b pairs), as only
     40  * symrecs can become the relative term in a #yasm_value.
     41  */
     42 typedef enum yasm_expr__type {
     43     YASM_EXPR_NONE = 0,     /**< Nothing */
     44     YASM_EXPR_REG = 1<<0,   /**< Register */
     45     YASM_EXPR_INT = 1<<1,   /**< Integer value */
     46     YASM_EXPR_SUBST = 1<<2, /**< Substitution placeholder */
     47     YASM_EXPR_FLOAT = 1<<3, /**< Floating point value */
     48     YASM_EXPR_SYM = 1<<4,   /**< Symbol */
     49     YASM_EXPR_PRECBC = 1<<5,/**< Direct bytecode ref (rather than via sym) */
     50     YASM_EXPR_EXPR = 1<<6   /**< Subexpression */
     51 } yasm_expr__type;
     52 
     53 /** Expression item. */
     54 typedef struct yasm_expr__item {
     55     yasm_expr__type type;   /**< Type */
     56 
     57     /** Expression item data.  Correct value depends on type. */
     58     union {
     59         yasm_bytecode *precbc;  /**< Direct bytecode ref (YASM_EXPR_PRECBC) */
     60         yasm_symrec *sym;       /**< Symbol (YASM_EXPR_SYM) */
     61         yasm_expr *expn;        /**< Subexpression (YASM_EXPR_EXPR) */
     62         yasm_intnum *intn;      /**< Integer value (YASM_EXPR_INT) */
     63         yasm_floatnum *flt;     /**< Floating point value (YASM_EXPR_FLOAT) */
     64         uintptr_t reg;          /**< Register (YASM_EXPR_REG) */
     65         unsigned int subst;     /**< Subst placeholder (YASM_EXPR_SUBST) */
     66     } data;
     67 } yasm_expr__item;
     68 
     69 /** Expression. */
     70 struct yasm_expr {
     71     yasm_expr_op op;    /**< Operation. */
     72     unsigned long line; /**< Line number where expression was defined. */
     73     int numterms;       /**< Number of terms in the expression. */
     74 
     75     /** Terms of the expression.  Structure may be extended to include more
     76      * terms, as some operations may allow more than two operand terms
     77      * (ADD, MUL, OR, AND, XOR).
     78      */
     79     yasm_expr__item terms[2];
     80 };
     81 
     82 /** Create a new expression e=a op b.
     83  * \param op        operation
     84  * \param a         expression item a
     85  * \param b         expression item b (optional depending on op)
     86  * \param line      virtual line (where expression defined)
     87  * \return Newly allocated expression.
     88  */
     89 YASM_LIB_DECL
     90 /*@only@*/ yasm_expr *yasm_expr_create
     91     (yasm_expr_op op, /*@only@*/ yasm_expr__item *a,
     92      /*@only@*/ /*@null@*/ yasm_expr__item *b, unsigned long line);
     93 
     94 /** Create a new preceding-bytecode expression item.
     95  * \param precbc    preceding bytecode
     96  * \return Newly allocated expression item.
     97  */
     98 YASM_LIB_DECL
     99 /*@only@*/ yasm_expr__item *yasm_expr_precbc(/*@keep@*/ yasm_bytecode *precbc);
    100 
    101 /** Create a new symbol expression item.
    102  * \param sym       symbol
    103  * \return Newly allocated expression item.
    104  */
    105 YASM_LIB_DECL
    106 /*@only@*/ yasm_expr__item *yasm_expr_sym(/*@keep@*/ yasm_symrec *sym);
    107 
    108 /** Create a new expression expression item.
    109  * \param e         expression
    110  * \return Newly allocated expression item.
    111  */
    112 YASM_LIB_DECL
    113 /*@only@*/ yasm_expr__item *yasm_expr_expr(/*@keep@*/ yasm_expr *e);
    114 
    115 /** Create a new intnum expression item.
    116  * \param intn      intnum
    117  * \return Newly allocated expression item.
    118  */
    119 YASM_LIB_DECL
    120 /*@only@*/ yasm_expr__item *yasm_expr_int(/*@keep@*/ yasm_intnum *intn);
    121 
    122 /** Create a new floatnum expression item.
    123  * \param flt       floatnum
    124  * \return Newly allocated expression item.
    125  */
    126 YASM_LIB_DECL
    127 /*@only@*/ yasm_expr__item *yasm_expr_float(/*@keep@*/ yasm_floatnum *flt);
    128 
    129 /** Create a new register expression item.
    130  * \param reg       register
    131  * \return Newly allocated expression item.
    132  */
    133 YASM_LIB_DECL
    134 /*@only@*/ yasm_expr__item *yasm_expr_reg(uintptr_t reg);
    135 
    136 /** Create a new expression tree e=l op r.
    137  * \param l     expression for left side of new expression
    138  * \param o     operation
    139  * \param r     expression for right side of new expression
    140  * \param i     line index
    141  * \return Newly allocated expression.
    142  */
    143 #define yasm_expr_create_tree(l,o,r,i) \
    144     yasm_expr_create ((o), yasm_expr_expr(l), yasm_expr_expr(r), i)
    145 
    146 /** Create a new expression branch e=op r.
    147  * \param o     operation
    148  * \param r     expression for right side of new expression
    149  * \param i     line index
    150  * \return Newly allocated expression.
    151  */
    152 #define yasm_expr_create_branch(o,r,i) \
    153     yasm_expr_create ((o), yasm_expr_expr(r), (yasm_expr__item *)NULL, i)
    154 
    155 /** Create a new expression identity e=r.
    156  * \param r     expression for identity within new expression
    157  * \param i     line index
    158  * \return Newly allocated expression.
    159  */
    160 #define yasm_expr_create_ident(r,i) \
    161     yasm_expr_create (YASM_EXPR_IDENT, (r), (yasm_expr__item *)NULL, i)
    162 
    163 /** Duplicate an expression.
    164  * \param e     expression
    165  * \return Newly allocated expression identical to e.
    166  */
    167 yasm_expr *yasm_expr_copy(const yasm_expr *e);
    168 #ifndef YASM_DOXYGEN
    169 #define yasm_expr_copy(e)   yasm_expr__copy_except(e, -1)
    170 #endif
    171 
    172 /** Destroy (free allocated memory for) an expression.
    173  * \param e     expression
    174  */
    175 YASM_LIB_DECL
    176 void yasm_expr_destroy(/*@only@*/ /*@null@*/ yasm_expr *e);
    177 
    178 /** Determine if an expression is a specified operation (at the top level).
    179  * \param e             expression
    180  * \param op            operator
    181  * \return Nonzero if the expression was the specified operation at the top
    182  *         level, zero otherwise.
    183  */
    184 YASM_LIB_DECL
    185 int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op);
    186 
    187 /** Extra transformation function for yasm_expr__level_tree().
    188  * \param e     expression being simplified
    189  * \param d     data provided as expr_xform_extra_data to
    190  *              yasm_expr__level_tree()
    191  * \return Transformed e.
    192  */
    193 typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func)
    194     (/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d);
    195 
    196 /** Level an entire expression tree.
    197  * \internal
    198  * \param e                 expression
    199  * \param fold_const        enable constant folding if nonzero
    200  * \param simplify_ident    simplify identities
    201  * \param simplify_reg_mul  simplify REG*1 identities
    202  * \param calc_bc_dist      nonzero if distances between bytecodes should be
    203  *                          calculated, 0 if they should be left intact
    204  * \param expr_xform_extra  extra transformation function
    205  * \param expr_xform_extra_data data to pass to expr_xform_extra
    206  * \return Leveled expression.
    207  */
    208 YASM_LIB_DECL
    209 /*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree
    210     (/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
    211      int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
    212      /*@null@*/ yasm_expr_xform_func expr_xform_extra,
    213      /*@null@*/ void *expr_xform_extra_data);
    214 
    215 /** Simplify an expression as much as possible.  Eliminates extraneous
    216  * branches and simplifies integer-only subexpressions.  Simplified version
    217  * of yasm_expr__level_tree().
    218  * \param e     expression
    219  * \param cbd   if distance between bytecodes should be calculated
    220  * \return Simplified expression.
    221  */
    222 #define yasm_expr_simplify(e, cbd) \
    223     yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL)
    224 
    225 /** Extract the segment portion of an expression containing SEG:OFF, leaving
    226  * the offset.
    227  * \param ep            expression (pointer to)
    228  * \return NULL if unable to extract a segment (expr does not contain a
    229  *         YASM_EXPR_SEGOFF operator), otherwise the segment expression.
    230  *         The input expression is modified such that on return, it's the
    231  *         offset expression.
    232  */
    233 YASM_LIB_DECL
    234 /*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_deep_segoff(yasm_expr **ep);
    235 
    236 /** Extract the segment portion of a SEG:OFF expression, leaving the offset.
    237  * \param ep            expression (pointer to)
    238  * \return NULL if unable to extract a segment (YASM_EXPR_SEGOFF not the
    239  *         top-level operator), otherwise the segment expression.  The input
    240  *         expression is modified such that on return, it's the offset
    241  *         expression.
    242  */
    243 YASM_LIB_DECL
    244 /*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep);
    245 
    246 /** Extract the right portion (y) of a x WRT y expression, leaving the left
    247  * portion (x).
    248  * \param ep            expression (pointer to)
    249  * \return NULL if unable to extract (YASM_EXPR_WRT not the top-level
    250  *         operator), otherwise the right side of the WRT expression.  The
    251  *         input expression is modified such that on return, it's the left side
    252  *         of the WRT expression.
    253  */
    254 YASM_LIB_DECL
    255 /*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep);
    256 
    257 /** Get the integer value of an expression if it's just an integer.
    258  * \param ep            expression (pointer to)
    259  * \param calc_bc_dist  nonzero if distances between bytecodes should be
    260  *                      calculated, 0 if NULL should be returned in this case
    261  * \return NULL if the expression is too complex (contains anything other than
    262  *         integers, ie floats, non-valued labels, registers); otherwise the
    263  *         intnum value of the expression.
    264  */
    265 YASM_LIB_DECL
    266 /*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum
    267     (yasm_expr **ep, int calc_bc_dist);
    268 
    269 /** Get the symbol value of an expression if it's just a symbol.
    270  * \param ep            expression (pointer to)
    271  * \param simplify      if nonzero, simplify the expression first
    272  * \return NULL if the expression is too complex; otherwise the symbol value of
    273  *         the expression.
    274  */
    275 YASM_LIB_DECL
    276 /*@dependent@*/ /*@null@*/ const yasm_symrec *yasm_expr_get_symrec
    277     (yasm_expr **ep, int simplify);
    278 
    279 /** Get the register value of an expression if it's just a register.
    280  * \param ep            expression (pointer to)
    281  * \param simplify      if nonzero, simplify the expression first
    282  * \return NULL if the expression is too complex; otherwise the register value
    283  *         of the expression.
    284  */
    285 YASM_LIB_DECL
    286 /*@dependent@*/ /*@null@*/ const uintptr_t *yasm_expr_get_reg
    287     (yasm_expr **ep, int simplify);
    288 
    289 /** Print an expression.  For debugging purposes.
    290  * \param e     expression
    291  * \param f     file
    292  */
    293 YASM_LIB_DECL
    294 void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
    295 
    296 /** Return the size of an expression, if the user provided it
    297  * \param e     expression
    298  */
    299 unsigned int yasm_expr_size(const yasm_expr *e);
    300 
    301 /** Return the segment of an expression, if the user provided it
    302  * \param e     expression
    303  */
    304 const char *yasm_expr_segment(const yasm_expr *e);
    305 
    306 /** Traverse over expression tree in order (const version).
    307  * Calls func for each leaf (non-operation).
    308  * \param e     expression
    309  * \param d     data passed to each call to func
    310  * \param func  callback function
    311  * \return Stops early (and returns 1) if func returns 1.
    312  *         Otherwise returns 0.
    313  */
    314 YASM_LIB_DECL
    315 int yasm_expr__traverse_leaves_in_const
    316     (const yasm_expr *e, /*@null@*/ void *d,
    317      int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d));
    318 
    319 /** Traverse over expression tree in order.
    320  * Calls func for each leaf (non-operation).
    321  * \param e     expression
    322  * \param d     data passed to each call to func
    323  * \param func  callback function
    324  * \return Stops early (and returns 1) if func returns 1.
    325  *         Otherwise returns 0.
    326  */
    327 YASM_LIB_DECL
    328 int yasm_expr__traverse_leaves_in
    329     (yasm_expr *e, /*@null@*/ void *d,
    330      int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d));
    331 
    332 /** Reorder terms of e into canonical order.  Only reorders if reordering
    333  * doesn't change meaning of expression.  (eg, doesn't reorder SUB).
    334  * Canonical order: REG, INT, FLOAT, SYM, EXPR.
    335  * Multiple terms of a single type are kept in the same order as in
    336  * the original expression.
    337  * \param e     expression
    338  * \note Only performs reordering on *one* level (no recursion).
    339  */
    340 YASM_LIB_DECL
    341 void yasm_expr__order_terms(yasm_expr *e);
    342 
    343 /** Copy entire expression EXCEPT for index "except" at *top level only*.
    344  * \param e         expression
    345  * \param except    term index not to copy; -1 to copy all terms
    346  * \return Newly allocated copy of expression.
    347  */
    348 YASM_LIB_DECL
    349 yasm_expr *yasm_expr__copy_except(const yasm_expr *e, int except);
    350 
    351 /** Test if expression contains an item.  Searches recursively into
    352  * subexpressions.
    353  * \param e     expression
    354  * \param t     type of item to look for
    355  * \return Nonzero if expression contains an item of type t, zero if not.
    356  */
    357 YASM_LIB_DECL
    358 int yasm_expr__contains(const yasm_expr *e, yasm_expr__type t);
    359 
    360 /** Transform symrec-symrec terms in expression into #YASM_EXPR_SUBST items.
    361  * Calls the callback function for each symrec-symrec term.
    362  * \param ep            expression (pointer to)
    363  * \param cbd           callback data passed to callback function
    364  * \param callback      callback function: given subst index for bytecode
    365  *                      pair, bytecode pair (bc2-bc1), and cbd (callback data)
    366  * \return Number of transformations made.
    367  */
    368 YASM_LIB_DECL
    369 int yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
    370                              void (*callback) (unsigned int subst,
    371                                                yasm_bytecode *precbc,
    372                                                yasm_bytecode *precbc2,
    373                                                void *cbd));
    374 
    375 /** Substitute items into expr YASM_EXPR_SUBST items (by index).  Items are
    376  * copied, so caller is responsible for freeing array of items.
    377  * \param e             expression
    378  * \param num_items     number of items in items array
    379  * \param items         items array
    380  * \return 1 on error (index out of range).
    381  */
    382 YASM_LIB_DECL
    383 int yasm_expr__subst(yasm_expr *e, unsigned int num_items,
    384                      const yasm_expr__item *items);
    385 
    386 #endif
    387