diff options
author | Jan Beulich <jbeulich@novell.com> | 2009-04-20 06:26:23 +0000 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2009-04-20 06:26:23 +0000 |
commit | fcaed75e5235a983da6edd87da4eadcf27b99fb7 (patch) | |
tree | 688dec4b25a842edfd10302a93ce041cee02755d /gas | |
parent | 383c383f84b11a0ee2acdc67b7d26751839be780 (diff) | |
download | gdb-fcaed75e5235a983da6edd87da4eadcf27b99fb7.zip gdb-fcaed75e5235a983da6edd87da4eadcf27b99fb7.tar.gz gdb-fcaed75e5235a983da6edd87da4eadcf27b99fb7.tar.bz2 |
gas/
2009-04-20 Jan Beulich <jbeulich@novell.com>
* expr.c (operand): Call md_need_index_operator() and
md_operator() if defined. Add unary label.
(operator): Call md_operator() if defined.
(expr): Adjust assertions on range and rank of op_left and
op_right. Don't abort on unhandled operators when reducing
expressions with both operands being constant.
(expr_set_rank): New.
* expr.h (expr_set_rank): Declare.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 11 | ||||
-rw-r--r-- | gas/expr.c | 111 | ||||
-rw-r--r-- | gas/expr.h | 1 |
3 files changed, 116 insertions, 7 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index a3442b3..cf41843 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2009-04-20 Jan Beulich <jbeulich@novell.com> + + * expr.c (operand): Call md_need_index_operator() and + md_operator() if defined. Add unary label. + (operator): Call md_operator() if defined. + (expr): Adjust assertions on range and rank of op_left and + op_right. Don't abort on unhandled operators when reducing + expressions with both operands being constant. + (expr_set_rank): New. + * expr.h (expr_set_rank): Declare. + 2008-04-15 Anthony Green <green@moxielogic.com> * config/tc-moxie.h: New file. @@ -950,10 +950,15 @@ operand (expressionS *expressionP, enum expr_mode mode) break; - case '(': #ifndef NEED_INDEX_OPERATOR case '[': +# ifdef md_need_index_operator + if (md_need_index_operator()) + goto de_fault; +# endif + /* FALLTHROUGH */ #endif + case '(': /* Didn't begin with digit & not a name. */ if (mode != expr_defer) segment = expression (expressionP); @@ -1011,6 +1016,9 @@ operand (expressionS *expressionP, enum expr_mode mode) case '-': case '+': { +#ifdef md_operator + unary: +#endif operand (expressionP, mode); if (expressionP->X_op == O_constant) { @@ -1207,7 +1215,7 @@ operand (expressionS *expressionP, enum expr_mode mode) #endif default: -#ifdef TC_M68K +#if defined(md_need_index_operator) || defined(TC_M68K) de_fault: #endif if (is_name_beginner (c)) /* Here if did not begin with a digit. */ @@ -1218,6 +1226,43 @@ operand (expressionS *expressionP, enum expr_mode mode) name = --input_line_pointer; c = get_symbol_end (); +#ifdef md_operator + { + operatorT operator = md_operator (name, 1, &c); + + switch (operator) + { + case O_uminus: + *input_line_pointer = c; + c = '-'; + goto unary; + case O_bit_not: + *input_line_pointer = c; + c = '~'; + goto unary; + case O_logical_not: + *input_line_pointer = c; + c = '!'; + goto unary; + case O_illegal: + as_bad (_("invalid use of operator \"%s\""), name); + break; + default: + break; + } + if (operator != O_absent && operator != O_illegal) + { + *input_line_pointer = c; + expr (9, expressionP, mode); + expressionP->X_add_symbol = make_expr_symbol (expressionP); + expressionP->X_op_symbol = NULL; + expressionP->X_add_number = 0; + expressionP->X_op = operator; + break; + } + } +#endif + #ifdef md_parse_name /* This is a hook for the backend to parse certain names specially in certain contexts. If a name always has a @@ -1516,6 +1561,13 @@ expr_set_precedence (void) } } +void +expr_set_rank (operatorT operator, operator_rankT rank) +{ + assert (operator >= O_md1 && operator < ARRAY_SIZE (op_rank)); + op_rank[operator] = rank; +} + /* Initialize the expression parser. */ void @@ -1547,10 +1599,50 @@ operator (int *num_chars) if (is_end_of_line[c]) return O_illegal; +#ifdef md_operator + if (is_name_beginner (c)) + { + char *name = input_line_pointer; + char c = get_symbol_end (); + + ret = md_operator (name, 2, &c); + switch (ret) + { + case O_absent: + *input_line_pointer = c; + input_line_pointer = name; + break; + case O_uminus: + case O_bit_not: + case O_logical_not: + as_bad (_("invalid use of operator \"%s\""), name); + ret = O_illegal; + /* FALLTHROUGH */ + default: + *input_line_pointer = c; + *num_chars = input_line_pointer - name; + input_line_pointer = name; + return ret; + } + } +#endif + switch (c) { default: - return op_encoding[c]; + ret = op_encoding[c]; +#ifdef md_operator + if (ret == O_illegal) + { + char *start = input_line_pointer; + + ret = md_operator (NULL, 2, NULL); + if (ret != O_illegal) + *num_chars = input_line_pointer - start; + input_line_pointer = start; + } +#endif + return ret; case '+': case '-': @@ -1689,10 +1781,14 @@ expr (int rankarg, /* Larger # is higher rank. */ op_right = operator (&op_chars); - know (op_right == O_illegal + know (op_right == O_illegal || op_left == O_index || op_rank[(int) op_right] <= op_rank[(int) op_left]); - know ((int) op_left >= (int) O_multiply - && (int) op_left <= (int) O_index); + know ((int) op_left >= (int) O_multiply); +#ifndef md_operator + know ((int) op_left <= (int) O_index); +#else + know ((int) op_left < (int) O_max); +#endif /* input_line_pointer->after right-hand quantity. */ /* left-hand quantity in resultP. */ @@ -1796,7 +1892,7 @@ expr (int rankarg, /* Larger # is higher rank. */ } switch (op_left) { - default: abort (); + default: goto general; case O_multiply: resultP->X_add_number *= v; break; case O_divide: resultP->X_add_number /= v; break; case O_modulus: resultP->X_add_number %= v; break; @@ -1871,6 +1967,7 @@ expr (int rankarg, /* Larger # is higher rank. */ } else { + general: /* The general case. */ resultP->X_add_symbol = make_expr_symbol (resultP); resultP->X_op_symbol = make_expr_symbol (&right); @@ -169,6 +169,7 @@ typedef char operator_rankT; extern char get_symbol_end (void); extern void expr_begin (void); extern void expr_set_precedence (void); +extern void expr_set_rank (operatorT, operator_rankT); extern segT expr (int, expressionS *, enum expr_mode); extern unsigned int get_single_number (void); extern symbolS *make_expr_symbol (expressionS * expressionP); |