aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-05-17 10:52:58 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-05-17 10:52:58 +0000
commite4f81565ce768256ff3f7acc368c38fa450098cc (patch)
tree0a8bc7b8cca8bc8c488119cf5a5f80dd27acc639 /gcc
parenteb69361d0c5e98423e7ad7a537bc3250e083de4a (diff)
downloadgcc-e4f81565ce768256ff3f7acc368c38fa450098cc.zip
gcc-e4f81565ce768256ff3f7acc368c38fa450098cc.tar.gz
gcc-e4f81565ce768256ff3f7acc368c38fa450098cc.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/c/ChangeLog8
-rw-r--r--gcc/c/gimple-parser.c61
-rw-r--r--gcc/gimple-pretty-print.c7
-rw-r--r--gcc/gimple.c11
-rw-r--r--gcc/internal-fn.c20
-rw-r--r--gcc/internal-fn.h2
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-28.c16
-rw-r--r--gcc/testsuite/gcc.dg/goacc/loop-processing-1.c2
-rw-r--r--gcc/tree-pretty-print.c5
-rw-r--r--gcc/tree-ssa-scopedtables.c4
13 files changed, 141 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2f8fd3c..9e22926 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
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.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index a8e2128..f31c86f 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 32513f1..c9abe24 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -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)
{
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 6695526..afe0147 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -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, " (");
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 9dc4911..745cdf3 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -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));
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index da205c9..ba94a61 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -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];
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index 67102fd..34ea8c6 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -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[];
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f02fa93..c20e717 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+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
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
index edc1ab2..c3e4da5 100644
--- a/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
@@ -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.*" }
diff --git a/gcc/testsuite/gcc.dg/gimplefe-28.c b/gcc/testsuite/gcc.dg/gimplefe-28.c
new file mode 100644
index 0000000..467172d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-28.c
@@ -0,0 +1,16 @@
+/* { 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
+}
diff --git a/gcc/testsuite/gcc.dg/goacc/loop-processing-1.c b/gcc/testsuite/gcc.dg/goacc/loop-processing-1.c
index 07f56a2..bd4c07e 100644
--- a/gcc/testsuite/gcc.dg/goacc/loop-processing-1.c
+++ b/gcc/testsuite/gcc.dg/goacc/loop-processing-1.c
@@ -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" } } */
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 276ad00..bc36c28 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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);
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index 2a40fda..9e751a2 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -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, " (");