From 162c6aef1f3a96923e75f0b4ef430822d273465c Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 18 Jun 2021 13:51:52 +0200 Subject: [PATCH] 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. --- gas/ChangeLog | 7 +++++ gas/expr.c | 55 ++++++++++++++++++++++++++++----- gas/testsuite/gas/elf/elf.exp | 1 + gas/testsuite/gas/elf/startof.d | 10 ++++++ gas/testsuite/gas/elf/startof.s | 6 ++++ 5 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 gas/testsuite/gas/elf/startof.d create mode 100644 gas/testsuite/gas/elf/startof.s diff --git a/gas/ChangeLog b/gas/ChangeLog index a1997d2c028..9e61c2f3a5e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2021-06-18 Jan Beulich + + * 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 PR 27904 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; diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 525f47c0023..23804758c5a 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -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" diff --git a/gas/testsuite/gas/elf/startof.d b/gas/testsuite/gas/elf/startof.d new file mode 100644 index 00000000000..9cffa93e22b --- /dev/null +++ b/gas/testsuite/gas/elf/startof.d @@ -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 diff --git a/gas/testsuite/gas/elf/startof.s b/gas/testsuite/gas/elf/startof.s new file mode 100644 index 00000000000..a90e1160dd8 --- /dev/null +++ b/gas/testsuite/gas/elf/startof.s @@ -0,0 +1,6 @@ + .data + .dc.a .startof.(.text) + .dc.a .sizeof.(.text) + .dc.a 0 + .dc.a .sizeof.(.text) + .dc.a .startof.(.text) -- 2.30.2