public inbox for binutils-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gas: tc-tic54x.c hash tables
@ 2022-07-09 12:36 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2022-07-09 12:36 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eb6dce11fca29245eafdde890dbf46ee2e7661bf

commit eb6dce11fca29245eafdde890dbf46ee2e7661bf
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Jul 8 17:37:07 2022 +0930

    gas: tc-tic54x.c hash tables
    
    Cleaning up the subsym_hash memory is a real pain.  Keys and values
    entered into the table are quite diverse.  In some cases the key is
    allocated and thus needs to be freed, in others the key is a const
    string.  Values are similar, and in some cases not even a string.
    Tidy this by inserting a new subsym_ent_t that describes key/value
    type.  This meant the math_hash table was no longer needed.  The patch
    also tidies how math functions are called, those that are supposed to
    return int now no longer return their value in a float.
    
            * config/tc-tic54x.c (math_hash): Delete.
            (subsym_proc_entry): Move earlier, make proc a union, merge with..
            (math_proc_entry): ..this.  Delete type.
            (math_procs): Merge into subsym_procs.
            (subsym_ent_t): New.  Use this type in subsym_hash..
            (stag_add_field_symbols, tic54x_var, tic54x_macro_info): ..here..
            (md_begin, subsym_create_or_replace, subsym_lookup): ..and here..
            (subsym_substitute): ..and here.  Adjust subsym_proc_entry
            function calls.  Free replacement when not returned.
            (subsym_get_arg): Adjust subsym_lookup.
            (free_subsym_ent, subsym_htab_create ): New functions, use when
            creating subsym_hash.
            (free_local_label_ent, local_label_htab_create): Similarly.
            (tic54x_remove_local_label): Delete.
            (tic54x_clear_local_labels): Simplify.
            (tic54x_asg): Use notes obstack to dup strings.
            (tic54x_eval): Likewise.
            (subsym_ismember): Likewise.
            (math_cvi, math_int, math_sgn): Return int.
            (tic54x_macro_start): Decrement macro_level before calling as_fatal.
            (tic54x_md_end): New function.
            * config/tc-tic54h.c (tic54x_md_end): Declare.
            (md_end): Define.

Diff:
---
 gas/config/tc-tic54x.c | 359 ++++++++++++++++++++++++++++++-------------------
 gas/config/tc-tic54x.h |   3 +
 2 files changed, 223 insertions(+), 139 deletions(-)

diff --git a/gas/config/tc-tic54x.c b/gas/config/tc-tic54x.c
index ebefcf1c83c..9bc4fa57033 100644
--- a/gas/config/tc-tic54x.c
+++ b/gas/config/tc-tic54x.c
@@ -182,12 +182,35 @@ static symbolS *last_label_seen = NULL;
 static int local_label_id;
 
 static htab_t subsym_recurse_hash; /* Prevent infinite recurse.  */
-static htab_t math_hash; /* Built-in math functions.  */
 /* Allow maximum levels of macro nesting; level 0 is the main substitution
    symbol table.  The other assembler only does 32 levels, so there!  */
 #define MAX_SUBSYM_HASH 100
 static htab_t subsym_hash[MAX_SUBSYM_HASH];
 
+typedef struct
+{
+  const char *name;
+  union {
+    int (*s) (char *, char *);
+    float (*f) (float, float);
+    int (*i) (float, float);
+  } proc;
+  int nargs;
+  int type;
+} subsym_proc_entry;
+
+typedef struct {
+  union {
+    char *s;
+    const subsym_proc_entry *p;
+  } u;
+  unsigned int freekey : 1;
+  unsigned int freeval : 1;
+  unsigned int isproc : 1;
+  unsigned int ismath : 1;
+} subsym_ent_t;
+
+
 /* Keep track of local labels so we can substitute them before GAS sees them
    since macros use their own 'namespace' for local labels, use a separate hash
 
@@ -197,7 +220,7 @@ static htab_t subsym_hash[MAX_SUBSYM_HASH];
    We use our own macro nesting counter, since GAS overloads it when expanding
    other things (like conditionals and repeat loops).  */
 static int macro_level = 0;
-static htab_t local_label_hash[100];
+static htab_t local_label_hash[MAX_SUBSYM_HASH];
 /* Keep track of struct/union tags.  */
 static htab_t stag_hash;
 static htab_t op_hash;
@@ -223,7 +246,7 @@ static htab_t misc_symbol_hash;
 
 
 static void subsym_create_or_replace (char *, char *);
-static char *subsym_lookup (char *, int);
+static subsym_ent_t *subsym_lookup (char *, int);
 static char *subsym_substitute (char *, int);
 
 
@@ -334,6 +357,7 @@ tic54x_asg (int x ATTRIBUTE_UNUSED)
     }
   else
     {
+      size_t len;
       str = input_line_pointer;
       while ((c = *input_line_pointer) != ',')
 	{
@@ -341,28 +365,30 @@ tic54x_asg (int x ATTRIBUTE_UNUSED)
 	    break;
 	  ++input_line_pointer;
 	}
-      *input_line_pointer = 0;
+      len = input_line_pointer - str;
+      str = notes_memdup (str, len, len + 1);
     }
   if (c != ',')
     {
       as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
+      notes_free (str);
       ignore_rest_of_line ();
       return;
     }
 
   ++input_line_pointer;
   c = get_symbol_name (&name);	/* Get terminator.  */
+  name = notes_strdup (name);
+  (void) restore_line_pointer (c);
   if (!ISALPHA (*name))
     {
       as_bad (_("symbols assigned with .asg must begin with a letter"));
+      notes_free (str);
       ignore_rest_of_line ();
       return;
     }
 
-  str = xstrdup (str);
-  name = xstrdup (name);
   subsym_create_or_replace (name, str);
-  (void) restore_line_pointer (c);
   demand_empty_rest_of_line ();
 }
 
@@ -407,15 +433,17 @@ tic54x_eval (int x ATTRIBUTE_UNUSED)
       return;
     }
   c = get_symbol_name (&name);	/* Get terminator.  */
-  name = xstrdup (name);
-  (void) restore_line_pointer (c);
 
   if (!ISALPHA (*name))
     {
       as_bad (_("symbols assigned with .eval must begin with a letter"));
+      (void) restore_line_pointer (c);
       ignore_rest_of_line ();
       return;
     }
+  name = notes_strdup (name);
+  (void) restore_line_pointer (c);
+
   symbolP = symbol_new (name, absolute_section, &zero_address_frag, value);
   SF_SET_LOCAL (symbolP);
   symbol_table_insert (symbolP);
@@ -424,7 +452,7 @@ tic54x_eval (int x ATTRIBUTE_UNUSED)
      But since there's not written rule as to when, don't even bother trying
      to match their behavior.  */
   sprintf (valuestr, "%d", value);
-  tmp = xstrdup (valuestr);
+  tmp = notes_strdup (valuestr);
   subsym_create_or_replace (name, tmp);
 
   demand_empty_rest_of_line ();
@@ -564,11 +592,14 @@ stag_add_field_symbols (struct stag *stag,
 	}
       else
 	{
-	  char *replacement;
-
-	  replacement = concat (S_GET_NAME (rootsym), "+", root_stag_name,
-				name + strlen (S_GET_NAME (rootsym)), NULL);
-	  str_hash_insert (subsym_hash[0], name, replacement, 0);
+	  subsym_ent_t *ent = xmalloc (sizeof (*ent));
+	  ent->u.s = concat (S_GET_NAME (rootsym), "+", root_stag_name,
+			     name + strlen (S_GET_NAME (rootsym)), NULL);
+	  ent->freekey = 1;
+	  ent->freeval = 1;
+	  ent->isproc = 0;
+	  ent->ismath = 0;
+	  str_hash_insert (subsym_hash[0], name, ent, 0);
 	  freename = NULL;
 	}
 
@@ -1115,16 +1146,40 @@ tic54x_global (int type)
   demand_empty_rest_of_line ();
 }
 
-/* Remove the symbol from the local label hash lookup.  */
+static void
+free_subsym_ent (void *ent)
+{
+  string_tuple_t *tuple = (string_tuple_t *) ent;
+  subsym_ent_t *val = (void *) tuple->value;
+  if (val->freekey)
+    free ((void *) tuple->key);
+  if (val->freeval)
+    free (val->u.s);
+  free (val);
+  free (ent);
+}
 
-static int
-tic54x_remove_local_label (void **slot, void *arg ATTRIBUTE_UNUSED)
+static htab_t
+subsym_htab_create (void)
 {
-  string_tuple_t *tuple = *((string_tuple_t **) slot);
-  void *elem = str_hash_find (local_label_hash[macro_level], tuple->key);
-  str_hash_delete (local_label_hash[macro_level], tuple->key);
-  free (elem);
-  return 0;
+  return htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
+			    free_subsym_ent, xcalloc, free);
+}
+
+static void
+free_local_label_ent (void *ent)
+{
+  string_tuple_t *tuple = (string_tuple_t *) ent;
+  free ((void *) tuple->key);
+  free ((void *) tuple->value);
+  free (ent);
+}
+
+static htab_t
+local_label_htab_create (void)
+{
+  return htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
+			    free_local_label_ent, xcalloc, free);
 }
 
 /* Reset all local labels.  */
@@ -1132,7 +1187,7 @@ tic54x_remove_local_label (void **slot, void *arg ATTRIBUTE_UNUSED)
 static void
 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED)
 {
-  htab_traverse (local_label_hash[macro_level], tic54x_remove_local_label, NULL);
+  htab_empty (local_label_hash[macro_level]);
 }
 
 /* .text
@@ -2215,7 +2270,6 @@ tic54x_sslist (int show)
 static void
 tic54x_var (int ignore ATTRIBUTE_UNUSED)
 {
-  static char empty[] = "";
   char *name;
   int c;
 
@@ -2236,10 +2290,17 @@ tic54x_var (int ignore ATTRIBUTE_UNUSED)
 	  return;
 	}
       c = get_symbol_name (&name);
-      /* .var symbols start out with a null string.  */
       name = xstrdup (name);
-      str_hash_insert (subsym_hash[macro_level], name, empty, 0);
       c = restore_line_pointer (c);
+
+      /* .var symbols start out with a null string.  */
+      subsym_ent_t *ent = xmalloc (sizeof (*ent));
+      ent->u.s = (char *) "";
+      ent->freekey = 1;
+      ent->freeval = 0;
+      ent->isproc = 0;
+      ent->ismath = 0;
+      str_hash_insert (subsym_hash[macro_level], name, ent, 0);
       if (c == ',')
 	{
 	  ++input_line_pointer;
@@ -2503,11 +2564,12 @@ tic54x_macro_start (void)
 {
   if (++macro_level >= MAX_SUBSYM_HASH)
     {
+      --macro_level;
       as_fatal (_("Macro nesting is too deep"));
       return;
     }
-  subsym_hash[macro_level] = str_htab_create ();
-  local_label_hash[macro_level] = str_htab_create ();
+  subsym_hash[macro_level] = subsym_htab_create ();
+  local_label_hash[macro_level] = local_label_htab_create ();
 }
 
 void
@@ -2519,11 +2581,14 @@ tic54x_macro_info (const macro_entry *macro)
   for (entry = macro->formals; entry; entry = entry->next)
     {
       char *name = xstrndup (entry->name.ptr, entry->name.len);
-      char *value = xstrndup (entry->actual.ptr, entry->actual.len);
+      subsym_ent_t *ent = xmalloc (sizeof (*ent));
 
-      name[entry->name.len] = '\0';
-      value[entry->actual.len] = '\0';
-      str_hash_insert (subsym_hash[macro_level], name, value, 0);
+      ent->u.s = xstrndup (entry->actual.ptr, entry->actual.len);
+      ent->freekey = 1;
+      ent->freeval = 1;
+      ent->isproc = 0;
+      ent->ismath = 0;
+      str_hash_insert (subsym_hash[macro_level], name, ent, 0);
     }
 }
 
@@ -2594,20 +2659,21 @@ subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED)
 static int
 subsym_ismember (char *sym, char *list)
 {
-  char *elem, *ptr, *listv;
+  char *elem, *ptr;
+  subsym_ent_t *listv;
 
   if (!list)
     return 0;
 
   listv = subsym_lookup (list, macro_level);
-  if (!listv)
+  if (!listv || listv->isproc)
     {
       as_bad (_("Undefined substitution symbol '%s'"), list);
       ignore_rest_of_line ();
       return 0;
     }
 
-  ptr = elem = xstrdup (listv);
+  ptr = elem = notes_strdup (listv->u.s);
   while (*ptr && *ptr != ',')
     ++ptr;
   *ptr++ = 0;
@@ -2728,7 +2794,7 @@ math_ceil (float arg1, float ignore ATTRIBUTE_UNUSED)
   return (float) ceil (arg1);
 }
 
-static float
+static int
 math_cvi (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
   return (int) arg1;
@@ -2746,10 +2812,10 @@ math_fmod (float arg1, float arg2)
   return (int) arg1 % (int) arg2;
 }
 
-static float
+static int
 math_int (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
-  return ((float) ((int) arg1)) == arg1;
+  return arg1 == (float) (int) arg1;
 }
 
 static float
@@ -2758,10 +2824,10 @@ math_round (float arg1, float ignore ATTRIBUTE_UNUSED)
   return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5);
 }
 
-static float
+static int
 math_sgn (float arg1, float ignore ATTRIBUTE_UNUSED)
 {
-  return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
+  return arg1 < 0.0f ? -1 : arg1 != 0.0f ? 1 : 0;
 }
 
 static float
@@ -2893,72 +2959,53 @@ math_tanh (float arg1, float ignore ATTRIBUTE_UNUSED)
 }
 
 /* Built-in substitution symbol functions and math functions.  */
-typedef struct
-{
-  const char *name;
-  int (*proc) (char *, char *);
-  int nargs;
-} subsym_proc_entry;
-
 static const subsym_proc_entry subsym_procs[] =
 {
   /* Assembler built-in string substitution functions.  */
-  { "$symlen", subsym_symlen, 1,  },
-  { "$symcmp", subsym_symcmp, 2,  },
-  { "$firstch", subsym_firstch, 2,  },
-  { "$lastch", subsym_lastch, 2,  },
-  { "$isdefed", subsym_isdefed, 1,  },
-  { "$ismember", subsym_ismember, 2,  },
-  { "$iscons", subsym_iscons, 1,  },
-  { "$isname", subsym_isname, 1,  },
-  { "$isreg", subsym_isreg, 1,  },
-  { "$structsz", subsym_structsz, 1,  },
-  { "$structacc", subsym_structacc, 1,  },
-  { NULL, NULL, 0 },
-};
-
-typedef struct
-{
-  const char *name;
-  float (*proc) (float, float);
-  int nargs;
-  int int_return;
-} math_proc_entry;
+  { "$symlen",    { .s = subsym_symlen },    1, 0 },
+  { "$symcmp",    { .s = subsym_symcmp },    2, 0 },
+  { "$firstch",   { .s = subsym_firstch },   2, 0 },
+  { "$lastch",    { .s = subsym_lastch },    2, 0 },
+  { "$isdefed",   { .s = subsym_isdefed },   1, 0 },
+  { "$ismember",  { .s = subsym_ismember },  2, 0 },
+  { "$iscons",    { .s = subsym_iscons },    1, 0 },
+  { "$isname",    { .s = subsym_isname },    1, 0 },
+  { "$isreg",     { .s = subsym_isreg },     1, 0 },
+  { "$structsz",  { .s = subsym_structsz },  1, 0 },
+  { "$structacc", { .s = subsym_structacc }, 1, 0 },
 
-static const math_proc_entry math_procs[] =
-{
   /* Integer-returning built-in math functions.  */
-  { "$cvi", math_cvi, 1, 1 },
-  { "$int", math_int, 1, 1 },
-  { "$sgn", math_sgn, 1, 1 },
+  { "$cvi",       { .i = math_cvi },         1, 2 },
+  { "$int",       { .i = math_int },         1, 2 },
+  { "$sgn",       { .i = math_sgn },         1, 2 },
 
   /* Float-returning built-in math functions.  */
-  { "$acos", math_acos, 1, 0 },
-  { "$asin", math_asin, 1, 0 },
-  { "$atan", math_atan, 1, 0 },
-  { "$atan2", math_atan2, 2, 0 },
-  { "$ceil", math_ceil, 1, 0 },
-  { "$cosh", math_cosh, 1, 0 },
-  { "$cos", math_cos, 1, 0 },
-  { "$cvf", math_cvf, 1, 0 },
-  { "$exp", math_exp, 1, 0 },
-  { "$fabs", math_fabs, 1, 0 },
-  { "$floor", math_floor, 1, 0 },
-  { "$fmod", math_fmod, 2, 0 },
-  { "$ldexp", math_ldexp, 2, 0 },
-  { "$log10", math_log10, 1, 0 },
-  { "$log", math_log, 1, 0 },
-  { "$max", math_max, 2, 0 },
-  { "$min", math_min, 2, 0 },
-  { "$pow", math_pow, 2, 0 },
-  { "$round", math_round, 1, 0 },
-  { "$sin", math_sin, 1, 0 },
-  { "$sinh", math_sinh, 1, 0 },
-  { "$sqrt", math_sqrt, 1, 0 },
-  { "$tan", math_tan, 1, 0 },
-  { "$tanh", math_tanh, 1, 0 },
-  { "$trunc", math_trunc, 1, 0 },
-  { NULL, NULL, 0, 0 },
+  { "$acos",      { .f = math_acos },        1, 1 },
+  { "$asin",      { .f = math_asin },        1, 1 },
+  { "$atan",      { .f = math_atan },        1, 1 },
+  { "$atan2",     { .f = math_atan2 },       2, 1 },
+  { "$ceil",      { .f = math_ceil },        1, 1 },
+  { "$cosh",      { .f = math_cosh },        1, 1 },
+  { "$cos",       { .f = math_cos },         1, 1 },
+  { "$cvf",       { .f = math_cvf },         1, 1 },
+  { "$exp",       { .f = math_exp },         1, 1 },
+  { "$fabs",      { .f = math_fabs },        1, 1 },
+  { "$floor",     { .f = math_floor },       1, 1 },
+  { "$fmod",      { .f = math_fmod },        2, 1 },
+  { "$ldexp",     { .f = math_ldexp },       2, 1 },
+  { "$log10",     { .f = math_log10 },       1, 1 },
+  { "$log",       { .f = math_log },         1, 1 },
+  { "$max",       { .f = math_max },         2, 1 },
+  { "$min",       { .f = math_min },         2, 1 },
+  { "$pow",       { .f = math_pow },         2, 1 },
+  { "$round",     { .f = math_round },       1, 1 },
+  { "$sin",       { .f = math_sin },         1, 1 },
+  { "$sinh",      { .f = math_sinh },        1, 1 },
+  { "$sqrt",      { .f = math_sqrt },        1, 1 },
+  { "$tan",       { .f = math_tan },         1, 1 },
+  { "$tanh",      { .f = math_tanh },        1, 1 },
+  { "$trunc",     { .f = math_trunc },       1, 1 },
+  { NULL, { NULL }, 0, 0 },
 };
 
 void
@@ -2967,7 +3014,6 @@ md_begin (void)
   insn_template *tm;
   const tic54x_symbol *sym;
   const subsym_proc_entry *subsym_proc;
-  const math_proc_entry *math_proc;
   const char **symname;
   char *TIC54X_DIR = getenv ("TIC54X_DIR");
   char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
@@ -3037,23 +3083,41 @@ md_begin (void)
 
   /* Only the base substitution table and local label table are initialized;
      the others (for local macro substitution) get instantiated as needed.  */
-  local_label_hash[0] = str_htab_create ();
-  subsym_hash[0] = str_htab_create ();
+  local_label_hash[0] = local_label_htab_create ();
+  subsym_hash[0] = subsym_htab_create ();
   for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
-    str_hash_insert (subsym_hash[0], subsym_proc->name, subsym_proc, 0);
-
-  math_hash = str_htab_create ();
-  for (math_proc = math_procs; math_proc->name; math_proc++)
     {
-      /* Insert into the main subsym hash for recognition; insert into
-	 the math hash to actually store information.  */
-      str_hash_insert (subsym_hash[0], math_proc->name, math_proc, 0);
-      str_hash_insert (math_hash, math_proc->name, math_proc, 0);
+      subsym_ent_t *ent = xmalloc (sizeof (*ent));
+      ent->u.p = subsym_proc;
+      ent->freekey = 0;
+      ent->freeval = 0;
+      ent->isproc = 1;
+      ent->ismath = subsym_proc->type != 0;
+      str_hash_insert (subsym_hash[0], subsym_proc->name, ent, 0);
     }
   subsym_recurse_hash = str_htab_create ();
   stag_hash = str_htab_create ();
 }
 
+void
+tic54x_md_end (void)
+{
+  htab_delete (stag_hash);
+  htab_delete (subsym_recurse_hash);
+  while (macro_level != -1)
+    tic54x_macro_end ();
+  macro_level = 0;
+  htab_delete (misc_symbol_hash);
+  htab_delete (sbit_hash);
+  htab_delete (cc3_hash);
+  htab_delete (cc2_hash);
+  htab_delete (cc_hash);
+  htab_delete (mmreg_hash);
+  htab_delete (reg_hash);
+  htab_delete (parop_hash);
+  htab_delete (op_hash);
+}
+
 static int
 is_accumulator (struct opstruct *operand)
 {
@@ -4295,7 +4359,6 @@ subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
   else
     {
       const char *term = terminators;
-      char *value = NULL;
 
       while (*ptr && *ptr != *term)
 	{
@@ -4310,8 +4373,12 @@ subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
       endp = ptr;
       *str = xmemdup0 (line, ptr - line);
       /* Do simple substitution, if available.  */
-      if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
-	*str = value;
+      if (!nosub)
+	{
+	  subsym_ent_t *ent = subsym_lookup (*str, macro_level);
+	  if (ent && !ent->isproc)
+	    *str = ent->u.s;
+	}
     }
 
   return endp;
@@ -4326,24 +4393,30 @@ static void
 subsym_create_or_replace (char *name, char *value)
 {
   int i;
+  subsym_ent_t *ent = xmalloc (sizeof (*ent));
+  ent->u.s = value;
+  ent->freekey = 0;
+  ent->freeval = 0;
+  ent->isproc = 0;
+  ent->ismath = 0;
 
   for (i = macro_level; i > 0; i--)
     if (str_hash_find (subsym_hash[i], name))
       {
-	str_hash_insert (subsym_hash[i], name, value, 1);
+	str_hash_insert (subsym_hash[i], name, ent, 1);
 	return;
       }
-  str_hash_insert (subsym_hash[0], name, value, 1);
+  str_hash_insert (subsym_hash[0], name, ent, 1);
 }
 
 /* Look up the substitution string replacement for the given symbol.
    Start with the innermost macro substitution table given and work
    outwards.  */
 
-static char *
+static subsym_ent_t *
 subsym_lookup (char *name, int nest_level)
 {
-  char *value = str_hash_find (subsym_hash[nest_level], name);
+  void *value = str_hash_find (subsym_hash[nest_level], name);
 
   if (value || nest_level == 0)
     return value;
@@ -4374,11 +4447,7 @@ subsym_substitute (char *line, int forced)
   int recurse = 1;
   int line_conditional = 0;
   char *tmp;
-
-  /* Work with a copy of the input line.  */
-  replacement = xstrdup (line);
-
-  ptr = head = replacement;
+  unsigned char current_char;
 
   /* Flag lines where we might need to replace a single '=' with two;
      GAS uses single '=' to assign macro args values, and possibly other
@@ -4398,7 +4467,10 @@ subsym_substitute (char *line, int forced)
   if (strstr (line, ".macro"))
     return line;
 
-  unsigned char current_char;
+  /* Work with a copy of the input line.  */
+  replacement = xstrdup (line);
+  ptr = head = replacement;
+
   while (!is_end_of_line[(current_char = * (unsigned char *) ptr)])
     {
       /* Need to update this since LINE may have been modified.  */
@@ -4445,6 +4517,7 @@ subsym_substitute (char *line, int forced)
 	  char *name; /* Symbol to be replaced.  */
 	  char *savedp = input_line_pointer;
 	  int c;
+	  subsym_ent_t *ent = NULL;
 	  char *value = NULL;
 	  char *tail; /* Rest of line after symbol.  */
 
@@ -4465,7 +4538,11 @@ subsym_substitute (char *line, int forced)
 	  /* Avoid infinite recursion; if a symbol shows up a second time for
 	     substitution, leave it as is.  */
 	  if (str_hash_find (subsym_recurse_hash, name) == NULL)
-	    value = subsym_lookup (name, macro_level);
+	    {
+	      ent = subsym_lookup (name, macro_level);
+	      if (ent && !ent->isproc)
+		value = ent->u.s;
+	    }
 	  else
 	    as_warn (_("%s symbol recursion stopped at "
 		       "second appearance of '%s'"),
@@ -4499,14 +4576,13 @@ subsym_substitute (char *line, int forced)
 	      ptr = tail;
 	    }
 	  /* Check for built-in subsym and math functions.  */
-	  else if (value != NULL && *name == '$')
+	  else if (ent != NULL && *name == '$')
 	    {
-	      subsym_proc_entry *entry = (subsym_proc_entry *) value;
-	      math_proc_entry *math_entry = str_hash_find (math_hash, name);
+	      const subsym_proc_entry *entry = ent->u.p;
 	      char *arg1, *arg2 = NULL;
 
 	      *ptr = c;
-	      if (entry == NULL)
+	      if (!ent->isproc)
 		{
 		  as_bad (_("Unrecognized substitution symbol function"));
 		  break;
@@ -4517,13 +4593,12 @@ subsym_substitute (char *line, int forced)
 		  break;
 		}
 	      ++ptr;
-	      if (math_entry != NULL)
+	      if (ent->ismath)
 		{
 		  float farg1, farg2 = 0;
-		  volatile float fresult;
 
 		  farg1 = (float) strtod (ptr, &ptr);
-		  if (math_entry->nargs == 2)
+		  if (entry->nargs == 2)
 		    {
 		      if (*ptr++ != ',')
 			{
@@ -4532,12 +4607,17 @@ subsym_substitute (char *line, int forced)
 			}
 		      farg2 = (float) strtod (ptr, &ptr);
 		    }
-		  fresult = (*math_entry->proc) (farg1, farg2);
 		  value = XNEWVEC (char, 128);
-		  if (math_entry->int_return)
-		    sprintf (value, "%d", (int) fresult);
+		  if (entry->type == 2)
+		    {
+		      int result = (*entry->proc.i) (farg1, farg2);
+		      sprintf (value, "%d", result);
+		    }
 		  else
-		    sprintf (value, "%f", fresult);
+		    {
+		      float result = (*entry->proc.f) (farg1, farg2);
+		      sprintf (value, "%f", result);
+		    }
 		  if (*ptr++ != ')')
 		    {
 		      as_bad (_("Extra junk in function call, expecting ')'"));
@@ -4593,7 +4673,7 @@ subsym_substitute (char *line, int forced)
 		      as_bad (_("Extra junk in function call, expecting ')'"));
 		      break;
 		    }
-		  val = (*entry->proc) (arg1, arg2);
+		  val = (*entry->proc.s) (arg1, arg2);
 		  value = XNEWVEC (char, 64);
 		  sprintf (value, "%d", val);
 		}
@@ -4703,8 +4783,9 @@ subsym_substitute (char *line, int forced)
 
   if (changed)
     return replacement;
-  else
-    return line;
+
+  free (replacement);
+  return line;
 }
 
 /* We use this to handle substitution symbols
diff --git a/gas/config/tc-tic54x.h b/gas/config/tc-tic54x.h
index d32e0bc095b..431895d1e4e 100644
--- a/gas/config/tc-tic54x.h
+++ b/gas/config/tc-tic54x.h
@@ -131,4 +131,7 @@ extern void tic54x_convert_frag(bfd *, segT, fragS *);
 
 extern void tic54x_global (int);
 
+extern void tic54x_md_end (void);
+#define md_end tic54x_md_end
+
 #endif


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-07-09 12:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-09 12:36 [binutils-gdb] gas: tc-tic54x.c hash tables Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).