From patchwork Sun Sep 29 17:50:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 1990636 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gjlay.de header.i=@gjlay.de header.a=rsa-sha256 header.s=strato-dkim-0002 header.b=ct+hEcxM; dkim=pass header.d=gjlay.de header.i=@gjlay.de header.a=ed25519-sha256 header.s=strato-dkim-0003 header.b=EwIxDE0h; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XGsFq5q9Nz1xt9 for ; Mon, 30 Sep 2024 03:51:27 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CBC94385EC20 for ; Sun, 29 Sep 2024 17:51:25 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de [85.215.255.25]) by sourceware.org (Postfix) with ESMTPS id 4061D385DDDB for ; Sun, 29 Sep 2024 17:50:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4061D385DDDB Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gjlay.de Authentication-Results: sourceware.org; spf=none smtp.mailfrom=gjlay.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4061D385DDDB Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=85.215.255.25 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1727632258; cv=pass; b=fSuwtLBv2fmSWlMNZi+ieBPgxBGm7Ho94BHWngfGMV9fgwHDIIji47WjDKjUKHgwBfvAGxUmLrMnSR7QigI/k+skEXT8jf/dkCKzHPNqFugsPGpUgWt93edyIA7C0RXqzipu21Nvk8pgcGk+cVFuFJzvjgzvRlCT/XACJauiSs8= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1727632258; c=relaxed/simple; bh=Mms15inNtE9FPVoY/1Qh34/Hv295YEqnHNqfcTs3mFI=; h=DKIM-Signature:DKIM-Signature:Message-ID:Date:MIME-Version:From: To:Subject; b=Arlbjh4qdiImZTQohn111FTAGFsaQny0V+DRPTKzlyLc9viIEurV/ewHKKySUwkqpBuPjPqrVDI6eq41wLT3vX5EX1P7+bT5q388KLmzkJ6tr2GCj/ZH8FF90FOoYG6wGom7vDiM8JoqvljzgteVgRcq20GnR/X2AazsPkA2UUo= ARC-Authentication-Results: i=2; server2.sourceware.org ARC-Seal: i=1; a=rsa-sha256; t=1727632252; cv=none; d=strato.com; s=strato-dkim-0002; b=k0Y1PlEGpgRw9JKtR7cmWPcOvCM/3uZhZJcFDeJVJnx0c2LrlukNgPOv/Du2grob2a SM7PZoAMYqCh+A6NVLs9MEQ0ONBii++sgvzHVmS8zUicJS30P5l0Z8IGaKs81WvKfZ3o ELT95wAxJjH6bpCZYmjx6MCT7Cyy7el/hzVeahR6XK8CqcU2fGCJ5Jo/Tci8s8/UPO5T ZFrDZM1fZjFeUvVV9ZCXrVBruT3tGvJsmCD46RIr406/mi06uVU66pp1ryWBnQiIweTK 6M5hSZrKnGquKnBiHyNFwQjECxaMWPi15N8wc/alwx9IUvUfdJaAriV0ootqpgvGjq4w O1EA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1727632252; s=strato-dkim-0002; d=strato.com; h=Subject:To:From:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=dKlBks9okzy4Tt+hya6dobLTCGclUKoEzdrCW1Wxb74=; b=looNtl34cMmwVb2gJ5FMTZm3ha3CjtUfnsAw9vE0T1hAtnbfz39c3iSQoMzcXBxJCa kj7QBd2elQK/bErNo7XNY6inIOhmbjSDrBMdXFrtN55yXiCZSbhsFu8knf5w/SVVEvmM Falj1WVIGoW4JFu28UoRwByOkmbeiILSGRSOSmaRX7pmdYGRstRUDHsqMBMqnCl0FKZg NwhKzi3Udko45tF4TVSFbr/wVJgIMWEaC+gQsQMna7tlzYa4R6CQplB1zSR/dje1/To+ ceLvHPzbDyUp7ebiIfLfsQMl7JVuCby1oEPRacXVVD0QKB16rqX5D0rb36WGhgUquIzc W/6A== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1727632252; s=strato-dkim-0002; d=gjlay.de; h=Subject:To:From:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=dKlBks9okzy4Tt+hya6dobLTCGclUKoEzdrCW1Wxb74=; b=ct+hEcxMk8BYaPGqt/hdURD4KFlFcOEwjcPrtFd+FtLKqwKOOoF+HmNvxFjFbGVaNz ibirMg8HVKiEzeGlRi7hDLWa8kGy0VWRKSDKrVDCHitBfdAO2V8eDjWzXMRWUppvyg9B +agJsr9lEUmG4yuYQmpgGV9wzgYtF5bGRhIDUSHMEi9zKz7pjLlFHojkWEmNLWCRFtpU vncpvz1qB6jGJV3vpp5eNBJAdfJ1zHJA/pmwxBnRhSlVsr669orB+1iOVuWBtxN1PreU SMmHu5Kuz+/JlSRk+y7SMcA/uBmosNMhmHKr0Clsbzxqf1TMKtL8h2OM7J4AOEvKFK4v wlsw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1727632252; s=strato-dkim-0003; d=gjlay.de; h=Subject:To:From:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=dKlBks9okzy4Tt+hya6dobLTCGclUKoEzdrCW1Wxb74=; b=EwIxDE0hHEgmOJ6N49PlFXZSWGmYdc5kL7LEDIDQ+sSAsZ20HawB4hJEfjuqSWyBp3 J2uj2o4dHiW0SjyJPQCw== X-RZG-AUTH: ":LXoWVUeid/7A29J/hMvvT3koxZnKXKoq0dKoR0vetzhr/2IDlGFRklUq" Received: from [192.168.2.102] by smtp.strato.de (RZmta 51.2.8 DYNA|AUTH) with ESMTPSA id x2e25d08THopiQa (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Sun, 29 Sep 2024 19:50:51 +0200 (CEST) Message-ID: <020fd262-e19b-4c68-ab3d-04356bc6ca0b@gjlay.de> Date: Sun, 29 Sep 2024 19:50:51 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird From: Georg-Johann Lay Content-Language: en-US To: Richard Sandiford , "gcc-patches@gcc.gnu.org" Subject: [patch,gensupport] Support (symbol_ref { code }) in insn attributes. X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org When md_reader is reading insn attributes from md files, it accepts expressions like (symbol_ref { code }) and (symbol_ref "{ code }") as valid expressions. However, when generating insn-attrtab.cc, it would print the {} block as an expression, which is not valid C++ syntax. The conclusion is that to date, no backend is using that syntax, and hence we can assign a new semantic to such {} blocks: | The value of a (symbol_ref { code }) expression is the value returned | by the {} code block (when taken as the body of a C++ function). No changes to the md scanner are required; all what's needed is to print the code from {} blocks in such a way that it works as the body of a C++ function / lambda expression. To that end, md_reader::fprint_c_condition() now issues code as follows to insn-attrtab.cc: return [&]() -> attr_desc.cxx_type { code } (); where the capture provides code access to local variables like "insn". Without this patch, the issued code was basically return { code }; The patch bootstraps + regtests with no changes. Ok for trunk? Johann p.s. Some months ago I discussed the feature with Richard, and he said that the printer should make no attempts whatsoever to detect invalid syntax (like for example a block without return statement), and all diagnosis should be performed by the compiler when insn-attrtab.cc is being compiled. --- md_reader: Support (symbol_ref { code }) in insn attributes. When md_reader is reading insn attributes from md files, it accepts expressions like (symbol_ref { code }) and (symbol_ref "{ code }") as valid expressions. However, when generating insn-attrtab.cc, it would print the {} block as an expression, which is not valid C++ syntax. The conclusion is that to date, no backend is using that syntax, and hence we can assign a new semantic to such {} blocks: | The value of a (symbol_ref { code }) expression is the value returned | by the {} code block (when taken as the body of a C++ function). No changes to the md scanner are required; all what's needed is to print the code from {} blocks in such a way that it works as the body of a C++ function / lambda expression. To that end, md_reader::fprint_c_condition() now issues code as follows to insn-attrtab.cc: return [&]() -> attr_desc.cxx_type { code } (); where the capture provides code access to local variables like "insn". Without this patch, the issued code was basically return { code }; gcc/ * doc/md.texi (Attribute Expressions) : Document it. * genattrtab.cc (write_attr_value) [SYMBOL_REF]: Pass down attr->cxx_type to rtx_reader_ptr->fprint_c_condition(). (write_test_expr) [MATCH_TEST]: Pass down "bool" as cxx_type to rtx_reader_ptr->fprint_c_condition(). * genconditions.cc (write_one_condition): Same. * genrecog.cc (print_test) [rtx_test::C_TEST]: Same. * read-md.cc (md_reader::fprint_c_condition): Add cxx_type argument and pass it down to recursive invocations. When cond starts with a '{', then use cond as the body of a C++ lambda expression that's evaluated in place. (md_reader::print_c_condition): Add cxx_type argument. * read-md.h (md_reader::fprint_c_condition) (md_reader::print_c_condition): Add cxx_type argument. md_reader: Support (symbol_ref { code }) in insn attributes. When md_reader is reading insn attributes from md files, it accepts expressions like (symbol_ref { code }) and (symbol_ref "{ code }") as valid expressions. However, when generating insn-attrtab.cc, it would print the {} block as an expression, which is not valid C++ syntax. The conclusion is that to date, no backend is using that syntax, and hence we can assign a new semantic to such {} blocks: | The value of a (symbol_ref { code }) expression is the value returned | by the {} code block (when taken as the body of a C++ function). No changes to the md scanner are required; all what's needed is to print the code from {} blocks in such a way that it works as the body of a C++ function / lambda expression. To that end, md_reader::fprint_c_condition() now issues code as follows to insn-attrtab.cc: return [&]() -> attr_desc.cxx_type { code } (); where the capture provides code access to local variables like "insn". Without this patch, the issued code was basically return { code }; gcc/ * doc/md.texi (Attribute Expressions) : Document it. * genattrtab.cc (write_attr_value) [SYMBOL_REF]: Pass down attr->cxx_type to rtx_reader_ptr->fprint_c_condition(). (write_test_expr) [MATCH_TEST]: Pass down "bool" as cxx_type to rtx_reader_ptr->fprint_c_condition(). * genconditions.cc (write_one_condition): Same. * genrecog.cc (print_test) [rtx_test::C_TEST]: Same. * read-md.cc (md_reader::fprint_c_condition): Add cxx_type argument and pass it down to recursive invocations. When cond starts with a '{', then use cond as the body of a C++ lambda expression that's evaluated in place. (md_reader::print_c_condition): Add cxx_type argument. * read-md.h (md_reader::fprint_c_condition) (md_reader::print_c_condition): Add cxx_type argument. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index a9259112251..4d18385a1d5 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -10277,6 +10277,57 @@ so there is no need to explicitly convert the expression into a boolean (match_test "(x & 2) != 0") @end smallexample +@cindex @code{symbol_ref} and attributes +@item (symbol_ref "@var{quoted-c-expr}") + +Specifies the value of the attribute sub-expression as a C++ expression, +where the surrounding quotes are not part of the expression. +Similar to @code{match_test}, variables @var{insn}, @var{operands[]} +and @var{which_alternative} are available. Moreover, code and mode +attributes can be used to compose the resulting C++ expression. +Here is an example for the case where the according insn +has exactly one mode iterator: + +@smallexample +(set (attr "length") + (symbol_ref "1 + GET_MODE_SIZE (mode)")) +@end smallexample + +See @ref{Mode Iterators} and @ref{Code Iterators}. + +@item (symbol_ref "@{ @var{quoted-c-code} @}") +@itemx (symbol_ref @{ @var{c-code} @}) + +The value of this subexpression is determined by running the specfied block +of C++ code which returns the desired value. The braces are part of the +code, whereas the quotes in the quoted form are not. + +This variant of @code{symbol_ref} allows for more complex code than +just a single C++ expression, like for example: + +@smallexample +(set (attr "length") + (symbol_ref + @{ + int len; + some_function (insn, , mode, & len); + return len; + @})) +@end smallexample + +for an insn that has one code iterator and one mode iterator. +Again, variables @var{insn}, @var{operands[]} and @var{which_alternative} +can be used. The unquoted form only supports a subset of C++, +for example no C comments are supported, and strings that contain +characters like @samp{@}} are problematic and may need to be escaped +as @samp{\@}}. + +The return type is @code{int} for the @var{length} attribute, and +@code{enum attr_@var{name}} for an insn attribute named @var{name}. +The types and available enum values can be looked up in +@file{$builddir/gcc/insn-attr-common.h}. + + @cindex @code{le} and attributes @cindex @code{leu} and attributes @cindex @code{lt} and attributes diff --git a/gcc/genattrtab.cc b/gcc/genattrtab.cc index 2a51549ddd4..63ddef84469 100644 --- a/gcc/genattrtab.cc +++ b/gcc/genattrtab.cc @@ -3707,7 +3707,7 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags, break; case MATCH_TEST: - rtx_reader_ptr->fprint_c_condition (outf, XSTR (exp, 0)); + rtx_reader_ptr->fprint_c_condition (outf, XSTR (exp, 0), "bool"); if (flags & FLG_BITWISE) fprintf (outf, " != 0"); break; @@ -4385,7 +4385,8 @@ write_attr_value (FILE *outf, class attr_desc *attr, rtx value) break; case SYMBOL_REF: - rtx_reader_ptr->fprint_c_condition (outf, XSTR (value, 0)); + rtx_reader_ptr->fprint_c_condition (outf, XSTR (value, 0), + attr->cxx_type); break; case ATTR: diff --git a/gcc/genconditions.cc b/gcc/genconditions.cc index 13963dc3ff4..8a55f0f1033 100644 --- a/gcc/genconditions.cc +++ b/gcc/genconditions.cc @@ -141,9 +141,9 @@ write_one_condition (void **slot, void * ARG_UNUSED (dummy)) } fputs ("\",\n __builtin_constant_p ", stdout); - rtx_reader_ptr->print_c_condition (test->expr); + rtx_reader_ptr->print_c_condition (test->expr, "$bool"); fputs ("\n ? (int) ", stdout); - rtx_reader_ptr->print_c_condition (test->expr); + rtx_reader_ptr->print_c_condition (test->expr, "$bool"); fputs ("\n : -1 },\n", stdout); return 1; } diff --git a/gcc/genrecog.cc b/gcc/genrecog.cc index ba09ec3b600..c597958a487 100644 --- a/gcc/genrecog.cc +++ b/gcc/genrecog.cc @@ -4762,7 +4762,7 @@ print_test (output_state *os, const rtx_test &test, bool is_param, gcc_assert (!is_param && value == 1); if (invert_p) printf ("!"); - rtx_reader_ptr->print_c_condition (test.u.string); + rtx_reader_ptr->print_c_condition (test.u.string, "bool"); break; case rtx_test::ACCEPT: diff --git a/gcc/read-md.cc b/gcc/read-md.cc index 93d1ea43781..2e04fffc45d 100644 --- a/gcc/read-md.cc +++ b/gcc/read-md.cc @@ -170,31 +170,54 @@ md_reader::join_c_conditions (const char *cond1, const char *cond2) directive for COND if its original file position is known. */ void -md_reader::fprint_c_condition (FILE *outf, const char *cond) +md_reader::fprint_c_condition (FILE *outf, const char *cond, + const char *cxx_type) { const char **halves = (const char **) htab_find (m_joined_conditions, &cond); if (halves != 0) { fprintf (outf, "("); - fprint_c_condition (outf, halves[1]); + fprint_c_condition (outf, halves[1], cxx_type); fprintf (outf, " && "); - fprint_c_condition (outf, halves[2]); + fprint_c_condition (outf, halves[2], cxx_type); fprintf (outf, ")"); } else { fputc ('\n', outf); fprint_md_ptr_loc (outf, cond); - fprintf (outf, "(%s)", cond); + if (cond[0] == '{') + { + /* Resulting C++ code is like "( [&]() -> () )" + where COND is actually the body of a function, including the + outer {}'s. Print this as a lambda that's evaluated in place. + The capture-all is required to have access to variables + like "insn". Objects like "operands[]" and "which_alternative" + are accessible since they are global or captured. + When the expression is not evaluated locally (not in a function), + then CXX_TYPE starts with a '$' to indicate that no capture + should be performed. */ + bool no_capture = cxx_type && cxx_type[0] == '$'; + if (cxx_type && no_capture) + fprintf (outf, "( []() -> %s %s () )", 1 + cxx_type, cond); + else if (cxx_type) + fprintf (outf, "( [&]() -> %s %s () )", cxx_type, cond); + else + fprintf (outf, "( [&]() /* unknown return type */ %s () )", cond); + } + else + { + fprintf (outf, "(%s)", cond); + } } } /* Special fprint_c_condition for writing to STDOUT. */ void -md_reader::print_c_condition (const char *cond) +md_reader::print_c_condition (const char *cond, const char *cxx_type) { - fprint_c_condition (stdout, cond); + fprint_c_condition (stdout, cond, cxx_type); } /* A vfprintf-like function for reporting an error against line LINENO diff --git a/gcc/read-md.h b/gcc/read-md.h index 9703551a8fd..b6ee68647ec 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -204,8 +204,9 @@ class md_reader void handle_enum (file_location loc, bool md_p); const char *join_c_conditions (const char *cond1, const char *cond2); - void fprint_c_condition (FILE *outf, const char *cond); - void print_c_condition (const char *cond); + void fprint_c_condition (FILE *outf, const char *cond, + const char *cxx_type = nullptr); + void print_c_condition (const char *cond, const char *cxx_type = nullptr); /* Defined in read-rtl.cc. */ const char *apply_iterator_to_string (const char *string);