From: Andi Kleen <ak@linux.intel.com>
To: gcc-patches@gcc.gnu.org
Cc: richard.guenther@gmail.com, nathan@acm.org, josmyers@redhat.com,
richard.sandiford@arm.com, jason@redhat.com,
Andi Kleen <ak@linux.intel.com>
Subject: [PATCH v7 5/9] C: Implement musttail attribute for returns
Date: Sun, 2 Jun 2024 10:16:49 -0700 [thread overview]
Message-ID: <20240602172205.2151579-6-ak@linux.intel.com> (raw)
In-Reply-To: <20240602172205.2151579-1-ak@linux.intel.com>
Implement a C23 clang compatible musttail attribute similar to the earlier
C++ implementation in the C parser.
PR83324
gcc/c/ChangeLog:
* c-parser.cc (struct attr_state): Define with musttail_p.
(c_parser_statement_after_labels): Handle [[musttail]]
(c_parser_std_attribute): Dito.
(c_parser_handle_musttail): Dito.
(c_parser_compound_statement_nostart): Dito.
(c_parser_all_labels): Dito.
(c_parser_statement): Dito.
* c-tree.h (c_finish_return): Add musttail_p flag.
* c-typeck.cc (c_finish_return): Handle musttail_p flag.
---
gcc/c/c-parser.cc | 61 +++++++++++++++++++++++++++++++++++++----------
gcc/c/c-tree.h | 2 +-
gcc/c/c-typeck.cc | 15 ++++++++++--
3 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 2d9e9c0969f0..6158d1d8ba4b 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1616,6 +1616,11 @@ struct omp_for_parse_data {
bool fail : 1;
};
+struct attr_state
+{
+ bool musttail_p; // parsed a musttail for return
+};
+
static bool c_parser_nth_token_starts_std_attributes (c_parser *,
unsigned int);
static tree c_parser_std_attribute_specifier_sequence (c_parser *);
@@ -1660,7 +1665,7 @@ static location_t c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *, tree);
static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
static void c_parser_statement_after_labels (c_parser *, bool *,
- vec<tree> * = NULL);
+ vec<tree> * = NULL, attr_state = {});
static tree c_parser_c99_block_statement (c_parser *, bool *,
location_t * = NULL);
static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
@@ -5756,6 +5761,8 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
}
goto out;
}
+ else if (is_attribute_p ("musttail", name))
+ error ("%<musttail%> attribute has arguments");
{
location_t open_loc = c_parser_peek_token (parser)->location;
matching_parens parens;
@@ -6941,6 +6948,28 @@ c_parser_handle_directive_omp_attributes (tree &attrs,
}
}
+/* Check if STD_ATTR contains a musttail attribute and handle it
+ PARSER is the parser and A is the output attr_state. */
+
+static tree
+c_parser_handle_musttail (c_parser *parser, tree std_attrs, attr_state &a)
+{
+ if (c_parser_next_token_is_keyword (parser, RID_RETURN))
+ {
+ if (lookup_attribute ("gnu", "musttail", std_attrs))
+ {
+ std_attrs = remove_attribute ("gnu", "musttail", std_attrs);
+ a.musttail_p = true;
+ }
+ if (lookup_attribute ("clang", "musttail", std_attrs))
+ {
+ std_attrs = remove_attribute ("clang", "musttail", std_attrs);
+ a.musttail_p = true;
+ }
+ }
+ return std_attrs;
+}
+
/* Parse a compound statement except for the opening brace. This is
used for parsing both compound statements and statement expressions
(which follow different paths to handling the opening). */
@@ -6957,6 +6986,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
bool in_omp_loop_block
= omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
tree sl = NULL_TREE;
+ attr_state a = {};
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
@@ -7095,7 +7125,10 @@ c_parser_compound_statement_nostart (c_parser *parser)
= c_parser_nth_token_starts_std_attributes (parser, 1);
tree std_attrs = NULL_TREE;
if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ {
+ std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ std_attrs = c_parser_handle_musttail (parser, std_attrs, a);
+ }
if (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
@@ -7243,7 +7276,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_stmt = true;
mark_valid_location_for_stdc_pragma (false);
if (!omp_for_parse_state)
- c_parser_statement_after_labels (parser, NULL);
+ c_parser_statement_after_labels (parser, NULL, NULL, a);
else
{
/* In canonical loop nest form, nested loops can only appear
@@ -7285,15 +7318,18 @@ c_parser_compound_statement_nostart (c_parser *parser)
/* Parse all consecutive labels, possibly preceded by standard
attributes. In this context, a statement is required, not a
declaration, so attributes must be followed by a statement that is
- not just a semicolon. */
+ not just a semicolon. Returns an attr_state. */
-static void
+static attr_state
c_parser_all_labels (c_parser *parser)
{
+ attr_state a = {};
bool have_std_attrs;
tree std_attrs = NULL;
if ((have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1)))
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ std_attrs = c_parser_handle_musttail (parser,
+ c_parser_std_attribute_specifier_sequence (parser), a);
+
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
@@ -7315,6 +7351,7 @@ c_parser_all_labels (c_parser *parser)
}
else if (have_std_attrs && c_parser_next_token_is (parser, CPP_SEMICOLON))
c_parser_error (parser, "expected statement");
+ return a;
}
/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
@@ -7558,11 +7595,11 @@ c_parser_label (c_parser *parser, tree std_attrs)
static void
c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
{
- c_parser_all_labels (parser);
+ attr_state a = c_parser_all_labels (parser);
if (loc_after_labels)
*loc_after_labels = c_parser_peek_token (parser)->location;
parser->omp_attrs_forbidden_p = false;
- c_parser_statement_after_labels (parser, if_p, NULL);
+ c_parser_statement_after_labels (parser, if_p, NULL, a);
}
/* Parse a statement, other than a labeled statement. CHAIN is a vector
@@ -7571,11 +7608,11 @@ c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
IF_P is used to track whether there's a (possibly labeled) if statement
which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
+ implement -Wparentheses. A has an earlier parsed attribute state. */
static void
c_parser_statement_after_labels (c_parser *parser, bool *if_p,
- vec<tree> *chain)
+ vec<tree> *chain, attr_state a)
{
location_t loc = c_parser_peek_token (parser)->location;
tree stmt = NULL_TREE;
@@ -7643,7 +7680,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
+ stmt = c_finish_return (loc, NULL_TREE, NULL_TREE, a.musttail_p);
c_parser_consume_token (parser);
}
else
@@ -7652,7 +7689,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
struct c_expr expr = c_parser_expression_conv (parser);
mark_exp_read (expr.value);
stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
- expr.value, expr.original_type);
+ expr.value, expr.original_type, a.musttail_p);
goto expect_semicolon;
}
break;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 56a33b8156c6..754117bccd0e 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -827,7 +827,7 @@ extern tree c_begin_stmt_expr (void);
extern tree c_finish_stmt_expr (location_t, tree);
extern tree c_process_expr_stmt (location_t, tree);
extern tree c_finish_expr_stmt (location_t, tree);
-extern tree c_finish_return (location_t, tree, tree);
+extern tree c_finish_return (location_t, tree, tree, bool = false);
extern tree c_finish_bc_stmt (location_t, tree, bool);
extern tree c_finish_goto_label (location_t, tree);
extern tree c_finish_goto_ptr (location_t, c_expr val);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index a0e7dbe1b481..5ec92900d50a 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -11692,10 +11692,10 @@ c_finish_goto_ptr (location_t loc, c_expr val)
to return, or a null pointer for `return;' with no value. LOC is
the location of the return statement, or the location of the expression,
if the statement has any. If ORIGTYPE is not NULL_TREE, it
- is the original type of RETVAL. */
+ is the original type of RETVAL. MUSTTAIL_P indicates a musttail attribute. */
tree
-c_finish_return (location_t loc, tree retval, tree origtype)
+c_finish_return (location_t loc, tree retval, tree origtype, bool musttail_p)
{
tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
bool no_warning = false;
@@ -11709,6 +11709,17 @@ c_finish_return (location_t loc, tree retval, tree origtype)
warning_at (xloc, 0,
"function declared %<noreturn%> has a %<return%> statement");
+ if (retval && musttail_p)
+ {
+ tree t = retval;
+ if (TREE_CODE (t) == TARGET_EXPR)
+ t = TARGET_EXPR_INITIAL (t);
+ if (TREE_CODE (t) != CALL_EXPR)
+ error_at (xloc, "cannot tail-call: return value must be call");
+ else
+ CALL_EXPR_MUST_TAIL_CALL (t) = 1;
+ }
+
if (retval)
{
tree semantic_type = NULL_TREE;
--
2.44.0
next prev parent reply other threads:[~2024-06-02 17:22 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-02 17:16 Updated musttail patchkit Andi Kleen
2024-06-02 17:16 ` [PATCH v7 1/9] Improve must tail in RTL backend Andi Kleen
2024-06-10 0:55 ` [PING] " Andi Kleen
2024-06-14 13:43 ` [PING^2] " Andi Kleen
2024-06-20 18:13 ` [PING^3] " Andi Kleen
2024-06-02 17:16 ` [PATCH v7 2/9] Fix pro_and_epilogue for sibcalls at -O0 Andi Kleen
2024-06-02 17:30 ` Andrew Pinski
2024-06-02 20:27 ` Andi Kleen
2024-06-02 17:16 ` [PATCH v7 3/9] Add a musttail generic attribute to the c-attribs table Andi Kleen
2024-06-02 17:16 ` [PATCH v7 4/9] C++: Support clang compatible [[musttail]] (PR83324) Andi Kleen
2024-06-03 14:42 ` Jason Merrill
2024-06-03 15:33 ` Andi Kleen
2024-06-03 15:44 ` Jakub Jelinek
2024-06-03 16:29 ` Jason Merrill
2024-06-03 19:35 ` Andi Kleen
2024-06-03 20:27 ` Jason Merrill
2024-06-04 0:17 ` Andi Kleen
2024-06-02 17:16 ` Andi Kleen [this message]
2024-06-02 17:16 ` [PATCH v7 6/9] Add tests for C/C++ musttail attributes Andi Kleen
2024-06-03 14:46 ` Jason Merrill
2024-06-02 17:16 ` [PATCH v7 7/9] Enable musttail tail conversion even when not optimizing Andi Kleen
2024-06-02 17:16 ` [PATCH v7 8/9] Give better error messages for musttail Andi Kleen
2024-06-02 17:16 ` [PATCH v7 9/9] Add documentation for musttail attribute Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240602172205.2151579-6-ak@linux.intel.com \
--to=ak@linux.intel.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=josmyers@redhat.com \
--cc=nathan@acm.org \
--cc=richard.guenther@gmail.com \
--cc=richard.sandiford@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).