|
|
dc1507 |
2013-05-06 Maxim Kuznetsov <maks.kuznetsov@gmail.com>
|
|
|
dc1507 |
|
|
|
dc1507 |
* final.c (do_assembler_dialects): Don't handle curly braces and
|
|
|
dc1507 |
vertical bar escaped by % as dialect delimiters.
|
|
|
dc1507 |
(output_asm_insn): Print curly braces and vertical bar if escaped
|
|
|
dc1507 |
by % and ASSEMBLER_DIALECT defined.
|
|
|
dc1507 |
* doc/tm.texi (ASSEMBLER_DIALECT): Document new standard escapes.
|
|
|
dc1507 |
|
|
|
dc1507 |
* gcc.target/i386/asm-dialect-2.c: New testcase.
|
|
|
dc1507 |
|
|
|
dc1507 |
2012-07-25 Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
|
dc1507 |
|
|
|
dc1507 |
* final.c [ASSEMBLER_DIALECT](do_assembler_dialects): New
|
|
|
dc1507 |
function to implement assembler dialects.
|
|
|
dc1507 |
(output_asm_insn): Use do_assembler_dialects.
|
|
|
dc1507 |
(asm_fprintf): Likewise.
|
|
|
dc1507 |
|
|
|
dc1507 |
* gcc.target/i386/asm-dialect-1.c: New test case.
|
|
|
dc1507 |
|
|
|
dc1507 |
--- gcc/final.c (revision 189853, 198640)
|
|
|
dc1507 |
+++ gcc/final.c (revision 189854, 198641)
|
|
|
dc1507 |
@@ -3134,6 +3134,96 @@ output_asm_operand_names (rtx *operands,
|
|
|
dc1507 |
}
|
|
|
dc1507 |
}
|
|
|
dc1507 |
|
|
|
dc1507 |
+#ifdef ASSEMBLER_DIALECT
|
|
|
dc1507 |
+/* Helper function to parse assembler dialects in the asm string.
|
|
|
dc1507 |
+ This is called from output_asm_insn and asm_fprintf. */
|
|
|
dc1507 |
+static const char *
|
|
|
dc1507 |
+do_assembler_dialects (const char *p, int *dialect)
|
|
|
dc1507 |
+{
|
|
|
dc1507 |
+ char c = *(p - 1);
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ switch (c)
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ case '{':
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ int i;
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ if (*dialect)
|
|
|
dc1507 |
+ output_operand_lossage ("nested assembly dialect alternatives");
|
|
|
dc1507 |
+ else
|
|
|
dc1507 |
+ *dialect = 1;
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ /* If we want the first dialect, do nothing. Otherwise, skip
|
|
|
dc1507 |
+ DIALECT_NUMBER of strings ending with '|'. */
|
|
|
dc1507 |
+ for (i = 0; i < dialect_number; i++)
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ while (*p && *p != '}')
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ if (*p == '|')
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ p++;
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ /* Skip over any character after a percent sign. */
|
|
|
dc1507 |
+ if (*p == '%')
|
|
|
dc1507 |
+ p++;
|
|
|
dc1507 |
+ if (*p)
|
|
|
dc1507 |
+ p++;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ if (*p == '}')
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ if (*p == '\0')
|
|
|
dc1507 |
+ output_operand_lossage ("unterminated assembly dialect alternative");
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ case '|':
|
|
|
dc1507 |
+ if (*dialect)
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ /* Skip to close brace. */
|
|
|
dc1507 |
+ do
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ if (*p == '\0')
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ output_operand_lossage ("unterminated assembly dialect alternative");
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ /* Skip over any character after a percent sign. */
|
|
|
dc1507 |
+ if (*p == '%' && p[1])
|
|
|
dc1507 |
+ {
|
|
|
dc1507 |
+ p += 2;
|
|
|
dc1507 |
+ continue;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ if (*p++ == '}')
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+ while (1);
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ *dialect = 0;
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+ else
|
|
|
dc1507 |
+ putc (c, asm_out_file);
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ case '}':
|
|
|
dc1507 |
+ if (! *dialect)
|
|
|
dc1507 |
+ putc (c, asm_out_file);
|
|
|
dc1507 |
+ *dialect = 0;
|
|
|
dc1507 |
+ break;
|
|
|
dc1507 |
+ default:
|
|
|
dc1507 |
+ gcc_unreachable ();
|
|
|
dc1507 |
+ }
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ return p;
|
|
|
dc1507 |
+}
|
|
|
dc1507 |
+#endif
|
|
|
dc1507 |
+
|
|
|
dc1507 |
/* Output text from TEMPLATE to the assembler output file,
|
|
|
dc1507 |
obeying %-directions to substitute operands taken from
|
|
|
dc1507 |
the vector OPERANDS.
|
|
|
dc1507 |
@@ -3200,63 +3290,24 @@ output_asm_insn (const char *templ, rtx
|
|
|
dc1507 |
|
|
|
dc1507 |
#ifdef ASSEMBLER_DIALECT
|
|
|
dc1507 |
case '{':
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- int i;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- if (dialect)
|
|
|
dc1507 |
- output_operand_lossage ("nested assembly dialect alternatives");
|
|
|
dc1507 |
- else
|
|
|
dc1507 |
- dialect = 1;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- /* If we want the first dialect, do nothing. Otherwise, skip
|
|
|
dc1507 |
- DIALECT_NUMBER of strings ending with '|'. */
|
|
|
dc1507 |
- for (i = 0; i < dialect_number; i++)
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- while (*p && *p != '}' && *p++ != '|')
|
|
|
dc1507 |
- ;
|
|
|
dc1507 |
- if (*p == '}')
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
- if (*p == '|')
|
|
|
dc1507 |
- p++;
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- if (*p == '\0')
|
|
|
dc1507 |
- output_operand_lossage ("unterminated assembly dialect alternative");
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- case '|':
|
|
|
dc1507 |
- if (dialect)
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- /* Skip to close brace. */
|
|
|
dc1507 |
- do
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- if (*p == '\0')
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- output_operand_lossage ("unterminated assembly dialect alternative");
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- while (*p++ != '}');
|
|
|
dc1507 |
- dialect = 0;
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- else
|
|
|
dc1507 |
- putc (c, asm_out_file);
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
case '}':
|
|
|
dc1507 |
- if (! dialect)
|
|
|
dc1507 |
- putc (c, asm_out_file);
|
|
|
dc1507 |
- dialect = 0;
|
|
|
dc1507 |
+ case '|':
|
|
|
dc1507 |
+ p = do_assembler_dialects (p, &dialect);
|
|
|
dc1507 |
break;
|
|
|
dc1507 |
#endif
|
|
|
dc1507 |
|
|
|
dc1507 |
case '%':
|
|
|
dc1507 |
- /* %% outputs a single %. */
|
|
|
dc1507 |
- if (*p == '%')
|
|
|
dc1507 |
+ /* %% outputs a single %. %{, %} and %| print {, } and | respectively
|
|
|
dc1507 |
+ if ASSEMBLER_DIALECT defined and these characters have a special
|
|
|
dc1507 |
+ meaning as dialect delimiters.*/
|
|
|
dc1507 |
+ if (*p == '%'
|
|
|
dc1507 |
+#ifdef ASSEMBLER_DIALECT
|
|
|
dc1507 |
+ || *p == '{' || *p == '}' || *p == '|'
|
|
|
dc1507 |
+#endif
|
|
|
dc1507 |
+ )
|
|
|
dc1507 |
{
|
|
|
dc1507 |
+ putc (*p, asm_out_file);
|
|
|
dc1507 |
p++;
|
|
|
dc1507 |
- putc (c, asm_out_file);
|
|
|
dc1507 |
}
|
|
|
dc1507 |
/* %= outputs a number which is unique to each insn in the entire
|
|
|
dc1507 |
compilation. This is useful for making local labels that are
|
|
|
dc1507 |
@@ -3600,6 +3651,9 @@ asm_fprintf (FILE *file, const char *p,
|
|
|
dc1507 |
{
|
|
|
dc1507 |
char buf[10];
|
|
|
dc1507 |
char *q, c;
|
|
|
dc1507 |
+#ifdef ASSEMBLER_DIALECT
|
|
|
dc1507 |
+ int dialect = 0;
|
|
|
dc1507 |
+#endif
|
|
|
dc1507 |
va_list argptr;
|
|
|
dc1507 |
|
|
|
dc1507 |
va_start (argptr, p);
|
|
|
dc1507 |
@@ -3611,29 +3665,9 @@ asm_fprintf (FILE *file, const char *p,
|
|
|
dc1507 |
{
|
|
|
dc1507 |
#ifdef ASSEMBLER_DIALECT
|
|
|
dc1507 |
case '{':
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- int i;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- /* If we want the first dialect, do nothing. Otherwise, skip
|
|
|
dc1507 |
- DIALECT_NUMBER of strings ending with '|'. */
|
|
|
dc1507 |
- for (i = 0; i < dialect_number; i++)
|
|
|
dc1507 |
- {
|
|
|
dc1507 |
- while (*p && *p++ != '|')
|
|
|
dc1507 |
- ;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- if (*p == '|')
|
|
|
dc1507 |
- p++;
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- }
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
- case '|':
|
|
|
dc1507 |
- /* Skip to close brace. */
|
|
|
dc1507 |
- while (*p && *p++ != '}')
|
|
|
dc1507 |
- ;
|
|
|
dc1507 |
- break;
|
|
|
dc1507 |
-
|
|
|
dc1507 |
case '}':
|
|
|
dc1507 |
+ case '|':
|
|
|
dc1507 |
+ p = do_assembler_dialects (p, &dialect);
|
|
|
dc1507 |
break;
|
|
|
dc1507 |
#endif
|
|
|
dc1507 |
|
|
|
dc1507 |
--- gcc/doc/tm.texi (revision 198640)
|
|
|
dc1507 |
+++ gcc/doc/tm.texi (revision 198641)
|
|
|
dc1507 |
@@ -8274,7 +8274,9 @@ first argument of @code{asm_fprintf}. T
|
|
|
dc1507 |
@code{ASSEMBLER_DIALECT} is zero, one, two, etc. Any special characters
|
|
|
dc1507 |
within these strings retain their usual meaning. If there are fewer
|
|
|
dc1507 |
alternatives within the braces than the value of
|
|
|
dc1507 |
-@code{ASSEMBLER_DIALECT}, the construct outputs nothing.
|
|
|
dc1507 |
+@code{ASSEMBLER_DIALECT}, the construct outputs nothing. If it's needed
|
|
|
dc1507 |
+to print curly braces or @samp{|} character in assembler output directly,
|
|
|
dc1507 |
+@samp{%@{}, @samp{%@}} and @samp{%|} can be used.
|
|
|
dc1507 |
|
|
|
dc1507 |
If you do not define this macro, the characters @samp{@{}, @samp{|} and
|
|
|
dc1507 |
@samp{@}} do not have any special meaning when used in templates or
|
|
|
dc1507 |
--- gcc/testsuite/gcc.target/i386/asm-dialect-1.c (revision 0)
|
|
|
dc1507 |
+++ gcc/testsuite/gcc.target/i386/asm-dialect-1.c (revision 189854)
|
|
|
dc1507 |
@@ -0,0 +1,15 @@
|
|
|
dc1507 |
+/* { dg-options "-masm=intel" } */
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+extern void abort (void);
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+int
|
|
|
dc1507 |
+main (void)
|
|
|
dc1507 |
+{
|
|
|
dc1507 |
+ int f = 0;
|
|
|
dc1507 |
+ asm ("{movl $42, %%eax | mov eax, 42}" : :);
|
|
|
dc1507 |
+ asm ("{movl $41, %0||mov %0, 43}" : "=r"(f));
|
|
|
dc1507 |
+ if (f != 42)
|
|
|
dc1507 |
+ abort ();
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+ return 0;
|
|
|
dc1507 |
+}
|
|
|
dc1507 |
--- gcc/testsuite/gcc.target/i386/asm-dialect-2.c (revision 0)
|
|
|
dc1507 |
+++ gcc/testsuite/gcc.target/i386/asm-dialect-2.c (revision 198641)
|
|
|
dc1507 |
@@ -0,0 +1,11 @@
|
|
|
dc1507 |
+/* { dg-do compile } */
|
|
|
dc1507 |
+/* { dg-options "-masm=att" } */
|
|
|
dc1507 |
+/* { dg-final { scan-assembler "%{a}|" } } */
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+int a, b;
|
|
|
dc1507 |
+
|
|
|
dc1507 |
+void f()
|
|
|
dc1507 |
+{
|
|
|
dc1507 |
+ /* Check for escaped curly braces support. */
|
|
|
dc1507 |
+ asm volatile ("{%%%{a%}%||%%%}b}" : :);
|
|
|
dc1507 |
+}
|