| /* expr.h -> header file for expr.c |
| Copyright (C) 1987-2016 Free Software Foundation, Inc. |
| |
| This file is part of GAS, the GNU Assembler. |
| |
| GAS is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GAS is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GAS; see the file COPYING. If not, write to the Free |
| Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
| 02110-1301, USA. */ |
| |
| /* |
| * By popular demand, we define a struct to represent an expression. |
| * This will no doubt mutate as expressions become baroque. |
| * |
| * Currently, we support expressions like "foo OP bar + 42". In other |
| * words we permit a (possibly undefined) symbol, a (possibly |
| * undefined) symbol and the operation used to combine the symbols, |
| * and an (absolute) augend. RMS says this is so we can have 1-pass |
| * assembly for any compiler emissions, and a 'case' statement might |
| * emit 'undefined1 - undefined2'. |
| * |
| * The type of an expression used to be stored as a segment. That got |
| * confusing because it overloaded the concept of a segment. I added |
| * an operator field, instead. |
| */ |
| |
| /* This is the type of an expression. The operator types are also |
| used while parsing an expression. |
| |
| NOTE: This enumeration must match the op_rank array in expr.c. */ |
| |
| typedef enum { |
| /* An illegal expression. */ |
| O_illegal, |
| /* A nonexistent expression. */ |
| O_absent, |
| /* X_add_number (a constant expression). */ |
| O_constant, |
| /* X_add_symbol + X_add_number. */ |
| O_symbol, |
| /* X_add_symbol + X_add_number - the base address of the image. */ |
| O_symbol_rva, |
| /* A register (X_add_number is register number). */ |
| O_register, |
| /* A big value. If X_add_number is negative or 0, the value is in |
| generic_floating_point_number. Otherwise the value is in |
| generic_bignum, and X_add_number is the number of LITTLENUMs in |
| the value. */ |
| O_big, |
| /* (- X_add_symbol) + X_add_number. */ |
| O_uminus, |
| /* (~ X_add_symbol) + X_add_number. */ |
| O_bit_not, |
| /* (! X_add_symbol) + X_add_number. */ |
| O_logical_not, |
| /* (X_add_symbol * X_op_symbol) + X_add_number. */ |
| O_multiply, |
| /* (X_add_symbol / X_op_symbol) + X_add_number. */ |
| O_divide, |
| /* (X_add_symbol % X_op_symbol) + X_add_number. */ |
| O_modulus, |
| /* (X_add_symbol << X_op_symbol) + X_add_number. */ |
| O_left_shift, |
| /* (X_add_symbol >> X_op_symbol) + X_add_number. */ |
| O_right_shift, |
| /* (X_add_symbol | X_op_symbol) + X_add_number. */ |
| O_bit_inclusive_or, |
| /* (X_add_symbol |~ X_op_symbol) + X_add_number. */ |
| O_bit_or_not, |
| /* (X_add_symbol ^ X_op_symbol) + X_add_number. */ |
| O_bit_exclusive_or, |
| /* (X_add_symbol & X_op_symbol) + X_add_number. */ |
| O_bit_and, |
| /* (X_add_symbol + X_op_symbol) + X_add_number. */ |
| O_add, |
| /* (X_add_symbol - X_op_symbol) + X_add_number. */ |
| O_subtract, |
| /* (X_add_symbol == X_op_symbol) + X_add_number. */ |
| O_eq, |
| /* (X_add_symbol != X_op_symbol) + X_add_number. */ |
| O_ne, |
| /* (X_add_symbol < X_op_symbol) + X_add_number. */ |
| O_lt, |
| /* (X_add_symbol <= X_op_symbol) + X_add_number. */ |
| O_le, |
| /* (X_add_symbol >= X_op_symbol) + X_add_number. */ |
| O_ge, |
| /* (X_add_symbol > X_op_symbol) + X_add_number. */ |
| O_gt, |
| /* (X_add_symbol && X_op_symbol) + X_add_number. */ |
| O_logical_and, |
| /* (X_add_symbol || X_op_symbol) + X_add_number. */ |
| O_logical_or, |
| /* X_op_symbol [ X_add_symbol ] */ |
| O_index, |
| /* machine dependent operators */ |
| O_md1, O_md2, O_md3, O_md4, O_md5, O_md6, O_md7, O_md8, |
| O_md9, O_md10, O_md11, O_md12, O_md13, O_md14, O_md15, O_md16, |
| O_md17, O_md18, O_md19, O_md20, O_md21, O_md22, O_md23, O_md24, |
| O_md25, O_md26, O_md27, O_md28, O_md29, O_md30, O_md31, O_md32, |
| /* this must be the largest value */ |
| O_max |
| } operatorT; |
| |
| typedef struct expressionS { |
| /* The main symbol. */ |
| symbolS *X_add_symbol; |
| /* The second symbol, if needed. */ |
| symbolS *X_op_symbol; |
| /* A number to add. */ |
| offsetT X_add_number; |
| |
| /* The type of the expression. We can't assume that an arbitrary |
| compiler can handle a bitfield of enum type. FIXME: We could |
| check this using autoconf. */ |
| #ifdef __GNUC__ |
| operatorT X_op : 8; |
| #else |
| unsigned char X_op; |
| #endif |
| |
| /* Non-zero if X_add_number should be regarded as unsigned. This is |
| only valid for O_constant expressions. It is only used when an |
| O_constant must be extended into a bignum (i.e., it is not used |
| when performing arithmetic on these values). |
| FIXME: This field is not set very reliably. */ |
| unsigned int X_unsigned : 1; |
| /* This is used to implement "word size + 1 bit" arithmetic, so that e.g. |
| expressions used with .sleb128 directives can use the full range available |
| for an unsigned word, but can also properly represent all values of a |
| signed word. */ |
| unsigned int X_extrabit : 1; |
| |
| /* 7 additional bits can be defined if needed. */ |
| |
| /* Machine dependent field */ |
| unsigned short X_md; |
| } expressionS; |
| |
| enum expr_mode |
| { |
| expr_evaluate, |
| expr_normal, |
| expr_defer |
| }; |
| |
| /* "result" should be type (expressionS *). */ |
| #define expression(result) expr (0, result, expr_normal) |
| #define expression_and_evaluate(result) expr (0, result, expr_evaluate) |
| #define deferred_expression(result) expr (0, result, expr_defer) |
| |
| /* If an expression is O_big, look here for its value. These common |
| data may be clobbered whenever expr() is called. */ |
| /* Flonums returned here. Big enough to hold most precise flonum. */ |
| extern FLONUM_TYPE generic_floating_point_number; |
| /* Bignums returned here. */ |
| extern LITTLENUM_TYPE generic_bignum[]; |
| /* Number of littlenums in above. */ |
| #define SIZE_OF_LARGE_NUMBER (20) |
| |
| typedef char operator_rankT; |
| |
| extern char get_symbol_name (char **); |
| extern char restore_line_pointer (char); |
| extern void expr_begin (void); |
| extern void expr_set_precedence (void); |
| extern void expr_set_rank (operatorT, operator_rankT); |
| extern void add_to_result (expressionS *, offsetT, int); |
| extern void subtract_from_result (expressionS *, offsetT, int); |
| extern segT expr (int, expressionS *, enum expr_mode); |
| extern unsigned int get_single_number (void); |
| extern symbolS *make_expr_symbol (expressionS * expressionP); |
| extern int expr_symbol_where (symbolS *, const char **, unsigned int *); |
| extern void current_location (expressionS *); |
| |
| extern symbolS *expr_build_uconstant (offsetT); |
| extern symbolS *expr_build_dot (void); |
| |
| int resolve_expression (expressionS *); |