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