x86: correctly handle KMOVD with VEX.W set outside of 64-bit mode
[binutils-gdb.git] / gas / symbols.c
index 2056981db2e2ed0382f350ef66fd1c981d717b65..1b9a257371370338d8e5cd2cb00f2246635da958 100644 (file)
 #include "safe-ctype.h"
 #include "obstack.h"           /* For "symbols.h" */
 #include "subsegs.h"
-#include "struc-symbol.h"
 #include "write.h"
 
+struct symbol_flags
+{
+  /* Whether the symbol is a local_symbol.  */
+  unsigned int sy_local_symbol : 1;
+
+  /* Weather symbol has been written.  */
+  unsigned int sy_written : 1;
+
+  /* Whether symbol value has been completely resolved (used during
+     final pass over symbol table).  */
+  unsigned int sy_resolved : 1;
+
+  /* Whether the symbol value is currently being resolved (used to
+     detect loops in symbol dependencies).  */
+  unsigned int sy_resolving : 1;
+
+  /* Whether the symbol value is used in a reloc.  This is used to
+     ensure that symbols used in relocs are written out, even if they
+     are local and would otherwise not be.  */
+  unsigned int sy_used_in_reloc : 1;
+
+  /* Whether the symbol is used as an operand or in an expression.
+     NOTE:  Not all the backends keep this information accurate;
+     backends which use this bit are responsible for setting it when
+     a symbol is used in backend routines.  */
+  unsigned int sy_used : 1;
+
+  /* Whether the symbol can be re-defined.  */
+  unsigned int sy_volatile : 1;
+
+  /* Whether the symbol is a forward reference.  */
+  unsigned int sy_forward_ref : 1;
+
+  /* This is set if the symbol is defined in an MRI common section.
+     We handle such sections as single common symbols, so symbols
+     defined within them must be treated specially by the relocation
+     routines.  */
+  unsigned int sy_mri_common : 1;
+
+  /* This is set if the symbol is set with a .weakref directive.  */
+  unsigned int sy_weakrefr : 1;
+
+  /* This is set when the symbol is referenced as part of a .weakref
+     directive, but only if the symbol was not in the symbol table
+     before.  It is cleared as soon as any direct reference to the
+     symbol is present.  */
+  unsigned int sy_weakrefd : 1;
+};
+
+/* The information we keep for a symbol.  Note that the symbol table
+   holds pointers both to this and to local_symbol structures.  See
+   below.  */
+
+struct symbol
+{
+  /* Symbol flags.  */
+  struct symbol_flags sy_flags;
+
+  /* BFD symbol */
+  asymbol *bsym;
+
+  /* The value of the symbol.  */
+  expressionS sy_value;
+
+  /* Forwards and (optionally) backwards chain pointers.  */
+  struct symbol *sy_next;
+  struct symbol *sy_previous;
+
+  /* Pointer to the frag this symbol is attached to, if any.
+     Otherwise, NULL.  */
+  struct frag *sy_frag;
+
+#ifdef OBJ_SYMFIELD_TYPE
+  OBJ_SYMFIELD_TYPE sy_obj;
+#endif
+
+#ifdef TC_SYMFIELD_TYPE
+  TC_SYMFIELD_TYPE sy_tc;
+#endif
+
+#ifdef TARGET_SYMBOL_FIELDS
+  TARGET_SYMBOL_FIELDS
+#endif
+};
+
+/* A pointer in the symbol may point to either a complete symbol
+   (struct symbol above) or to a local symbol (struct local_symbol
+   defined here).  The symbol code can detect the case by examining
+   the first field.  It is always NULL for a local symbol.
+
+   We do this because we ordinarily only need a small amount of
+   information for a local symbol.  The symbol table takes up a lot of
+   space, and storing less information for a local symbol can make a
+   big difference in assembler memory usage when assembling a large
+   file.  */
+
+struct local_symbol
+{
+  /* Symbol flags.  Only sy_local_symbol and sy_resolved are relevant.  */
+  struct symbol_flags lsy_flags;
+
+  /* The symbol section.  This also serves as a flag.  If this is
+     reg_section, then this symbol has been converted into a regular
+     symbol, and lsy_sym points to it.  */
+  segT lsy_section;
+
+  /* The symbol name.  */
+  const char *lsy_name;
+
+  /* The symbol frag or the real symbol, depending upon the value in
+     lsy_section.  */
+  union
+  {
+    fragS *lsy_frag;
+    symbolS *lsy_sym;
+  } u;
+
+  /* The value of the symbol.  */
+  valueT lsy_value;
+
+#ifdef TC_LOCAL_SYMFIELD_TYPE
+  TC_LOCAL_SYMFIELD_TYPE lsy_tc;
+#endif
+};
+
+#define local_symbol_converted_p(l) ((l)->lsy_section == reg_section)
+#define local_symbol_mark_converted(l) ((l)->lsy_section = reg_section)
+#define local_symbol_resolved_p(l) ((l)->lsy_flags.sy_resolved)
+#define local_symbol_mark_resolved(l) ((l)->lsy_flags.sy_resolved = 1)
+#define local_symbol_get_frag(l) ((l)->u.lsy_frag)
+#define local_symbol_set_frag(l, f) ((l)->u.lsy_frag = (f))
+#define local_symbol_get_real_symbol(l) ((l)->u.lsy_sym)
+#define local_symbol_set_real_symbol(l, s) ((l)->u.lsy_sym = (s))
+
 /* This is non-zero if symbols are case sensitive, which is the
    default.  */
 int symbols_case_sensitive = 1;
@@ -928,6 +1061,20 @@ verify_symbol_chain (symbolS *rootP, symbolS *lastP)
   gas_assert (lastP == symbolP);
 }
 
+int
+symbol_on_chain (symbolS *s, symbolS *rootPP, symbolS *lastPP)
+{
+  return (!LOCAL_SYMBOL_CHECK (s)
+         && ((s->sy_next != s
+              && s->sy_next != NULL
+              && s->sy_next->sy_previous == s)
+             || s == lastPP)
+         && ((s->sy_previous != s
+              && s->sy_previous != NULL
+              && s->sy_previous->sy_next == s)
+             || s == rootPP));
+}
+
 #ifdef OBJ_COMPLEX_RELC
 
 static int
@@ -2733,6 +2880,18 @@ symbol_shadow_p (symbolS *s)
   return s->sy_next == s;
 }
 
+/* If S was created as a struct symbol, return S, otherwise if S is a
+   converted local_symbol return the converted symbol, otherwise
+   return NULL.  */
+
+symbolS *
+symbol_symbolS (symbolS *s)
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return NULL;
+  return s;
+}
+
 /* Return the BFD symbol for a symbol.  */
 
 asymbol *