@@ -437,6 +437,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__volatile__", RID_VOLATILE, 0 },
{ "__GIMPLE", RID_GIMPLE, D_CONLY },
{ "__PHI", RID_PHI, D_CONLY },
+ { "__RTL", RID_RTL, D_CONLY },
{ "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "asm", RID_ASM, D_ASM },
@@ -124,6 +124,9 @@ enum rid
/* "__PHI", for parsing PHI function in GIMPLE FE. */
RID_PHI,
+ /* "__RTL", for the RTL-parsing extension to the C frontend. */
+ RID_RTL,
+
/* C11 */
RID_ALIGNAS, RID_GENERIC,
@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3. If not see
#include "gcc-rich-location.h"
#include "c-parser.h"
#include "gimple-parser.h"
+#include "read-rtl-function.h"
+#include "run-rtl-passes.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -1311,6 +1313,8 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
static void c_parser_cilk_grainsize (c_parser *, bool *);
+static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass);
+
/* Parse a translation unit (C90 6.7, C99 6.9).
translation-unit:
@@ -1547,7 +1551,11 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
GIMPLE:
gimple-function-definition:
- declaration-specifiers[opt] __GIMPLE (gimple-pass-list) declarator
+ declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
+ declaration-list[opt] compound-statement
+
+ rtl-function-definition:
+ declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
declaration-list[opt] compound-statement */
static void
@@ -2043,7 +2051,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tv = TV_PARSE_INLINE;
else
tv = TV_PARSE_FUNC;
- timevar_push (tv);
+ auto_timevar at (g_timer, tv);
/* Parse old-style parameter declarations. ??? Attributes are
not allowed to start declaration specifiers here because of a
@@ -2075,12 +2083,28 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
function body as GIMPLE. */
if (specs->gimple_p)
{
- cfun->pass_startwith = specs->gimple_pass;
+ cfun->pass_startwith = specs->gimple_or_rtl_pass;
bool saved = in_late_binary_op;
in_late_binary_op = true;
c_parser_parse_gimple_body (parser);
in_late_binary_op = saved;
}
+ /* Similarly, if it was marked with __RTL, use the RTL parser now,
+ consuming the function body. */
+ else if (specs->rtl_p)
+ {
+ c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
+
+ /* Normally, store_parm_decls sets next_is_function_body,
+ anticipating a function body. We need a push_scope/pop_scope
+ pair to flush out this state, or subsequent function parsing
+ will go wrong. */
+ push_scope ();
+ pop_scope ();
+
+ finish_function ();
+ return;
+ }
else
{
fnbody = c_parser_compound_statement (parser);
@@ -2111,7 +2135,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
if (specs->gimple_p)
DECL_SAVED_TREE (fndecl) = NULL_TREE;
- timevar_pop (tv);
break;
}
}
@@ -2603,7 +2626,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
c_parser_consume_token (parser);
specs->gimple_p = true;
specs->locations[cdw_gimple] = loc;
- specs->gimple_pass = c_parser_gimple_pass_list (parser);
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+ break;
+ case RID_RTL:
+ c_parser_consume_token (parser);
+ specs->rtl_p = true;
+ specs->locations[cdw_rtl] = loc;
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
break;
default:
goto out;
@@ -18281,4 +18310,74 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return value_tree;
}
+/* Parse the body of a function declaration marked with "__RTL".
+
+ The RTL parser works on the level of characters read from a
+ FILE *, whereas c_parser works at the level of tokens.
+ Square this circle by consuming all of the tokens up to and
+ including the closing brace, recording the start/end of the RTL
+ fragment, and reopening the file and re-reading the relevant
+ lines within the RTL parser.
+
+ This requires the opening and closing braces of the C function
+ to be on separate lines from the RTL they wrap.
+
+ Take ownership of START_WITH_PASS, if non-NULL. */
+
+void
+c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
+{
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ location_t start_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume all tokens, up to the closing brace, handling
+ matching pairs of braces in the rtl dump. */
+ int num_open_braces = 1;
+ while (1)
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_BRACE:
+ num_open_braces++;
+ break;
+ case CPP_CLOSE_BRACE:
+ if (--num_open_braces == 0)
+ goto found_closing_brace;
+ break;
+ case CPP_EOF:
+ error_at (start_loc, "no closing brace");
+ free (start_with_pass);
+ return;
+ default:
+ break;
+ }
+ c_parser_consume_token (parser);
+ }
+
+ found_closing_brace:
+ /* At the closing brace; record its location. */
+ location_t end_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume the closing brace. */
+ c_parser_consume_token (parser);
+
+ /* Invoke the RTL parser. */
+ if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ /* If a pass name was provided for START_WITH_PASS, run the backend
+ accordingly now, on the cfun created above, transferring
+ ownership of START_WITH_PASS. */
+ if (start_with_pass)
+ run_rtl_passes (start_with_pass);
+}
+
#include "gt-c-c-parser.h"
@@ -268,6 +268,7 @@ enum c_declspec_word {
cdw_alignas,
cdw_address_space,
cdw_gimple,
+ cdw_rtl,
cdw_number_of_elements /* This one must always be the last
enumerator. */
};
@@ -291,8 +292,8 @@ struct c_declspecs {
NULL; attributes (possibly from multiple lists) will be passed
separately. */
tree attrs;
- /* The pass to start compiling a __GIMPLE function with. */
- char *gimple_pass;
+ /* The pass to start compiling a __GIMPLE or __RTL function with. */
+ char *gimple_or_rtl_pass;
/* The base-2 log of the greatest alignment required by an _Alignas
specifier, in bytes, or -1 if no such specifiers with nonzero
alignment. */
@@ -367,6 +368,8 @@ struct c_declspecs {
BOOL_BITFIELD alignas_p : 1;
/* Whether any __GIMPLE specifier was specified. */
BOOL_BITFIELD gimple_p : 1;
+ /* Whether any __RTL specifier was specified. */
+ BOOL_BITFIELD rtl_p : 1;
/* The address space that the declaration belongs to. */
addr_space_t address_space;
};
@@ -1008,18 +1008,18 @@ c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
return;
}
-/* Parse gimple pass list.
+/* Parse gimple/RTL pass list.
- gimple-pass-list:
+ gimple-or-rtl-pass-list:
startwith("pass-name")
*/
char *
-c_parser_gimple_pass_list (c_parser *parser)
+c_parser_gimple_or_rtl_pass_list (c_parser *parser)
{
char *pass = NULL;
- /* Accept __GIMPLE. */
+ /* Accept __GIMPLE/__RTL. */
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
return NULL;
c_parser_consume_token (parser);
@@ -22,6 +22,6 @@ along with GCC; see the file COPYING3. If not see
/* Gimple parsing functions. */
extern void c_parser_parse_gimple_body (c_parser *);
-extern char *c_parser_gimple_pass_list (c_parser *);
+extern char *c_parser_gimple_or_rtl_pass_list (c_parser *);
#endif
@@ -236,7 +236,7 @@ struct GTY(()) function {
/* The loops in this function. */
struct loops *x_current_loops;
- /* Filled by the GIMPLE FE, pass to start compilation with. */
+ /* Filled by the GIMPLE and RTL FEs, pass to start compilation with. */
char *pass_startwith;
/* The stack usage of this function. */