Hello again,

most of this patch was posted at the beginning of my GSOC adventure and primarily is about replacing fprintf() calls with custom faster ones. From that time I changed minor things you suggested, omitted some complexities that offered minor speed-up, and made the code as clear as possible, while following more closely coding guidelines.

Bootstrapped and tested on both i386 and x86_64, showing runtime improvement when compiling with debug info enabled.

The only thing I am not sure is the differentiation between HOST_WIDE_INT and long, so I provided two versions of the same function. Please let me know if I should handle this differently.


Future speedup in assembly generation *is possible* but requires more intrusive changes, maybe making assembly hard to read by human:
* Always use hex numbers, they are much faster to produce
* Call GNU assembler with -s parameter, though it's pretty hard to be compliant. * Even further in the future we could generate binary data, if we *know* the assembler is GAS.


Changelog:

2011-08-12  Dimitrios Apostolou  <ji...@gmx.net>

        * final.c, output.h (fprint_whex, fprint_w, fprint_ul, sprint_ul):
        New functions serving as fast replacements for fprintf() integer
        to string conversions. They were used in the following changes.
        * final.c (sprint_ul_rev): Internal helper for the above.
        (output_addr_const): case CONST_INT: don't use fprintf().
        * elfos.h (ASM_GENERATE_INTERNAL_LABEL): Don't use sprintf("%u"),
        use sprint_ul() and custom loop which are much faster.
        (TARGET_ASM_INTERNAL_LABEL): Define as default_elf_internal_label.
        (ELF_ASCII_ESCAPES, ELF_STRING_LIMIT): Are the old ESCAPES and
        STRING_LIMIT macros.
        (ASM_OUTPUT_LIMITED_STRING, ASM_OUTPUT_ASCII): Macros now just
        call respective functions that provide now the same
        functionality. Those are default_elf_asm_output_limited_string()
        and default_elf_asm_output_ascii() in varasm.c.
        * varasm.c: Fixed some whitespace inconsistencies.
        (default_elf_asm_output_limited_string)
        (default_elf_asm_output_ascii): The above macros from elfos.h are
        implemented here, avoiding superfluous calls to fprintf().
        (default_elf_internal_label): Hook for
        targetm.asm_out.internal_label and ASM_OUTPUT_DEBUG_LABEL.
        * i386.c: Don't call fprintf("%u") but fprint_ul() instead.
        * defaults.h (ASM_OUTPUT_LABEL, ASM_OUTPUT_INTERNAL_LABEL):
        Expanded the macros on multiple lines for readability.
        (ASM_OUTPUT_LABELREF): Have two calls to fputs() instead of one to
        asm_fprintf().
        * dwarf2asm.c (dw2_assemble_integer, dw2_asm_output_data)
        (dw2_asm_data_uleb128, dw2_asm_delta_uleb128)
        (dw2_asm_delta_sleb128): Convert fprintf() calls to faster,
        simpler functions.
        * dwarf2out.c (dwarf2out_source_line): Convert fprintf() calls to
        faster, simpler functions.



Thanks,
Dimitris
=== modified file 'gcc/config/elfos.h'
--- gcc/config/elfos.h  2010-11-21 00:54:14 +0000
+++ gcc/config/elfos.h  2011-08-22 11:39:43 +0000
@@ -117,10 +117,23 @@ see the files COPYING3 and COPYING.RUNTI
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM)                \
   do                                                           \
     {                                                          \
-      sprintf (LABEL, "*.%s%u", PREFIX, (unsigned) (NUM));     \
+      int __i = 2;                                             \
+      int __j = 0;                                             \
+      (LABEL)[0] = '*';                                                \
+      (LABEL)[1] = '.';                                                \
+      do                                                       \
+       {                                                       \
+         (LABEL)[__i] = (PREFIX)[__j];                         \
+         __i++; __j++;                                         \
+       }                                                       \
+      while ((PREFIX)[__j] != '\0');                           \
+      sprint_ul (&(LABEL)[__i], (unsigned long) (NUM));                \
     }                                                          \
   while (0)
 
+#undef TARGET_ASM_INTERNAL_LABEL
+#define TARGET_ASM_INTERNAL_LABEL default_elf_internal_label
+
 /* Output the label which precedes a jumptable.  Note that for all svr4
    systems where we actually generate jumptables (which is to say every
    svr4 target except i386, where we use casesi instead) we put the jump-
@@ -371,7 +384,7 @@ see the files COPYING3 and COPYING.RUNTI
    the i386) don't know about that.  Also, we don't use \v
    since some versions of gas, such as 2.2 did not accept it.  */
 
-#define ESCAPES \
+#define ELF_ASCII_ESCAPES \
 "\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
 \0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
@@ -393,9 +406,7 @@ see the files COPYING3 and COPYING.RUNTI
    should define this to zero.
 */
 
-#define STRING_LIMIT   ((unsigned) 256)
-
-#define STRING_ASM_OP  "\t.string\t"
+#define ELF_STRING_LIMIT       ((unsigned) 256)
 
 /* The routine used to output NUL terminated strings.  We use a special
    version of this for most svr4 targets because doing so makes the
@@ -405,36 +416,7 @@ see the files COPYING3 and COPYING.RUNTI
    comma separated lists of numbers).  */
 
 #define ASM_OUTPUT_LIMITED_STRING(FILE, STR)           \
-  do                                                   \
-    {                                                  \
-      register const unsigned char *_limited_str =     \
-       (const unsigned char *) (STR);                  \
-      register unsigned ch;                            \
-                                                       \
-      fprintf ((FILE), "%s\"", STRING_ASM_OP);         \
-                                                       \
-      for (; (ch = *_limited_str); _limited_str++)     \
-        {                                              \
-         register int escape;                          \
-                                                       \
-         switch (escape = ESCAPES[ch])                 \
-           {                                           \
-           case 0:                                     \
-             putc (ch, (FILE));                        \
-             break;                                    \
-           case 1:                                     \
-             fprintf ((FILE), "\\%03o", ch);           \
-             break;                                    \
-           default:                                    \
-             putc ('\\', (FILE));                      \
-             putc (escape, (FILE));                    \
-             break;                                    \
-           }                                           \
-        }                                              \
-                                                       \
-      fprintf ((FILE), "\"\n");                                \
-    }                                                  \
-  while (0)
+  default_elf_asm_output_limited_string ((FILE), (STR))
 
 /* The routine used to output sequences of byte values.  We use a special
    version of this for most svr4 targets because doing so makes the
@@ -444,76 +426,8 @@ see the files COPYING3 and COPYING.RUNTI
    STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
 
 #undef  ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH)                            \
-  do                                                                   \
-    {                                                                  \
-      const unsigned char *_ascii_bytes =                              \
-       (const unsigned char *) (STR);                                  \
-      const unsigned char *limit = _ascii_bytes + (LENGTH);            \
-      const unsigned char *last_null = NULL;                           \
-      unsigned bytes_in_chunk = 0;                                     \
-                                                                       \
-      for (; _ascii_bytes < limit; _ascii_bytes++)                     \
-        {                                                              \
-         const unsigned char *p;                                       \
-                                                                       \
-         if (bytes_in_chunk >= 60)                                     \
-           {                                                           \
-             fprintf ((FILE), "\"\n");                                 \
-             bytes_in_chunk = 0;                                       \
-           }                                                           \
-                                                                       \
-         if (_ascii_bytes > last_null)                                 \
-           {                                                           \
-             for (p = _ascii_bytes; p < limit && *p != '\0'; p++)      \
-               continue;                                               \
-             last_null = p;                                            \
-           }                                                           \
-         else                                                          \
-           p = last_null;                                              \
-                                                                       \
-         if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT)    \
-           {                                                           \
-             if (bytes_in_chunk > 0)                                   \
-               {                                                       \
-                 fprintf ((FILE), "\"\n");                             \
-                 bytes_in_chunk = 0;                                   \
-               }                                                       \
-                                                                       \
-             ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes);         \
-             _ascii_bytes = p;                                         \
-           }                                                           \
-         else                                                          \
-           {                                                           \
-             register int escape;                                      \
-             register unsigned ch;                                     \
-                                                                       \
-             if (bytes_in_chunk == 0)                                  \
-               fprintf ((FILE), "%s\"", ASCII_DATA_ASM_OP);            \
-                                                                       \
-             switch (escape = ESCAPES[ch = *_ascii_bytes])             \
-               {                                                       \
-               case 0:                                                 \
-                 putc (ch, (FILE));                                    \
-                 bytes_in_chunk++;                                     \
-                 break;                                                \
-               case 1:                                                 \
-                 fprintf ((FILE), "\\%03o", ch);                       \
-                 bytes_in_chunk += 4;                                  \
-                 break;                                                \
-               default:                                                \
-                 putc ('\\', (FILE));                                  \
-                 putc (escape, (FILE));                                \
-                 bytes_in_chunk += 2;                                  \
-                 break;                                                \
-               }                                                       \
-           }                                                           \
-       }                                                               \
-                                                                       \
-      if (bytes_in_chunk > 0)                                          \
-        fprintf ((FILE), "\"\n");                                      \
-    }                                                                  \
-  while (0)
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH)                    \
+  default_elf_asm_output_ascii ((FILE), (STR), (LENGTH));
 
 /* Allow the use of the -frecord-gcc-switches switch via the
    elf_record_gcc_switches function defined in varasm.c.  */
@@ -526,6 +440,6 @@ see the files COPYING3 and COPYING.RUNTI
    It is needed to properly support non-default visibility.  */
 
 #ifndef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)          \
   default_elf_asm_output_external (FILE, DECL, NAME)
 #endif

=== modified file 'gcc/config/i386/i386.c'
--- gcc/config/i386/i386.c      2011-06-02 17:43:22 +0000
+++ gcc/config/i386/i386.c      2011-08-22 11:39:43 +0000
@@ -13762,26 +13762,28 @@ print_reg (rtx x, int code, FILE *file)
     code = GET_MODE_SIZE (GET_MODE (x));
 
   /* Irritatingly, AMD extended registers use different naming convention
-     from the normal registers.  */
+     from the normal registers: "r%d[bwd]"  */
   if (REX_INT_REG_P (x))
     {
       gcc_assert (TARGET_64BIT);
+      putc ('r', file);
+      fprint_ul (file, REGNO (x) - FIRST_REX_INT_REG + 8);
       switch (code)
        {
          case 0:
            error ("extended registers have no high halves");
            break;
          case 1:
-           fprintf (file, "r%ib", REGNO (x) - FIRST_REX_INT_REG + 8);
+           putc ('b', file);
            break;
          case 2:
-           fprintf (file, "r%iw", REGNO (x) - FIRST_REX_INT_REG + 8);
+           putc ('w', file);
            break;
          case 4:
-           fprintf (file, "r%id", REGNO (x) - FIRST_REX_INT_REG + 8);
+           putc ('d', file);
            break;
          case 8:
-           fprintf (file, "r%i", REGNO (x) - FIRST_REX_INT_REG + 8);
+           /* no suffix */
            break;
          default:
            error ("unsupported operand size for extended register");

=== modified file 'gcc/defaults.h'
--- gcc/defaults.h      2010-11-29 14:09:41 +0000
+++ gcc/defaults.h      2011-08-22 11:39:43 +0000
@@ -137,7 +137,10 @@ see the files COPYING3 and COPYING.RUNTI
 
 #ifndef ASM_OUTPUT_LABEL
 #define ASM_OUTPUT_LABEL(FILE,NAME) \
-  do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
+  do {                                         \
+    assemble_name ((FILE), (NAME));            \
+    fputs (":\n", (FILE));                     \
+  } while (0)
 #endif
 
 /* This is how to output the definition of a user-level label named
@@ -160,7 +163,11 @@ see the files COPYING3 and COPYING.RUNTI
 /* This is how to output a reference to a user-level label named NAME.  */
 
 #ifndef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME)  asm_fprintf ((FILE), "%U%s", (NAME))
+#define ASM_OUTPUT_LABELREF(FILE,NAME)  \
+  do {                                                 \
+    fputs (user_label_prefix, (FILE));                 \
+    fputs ((NAME), (FILE));                            \
+  } while (0);
 #endif
 
 /* Allow target to print debug info labels specially.  This is useful for

=== modified file 'gcc/dwarf2asm.c'
--- gcc/dwarf2asm.c     2011-03-25 16:39:10 +0000
+++ gcc/dwarf2asm.c     2011-08-22 11:39:43 +0000
@@ -53,8 +53,7 @@ dw2_assemble_integer (int size, rtx x)
     {
       fputs (op, asm_out_file);
       if (CONST_INT_P (x))
-       fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX,
-                (unsigned HOST_WIDE_INT) INTVAL (x));
+       fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
       else
        output_addr_const (asm_out_file, x);
     }
@@ -106,16 +105,19 @@ dw2_asm_output_data (int size, unsigned 
     value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
 
   if (op)
-    fprintf (asm_out_file, "%s" HOST_WIDE_INT_PRINT_HEX, op, value);
+    {
+      fputs (op, asm_out_file);
+      fprint_whex (asm_out_file, value);
+    }
   else
     assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
 
   if (flag_debug_asm && comment)
     {
-      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+      fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
       vfprintf (asm_out_file, comment, ap);
     }
-  fputc ('\n', asm_out_file);
+  putc ('\n', asm_out_file);
 
   va_end (ap);
 }
@@ -596,7 +598,8 @@ dw2_asm_output_data_uleb128 (unsigned HO
   va_start (ap, comment);
 
 #ifdef HAVE_AS_LEB128
-  fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
+  fputs ("\t.uleb128 ", asm_out_file);
+  fprint_whex (asm_out_file, value);
 
   if (flag_debug_asm && comment)
     {
@@ -641,7 +644,7 @@ dw2_asm_output_data_uleb128 (unsigned HO
     }
   }
 #endif
-  fputc ('\n', asm_out_file);
+  putc ('\n', asm_out_file);
 
   va_end (ap);
 }
@@ -745,7 +748,7 @@ dw2_asm_output_delta_uleb128 (const char
 #ifdef HAVE_AS_LEB128
   fputs ("\t.uleb128 ", asm_out_file);
   assemble_name (asm_out_file, lab1);
-  fputc ('-', asm_out_file);
+  putc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
   gcc_unreachable ();
@@ -775,7 +778,7 @@ dw2_asm_output_delta_sleb128 (const char
 #ifdef HAVE_AS_LEB128
   fputs ("\t.sleb128 ", asm_out_file);
   assemble_name (asm_out_file, lab1);
-  fputc ('-', asm_out_file);
+  putc ('-', asm_out_file);
   assemble_name (asm_out_file, lab2);
 #else
   gcc_unreachable ();

=== modified file 'gcc/dwarf2out.c'
--- gcc/dwarf2out.c     2011-06-06 17:46:00 +0000
+++ gcc/dwarf2out.c     2011-08-22 11:39:43 +0000
@@ -23274,12 +23274,27 @@ dwarf2out_source_line (unsigned int line
   if (DWARF2_ASM_LINE_DEBUG_INFO)
     {
       /* Emit the .loc directive understood by GNU as.  */
-      fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
+      /* "\t.loc %u %u 0 is_stmt %u discriminator %u",
+        file_num, line, is_stmt, discriminator */
+      fputs ("\t.loc ", asm_out_file);
+      fprint_ul (asm_out_file, file_num);
+      putc (' ', asm_out_file);
+      fprint_ul (asm_out_file, line);
+      putc (' ', asm_out_file);
+      putc ('0', asm_out_file);
+
       if (is_stmt != table->is_stmt)
-       fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
+       {
+         fputs (" is_stmt ", asm_out_file);
+         putc (is_stmt ? '1' : '0', asm_out_file);
+       }
       if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
-       fprintf (asm_out_file, " discriminator %d", discriminator);
-      fputc ('\n', asm_out_file);
+       {
+         gcc_assert (discriminator > 0);
+         fputs (" discriminator ", asm_out_file);
+         fprint_ul (asm_out_file, (unsigned long) discriminator);
+       }
+      putc ('\n', asm_out_file);
     }
   else
     {

=== modified file 'gcc/final.c'
--- gcc/final.c 2011-06-06 13:24:55 +0000
+++ gcc/final.c 2011-08-22 11:39:43 +0000
@@ -3604,7 +3604,7 @@ output_addr_const (FILE *file, rtx x)
       break;
 
     case CONST_INT:
-      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+      fprint_w (file, INTVAL (x));
       break;
 
     case CONST:
@@ -3719,6 +3719,125 @@ output_quoted_string (FILE *asm_file, co
 #endif
 }
 
+
+/* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */
+
+void
+fprint_whex (FILE *f, unsigned HOST_WIDE_INT value)
+{
+  char buf[2 + CHAR_BIT * sizeof (value) / 4];
+  if (value == 0)
+    putc ('0', f);
+  else
+    {
+      char *p = buf + sizeof (buf);
+      do
+        *--p = "0123456789abcdef"[value % 16];
+      while ((value /= 16) != 0);
+      *--p = 'x';
+      *--p = '0';
+      fwrite (p, 1, buf + sizeof (buf) - p, f);
+    }
+}
+
+/* Internal function that prints an unsigned long in decimal in reverse. 
+   The output string IS NOT null-terminated. */
+
+static int
+sprint_ul_rev (char *s, unsigned long value)
+{
+  int i = 0;
+  do
+    {
+      s[i] = "0123456789"[value % 10];
+      value /= 10;
+      i++;
+      /* alternate version, without modulo */
+      /* oldval = value; */
+      /* value /= 10; */
+      /* s[i] = "0123456789" [oldval - 10*value]; */
+      /* i++ */
+    }
+  while (value != 0);
+  return i;
+}
+
+/* Write a signed HOST_WIDE_INT as decimal to a file, fast. */
+
+void
+fprint_w (FILE *f, HOST_WIDE_INT value)
+{
+  /* python says: len(str(2**64)) == 20 */
+  char s[20];
+  int i;
+
+  if (value >= 0)
+    i = sprint_ul_rev (s, (unsigned long) value);
+  else
+    {
+      /* cast to long long to output max negative correctly! */
+      i = sprint_ul_rev (s, ((unsigned long long) value) * -1);
+      putc('-', f);
+    }
+
+  /* It's probably too small so it's not worth string reversal and fputs */
+  do
+    {
+      i--;
+      putc (s[i], f);
+    }
+  while (i != 0);
+}
+
+/* Write an unsigned long as decimal to a file, fast. */
+
+void
+fprint_ul (FILE *f, unsigned long value)
+{
+  /* python says: len(str(2**64)) == 20 */
+  char s[20];
+  int i;
+
+  i = sprint_ul_rev (s, value);
+
+  /* It's probably too small so it's not worth string reversal and fputs */
+  do
+    {
+      i--;
+      putc (s[i], f);
+    }
+  while (i != 0);
+}
+
+/* Write an unsigned long as decimal to a string, fast. 
+   s must be wide enough to not overflow, at least 21 chars.
+   Returns the length of the string (without terminating '\0'). */
+
+int
+sprint_ul (char *s, unsigned long value)
+{
+  int len;
+  char tmp_c;
+  int i;
+  int j;
+
+  len = sprint_ul_rev (s, value);
+  s[len] = '\0';
+  
+  /* String reversal */
+  i = 0;
+  j = len - 1;
+  while (i < j)
+    {
+      tmp_c = s[i];
+      s[i] = s[j];
+      s[j] = tmp_c;
+      i++; j--;
+    }
+
+  return len;
+}
+
 /* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
    %R prints the value of REGISTER_PREFIX.
    %L prints the value of LOCAL_LABEL_PREFIX.

=== modified file 'gcc/output.h'
--- gcc/output.h        2011-02-03 19:12:07 +0000
+++ gcc/output.h        2011-08-22 11:39:43 +0000
@@ -129,6 +129,11 @@ typedef HOST_WIDE_INT __gcc_host_wide_in
 #define ATTRIBUTE_ASM_FPRINTF(m, n) ATTRIBUTE_NONNULL(m)
 #endif
 
+extern void fprint_w (FILE *, HOST_WIDE_INT);
+extern void fprint_whex (FILE *, unsigned HOST_WIDE_INT);
+extern void fprint_ul (FILE *, unsigned long);
+extern int sprint_ul (char *, unsigned long);
+
 extern void asm_fprintf (FILE *file, const char *p, ...)
      ATTRIBUTE_ASM_FPRINTF(2, 3);
 
@@ -652,8 +657,11 @@ extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
 extern void file_end_indicate_split_stack (void);
 
-extern void default_elf_asm_output_external (FILE *file, tree,
-                                            const char *);
+extern void default_elf_asm_output_external (FILE *file, tree, const char *);
+extern void default_elf_asm_output_limited_string (FILE *, const char *);
+extern void default_elf_asm_output_ascii (FILE *, const char *, unsigned int);
+extern void default_elf_internal_label (FILE *, const char *, unsigned long);
+
 extern int maybe_assemble_visibility (tree);
 
 extern int default_address_cost (rtx, bool);

=== modified file 'gcc/varasm.c'
--- gcc/varasm.c        2011-05-30 16:42:05 +0000
+++ gcc/varasm.c        2011-08-22 11:39:43 +0000
@@ -559,7 +559,7 @@ default_function_section (tree decl, enu
 /* Return the section for function DECL.
 
    If DECL is NULL_TREE, return the text section.  We can be passed
-   NULL_TREE under some circumstances by dbxout.c at least. 
+   NULL_TREE under some circumstances by dbxout.c at least.
 
    If FORCE_COLD is true, return cold function section ignoring
    the frequency info of cgraph_node.  */
@@ -1921,7 +1921,7 @@ assemble_variable (tree decl, int top_le
 
   /* Emulated TLS had better not get this far.  */
   gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl));
-              
+
   last_assemble_variable_decl = 0;
 
   /* Normally no need to say anything here for external references,
@@ -2838,7 +2838,7 @@ compare_constant (const tree t1, const t
              return 0;
            link2 = TREE_CHAIN (link2);
          }
-       
+
        return 1;
       }
 
@@ -5740,7 +5740,7 @@ finish_aliases_1 (void)
               && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
        {
          error ("%q+D aliased to external symbol %qE",
-                p->decl, p->target);     
+                p->decl, p->target);
          p->emitted_diags |= ALIAS_DIAG_TO_EXTERN;
        }
     }
@@ -5806,7 +5806,7 @@ assemble_alias (tree decl, tree target)
          if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
            error_at (DECL_SOURCE_LOCATION (decl),
                      "ifunc is not supported in this configuration");
-         else  
+         else
            error_at (DECL_SOURCE_LOCATION (decl),
                      "only weak aliases are supported in this configuration");
          return;
@@ -5849,7 +5849,7 @@ assemble_alias (tree decl, tree target)
    the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
 
 void
-default_assemble_visibility (tree decl ATTRIBUTE_UNUSED, 
+default_assemble_visibility (tree decl ATTRIBUTE_UNUSED,
                             int vis ATTRIBUTE_UNUSED)
 {
 #ifdef HAVE_GAS_HIDDEN
@@ -7347,4 +7347,122 @@ make_debug_expr_from_rtl (const_rtx exp)
   return dval;
 }
 
+void
+default_elf_asm_output_limited_string (FILE *f, const char *s)
+{
+  int escape;
+  unsigned char c;
+
+  fputs ("\t.string\t\"", f);
+  while (*s != '\0')
+    {
+      c = *s;
+      escape = ELF_ASCII_ESCAPES[c];
+      switch (escape)
+       {
+       case 0:
+         putc (c, f);
+         break;
+       case 1:
+         /* TODO: Print in hex with fast function... VERY IMPORTANT FOR 
-flto!!! */
+         fprintf (f, "\\%03o", c);
+         break;
+       default:
+         putc ('\\', f);
+         putc (escape, f);
+         break;
+       }
+      s++;
+    }
+  putc ('\"', f);
+  putc ('\n', f);
+}
+
+void
+default_elf_asm_output_ascii (FILE *f, const char *s, unsigned int len)
+{
+  const char *limit = s + len;
+  const char *last_null = NULL;
+  unsigned bytes_in_chunk = 0;
+  unsigned char c;
+  int escape;
+
+  for (; s < limit; s++)
+    {
+      const char *p;
+
+      if (bytes_in_chunk >= 60)
+       {
+         putc ('\"', f);
+         putc ('\n', f);
+         bytes_in_chunk = 0;
+       }
+
+      if (s > last_null)
+       {
+         for (p = s; p < limit && *p != '\0'; p++)
+           continue;
+         last_null = p;
+       }
+      else
+       p = last_null;
+
+      if (p < limit && (p - s) <= (long) ELF_STRING_LIMIT)
+       {
+         if (bytes_in_chunk > 0)
+           {
+             putc ('\"', f);
+             putc ('\n', f);
+             bytes_in_chunk = 0;
+           }
+
+         default_elf_asm_output_limited_string (f, s);
+         s = p;
+       }
+      else
+       {
+         if (bytes_in_chunk == 0)
+           fputs (ASCII_DATA_ASM_OP "\"", f);
+         
+         c = *s;
+         escape = ELF_ASCII_ESCAPES[c];
+         switch (escape)
+           {
+           case 0:
+             putc (c, f);
+             bytes_in_chunk++;
+             break;
+           case 1:
+             /* TODO: Print in hex with fast function... VERY IMPORTANT FOR 
-flto!!! */
+             fprintf (f, "\\%03o", c);
+             bytes_in_chunk += 4;
+             break;
+           default:
+             putc ('\\', f);
+             putc (escape, f);
+             bytes_in_chunk += 2;
+             break;
+           }
+
+       }
+    }
+
+  if (bytes_in_chunk > 0)
+    {
+      putc ('\"', f);
+      putc ('\n', f);
+    }
+}
+
+void
+default_elf_internal_label (FILE *f, const char *prefix,
+                           unsigned long labelno)
+{
+  putc ('.', f);
+  fputs (prefix, f);
+  fprint_ul (f, labelno);
+  putc (':', f);
+  putc ('\n', f);
+}
+
 #include "gt-varasm.h"

Reply via email to