The following fills the gap of missed handling of MEM_REF parsing.
As we want to represent all info that is on a MEM_REF the existing
dumping isn't sufficent so I resorted to

  __MEM '<' type-name [ ',' number ] '>'
        '(' [ '(' type-name ')' ] unary-expression
         [ '+' number ] ')'  */

where optional parts are in []s.  So for

  __MEM < int, 16 > ( (char *) &x + 1 )

we access x as 16-bit aligned int at offset 1 with TBAA type 'char'.

Naturally VIEW_CONVERT_EXPR would look like __VCE < int > (x) then,
TARGET_MEM_REF would simply get some additional operands in the
above function-like __MEM (rather than + step * index + index2).

Bootstrap / regtest running on x86_64-unknown-linux-gnu.

The testcase parses, dumps and then parses again to the same output.

Any comments / objections to the syntax (of __MEM) and/or suggestions
for VIEW_CONVERT_EXPR or TARGET_MEM_REF?

As you can see I adjusted dumping of pointer constants (we can't
parse the B suffix and large unsigned numbers get a warning so
add 'U').  There's the general issue that we dump

  short x;
  x = 1;

and then lex the '1' as type int and there's no suffixes for integer
types smaller than int which means we can't write those constants
type correct :/  Suggestions welcome (currently we ICE with type
mismatches in those cases, we can avoid that by auto-fixing during
parsing but I'd like to be explicit somehow).

Thanks,
Richard.

2017-01-11  Richard Biener  <rguent...@suse.de>

        * tree-pretty-print.c (dump_generic_node): Provide -gimple
        variant for MEM_REF.  Sanitize INTEGER_CST for -gimple.

        c/
        * gimple-parser.c (c_parser_gimple_postfix_expression): Parse
        __MEM.

        * gcc.dg/gimplefe-21.c: New testcase.

Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c     (revision 244312)
--- gcc/tree-pretty-print.c     (working copy)
*************** dump_generic_node (pretty_printer *pp, t
*** 1459,1465 ****
  
      case MEM_REF:
        {
!       if (integer_zerop (TREE_OPERAND (node, 1))
            /* Dump the types of INTEGER_CSTs explicitly, for we can't
               infer them and MEM_ATTR caching will share MEM_REFs
               with differently-typed op0s.  */
--- 1459,1496 ----
  
      case MEM_REF:
        {
!       if (flags & TDF_GIMPLE)
!         {
!           pp_string (pp, "__MEM <");
!           dump_generic_node (pp, TREE_TYPE (node),
!                              spc, flags | TDF_SLIM, false);
!           if (TYPE_ALIGN (TREE_TYPE (node))
!               != TYPE_ALIGN (TYPE_MAIN_VARIANT (TREE_TYPE (node))))
!             {
!               pp_string (pp, ", ");
!               pp_decimal_int (pp, TYPE_ALIGN (TREE_TYPE (node)));
!             }
!           pp_greater (pp);
!           pp_string (pp, " (");
!           if (TREE_TYPE (TREE_OPERAND (node, 0))
!               != TREE_TYPE (TREE_OPERAND (node, 1)))
!             {
!               pp_left_paren (pp);
!               dump_generic_node (pp, TREE_TYPE (TREE_OPERAND (node, 1)),
!                                  spc, flags | TDF_SLIM, false);
!               pp_right_paren (pp);
!             }
!           dump_generic_node (pp, TREE_OPERAND (node, 0),
!                              spc, flags | TDF_SLIM, false);
!           if (! integer_zerop (TREE_OPERAND (node, 1)))
!             {
!               pp_string (pp, " + ");
!               dump_generic_node (pp, TREE_OPERAND (node, 1),
!                                  spc, flags | TDF_SLIM, false);
!             }
!           pp_right_paren (pp);
!         }
!       else if (integer_zerop (TREE_OPERAND (node, 1))
            /* Dump the types of INTEGER_CSTs explicitly, for we can't
               infer them and MEM_ATTR caching will share MEM_REFs
               with differently-typed op0s.  */
*************** dump_generic_node (pretty_printer *pp, t
*** 1633,1639 ****
        break;
  
      case INTEGER_CST:
!       if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
        {
          /* In the case of a pointer, one may want to divide by the
             size of the pointed-to type.  Unfortunately, this not
--- 1664,1671 ----
        break;
  
      case INTEGER_CST:
!       if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
!         && ! (flags & TDF_GIMPLE))
        {
          /* In the case of a pointer, one may want to divide by the
             size of the pointed-to type.  Unfortunately, this not
*************** dump_generic_node (pretty_printer *pp, t
*** 1661,1667 ****
        else if (tree_fits_shwi_p (node))
        pp_wide_integer (pp, tree_to_shwi (node));
        else if (tree_fits_uhwi_p (node))
!       pp_unsigned_wide_integer (pp, tree_to_uhwi (node));
        else
        {
          wide_int val = node;
--- 1693,1703 ----
        else if (tree_fits_shwi_p (node))
        pp_wide_integer (pp, tree_to_shwi (node));
        else if (tree_fits_uhwi_p (node))
!       {
!         pp_unsigned_wide_integer (pp, tree_to_uhwi (node));
!         if (flags & TDF_GIMPLE)
!           pp_character (pp, 'U');
!       }
        else
        {
          wide_int val = node;
Index: gcc/c/gimple-parser.c
===================================================================
*** gcc/c/gimple-parser.c       (revision 244312)
--- gcc/c/gimple-parser.c       (working copy)
*************** c_parser_gimple_postfix_expression (c_pa
*** 727,732 ****
--- 727,804 ----
        if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
        {
          tree id = c_parser_peek_token (parser)->value;
+         if (strcmp (IDENTIFIER_POINTER (id), "__MEM") == 0)
+           {
+             /* __MEM '<' type-name [ ',' number ] '>'
+                      '(' [ '(' type-name ')' ] unary-expression
+                          [ '+' number ] ')'  */
+             location_t loc = c_parser_peek_token (parser)->location;
+             c_parser_consume_token (parser);
+             struct c_type_name *type_name = NULL;
+             tree alignment = NULL_TREE;
+             if (c_parser_require (parser, CPP_LESS, "expected %<<%>"))
+               {
+                 type_name = c_parser_type_name (parser);
+                 /* Optional alignment.  */
+                 if (c_parser_next_token_is (parser, CPP_COMMA))
+                   {
+                     c_parser_consume_token (parser);
+                     alignment
+                       = c_parser_gimple_postfix_expression (parser).value;
+                   }
+                 c_parser_skip_until_found (parser,
+                                            CPP_GREATER, "expected %<>%>");
+               }
+             struct c_expr ptr;
+             tree alias_off = NULL_TREE;
+             if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+               {
+                 tree alias_type = NULL_TREE;
+                 /* Optional alias-type cast.  */
+                 if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+                   {
+                     c_parser_consume_token (parser);
+                     struct c_type_name *alias_type_name
+                       = c_parser_type_name (parser);
+                     c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                                "expected %<)%>");
+                     if (alias_type_name)
+                       {
+                         tree tem;
+                         alias_type = groktypename (alias_type_name,
+                                                    &tem, NULL);
+                       }
+                   }
+                 ptr = c_parser_gimple_unary_expression (parser);
+                 if (! alias_type)
+                   alias_type = TREE_TYPE (ptr.value);
+                 /* Optional constant offset.  */
+                 if (c_parser_next_token_is (parser, CPP_PLUS))
+                   {
+                     c_parser_consume_token (parser);
+                     alias_off
+                       = c_parser_gimple_postfix_expression (parser).value;
+                     alias_off = fold_convert (alias_type, alias_off);
+                   }
+                 if (! alias_off)
+                   alias_off = build_int_cst (alias_type, 0);
+                 c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                            "expected %<)%>");
+               }
+             if (! type_name || c_parser_error (parser))
+               {
+                 c_parser_set_error (parser, false);
+                 return expr;
+               }
+             tree tem = NULL_TREE;
+             tree type = groktypename (type_name, &tem, NULL);
+             if (alignment)
+               type = build_aligned_type (type, tree_to_uhwi (alignment));
+             expr.value = build2_loc (loc, MEM_REF,
+                                      type, ptr.value, alias_off);
+             break;
+           }
+         /* SSA name.  */
          unsigned version, ver_offset;
          if (! lookup_name (id)
              && c_parser_parse_ssa_name_id (id, &version, &ver_offset))
Index: gcc/testsuite/gcc.dg/gimplefe-21.c
===================================================================
*** gcc/testsuite/gcc.dg/gimplefe-21.c  (nonexistent)
--- gcc/testsuite/gcc.dg/gimplefe-21.c  (working copy)
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fgimple" } */
+ 
+ float __GIMPLE ()
+ foo (int * p)
+ {
+   float f;
+   float D1800;
+   unsigned int D1799;
+ 
+   D1799 = __MEM <unsigned int, 8> ((char *)p + 1);
+   __MEM <unsigned int, 16> ((char *)&f + 0xfffffffffffffffe) = D1799;
+   __MEM <int> (p) = 1;
+   __MEM <int, 2> (p) = 1;
+   __MEM <int> (p + 2) = 1;
+   __MEM <int> ((char *)p) = 1;
+   D1800 = f;
+   return D1800;
+ }

Reply via email to