diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/yasm/libyasm/expr.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/yasm/libyasm/expr.h')
-rw-r--r-- | contrib/tools/yasm/libyasm/expr.h | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/contrib/tools/yasm/libyasm/expr.h b/contrib/tools/yasm/libyasm/expr.h new file mode 100644 index 00000000000..0de62dfed7b --- /dev/null +++ b/contrib/tools/yasm/libyasm/expr.h @@ -0,0 +1,388 @@ +/** + * \file libyasm/expr.h + * \brief YASM expression interface. + * + * \license + * Copyright (C) 2001-2007 Michael Urman, Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * \endlicense + */ +#ifndef YASM_EXPR_H +#define YASM_EXPR_H + +#ifndef YASM_LIB_DECL +#define YASM_LIB_DECL +#endif + +/** Type of an expression item. Types are listed in canonical sorting order. + * See expr_order_terms(). + * Note #YASM_EXPR_PRECBC must be used carefully (in a-b pairs), as only + * symrecs can become the relative term in a #yasm_value. + */ +typedef enum yasm_expr__type { + YASM_EXPR_NONE = 0, /**< Nothing */ + YASM_EXPR_REG = 1<<0, /**< Register */ + YASM_EXPR_INT = 1<<1, /**< Integer value */ + YASM_EXPR_SUBST = 1<<2, /**< Substitution placeholder */ + YASM_EXPR_FLOAT = 1<<3, /**< Floating point value */ + YASM_EXPR_SYM = 1<<4, /**< Symbol */ + YASM_EXPR_PRECBC = 1<<5,/**< Direct bytecode ref (rather than via sym) */ + YASM_EXPR_EXPR = 1<<6 /**< Subexpression */ +} yasm_expr__type; + +/** Expression item. */ +typedef struct yasm_expr__item { + yasm_expr__type type; /**< Type */ + + /** Expression item data. Correct value depends on type. */ + union { + yasm_bytecode *precbc; /**< Direct bytecode ref (YASM_EXPR_PRECBC) */ + yasm_symrec *sym; /**< Symbol (YASM_EXPR_SYM) */ + yasm_expr *expn; /**< Subexpression (YASM_EXPR_EXPR) */ + yasm_intnum *intn; /**< Integer value (YASM_EXPR_INT) */ + yasm_floatnum *flt; /**< Floating point value (YASM_EXPR_FLOAT) */ + uintptr_t reg; /**< Register (YASM_EXPR_REG) */ + unsigned int subst; /**< Subst placeholder (YASM_EXPR_SUBST) */ + } data; +} yasm_expr__item; + +/** Expression. */ +struct yasm_expr { + yasm_expr_op op; /**< Operation. */ + unsigned long line; /**< Line number where expression was defined. */ + int numterms; /**< Number of terms in the expression. */ + + /** Terms of the expression. Structure may be extended to include more + * terms, as some operations may allow more than two operand terms + * (ADD, MUL, OR, AND, XOR). + */ + yasm_expr__item terms[2]; +}; + +/** Create a new expression e=a op b. + * \param op operation + * \param a expression item a + * \param b expression item b (optional depending on op) + * \param line virtual line (where expression defined) + * \return Newly allocated expression. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr *yasm_expr_create + (yasm_expr_op op, /*@only@*/ yasm_expr__item *a, + /*@only@*/ /*@null@*/ yasm_expr__item *b, unsigned long line); + +/** Create a new preceding-bytecode expression item. + * \param precbc preceding bytecode + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_precbc(/*@keep@*/ yasm_bytecode *precbc); + +/** Create a new symbol expression item. + * \param sym symbol + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_sym(/*@keep@*/ yasm_symrec *sym); + +/** Create a new expression expression item. + * \param e expression + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_expr(/*@keep@*/ yasm_expr *e); + +/** Create a new intnum expression item. + * \param intn intnum + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_int(/*@keep@*/ yasm_intnum *intn); + +/** Create a new floatnum expression item. + * \param flt floatnum + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_float(/*@keep@*/ yasm_floatnum *flt); + +/** Create a new register expression item. + * \param reg register + * \return Newly allocated expression item. + */ +YASM_LIB_DECL +/*@only@*/ yasm_expr__item *yasm_expr_reg(uintptr_t reg); + +/** Create a new expression tree e=l op r. + * \param l expression for left side of new expression + * \param o operation + * \param r expression for right side of new expression + * \param i line index + * \return Newly allocated expression. + */ +#define yasm_expr_create_tree(l,o,r,i) \ + yasm_expr_create ((o), yasm_expr_expr(l), yasm_expr_expr(r), i) + +/** Create a new expression branch e=op r. + * \param o operation + * \param r expression for right side of new expression + * \param i line index + * \return Newly allocated expression. + */ +#define yasm_expr_create_branch(o,r,i) \ + yasm_expr_create ((o), yasm_expr_expr(r), (yasm_expr__item *)NULL, i) + +/** Create a new expression identity e=r. + * \param r expression for identity within new expression + * \param i line index + * \return Newly allocated expression. + */ +#define yasm_expr_create_ident(r,i) \ + yasm_expr_create (YASM_EXPR_IDENT, (r), (yasm_expr__item *)NULL, i) + +/** Duplicate an expression. + * \param e expression + * \return Newly allocated expression identical to e. + */ +yasm_expr *yasm_expr_copy(const yasm_expr *e); +#ifndef YASM_DOXYGEN +#define yasm_expr_copy(e) yasm_expr__copy_except(e, -1) +#endif + +/** Destroy (free allocated memory for) an expression. + * \param e expression + */ +YASM_LIB_DECL +void yasm_expr_destroy(/*@only@*/ /*@null@*/ yasm_expr *e); + +/** Determine if an expression is a specified operation (at the top level). + * \param e expression + * \param op operator + * \return Nonzero if the expression was the specified operation at the top + * level, zero otherwise. + */ +YASM_LIB_DECL +int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op); + +/** Extra transformation function for yasm_expr__level_tree(). + * \param e expression being simplified + * \param d data provided as expr_xform_extra_data to + * yasm_expr__level_tree() + * \return Transformed e. + */ +typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func) + (/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d); + +/** Level an entire expression tree. + * \internal + * \param e expression + * \param fold_const enable constant folding if nonzero + * \param simplify_ident simplify identities + * \param simplify_reg_mul simplify REG*1 identities + * \param calc_bc_dist nonzero if distances between bytecodes should be + * calculated, 0 if they should be left intact + * \param expr_xform_extra extra transformation function + * \param expr_xform_extra_data data to pass to expr_xform_extra + * \return Leveled expression. + */ +YASM_LIB_DECL +/*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree + (/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const, + int simplify_ident, int simplify_reg_mul, int calc_bc_dist, + /*@null@*/ yasm_expr_xform_func expr_xform_extra, + /*@null@*/ void *expr_xform_extra_data); + +/** Simplify an expression as much as possible. Eliminates extraneous + * branches and simplifies integer-only subexpressions. Simplified version + * of yasm_expr__level_tree(). + * \param e expression + * \param cbd if distance between bytecodes should be calculated + * \return Simplified expression. + */ +#define yasm_expr_simplify(e, cbd) \ + yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL) + +/** Extract the segment portion of an expression containing SEG:OFF, leaving + * the offset. + * \param ep expression (pointer to) + * \return NULL if unable to extract a segment (expr does not contain a + * YASM_EXPR_SEGOFF operator), otherwise the segment expression. + * The input expression is modified such that on return, it's the + * offset expression. + */ +YASM_LIB_DECL +/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_deep_segoff(yasm_expr **ep); + +/** Extract the segment portion of a SEG:OFF expression, leaving the offset. + * \param ep expression (pointer to) + * \return NULL if unable to extract a segment (YASM_EXPR_SEGOFF not the + * top-level operator), otherwise the segment expression. The input + * expression is modified such that on return, it's the offset + * expression. + */ +YASM_LIB_DECL +/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep); + +/** Extract the right portion (y) of a x WRT y expression, leaving the left + * portion (x). + * \param ep expression (pointer to) + * \return NULL if unable to extract (YASM_EXPR_WRT not the top-level + * operator), otherwise the right side of the WRT expression. The + * input expression is modified such that on return, it's the left side + * of the WRT expression. + */ +YASM_LIB_DECL +/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep); + +/** Get the integer value of an expression if it's just an integer. + * \param ep expression (pointer to) + * \param calc_bc_dist nonzero if distances between bytecodes should be + * calculated, 0 if NULL should be returned in this case + * \return NULL if the expression is too complex (contains anything other than + * integers, ie floats, non-valued labels, registers); otherwise the + * intnum value of the expression. + */ +YASM_LIB_DECL +/*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum + (yasm_expr **ep, int calc_bc_dist); + +/** Get the symbol value of an expression if it's just a symbol. + * \param ep expression (pointer to) + * \param simplify if nonzero, simplify the expression first + * \return NULL if the expression is too complex; otherwise the symbol value of + * the expression. + */ +YASM_LIB_DECL +/*@dependent@*/ /*@null@*/ const yasm_symrec *yasm_expr_get_symrec + (yasm_expr **ep, int simplify); + +/** Get the register value of an expression if it's just a register. + * \param ep expression (pointer to) + * \param simplify if nonzero, simplify the expression first + * \return NULL if the expression is too complex; otherwise the register value + * of the expression. + */ +YASM_LIB_DECL +/*@dependent@*/ /*@null@*/ const uintptr_t *yasm_expr_get_reg + (yasm_expr **ep, int simplify); + +/** Print an expression. For debugging purposes. + * \param e expression + * \param f file + */ +YASM_LIB_DECL +void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f); + +/** Return the size of an expression, if the user provided it + * \param e expression + */ +YASM_LIB_DECL +unsigned int yasm_expr_size(const yasm_expr *e); + +/** Return the segment of an expression, if the user provided it + * \param e expression + */ +YASM_LIB_DECL +const char *yasm_expr_segment(const yasm_expr *e); + +/** Traverse over expression tree in order (const version). + * Calls func for each leaf (non-operation). + * \param e expression + * \param d data passed to each call to func + * \param func callback function + * \return Stops early (and returns 1) if func returns 1. + * Otherwise returns 0. + */ +YASM_LIB_DECL +int yasm_expr__traverse_leaves_in_const + (const yasm_expr *e, /*@null@*/ void *d, + int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d)); + +/** Traverse over expression tree in order. + * Calls func for each leaf (non-operation). + * \param e expression + * \param d data passed to each call to func + * \param func callback function + * \return Stops early (and returns 1) if func returns 1. + * Otherwise returns 0. + */ +YASM_LIB_DECL +int yasm_expr__traverse_leaves_in + (yasm_expr *e, /*@null@*/ void *d, + int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d)); + +/** Reorder terms of e into canonical order. Only reorders if reordering + * doesn't change meaning of expression. (eg, doesn't reorder SUB). + * Canonical order: REG, INT, FLOAT, SYM, EXPR. + * Multiple terms of a single type are kept in the same order as in + * the original expression. + * \param e expression + * \note Only performs reordering on *one* level (no recursion). + */ +YASM_LIB_DECL +void yasm_expr__order_terms(yasm_expr *e); + +/** Copy entire expression EXCEPT for index "except" at *top level only*. + * \param e expression + * \param except term index not to copy; -1 to copy all terms + * \return Newly allocated copy of expression. + */ +YASM_LIB_DECL +yasm_expr *yasm_expr__copy_except(const yasm_expr *e, int except); + +/** Test if expression contains an item. Searches recursively into + * subexpressions. + * \param e expression + * \param t type of item to look for + * \return Nonzero if expression contains an item of type t, zero if not. + */ +YASM_LIB_DECL +int yasm_expr__contains(const yasm_expr *e, yasm_expr__type t); + +/** Transform symrec-symrec terms in expression into #YASM_EXPR_SUBST items. + * Calls the callback function for each symrec-symrec term. + * \param ep expression (pointer to) + * \param cbd callback data passed to callback function + * \param callback callback function: given subst index for bytecode + * pair, bytecode pair (bc2-bc1), and cbd (callback data) + * \return Number of transformations made. + */ +YASM_LIB_DECL +int yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd, + void (*callback) (unsigned int subst, + yasm_bytecode *precbc, + yasm_bytecode *precbc2, + void *cbd)); + +/** Substitute items into expr YASM_EXPR_SUBST items (by index). Items are + * copied, so caller is responsible for freeing array of items. + * \param e expression + * \param num_items number of items in items array + * \param items items array + * \return 1 on error (index out of range). + */ +YASM_LIB_DECL +int yasm_expr__subst(yasm_expr *e, unsigned int num_items, + const yasm_expr__item *items); + +#endif |