diff options
author | Jan Beulich <jbeulich@suse.com> | 2021-06-18 13:51:52 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2021-06-18 13:51:52 +0200 |
commit | 162c6aef1f3a96923e75f0b4ef430822d273465c (patch) | |
tree | 81686d89de13a729cde555aae7d4b3ac0033005d /gas/expr.c | |
parent | 1fef66b0dcc09c9114100e782ea54594550e8fb7 (diff) | |
download | binutils-162c6aef1f3a96923e75f0b4ef430822d273465c.zip binutils-162c6aef1f3a96923e75f0b4ef430822d273465c.tar.gz binutils-162c6aef1f3a96923e75f0b4ef430822d273465c.tar.bz2 |
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.c | 55 |
1 files changed, 47 insertions, 8 deletions
@@ -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; |