summaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-06-18 13:51:52 +0200
committerJan Beulich <jbeulich@suse.com>2021-06-18 13:51:52 +0200
commit162c6aef1f3a96923e75f0b4ef430822d273465c (patch)
tree81686d89de13a729cde555aae7d4b3ac0033005d /gas/expr.c
parent1fef66b0dcc09c9114100e782ea54594550e8fb7 (diff)
downloadbinutils-gdb-162c6aef1f3a96923e75f0b4ef430822d273465c.tar.gz
gas: fold symbol table entries generated for .startof.() / .sizeof.()
When the same such construct is used multiple times in a source file, there's still no need to emit a separate symbol each time. Under the assumption that there won't be many of these, use a simple array lookup method to record previously used symbols.
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/gas/expr.c b/gas/expr.c
index afd065c23be..03caa91f4d1 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -127,6 +127,52 @@ expr_symbol_where (symbolS *sym, const char **pfile, unsigned int *pline)
return 0;
}
+
+/* Look up a previously used .startof. / .sizeof. symbol, or make a fresh
+ one. */
+
+static symbolS *
+symbol_lookup_or_make (const char *name, bool start)
+{
+ static symbolS **seen[2];
+ static unsigned int nr_seen[2];
+ char *buf = concat (start ? ".startof." : ".sizeof.", name, NULL);
+ symbolS *symbolP;
+ unsigned int i;
+
+ for (i = 0; i < nr_seen[start]; ++i)
+ {
+ symbolP = seen[start][i];
+
+ if (! symbolP)
+ break;
+
+ name = S_GET_NAME (symbolP);
+ if ((symbols_case_sensitive
+ ? strcasecmp (buf, name)
+ : strcmp (buf, name)) == 0)
+ {
+ free (buf);
+ return symbolP;
+ }
+ }
+
+ symbolP = symbol_make (buf);
+ free (buf);
+
+ if (i >= nr_seen[start])
+ {
+ unsigned int nr = (i + 1) * 2;
+
+ seen[start] = XRESIZEVEC (symbolS *, seen[start], nr);
+ nr_seen[start] = nr;
+ memset (&seen[start][i + 1], 0, (nr - i - 1) * sizeof(seen[0][0]));
+ }
+
+ seen[start][i] = symbolP;
+
+ return symbolP;
+}
/* Utilities for building expressions.
Since complex expressions are recorded as symbols for use in other
@@ -1159,8 +1205,6 @@ operand (expressionS *expressionP, enum expr_mode mode)
as_bad (_("syntax error in .startof. or .sizeof."));
else
{
- char *buf;
-
++input_line_pointer;
SKIP_WHITESPACE ();
c = get_symbol_name (& name);
@@ -1175,13 +1219,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
break;
}
- buf = concat (start ? ".startof." : ".sizeof.", name,
- (char *) NULL);
- symbolP = symbol_make (buf);
- free (buf);
-
expressionP->X_op = O_symbol;
- expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_symbol = symbol_lookup_or_make (name, start);
expressionP->X_add_number = 0;
*input_line_pointer = c;