From 2c4008a008b1b5bf7e2b201c5db16a04ba6f0260 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 10 May 2016 16:20:48 -0400
Subject: [PATCH 10/36] [rtlfe] Barebones implementation of "__RTL"; next
 steps?

[CCing Prasad since this may be useful for his gimple FE work, by
replacing "rtl" with "gimple" in the patch]

On Mon, 2016-05-09 at 11:44 +0200, Richard Biener wrote:
> On Wed, May 4, 2016 at 10:49 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:

> > This patch kit introduces an RTL frontend, for the purpose
> > of unit testing: primarly for unit testing of RTL passes, and
> > possibly for unit testing of .md files.
> >
> > It's very much a work-in-progress; I'm posting it now to get
> > feedback.

[...snip...]

> > * The RTL frontend doesn't have any knowledge of the name of the
> > function,
> >   of parameters, types, locals, globals, etc.  It creates a single
> > function.
> >   The function is currently hardcoded to have this signature:
> >
> >      int test_1 (int, int, int);
> >
> >   since there's no syntax for specify otherwise, and we need to
> > provide
> >   a FUNCTION_DECL tree when building a function object (by calling
> >   allocate_struct_function).
> >
> > * Similarly, there are no types beyond the built-in ones; all
> > expressions
> >   are treated as being of type int.  I suspect that this approach
> >   will be too simplistic when it comes to e.g. aliasing.
>
> To address this and the previous issue I suggest to implement the RTL
> FE
> similar to how I proposed the GIMPLE FE - piggy-back on the C FE and
> thus
> allow
>
> int __RTL foo (int a, int b) // gets you function decl and param
> decls
> {
>  (insn ...)
> ...
>
> }
>
> int main()
> {
>   if (foo (1) != 0)
>     abort ();
> }
>
> That would also allow dg-do run testcases and not rely solely on
> scanning
> RTL dumps.

The following is an attempt at implementing this, by adding a new
"__RTL" keyword, and detecting it in the C frontend, switching
to a custom parser for the function body.

Does this look like the kind of thing you had in mind for the
RTL and gimple "frontends"?

Wiring this up to the existing RTL parser might be awkward: the
existing RTL parser in read-md.c etc works at the level of
characters (read_char and unread_char from a FILE *), whereas the
C frontend is in terms of tokens.

I have a patch that ports the RTL parser to using libcpp for
location-tracking, and another that updates it to use libcpp
for diagnostics.  This adds more dependency on a build-time
libcpp to the gen* tools.  Both patches are currently messy.
Potentially I could build on them and attempt to update the RTL
parser further, to use libcpp's tokenizer.

Does that general approach sound sane?  In particular:
- is it sane to eliminate errors.c in favor of building
diagnostics*.c for the build machine as well as the host machine?
- is it sane to rewrite the read-md.c/read-rtl.c code to
a token-based approach, using libcpp?

Alternatively, the shorter term approach would be to kludge
in reading from a FILE * in read-md.c based on where the
C parser has got to, with a hybrid of the two approaches
(character-based vs token-based).

Thoughts?

Thanks
Dave

[...snip...]

gcc/c-family/ChangeLog:
	* c-common.c (c_common_reswords): Add __RTL.
	* c-common.h (enum rid): Add RID_RTL.

gcc/c/ChangeLog:
	* c-parser.c (c_parser_declaration_or_fndef): Handle "__RTL"
	before a function name by calling c_parser_parse_rtl_body rather
	than c_parser_compound_statement.
	(c_parser_parse_rtl_body): New function.
---
 gcc/c-family/c-common.c |  1 +
 gcc/c-family/c-common.h |  3 +++
 gcc/c/c-parser.c        | 41 +++++++++++++++++++++++++++++++++++++++--
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 936ddfb..e41845b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -511,6 +511,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "__RTL",		RID_RTL,	0 },
   { "alignas",		RID_ALIGNAS,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "alignof",		RID_ALIGNOF,	D_CXXONLY | D_CXX11 | D_CXXWARN },
   { "asm",		RID_ASM,	D_ASM },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 3ad5400..d07feb9 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -104,6 +104,9 @@ enum rid
   RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
 
+  /* "__RTL", for the RTL-parsing extension to the C frontend.  */
+  RID_RTL,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 1a50dea..0661ad2 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1404,6 +1404,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);
+
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
    translation-unit:
@@ -1645,6 +1647,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
   tree all_prefix_attrs;
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
+  bool rtl_body_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1729,6 +1732,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       c_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
+
+  if (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      c_token *kw_token = c_parser_peek_token (parser);
+      if (kw_token->keyword == RID_RTL)
+	{
+	  rtl_body_p = true;
+	  c_parser_consume_token (parser);
+	}
+    }
+
   finish_declspecs (specs);
   bool auto_type_p = specs->typespec_word == cts_auto_type;
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -2116,7 +2130,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
@@ -2144,6 +2158,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 			       oacc_routine_clauses, false, first, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
+      if (rtl_body_p)
+	{
+	  c_parser_parse_rtl_body (parser);
+	  finish_function ();
+	  return;
+	}
+
       fnbody = c_parser_compound_statement (parser);
       if (flag_cilkplus && contains_array_notation_expr (fnbody))
 	fnbody = expand_array_notation_exprs (fnbody);
@@ -2166,7 +2187,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	  finish_function ();
 	}
 
-      timevar_pop (tv);
       break;
     }
 }
@@ -18129,4 +18149,21 @@ 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".  */
+
+void
+c_parser_parse_rtl_body (c_parser *parser)
+{
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    return;
+
+  location_t start_loc = c_parser_peek_token (parser)->location;
+  inform (start_loc, "start of RTL");
+
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+      c_parser_consume_token (parser);
+
+  c_parser_consume_token (parser);
+}
+
 #include "gt-c-c-parser.h"
-- 
1.8.5.3

