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 <[email protected]>
* 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;
+ }