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