diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 928eb0910de..5a635683c27 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-07-25 Siddhesh Poyarekar + + * final.c [ASSEMBLER_DIALECT](do_assembler_dialects): New + function to implement assembler dialects. + (output_asm_insn): Use do_assembler_dialects. + (asm_fprintf): Likewise. + 2012-07-25 Richard Henderson PR bootstrap/54092 diff --git a/gcc/final.c b/gcc/final.c index 7db047104fb..095d608cdc3 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -3338,6 +3338,72 @@ output_asm_operand_names (rtx *operands, int *oporder, int nops) } } +#ifdef ASSEMBLER_DIALECT +/* Helper function to parse assembler dialects in the asm string. + This is called from output_asm_insn and asm_fprintf. */ +static const char * +do_assembler_dialects (const char *p, int *dialect) +{ + char c = *(p - 1); + + switch (c) + { + case '{': + { + int i; + + if (*dialect) + output_operand_lossage ("nested assembly dialect alternatives"); + else + *dialect = 1; + + /* If we want the first dialect, do nothing. Otherwise, skip + DIALECT_NUMBER of strings ending with '|'. */ + for (i = 0; i < dialect_number; i++) + { + while (*p && *p != '}' && *p++ != '|') + ; + if (*p == '}') + break; + } + + if (*p == '\0') + output_operand_lossage ("unterminated assembly dialect alternative"); + } + break; + + case '|': + if (*dialect) + { + /* Skip to close brace. */ + do + { + if (*p == '\0') + { + output_operand_lossage ("unterminated assembly dialect alternative"); + break; + } + } + while (*p++ != '}'); + *dialect = 0; + } + else + putc (c, asm_out_file); + break; + + case '}': + if (! *dialect) + putc (c, asm_out_file); + *dialect = 0; + break; + default: + gcc_unreachable (); + } + + return p; +} +#endif + /* Output text from TEMPLATE to the assembler output file, obeying %-directions to substitute operands taken from the vector OPERANDS. @@ -3404,54 +3470,9 @@ output_asm_insn (const char *templ, rtx *operands) #ifdef ASSEMBLER_DIALECT case '{': - { - int i; - - if (dialect) - output_operand_lossage ("nested assembly dialect alternatives"); - else - dialect = 1; - - /* If we want the first dialect, do nothing. Otherwise, skip - DIALECT_NUMBER of strings ending with '|'. */ - for (i = 0; i < dialect_number; i++) - { - while (*p && *p != '}' && *p++ != '|') - ; - if (*p == '}') - break; - if (*p == '|') - p++; - } - - if (*p == '\0') - output_operand_lossage ("unterminated assembly dialect alternative"); - } - break; - - case '|': - if (dialect) - { - /* Skip to close brace. */ - do - { - if (*p == '\0') - { - output_operand_lossage ("unterminated assembly dialect alternative"); - break; - } - } - while (*p++ != '}'); - dialect = 0; - } - else - putc (c, asm_out_file); - break; - case '}': - if (! dialect) - putc (c, asm_out_file); - dialect = 0; + case '|': + p = do_assembler_dialects (p, &dialect); break; #endif @@ -3910,6 +3931,9 @@ asm_fprintf (FILE *file, const char *p, ...) { char buf[10]; char *q, c; +#ifdef ASSEMBLER_DIALECT + int dialect = 0; +#endif va_list argptr; va_start (argptr, p); @@ -3921,29 +3945,9 @@ asm_fprintf (FILE *file, const char *p, ...) { #ifdef ASSEMBLER_DIALECT case '{': - { - int i; - - /* If we want the first dialect, do nothing. Otherwise, skip - DIALECT_NUMBER of strings ending with '|'. */ - for (i = 0; i < dialect_number; i++) - { - while (*p && *p++ != '|') - ; - - if (*p == '|') - p++; - } - } - break; - - case '|': - /* Skip to close brace. */ - while (*p && *p++ != '}') - ; - break; - case '}': + case '|': + p = do_assembler_dialects (p, &dialect); break; #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d46615fe769..0c57bc34388 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-07-25 Siddhesh Poyarekar + + * gcc.target/i386/asm-dialect-1.c: New test case. + 2012-07-25 Kirill Yukhin Michael Zolotukhin diff --git a/gcc/testsuite/gcc.target/i386/asm-dialect-1.c b/gcc/testsuite/gcc.target/i386/asm-dialect-1.c new file mode 100644 index 00000000000..a53d2e939f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/asm-dialect-1.c @@ -0,0 +1,15 @@ +/* { dg-options "-masm=intel" } */ + +extern void abort (void); + +int +main (void) +{ + int f = 0; + asm ("{movl $42, %%eax | mov eax, 42}" : :); + asm ("{movl $41, %0||mov %0, 43}" : "=r"(f)); + if (f != 42) + abort (); + + return 0; +}