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 */ 42typedef 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. */ 54typedef 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. */ 70struct 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 */ 89YASM_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 */ 98YASM_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 */ 105YASM_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 */ 112YASM_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 */ 119YASM_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 */ 126YASM_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 */ 133YASM_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 */ 167yasm_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 */ 175YASM_LIB_DECL 176void 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 */ 184YASM_LIB_DECL 185int 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 */ 193typedef /*@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 */ 208YASM_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 */ 233YASM_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 */ 243YASM_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 */ 254YASM_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 */ 265YASM_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 */ 275YASM_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 */ 285YASM_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 */ 293YASM_LIB_DECL 294void 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 */ 299unsigned 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 */ 304const 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 */ 314YASM_LIB_DECL 315int 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 */ 327YASM_LIB_DECL 328int 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 */ 340YASM_LIB_DECL 341void 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 */ 348YASM_LIB_DECL 349yasm_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 */ 357YASM_LIB_DECL 358int 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 */ 368YASM_LIB_DECL 369int 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 */ 382YASM_LIB_DECL 383int yasm_expr__subst(yasm_expr *e, unsigned int num_items, 384 const yasm_expr__item *items); 385 386#endif 387