On 6 June 2016 at 15:49, Richard Biener <richard.guent...@gmail.com> wrote:
> On Mon, Jun 6, 2016 at 11:27 AM, Prasad Ghangal
> <prasad.ghan...@gmail.com> wrote:
>> Hi,
>>
>> This patch parses simple assignment statement
>>
>> int a;
>> void __GIMPLE foo()
>> {
>>   a = 1;
>> }
>>
>> but it does not produce gimple dump. In debugging I found that
>> cfun->gimple_body is not NULL and it contains GIMPLE_ASSIGN statement.
>> Am I missing something ?
>
> This is because the cgraph code does not call gimplify_function_tree
> () on functions
> with a gimple body (undertstandably) but that function produces said dump 
> file.
>
> Now, we don't even get that far as as you call finish_function () the C FE 
> sees
> no DECL_INITIAL on the fndecl (that contains the BLOCK tree), it doesn't even
> finalize the function via the cgraph (cgraph_node::finalize_function ()).
>
> While I believe that in the end we want a custom finish_function for
> the GIMPLE FE
> the immediate issue is the lack of a BLOCK tree which you can try initializing
> to NULL_TREE or an empty scope by simply doing
>
>  DECL_INITIAL (fndecl) = make_node (BLOCK);
>  BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
>
> that then runs into
>
> #1  0x0000000001798f21 in lower_function_body ()
>     at /space/rguenther/src/svn/GSoC/gcc/gimple-low.c:93
> 93        gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
> (gdb) l
> 88        gimple *bind;
> 89        gimple *x;
> 90
> 91        /* The gimplifier should've left a body of exactly one statement,
> 92           namely a GIMPLE_BIND.  */
> 93        gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
> 94                    && gimple_code (gimple_seq_first_stmt (body)) ==
> GIMPLE_BIND);
>
> as GIMPLE lowering expects "high GIMPLE" and thus an outer GIMPLE_BIND.
>
> It might be the time to investigate how to "skip" some early passes, for 
> example
> by first of all declaring what kind of GIMPLE you emit via setting
> cfun->curr_properties - in this case to PROP_gimple_any | PROP_gimple_lcf
>
> Ideally the pass manager would then skip parts of the pipeline that
> are not necessary.
>
> You will notice that a lot of time GCC development is chasing asserts
> / assumptions
> of some part of the compiler and in this process understand GCC some more ;)
Hi,
I was playing a bit with Prasad's patch and got it to work for the
following test-case:
int a;
void __GIMPLE foo()
{
  a = 1;
}

Surprisingly there were very few changes needed for the above test-case
(perhaps more will be needed for a non-trivial case).
I called cgraph_node::finalize_decl(current_function_decl, false)
after parsing was done,
and following hacks were required to get the test-case compiled:

1) Setting empty block scope:
 DECL_INITIAL (current_function_decl) = make_node (BLOCK);
 BLOCK_SUPERCONTEXT (DECL_INITIAL (current_function_decl)) =
current_function_decl;

2) Setting property to PROP_gimple_any however hits the assert in
lower_function_body() since
it expects GIMPLE_BODY.

To workaround that I changed it to:
 if  (! (gimple_seq_first (body) == gimple_seq_last (body)
          && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND))
    return 0;
which effectively disables pass_lower_cf in gimple mode.

3) After that, it appears middle-end expects a compulsory return stmt,
which is built implicitly
by pass_lower_cf if none exists, but now ICE's since we disable it, so
built it implicitly after parsing gimple body.

4) Added the following code from lower_function_body() to
c_parser_parse_gimple_body (),
not sure if it's really required, I added it because it initialized
different fields of current_function_decl.

  tree block = DECL_INITIAL (current_function_decl);
  BLOCK_SUBBLOCKS (block) = NULL_TREE;
  BLOCK_CHAIN (block) = NULL_TREE;
  TREE_ASM_WRITTEN (block) = 1;

5) Call init_tree_ssa() from C FE since we don't call gimplify_body()
in gimple mode and
init_tree_ssa() is called from gimplify_body().

Extending to basic block should be (hopefully) straight-forward.
I have a silly question - For control-flow  I suppose we can build
"plain" gimple
and let cfg pass take care of building the control flow graph ? Which
makes me wonder how to handle phi's in gimple input ?
create_phi_node() would expect cfg to be built beforehand, so would we
need to build cfg by hand instead of tree-cfg pass ?

Thanks,
Prathamesh
>
> Richard.
>
>>
>>
>> Thanks,
>> Prasad Ghangal
>>
>> On 31 May 2016 at 15:57, Richard Biener <richard.guent...@gmail.com> wrote:
>>> On Mon, May 30, 2016 at 5:15 PM, Prasad Ghangal
>>> <prasad.ghan...@gmail.com> wrote:
>>>> Hi,
>>>>
>>>> As David suggested in his rtlfe patch,
>>>> this patch recognizes __GIMPLE keyword and switches to
>>>> c_parser_parse_gimple_body by providing -fgimple option.
>>>>
>>>>
>>>> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
>>>> index 4568cf6..41a8f05 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 },
>>>> +  { "__GIMPLE",        RID_GIMPLE,    0 },
>>>
>>> I think we need a D_GIMPLE_ONLY flag which disables this reserved word
>>> when -fgimple is not
>>> in effect.  That's something to put on a list of TODOs once everything
>>> else works fine (it's not
>>> high priority but a requirement to merge to trunk).  For now you can
>>> at least put D_CONLY there
>>> (as -fgimple is a C only flag).
>>>
>>>>    { "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 0295532..23a401d 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,
>>>>
>>>> +  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
>>>> +  RID_GIMPLE,
>>>> +
>>>>    /* C11 */
>>>>    RID_ALIGNAS, RID_GENERIC,
>>>>
>>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>>> index 918df16..8ab56af 100644
>>>> --- a/gcc/c-family/c.opt
>>>> +++ b/gcc/c-family/c.opt
>>>> @@ -200,6 +200,10 @@ F
>>>>  Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path
>>>> after %qs)
>>>>  -F <dir>    Add <dir> to the end of the main framework include path.
>>>>
>>>> +fgimple
>>>> +C Var(flag_gimple) Init(0)
>>>> +Enable parsing GIMPLE
>>>> +
>>>>  H
>>>>  C ObjC C++ ObjC++
>>>>  Print the name of header files as they are used.
>>>> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
>>>> index 1cf4fb4..c5a4d3f 100644
>>>> --- a/gcc/c/c-parser.c
>>>> +++ b/gcc/c/c-parser.c
>>>> @@ -1396,6 +1396,7 @@ static bool c_parser_cilk_verify_simd (c_parser
>>>> *, enum pragma_context);
>>>>  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_gimple_body (c_parser *parser);
>>>>
>>>>  /* Parse a translation unit (C90 6.7, C99 6.9).
>>>>
>>>> @@ -1638,6 +1639,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 gimple_body_p = false;
>>>>
>>>>    if (static_assert_ok
>>>>        && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
>>>> @@ -1687,6 +1689,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_GIMPLE)
>>>> +    {
>>>> +      gimple_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))
>>>> @@ -2102,6 +2115,14 @@ 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 (gimple_body_p && flag_gimple)
>>>> +    {
>>>> +      c_parser_parse_gimple_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);
>>>> @@ -2123,7 +2144,7 @@ c_parser_declaration_or_fndef (c_parser *parser,
>>>> bool fndef_ok,
>>>>        add_stmt (fnbody);
>>>>        finish_function ();
>>>>      }
>>>> -
>>>> +
>>>>        timevar_pop (tv);
>>>>        break;
>>>>      }
>>>
>>> Always avoid stay changes like this.
>>>
>>>> @@ -18055,4 +18076,23 @@ 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 "__GIMPLE".  */
>>>> +
>>>> +void
>>>> +c_parser_parse_gimple_body (c_parser *parser)
>>>> +{
>>>> +  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
>>>> +    return;
>>>> +
>>>> +  location_t loc1 = c_parser_peek_token (parser)->location;
>>>> +  inform (loc1, "start of GIMPLE");
>>>> +
>>>> +  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"
>>>>
>>>>
>>>>
>>>>
>>>> GIMPLE function body consists of GIMPLE statements. For parsing GIMPLE
>>>> function body, we need to populate gimple body with gimple statements
>>>> which will emit GIMPLE as it is.
>>>>
>>>> I would like to hear suggestions about how can I emit GIMPLE directly from 
>>>> FE.
>>>
>>> You should be able to use gimple_build_* functions declared in gimple.h, for
>>> example
>>>
>>>   stmt = gimple_build_assign (res, PLUS_EXPR, op0, op1);
>>>
>>> will build an assignment to res computing op0 + op1.  res, op0 and op1 can 
>>> be
>>> most easily parsed using the appropriate C parsing functions for 
>>> identifiers.
>>>
>>> You'll need to queue stmts you built in a gimple_seq and attach that to the
>>> function via gimple_set_body (fndecl, sequence).
>>>
>>> I suggest you try with a "simple" example like
>>>
>>> int a;
>>>
>>> __GIMPLE void foo (void)
>>> {
>>>   a = 1;
>>> }
>>>
>>> going forward with handling a = 1 + 2; and then, sth you'll need very 
>>> quickly,
>>> handle local declarations like
>>>
>>> int a;
>>> __GIMPLE int foo (void)
>>> {
>>>   int b;
>>>   b = a;
>>>   b = b + 1;
>>>   a = b;
>>> }
>>>
>>> this is sth C code like int foo (void) { a = a + 1; } is gimplified to.
>>>
>>> Richard.
>>>
>>>>
>>>>
>>>> Thanks,
>>>> Prasad Ghangal
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4e75e51..a69e3c0 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 },
+  { "__GIMPLE",                RID_GIMPLE,     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 },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4e6aa00..35558e7 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,
 
+  /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+  RID_GIMPLE,
+
   /* C11 */
   RID_ALIGNAS, RID_GENERIC,
 
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 918df16..8ab56af 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -200,6 +200,10 @@ F
 Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after 
%qs)
 -F <dir>       Add <dir> to the end of the main framework include path.
 
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE
+
 H
 C ObjC C++ ObjC++
 Print the name of header files as they are used.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 2fef1ac..474209e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -58,6 +58,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-indentation.h"
 #include "gimple-expr.h"
 #include "context.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
 
 /* We need to walk over decls with incomplete struct/union/enum types
    after parsing the whole translation unit.
@@ -1396,6 +1403,9 @@ static bool c_parser_cilk_verify_simd (c_parser *, enum 
pragma_context);
 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_gimple_body (c_parser *);
+static void c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_finish_gimple_expr_stmt (tree, gimple_seq *);
 
 /* Parse a translation unit (C90 6.7, C99 6.9).
 
@@ -1638,6 +1648,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 gimple_body_p = false;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1687,6 +1698,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_GIMPLE)
+       {
+         gimple_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))
@@ -2102,6 +2124,16 @@ 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 (gimple_body_p && flag_gimple)
+       {
+         c_parser_parse_gimple_body (parser);
+         //finish_function ();
+         cgraph_node::finalize_function (current_function_decl, false);
+         timevar_pop (tv);
+         return;
+       }
+
       fnbody = c_parser_compound_statement (parser);
       if (flag_cilkplus && contains_array_notation_expr (fnbody))
        fnbody = expand_array_notation_exprs (fnbody);
@@ -18085,4 +18117,116 @@ 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 "__GIMPLE".  */
+
+void 
+c_parser_parse_gimple_body (c_parser *parser)
+{
+  debug_generic_expr (current_function_decl); 
+  gimple_seq seq;
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  inform (loc1, "start of GIMPLE");
+  seq = NULL;
+  c_parser_gimple_compound_statement (parser, &seq);
+  
+  greturn *r = gimple_build_return (NULL);
+  gimple_seq_add_stmt (&seq, r);
+
+  DECL_INITIAL (current_function_decl) = make_node (BLOCK);
+  BLOCK_SUPERCONTEXT (DECL_INITIAL (current_function_decl)) = 
current_function_decl; 
+
+  tree block = DECL_INITIAL (current_function_decl);
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
+  TREE_ASM_WRITTEN (block) = 1;
+
+
+
+  gimple_set_body (current_function_decl, seq);
+  cfun->curr_properties = PROP_gimple_any;
+  fprintf (stderr, "parsed gimple body\n");
+
+  debug_gimple_seq (seq);
+  init_tree_ssa (cfun);
+  return;
+}
+
+/* Parser a compound statement in gimple function body */
+
+static void
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+  location_t brace_loc;
+  brace_loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      return;
+    }
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      goto out;
+    }
+
+  /* We must now have at least one statement, label or declaration.  */
+  
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      goto out;
+    }
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+      if (c_parser_next_token_is (parser, CPP_EOF))
+       {
+         c_parser_error (parser, "expected declaration or statement");
+         goto out;
+       }
+      else
+       {
+         switch (c_parser_peek_token (parser)->type)
+           {
+           case CPP_KEYWORD:
+             switch (c_parser_peek_token (parser)->keyword)
+               {
+               default:
+                 goto expr_stmt;
+               }
+             break;
+           case CPP_SEMICOLON:
+             c_parser_consume_token (parser);
+             break;
+           default:
+           expr_stmt:
+             c_finish_gimple_expr_stmt (c_parser_expression_conv 
(parser).value, seq);
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected 
%<;%>");
+             break;
+           }
+       }
+      parser->error = false;
+    }
+  c_parser_consume_token (parser);
+
+  out:
+  return;
+}
+
+/* Emit an expression as a statement. */
+
+static void
+c_finish_gimple_expr_stmt (tree expr, gimple_seq *seq)
+{
+  tree lhs, rhs;
+  gimple *stmt;
+  if (expr)
+    {
+      lhs = TREE_OPERAND (expr, 0);
+      rhs = TREE_OPERAND (expr, 1);
+      stmt = gimple_build_assign (lhs, rhs);
+      gimple_seq_add_stmt (seq, stmt);
+      return;
+    }
+}
+
 #include "gt-c-c-parser.h"
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 9ea17af..1934ce6 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -90,8 +90,9 @@ lower_function_body (void)
 
   /* The gimplifier should've left a body of exactly one statement,
      namely a GIMPLE_BIND.  */
-  gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
-             && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND);
+  if  (! (gimple_seq_first (body) == gimple_seq_last (body)
+          && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND))
+    return 0;
 
   memset (&data, 0, sizeof (data));
   data.block = DECL_INITIAL (current_function_decl);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f12c6a1..1932ca7 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11685,7 +11685,10 @@ gimplify_function_tree (tree fndecl)
       && !needs_to_live_in_memory (ret))
     DECL_GIMPLE_REG_P (ret) = 1;
 
-  bind = gimplify_body (fndecl, true);
+  if (!cfun->gimple_body)
+    bind = gimplify_body (fndecl, true);
+  else
+    bind = NULL;
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */

Reply via email to