aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog6
-rw-r--r--gas/symbols.c135
2 files changed, 88 insertions, 53 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index ef0ae72..34d6970 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2002-12-01 Nathan Sidwell <nathan@codesourcery.com>
+
+ * symbols.c (report_op_error): New function, broken out of ...
+ (resolve_symbol_value): ... here. Use for both monadic and dyadic
+ operators.
+
2002-11-30 Kaz Kojima <kkojima@rr.iij4u.or.jp>
* config/tc-sh.c (md_apply_fix3): Take account of fx_offset
diff --git a/gas/symbols.c b/gas/symbols.c
index ccad71b..fd969f0 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -66,6 +66,7 @@ static long dollar_label_instance PARAMS ((long));
static long fb_label_instance PARAMS ((long));
static void print_binary PARAMS ((FILE *, const char *, expressionS *));
+static void report_op_error PARAMS ((symbolS *, symbolS *, symbolS *));
/* Return a pointer to a new symbol. Die if we can't make a new
symbol. Fill in the symbol's values. Add symbol to end of symbol
@@ -837,6 +838,63 @@ verify_symbol_chain_2 (sym)
verify_symbol_chain (p, n);
}
+static void
+report_op_error (symp, left, right)
+ symbolS *symp;
+ symbolS *left, *right;
+{
+ char *file;
+ unsigned int line;
+ segT seg_left = S_GET_SEGMENT (left);
+ segT seg_right = right ? S_GET_SEGMENT (right) : 0;
+
+ if (expr_symbol_where (symp, &file, &line))
+ {
+ if (seg_left == undefined_section)
+ as_bad_where (file, line,
+ _("undefined symbol `%s' in operation"),
+ S_GET_NAME (left));
+ if (seg_right == undefined_section)
+ as_bad_where (file, line,
+ _("undefined symbol `%s' in operation"),
+ S_GET_NAME (right));
+ if (seg_left != undefined_section
+ && seg_right != undefined_section)
+ {
+ if (right)
+ as_bad_where (file, line,
+ _("invalid sections for operation on `%s' and `%s'"),
+ S_GET_NAME (left), S_GET_NAME (right));
+ else
+ as_bad_where (file, line,
+ _("invalid section for operation on `%s'"),
+ S_GET_NAME (left));
+ }
+
+ }
+ else
+ {
+ if (seg_left == undefined_section)
+ as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+ S_GET_NAME (left), S_GET_NAME (symp));
+ if (seg_right == undefined_section)
+ as_bad (_("undefined symbol `%s' in operation setting `%s'"),
+ S_GET_NAME (right), S_GET_NAME (symp));
+ if (seg_left != undefined_section
+ && seg_right != undefined_section)
+ {
+ if (right)
+ as_bad_where (file, line,
+ _("invalid sections for operation on `%s' and `%s' setting `%s'"),
+ S_GET_NAME (left), S_GET_NAME (right), S_GET_NAME (symp));
+ else
+ as_bad_where (file, line,
+ _("invalid section for operation on `%s' setting `%s'"),
+ S_GET_NAME (left), S_GET_NAME (symp));
+ }
+ }
+}
+
/* Resolve the value of a symbol. This is called during the final
pass over the symbol table to resolve any symbols with complex
values. */
@@ -1002,6 +1060,17 @@ resolve_symbol_value (symp)
left = resolve_symbol_value (add_symbol);
seg_left = S_GET_SEGMENT (add_symbol);
+ /* By reducing these to the relevant dyadic operator, we get
+ !S -> S == 0 permitted on anything,
+ -S -> 0 - S only permitted on absolute
+ ~S -> S ^ ~0 only permitted on absolute */
+ if (op != O_logical_not && seg_left != absolute_section
+ && finalize_syms)
+ report_op_error (symp, add_symbol, NULL);
+
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
+
if (op == O_uminus)
left = -left;
else if (op == O_logical_not)
@@ -1010,8 +1079,6 @@ resolve_symbol_value (symp)
left = ~left;
final_val += left + symp->sy_frag->fr_address;
- if (final_seg == expr_section || final_seg == undefined_section)
- final_seg = seg_left;
resolved = symbol_resolved_p (add_symbol);
break;
@@ -1077,57 +1144,19 @@ resolve_symbol_value (symp)
Don't emit messages unless we're finalizing the symbol value,
otherwise we may get the same message multiple times. */
- if ((op == O_eq || op == O_ne)
- || ((op == O_subtract
- || op == O_lt || op == O_le || op == O_ge || op == O_gt)
- && seg_left == seg_right
- && (seg_left != undefined_section
- || add_symbol == op_symbol))
- || (seg_left == absolute_section
- && seg_right == absolute_section))
- {
- if (final_seg == expr_section || final_seg == undefined_section)
- final_seg = absolute_section;
- }
- else if (finalize_syms)
- {
- char *file;
- unsigned int line;
-
- if (expr_symbol_where (symp, &file, &line))
- {
- if (seg_left == undefined_section)
- as_bad_where (file, line,
- _("undefined symbol `%s' in operation"),
- S_GET_NAME (symp->sy_value.X_add_symbol));
- if (seg_right == undefined_section)
- as_bad_where (file, line,
- _("undefined symbol `%s' in operation"),
- S_GET_NAME (symp->sy_value.X_op_symbol));
- if (seg_left != undefined_section
- && seg_right != undefined_section)
- as_bad_where (file, line,
- _("invalid section for operation"));
- }
- else
- {
- if (seg_left == undefined_section)
- as_bad (_("undefined symbol `%s' in operation setting `%s'"),
- S_GET_NAME (symp->sy_value.X_add_symbol),
- S_GET_NAME (symp));
- if (seg_right == undefined_section)
- as_bad (_("undefined symbol `%s' in operation setting `%s'"),
- S_GET_NAME (symp->sy_value.X_op_symbol),
- S_GET_NAME (symp));
- if (seg_left != undefined_section
- && seg_right != undefined_section)
- as_bad (_("invalid section for operation setting `%s'"),
- S_GET_NAME (symp));
- }
- /* Prevent the error propagating. */
- if (final_seg == expr_section || final_seg == undefined_section)
- final_seg = absolute_section;
- }
+ if (finalize_syms
+ && !(seg_left == absolute_section
+ && seg_right == absolute_section)
+ && !(op == O_eq || op == O_ne)
+ && !((op == O_subtract
+ || op == O_lt || op == O_le || op == O_ge || op == O_gt)
+ && seg_left == seg_right
+ && (seg_left != undefined_section
+ || add_symbol == op_symbol)))
+ report_op_error (symp, add_symbol, op_symbol);
+
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
/* Check for division by zero. */
if ((op == O_divide || op == O_modulus) && right == 0)