mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
groundwork for further features and possible cleanups. Note: this commit changes the way in which relocations in the COFF/Win32/Win64 target can be forced to reference a different symbol than is being pointed to; instead of the ambiguous "trap+(trap.end-trap)" to get the reloc to point at trap.end but reference the trap symbol, after this commit "trap.end wrt trap" is the way to say this. This also reads a lot more clearly and is not ambiguous. This should really only affect people who write .pdata sections for Win64. See the objfmts/win64/tests/win64-dataref.asm testcase for an example of usage. This cleanup adds a new data structure, yasm_value, which is used for all expressions that can be potentially relocatable. This data structure splits the absolute portion of the expression away from the relative portion and any modifications to the relative portion (SEG, WRT, PC-relative, etc). A large amount of code in the new value module breaks a general expression into its absolute and relative parts (yasm_value_finalize_expr) and provides a common set of code for writing out non-relocated values (yasm_value_output_basic). All bytecode handling in both libyasm and the architecture modules was rewritten to use yasm_values when appropriate (e.g. data values, immediates, and effective addresses). The yasm_output_expr_func is now yasm_output_value_func and all users and implementors (mainly in object formats) have been updated to handle yasm_values. Simultaneously with this change, yasm_effaddr and yasm_immval full structure definitions have been moved from bc-int.h to bytecode.h. The data hiding provided by bc-int.h was relatively minimal and probably overkill. Also, great simplifications have been made to x86 effective address expression handling. svn path=/trunk/yasm/; revision=1419
230 lines
8.6 KiB
C
230 lines
8.6 KiB
C
/**
|
|
* \file libyasm/expr.h
|
|
* \brief YASM expression interface.
|
|
*
|
|
* \rcs
|
|
* $Id$
|
|
* \endrcs
|
|
*
|
|
* \license
|
|
* Copyright (C) 2001 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
|
|
|
|
/** Expression item (opaque type). \internal */
|
|
typedef struct yasm_expr__item yasm_expr__item;
|
|
|
|
/** 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.
|
|
*/
|
|
/*@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 symbol expression item.
|
|
* \param sym symbol
|
|
* \return Newly allocated expression item.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@only@*/ yasm_expr__item *yasm_expr_reg(unsigned long 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);
|
|
|
|
/** Destroy (free allocated memory for) an expression.
|
|
* \param e expression
|
|
*/
|
|
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.
|
|
*/
|
|
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);
|
|
|
|
/** Linked list of expression entries.
|
|
* \internal
|
|
* Used internally by yasm_expr__level_tree().
|
|
*/
|
|
typedef struct yasm__exprhead yasm__exprhead;
|
|
#ifdef YASM_LIB_INTERNAL
|
|
SLIST_HEAD(yasm__exprhead, yasm__exprentry);
|
|
#endif
|
|
|
|
/** 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 bytecode distance-calculation function
|
|
* \param expr_xform_extra extra transformation function
|
|
* \param expr_xform_extra_data data to pass to expr_xform_extra
|
|
* \param eh call with NULL (for internal use in recursion)
|
|
* \param error if non-NULL, set to 1 if an error is encountered
|
|
* (e.g. circular reference errors)
|
|
* \return Leveled expression.
|
|
*/
|
|
/*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree
|
|
(/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
|
|
int simplify_ident, int simplify_reg_mul,
|
|
/*@null@*/ yasm_calc_bc_dist_func calc_bc_dist,
|
|
/*@null@*/ yasm_expr_xform_func expr_xform_extra,
|
|
/*@null@*/ void *expr_xform_extra_data, /*@null@*/ yasm__exprhead *eh,
|
|
/*@null@*/ int *error);
|
|
|
|
/** 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 bytecode distance-calculation function
|
|
* \return Simplified expression.
|
|
*/
|
|
#define yasm_expr_simplify(e, cbd) \
|
|
yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL, NULL, NULL)
|
|
|
|
/** 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.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@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 bytecode distance-calculation function
|
|
* \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.
|
|
*/
|
|
/*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum
|
|
(yasm_expr **ep, /*@null@*/ yasm_calc_bc_dist_func 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.
|
|
*/
|
|
/*@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.
|
|
*/
|
|
/*@dependent@*/ /*@null@*/ const unsigned long *yasm_expr_get_reg
|
|
(yasm_expr **ep, int simplify);
|
|
|
|
/** Print an expression. For debugging purposes.
|
|
* \param e expression
|
|
* \param f file
|
|
*/
|
|
void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
|
|
|
|
#endif
|