Commit e4f81565 by Richard Sandiford Committed by Richard Sandiford

Gimple FE support for internal functions

This patch gets the gimple FE to parse calls to internal functions.
The only non-obvious thing was how the functions should be written
to avoid clashes with real function names.  One option would be to
go the magic number of underscores route, but we already do that for
built-in functions, and it would be good to keep them visually
distinct.  In the end I borrowed the local/internal label convention
from asm and used:

  x = .SQRT (y);

2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* internal-fn.h (lookup_internal_fn): Declare
	* internal-fn.c (lookup_internal_fn): New function.
	* gimple.c (gimple_build_call_from_tree): Handle calls to
	internal functions.
	* gimple-pretty-print.c (dump_gimple_call): Print "." before
	internal function names.
	* tree-pretty-print.c (dump_generic_node): Likewise.
	* tree-ssa-scopedtables.c (expr_hash_elt::print): Likewise.

gcc/c/
	* gimple-parser.c: Include internal-fn.h.
	(c_parser_gimple_statement): Treat a leading CPP_DOT as a call.
	(c_parser_gimple_call_internal): New function.
	(c_parser_gimple_postfix_expression): Use it to handle CPP_DOT.
	Fix typos in comment.

gcc/testsuite/
	* gcc.dg/gimplefe-28.c: New test.
	* gcc.dg/asan/use-after-scope-9.c: Adjust expected output for
	internal function calls.
	* gcc.dg/goacc/loop-processing-1.c: Likewise.

From-SVN: r260316
parent eb69361d
2018-05-17 Richard Sandiford <richard.sandiford@linaro.org>
* internal-fn.h (lookup_internal_fn): Declare
* internal-fn.c (lookup_internal_fn): New function.
* gimple.c (gimple_build_call_from_tree): Handle calls to
internal functions.
* gimple-pretty-print.c (dump_gimple_call): Print "." before
internal function names.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree-ssa-scopedtables.c (expr_hash_elt::print): Likewise.
2018-05-17 Richard Sandiford <richard.sandiford@linaro.org>
* gimple-fold.h (gimple_build): Make the function forms take
combined_fn rather than built_in_function.
(gimple_simplify): Likewise.
......
2018-05-17 Richard Sandiford <richard.sandiford@linaro.org>
* gimple-parser.c: Include internal-fn.h.
(c_parser_gimple_statement): Treat a leading CPP_DOT as a call.
(c_parser_gimple_call_internal): New function.
(c_parser_gimple_postfix_expression): Use it to handle CPP_DOT.
Fix typos in comment.
2018-05-10 Jakub Jelinek <jakub@redhat.com>
PR c++/85662
......
......@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssanames.h"
#include "gimple-ssa.h"
#include "tree-dfa.h"
#include "internal-fn.h"
/* Gimple parsing functions. */
......@@ -400,9 +401,10 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
}
/* GIMPLE call with lhs. */
if (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
&& lookup_name (c_parser_peek_token (parser)->value))
if (c_parser_next_token_is (parser, CPP_DOT)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
&& lookup_name (c_parser_peek_token (parser)->value)))
{
rhs = c_parser_gimple_unary_expression (parser);
if (rhs.value != error_mark_node)
......@@ -726,14 +728,57 @@ c_parser_parse_ssa_name (c_parser *parser,
return name;
}
/* Parse a gimple call to an internal function.
gimple-call-internal:
. identifier ( gimple-argument-expression-list[opt] ) */
static struct c_expr
c_parser_gimple_call_internal (c_parser *parser)
{
struct c_expr expr;
expr.set_error ();
gcc_assert (c_parser_next_token_is (parser, CPP_DOT));
c_parser_consume_token (parser);
location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_next_token_is (parser, CPP_NAME)
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
{
c_parser_error (parser, "expecting internal function name");
return expr;
}
tree id = c_parser_peek_token (parser)->value;
internal_fn ifn = lookup_internal_fn (IDENTIFIER_POINTER (id));
c_parser_consume_token (parser);
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
auto_vec<tree> exprlist;
if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
c_parser_gimple_expr_list (parser, &exprlist);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
if (ifn == IFN_LAST)
error_at (loc, "unknown internal function %qE", id);
else
{
expr.value = build_call_expr_internal_loc_array
(loc, ifn, void_type_node, exprlist.length (),
exprlist.address ());
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
}
}
return expr;
}
/* Parse gimple postfix expression.
gimple-postfix-expression:
gimple-primary-expression
gimple-primary-xpression [ gimple-primary-expression ]
gimple-primary-expression [ gimple-primary-expression ]
gimple-primary-expression ( gimple-argument-expression-list[opt] )
postfix-expression . identifier
postfix-expression -> identifier
gimple-postfix-expression . identifier
gimple-postfix-expression -> identifier
gimple-argument-expression-list:
gimple-unary-expression
......@@ -743,6 +788,7 @@ c_parser_parse_ssa_name (c_parser *parser,
identifier
constant
string-literal
gimple-call-internal
*/
......@@ -779,6 +825,9 @@ c_parser_gimple_postfix_expression (c_parser *parser)
expr.original_code = STRING_CST;
c_parser_consume_token (parser);
break;
case CPP_DOT:
expr = c_parser_gimple_call_internal (parser);
break;
case CPP_NAME:
if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
{
......
......@@ -874,7 +874,7 @@ dump_gimple_call (pretty_printer *buffer, gcall *gs, int spc,
if (flags & TDF_RAW)
{
if (gimple_call_internal_p (gs))
dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
dump_gimple_fmt (buffer, spc, flags, "%G <.%s, %T", gs,
internal_fn_name (gimple_call_internal_fn (gs)), lhs);
else
dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", gs, fn, lhs);
......@@ -898,7 +898,10 @@ dump_gimple_call (pretty_printer *buffer, gcall *gs, int spc,
pp_space (buffer);
}
if (gimple_call_internal_p (gs))
pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
{
pp_dot (buffer);
pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
}
else
print_call_name (buffer, fn, flags);
pp_string (buffer, " (");
......
......@@ -350,12 +350,19 @@ gimple_build_call_from_tree (tree t, tree fnptrtype)
{
unsigned i, nargs;
gcall *call;
tree fndecl = get_callee_fndecl (t);
gcc_assert (TREE_CODE (t) == CALL_EXPR);
nargs = call_expr_nargs (t);
call = gimple_build_call_1 (fndecl ? fndecl : CALL_EXPR_FN (t), nargs);
tree fndecl = NULL_TREE;
if (CALL_EXPR_FN (t) == NULL_TREE)
call = gimple_build_call_internal_1 (CALL_EXPR_IFN (t), nargs);
else
{
fndecl = get_callee_fndecl (t);
call = gimple_build_call_1 (fndecl ? fndecl : CALL_EXPR_FN (t), nargs);
}
for (i = 0; i < nargs; i++)
gimple_call_set_arg (call, i, CALL_EXPR_ARG (t, i));
......
......@@ -64,6 +64,26 @@ const int internal_fn_flags_array[] = {
0
};
/* Return the internal function called NAME, or IFN_LAST if there's
no such function. */
internal_fn
lookup_internal_fn (const char *name)
{
typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
static name_to_fn_map_type *name_to_fn_map;
if (!name_to_fn_map)
{
name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
for (unsigned int i = 0; i < IFN_LAST; ++i)
name_to_fn_map->put (internal_fn_name (internal_fn (i)),
internal_fn (i));
}
internal_fn *entry = name_to_fn_map->get (name);
return entry ? *entry : IFN_LAST;
}
/* Fnspec of each internal function, indexed by function number. */
const_tree internal_fn_fnspec_array[IFN_LAST + 1];
......
......@@ -107,6 +107,8 @@ internal_fn_name (enum internal_fn fn)
return internal_fn_name_array[(int) fn];
}
extern internal_fn lookup_internal_fn (const char *);
/* Return the ECF_* flags for function FN. */
extern const int internal_fn_flags_array[];
......
2018-05-17 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.dg/gimplefe-28.c: New test.
* gcc.dg/asan/use-after-scope-9.c: Adjust expected output for
internal function calls.
* gcc.dg/goacc/loop-processing-1.c: Likewise.
2018-05-17 Martin Liska <mliska@suse.cz>
* gcc.dg/plugin/ggcplug.c (plugin_init): Do not use
......
......@@ -17,7 +17,7 @@ main (int argc, char **argv)
return *ptr;
}
// { dg-final { scan-tree-dump-times "= ASAN_POISON \\(\\)" 1 "asan1" } }
// { dg-final { scan-tree-dump-times {= \.ASAN_POISON \(\)} 1 "asan1" } }
// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
// { dg-output "READ of size .*" }
// { dg-output ".*'a' <== Memory access at offset \[0-9\]* is inside this variable.*" }
/* { dg-do compile { target sqrt_insn } } */
/* { dg-options "-fgimple -O2" } */
double __GIMPLE
f1 (double x)
{
double res;
res = .SQRT (x);
return res;
}
void __GIMPLE
f2 (double x)
{
.SQRT (x); // Dead code
}
......@@ -15,4 +15,4 @@ void vector_1 (int *ary, int size)
}
}
/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 24\(1\).*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*Head-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccdevlow" } } */
/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 24\(1\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccdevlow" } } */
......@@ -2262,7 +2262,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
if (CALL_EXPR_FN (node) != NULL_TREE)
print_call_name (pp, CALL_EXPR_FN (node), flags);
else
pp_string (pp, internal_fn_name (CALL_EXPR_IFN (node)));
{
pp_dot (pp);
pp_string (pp, internal_fn_name (CALL_EXPR_IFN (node)));
}
/* Print parameters. */
pp_space (pp);
......
......@@ -906,8 +906,8 @@ expr_hash_elt::print (FILE *stream)
fn_from = m_expr.ops.call.fn_from;
if (gimple_call_internal_p (fn_from))
fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
stream);
fprintf (stream, ".%s",
internal_fn_name (gimple_call_internal_fn (fn_from)));
else
print_generic_expr (stream, gimple_call_fn (fn_from));
fprintf (stream, " (");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment