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.
This commit is contained in:
Jan Beulich 2021-06-18 13:51:52 +02:00
parent 1fef66b0dc
commit 162c6aef1f
5 changed files with 71 additions and 8 deletions

View File

@ -1,3 +1,10 @@
2021-06-18 Jan Beulich <jbeulich@suse.com>
* expr.c (symbol_lookup_or_make): New.
(operand): Use it.
* testsuite/gas/elf/startof.s, testsuite/gas/elf/startof.d: New.
* testsuite/gas/elf/elf.exp: Run new test.
2021-06-17 Nick Clifton <nickc@redhat.com>
PR 27904

View File

@ -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;

View File

@ -309,6 +309,7 @@ if { [is_elf_format] } then {
run_dump_test "pr27355"
run_dump_test "syms"
run_dump_test "startof"
run_dump_test "missing-build-notes"

View File

@ -0,0 +1,10 @@
#name: .startof. / .sizeof.
#readelf: -s
Symbol table .*
Num: .*
0: 0+ .*
#...
[1-8]: 0+ .* UND \.startof\.\.text
[2-9]: 0+ .* UND \.sizeof\.\.text
#pass

View File

@ -0,0 +1,6 @@
.data
.dc.a .startof.(.text)
.dc.a .sizeof.(.text)
.dc.a 0
.dc.a .sizeof.(.text)
.dc.a .startof.(.text)