/* symbols.c -symbol table-
-
Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#define DEBUG
+/* #define DEBUG_SYMS / * to debug symbol list maintenance */
#include <ctype.h>
symbolS *symbol_lastP;
symbolS abs_symbol;
-symbolS *dot_text_symbol;
-symbolS *dot_data_symbol;
-symbolS *dot_bss_symbol;
-
struct obstack notes;
static void fb_label_init PARAMS ((void));
-void
-symbol_begin ()
-{
- symbol_lastP = NULL;
- symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
- sy_hash = hash_new ();
- memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
-#ifdef BFD_ASSEMBLER
- abs_symbol.bsym = bfd_abs_section.symbol;
-#else
- /* Can't initialise a union. Sigh. */
- S_SET_SEGMENT (&abs_symbol, absolute_section);
-#endif
-#ifdef LOCAL_LABELS_FB
- fb_label_init ();
-#endif /* LOCAL_LABELS_FB */
-}
-
/*
* symbol_new()
*
*/
symbolS *
-symbol_new (name, segment, value, frag)
+symbol_new (name, segment, valu, frag)
CONST char *name; /* It is copied, the caller can destroy/modify */
segT segment; /* Segment identifier (SEG_<something>) */
- valueT value; /* Symbol value */
+ valueT valu; /* Symbol value */
fragS *frag; /* Associated fragment */
{
unsigned int name_length;
S_SET_NAME (symbolP, preserved_copy_of_name);
S_SET_SEGMENT (symbolP, segment);
- S_SET_VALUE (symbolP, value);
+ S_SET_VALUE (symbolP, valu);
symbol_clear_list_pointers(symbolP);
symbolP->sy_frag = frag;
#ifndef BFD_ASSEMBLER
symbolP->sy_number = ~0;
- symbolP->sy_name_offset = ~0;
+ symbolP->sy_name_offset = (unsigned int) ~0;
#endif
/*
obj_symbol_new_hook (symbolP);
-#ifdef DEBUG
+#ifdef DEBUG_SYMS
verify_symbol_chain(symbol_rootP, symbol_lastP);
-#endif /* DEBUG */
+#endif /* DEBUG_SYMS */
return symbolP;
}
S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
(long) S_GET_VALUE (symbolP));
#else
- as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.",
+ as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%ld.",
sym_name,
segment_name (S_GET_SEGMENT (symbolP)),
- S_GET_VALUE (symbolP));
+ (long) S_GET_VALUE (symbolP));
#endif
}
} /* if the undefined symbol has no value */
symbol_table_insert (symbolP);
} /* if we have seen this symbol before */
-#ifdef TC_HPPA
- pa_define_label(symbolP);
-#endif
- return;
-} /* colon() */
+#ifdef tc_frob_label
+ tc_frob_label (symbolP);
+#endif
+}
\f
/*
symbol_table_insert (symbolP)
symbolS *symbolP;
{
- register char *error_string;
+ register const char *error_string;
know (symbolP);
know (S_GET_NAME (symbolP));
- if (*(error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (char *) symbolP)))
+ if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
{
as_fatal ("Inserting \"%s\" into symbol table failed: %s",
S_GET_NAME (symbolP), error_string);
symbolP->sy_previous->sy_next = symbolP->sy_next;
} /* if not first */
-#ifdef DEBUG
+#ifdef DEBUG_SYMS
verify_symbol_chain (*rootPP, *lastPP);
-#endif /* DEBUG */
+#endif /* DEBUG_SYMS */
}
/* Set the chain pointers of SYMBOL to null. */
target->sy_previous = addme;
addme->sy_next = target;
-#ifdef DEBUG
+#ifdef DEBUG_SYMS
verify_symbol_chain (*rootPP, *lastPP);
-#endif /* DEBUG */
+#endif /* DEBUG_SYMS */
}
#endif /* SYMBOLS_NEED_BACKPOINTERS */
know (symbolP->sy_next->sy_previous == symbolP);
#else
/* Walk the list anyways, to make sure pointers are still good. */
- *symbolP;
+ ;
#endif /* SYMBOLS_NEED_BACKPOINTERS */
}
resolve_symbol_value (symp)
symbolS *symp;
{
+ int resolved;
+
if (symp->sy_resolved)
return;
+ resolved = 0;
+
if (symp->sy_resolving)
{
as_bad ("Symbol definition loop encountered at %s",
S_GET_NAME (symp));
S_SET_VALUE (symp, (valueT) 0);
+ resolved = 1;
}
else
{
+ offsetT left, right, val;
+ segT seg_left, seg_right;
+
symp->sy_resolving = 1;
- if (symp->sy_value.X_seg == absolute_section)
- S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
- else if (symp->sy_value.X_seg == undefined_section)
+ switch (symp->sy_value.X_op)
{
+ case O_absent:
+ S_SET_VALUE (symp, 0);
+ /* Fall through. */
+ case O_constant:
+ S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
+ if (S_GET_SEGMENT (symp) == expr_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ resolved = 1;
+ break;
+
+ case O_symbol:
resolve_symbol_value (symp->sy_value.X_add_symbol);
#ifdef obj_frob_forward_symbol
(symp->sy_value.X_add_number
+ symp->sy_frag->fr_address
+ S_GET_VALUE (symp->sy_value.X_add_symbol)));
- }
- else if (symp->sy_value.X_seg == diff_section)
- {
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp,
+ S_GET_SEGMENT (symp->sy_value.X_add_symbol));
+
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
+ break;
+
+ case O_uminus:
+ case O_bit_not:
+ resolve_symbol_value (symp->sy_value.X_add_symbol);
+ if (symp->sy_value.X_op == O_uminus)
+ val = - S_GET_VALUE (symp->sy_value.X_add_symbol);
+ else
+ val = ~ S_GET_VALUE (symp->sy_value.X_add_symbol);
+ S_SET_VALUE (symp,
+ (val
+ + symp->sy_value.X_add_number
+ + symp->sy_frag->fr_address));
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ resolved = symp->sy_value.X_add_symbol->sy_resolved;
+ break;
+
+ case O_multiply:
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
resolve_symbol_value (symp->sy_value.X_add_symbol);
- resolve_symbol_value (symp->sy_value.X_subtract_symbol);
- if (S_GET_SEGMENT (symp->sy_value.X_add_symbol)
- != S_GET_SEGMENT (symp->sy_value.X_subtract_symbol))
- as_bad ("%s is difference of symbols in different sections",
+ resolve_symbol_value (symp->sy_value.X_op_symbol);
+ seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
+ seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
+ if (seg_left != seg_right
+ && seg_left != undefined_section
+ && seg_right != undefined_section)
+ as_bad ("%s is operation on symbols in different sections",
+ S_GET_NAME (symp));
+ if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+ != absolute_section)
+ && symp->sy_value.X_op != O_subtract)
+ as_bad ("%s is illegal operation on non-absolute symbols",
S_GET_NAME (symp));
+ left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+ right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+ switch (symp->sy_value.X_op)
+ {
+ case O_multiply: val = left * right; break;
+ case O_divide: val = left / right; break;
+ case O_modulus: val = left % right; break;
+ case O_left_shift: val = left << right; break;
+ case O_right_shift: val = left >> right; break;
+ case O_bit_inclusive_or: val = left | right; break;
+ case O_bit_or_not: val = left |~ right; break;
+ case O_bit_exclusive_or: val = left ^ right; break;
+ case O_bit_and: val = left & right; break;
+ case O_add: val = left + right; break;
+ case O_subtract: val = left - right; break;
+ default: abort ();
+ }
S_SET_VALUE (symp,
(symp->sy_value.X_add_number
+ symp->sy_frag->fr_address
- + S_GET_VALUE (symp->sy_value.X_add_symbol)
- - S_GET_VALUE (symp->sy_value.X_subtract_symbol)));
- S_SET_SEGMENT (symp, absolute_section);
- }
- else
- {
- /* More cases need to be added here. */
- abort ();
+ + val));
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ resolved = (symp->sy_value.X_add_symbol->sy_resolved
+ && symp->sy_value.X_op_symbol->sy_resolved);
+ break;
+
+ case O_register:
+ case O_big:
+ case O_illegal:
+ /* Give an error (below) if not in expr_section. We don't
+ want to worry about expr_section symbols, because they
+ are fictional (they are created as part of expression
+ resolution), and any problems may not actually mean
+ anything. */
+ break;
}
}
- symp->sy_resolved = 1;
+ /* Don't worry if we can't resolve an expr_section symbol. */
+ if (resolved)
+ symp->sy_resolved = 1;
+ else if (S_GET_SEGMENT (symp) != expr_section)
+ {
+ as_bad ("can't resolve value for symbol \"%s\"", S_GET_NAME (symp));
+ symp->sy_resolved = 1;
+ }
}
#ifdef LOCAL_LABELS_DOLLAR
static long *dollar_label_instances;
static char *dollar_label_defines;
static long dollar_label_count;
-static long dollar_label_max;
+static unsigned long dollar_label_max;
int
dollar_label_defined (label)
void
dollar_label_clear ()
{
- memset (dollar_label_defines, '\0', dollar_label_count);
+ memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
}
#define DOLLAR_LABEL_BUMP_BY 10
static long fb_low_counter[FB_LABEL_SPECIAL];
static long *fb_labels;
static long *fb_label_instances;
-static long fb_label_count = 0;
-static long fb_label_max = 0;
+static long fb_label_count;
+static long fb_label_max;
/* this must be more than FB_LABEL_SPECIAL */
#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
fb_labels[fb_label_count] = label;
fb_label_instances[fb_label_count] = 1;
++fb_label_count;
- return;
-} /* fb_label_instance_inc() */
+}
static long
fb_label_instance (label)
S_GET_VALUE (s)
symbolS *s;
{
- if (s->sy_value.X_seg != absolute_section)
+ if (s->sy_value.X_op != O_constant)
as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
return (valueT) s->sy_value.X_add_number;
}
symbolS *s;
valueT val;
{
- s->sy_value.X_seg = absolute_section;
+ s->sy_value.X_op = O_constant;
s->sy_value.X_add_number = (offsetT) val;
+ s->sy_value.X_unsigned = 0;
}
#ifdef BFD_ASSEMBLER
flagword flags = s->bsym->flags;
/* sanity check */
- if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
+ if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
abort ();
- return (flags & (BSF_EXPORT | BSF_GLOBAL)) != 0;
+ return (flags & BSF_GLOBAL) != 0;
}
int
S_IS_COMMON (s)
symbolS *s;
{
- return s->bsym->section == &bfd_com_section;
+ return bfd_is_com_section (s->bsym->section);
}
int
flagword flags = s->bsym->flags;
/* sanity check */
- if (flags & BSF_LOCAL && flags & (BSF_EXPORT | BSF_GLOBAL))
+ if (flags & BSF_LOCAL && flags & BSF_GLOBAL)
abort ();
return (S_GET_NAME (s)
S_SET_EXTERNAL (s)
symbolS *s;
{
- s->bsym->flags |= BSF_EXPORT | BSF_GLOBAL;
- s->bsym->flags &= ~BSF_LOCAL;
+ s->bsym->flags |= BSF_GLOBAL;
+ s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
}
void
symbolS *s;
{
s->bsym->flags |= BSF_LOCAL;
- s->bsym->flags &= ~(BSF_EXPORT | BSF_GLOBAL);
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
+}
+
+void
+S_SET_WEAK (s)
+ symbolS *s;
+{
+ s->bsym->flags |= BSF_WEAK;
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
}
void
}
#endif /* BFD_ASSEMBLER */
+void
+symbol_begin ()
+{
+ symbol_lastP = NULL;
+ symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
+ sy_hash = hash_new ();
+ memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
+#ifdef BFD_ASSEMBLER
+ abs_symbol.bsym = bfd_abs_section.symbol;
+#else
+ /* Can't initialise a union. Sigh. */
+ S_SET_SEGMENT (&abs_symbol, absolute_section);
+#endif
+#ifdef LOCAL_LABELS_FB
+ fb_label_init ();
+#endif /* LOCAL_LABELS_FB */
+}
+
/* end of symbols.c */