gas: fold symbol table entries generated for .startof.() / .sizeof.()
authorJan Beulich <jbeulich@suse.com>
Fri, 18 Jun 2021 11:51:52 +0000 (13:51 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 18 Jun 2021 11:51:52 +0000 (13:51 +0200)
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
gas/expr.c
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/startof.d [new file with mode: 0644]
gas/testsuite/gas/elf/startof.s [new file with mode: 0644]

index a1997d2c028172bc99a3c447e1bd984884396df7..9e61c2f3a5e95f3df58acab629dd2e38a9b7569c 100644 (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
index afd065c23be3a4c0f6dcc3e712acdb5abbce60b6..03caa91f4d18a8f25361d8d36b4b975cc0c83840 100644 (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;
+}
 \f
 /* 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;
index 525f47c002373900a4b6d3ac283c1855ca2098ad..23804758c5a9a451d11e2cd0ea7508c6a5a3e8e6 100644 (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"
     
diff --git a/gas/testsuite/gas/elf/startof.d b/gas/testsuite/gas/elf/startof.d
new file mode 100644 (file)
index 0000000..9cffa93
--- /dev/null
@@ -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 (file)
index 0000000..a90e116
--- /dev/null
@@ -0,0 +1,6 @@
+       .data
+       .dc.a   .startof.(.text)
+       .dc.a   .sizeof.(.text)
+       .dc.a   0
+       .dc.a   .sizeof.(.text)
+       .dc.a   .startof.(.text)