From patchwork Wed Jul 25 15:10:29 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 173195 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id CD08A2C0098 for ; Thu, 26 Jul 2012 01:11:12 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1343833873; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Date:From:To:Subject:Message-ID:Mime-Version:Content-Type: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=DnrFhEDGbhj1eI40GfE6 WHvxeK8=; b=lKDMOb341R+oGv1sxjbJ365r45dbS7MtPU0MEsMrUi+54GReLbm6 I+Nqk+jZxRxp+WeLHsQEvI0c2H63sUfHSgWe8wVzQ5EoSkGx0ohXI4kaRVbVPl/6 nN3v99aIqVp0LWuLGvrVCFcQ5j/CQX4oMjbA1C0rQJ7Tc2ujx55ONwE= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Date:From:To:Subject:Message-ID:Mime-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Q/Pg/AYEaGgoIL8OTtpjQ1WX1qm7G6T/xSWj0Djm1yZLLBR1LkMUB83iH5SKk2 TgVX/0DntdGiyHlisyrS+IMh0j7Z4qgJfAotOaBil5c6aFs6eoQJVa406gF4znfo 9R7MSn/irGitRzL7g9Y48Nm0R9J60aqRJ7KAqI0fDE7y0=; Received: (qmail 6397 invoked by alias); 25 Jul 2012 15:11:05 -0000 Received: (qmail 6378 invoked by uid 22791); 25 Jul 2012 15:11:02 -0000 X-SWARE-Spam-Status: No, hits=-6.9 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 Jul 2012 15:10:48 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q6PFAmVD005964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 25 Jul 2012 11:10:48 -0400 Received: from spoyarek (vpn-235-231.phx2.redhat.com [10.3.235.231]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q6PFAkpt027297 for ; Wed, 25 Jul 2012 11:10:47 -0400 Date: Wed, 25 Jul 2012 20:40:29 +0530 From: Siddhesh Poyarekar To: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix assembly dialect handling in asm_fprintf Message-ID: <20120725204029.5ccf50b8@spoyarek> Mime-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, While reviewing code to fix a previous patch submission around assembly dialect handling[1], I found that the dialect handling in asm_fprintf is different from that in output_asm_insn and it might be broken too, since encountering a '|' simply leads to skipping all of the string until a '}' is encountered, instead of printing it if it is not part of the assembly dialect syntax. This is just never hit with user code since asm_fprintf is used only internally. Attached patch moves the asm dialect handling into a separate function that both output_asm_insn and asm_fprintf call. I have also removed the extra: if (*p == '|') p++; in the '{' case, since it is unnecessary. In fact it will behave incorrectly if a target has more than two dialects (none of the targets have that currently) since something like this: foo||bar will incorrectly give 'bar' for dialect 1 and nothing for dialect 2 (and of course, foo for dialect 0) instead of nothing for dialect 1 and bar for dialect 2. I have verified that this does not cause a regression in the testsuite on x86_64. There is also an additional test case in this patch that verifies that the double '|' bug I mentioned above is fixed. Regards, Siddhesh [1] http://gcc.gnu.org/ml/gcc-patches/2012-07/msg00840.html gcc/ChangeLog: 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. testsuite/ChangeLog: 2012-07-25 Siddhesh Poyarekar * gcc.dg/asm-dialect-1.c: New test case. diff --git a/gcc/final.c b/gcc/final.c index 7db0471..095d608 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/gcc.dg/asm-dialect-1.c b/gcc/testsuite/gcc.dg/asm-dialect-1.c new file mode 100644 index 0000000..b3da004 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asm-dialect-1.c @@ -0,0 +1,16 @@ +/* { dg-do run { target *86*-*-* } } */ +/* { 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; +}