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; + }