* [gimplefe] Skeleton GIMPLE front end
@ 2010-08-13 15:34 Diego Novillo
2010-08-13 15:35 ` Diego Novillo
2010-08-23 9:46 ` Sandeep Soni
0 siblings, 2 replies; 4+ messages in thread
From: Diego Novillo @ 2010-08-13 15:34 UTC (permalink / raw)
To: gcc-patches, Sandeep Soni
This adds a new front end in gcc/gimple. It moves all the
parsing bits from lto/lto.c into gimple/gimple.c and nothing
else.
The front end is built by default, or it can be configured with
--enable-languages=gimple. The binary is named gimple1.
I have not changed anything else, other than what was needed to
get gimple1 built. In particular, it still tries to open
/tmp/gimple.txt unconditionally. I will change that in a follow
up patch, to recognize .gimple files as source code.
Sandeep, when modifying the parser now, you need to edit
gcc/gimple/parser.c.
ChangeLog entries for everything under gcc/gimple/ should go to
gcc/gimple/ChangeLog. Only use gcc/ChangeLog.gimplefe when
changing files in gcc/
Tested on x86_64. Committed.
ChangeLog.gimplefe:
2010-08-13 Diego Novillo <dnovillo@google.com>
* lto/lto-lang.c (LANG_HOOKS_NAME): Update.
* common.opt (fgimple-parser): Remove.
* lto/lto.c (lto_main): Do not handle flag_gimple_parser.
* lto/lto.c (gimple parse_expect_op1,
gimple_parse_assign_stmt,
gimple_parse_call_stmt,
gimple_parse_cond_stmt,
gimple_parse_expect_argument,
gimple_parse_expect_false_label,
gimple_parse_expect_function_name,
gimple_parse_expect_lhs,
gimple_parse_expect_op1,
gimple_parse_expect_op2,
gimple_parse_expect_return_var,
gimple_parse_expect_rhs1,
gimple_parse_expect_rhs2,
gimple_parse_expect_subcode,
gimple_parse_expect_token,
gimple_parse_expect_true_label,
gimple_parse_goto_stmt,
gimple_parse_label_stmt,
gimple_parse_return_stmt,
gimple_parse_stmt,
gimple_parse_switch_stmt): Move to gimple/parser.c.
gimple/ChangeLog:
2010-08-12 Diego Novillo <dnovillo@google.com>
* parser.c (gimple parse_expect_op1,
gimple_parse_assign_stmt,
gimple_parse_call_stmt,
gimple_parse_cond_stmt,
gimple_parse_expect_argument,
gimple_parse_expect_false_label,
gimple_parse_expect_function_name,
gimple_parse_expect_lhs,
gimple_parse_expect_op1,
gimple_parse_expect_op2,
gimple_parse_expect_return_var,
gimple_parse_expect_rhs1,
gimple_parse_expect_rhs2,
gimple_parse_expect_subcode,
gimple_parse_expect_token,
gimple_parse_expect_true_label,
gimple_parse_goto_stmt,
gimple_parse_label_stmt,
gimple_parse_return_stmt,
gimple_parse_stmt,
gimple_parse_switch_stmt): Move from ../lto/lto.c.
2010-08-12 Diego Novillo <dnovillo@google.com>
* Make-lang.in: New file.
* config-lang.in: New file.
* gimple-lang.c: New file.
* lang-specs.h: New file.
* lang.opt: New file.
* parser.c: New file.
* parser.h: New file.
diff --git a/gcc/common.opt b/gcc/common.opt
index ecd2340..0fe09a8 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -605,11 +605,6 @@ Perform global common subexpression elimination after register allocation
has finished
; This option is not documented yet as its semantics will change.
-fgimple-parser
-Common Var(flag_gimple_parser)
-This option will be used to invoke the gimple text parser.
-
-; This option is not documented yet as its semantics will change.
fgraphite
Common Report Var(flag_graphite)
Enable in and out of Graphite representation
diff --git a/gcc/gimple/Make-lang.in b/gcc/gimple/Make-lang.in
new file mode 100644
index 0000000..bb50d32
--- /dev/null
+++ b/gcc/gimple/Make-lang.in
@@ -0,0 +1,84 @@
+# Top level -*- makefile -*- fragment for GIMPLE
+# Copyright (C) 2010
+# Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Variables
+
+# The name of the GIMPLE compiler.
+GIMPLE_EXE = gimple1$(exeext)
+# The GIMPLE-specific object files inclued in $(GIMPLE_EXE).
+GIMPLE_OBJS = gimple/gimple-lang.o gimple/parser.o attribs.o
+GIMPLE_PARSER_H = gimple/parser.h
+GIMPLE_TREE_H = gimple/gimple-tree.h
+
+# Rules
+
+# These hooks are used by the main GCC Makefile. Consult that
+# Makefile for documentation.
+gimple.all.cross: $(GIMPLE_EXE)
+gimple.start.encap: $(GIMPLE_EXE)
+gimple.rest.encap:
+gimple.tags:
+gimple.install-common:
+gimple.install-man:
+gimple.install-info:
+gimple.dvi:
+gimple.pdf:
+gimple.install-pdf:
+gimple.html:
+gimple.install-html:
+gimple.uninstall:
+gimple.info:
+gimple.man:
+gimple.srcextra:
+gimple.srcman:
+gimple.srcinfo:
+gimple.install-plugin:
+
+gimple.mostlyclean:
+ rm -f $(GIMPLE_OBJS) $(GIMPLE_EXE)
+
+gimple.clean:
+gimple.distclean:
+gimple.maintainer-clean:
+gimple.stage1:
+gimple.stage2:
+gimple.stage3:
+gimple.stage4:
+gimple.stageprofile:
+gimple.stagefeedback:
+
+# GIMPLE rules.
+
+# Use strict warnings for this front end.
+gimple-warn = $(STRICT_WARN)
+
+$(GIMPLE_EXE): $(GIMPLE_OBJS) $(BACKEND) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ $(GIMPLE_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
+
+# Dependencies
+gimple/gimple-lang.o: gimple/gimple-lang.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h flags.h $(TM_H) $(TREE_H) $(TARGET_H) \
+ langhooks.h $(LANGHOOKS_DEF_H) debug.h $(GIMPLE_PARSER_H) \
+ $(DIAGNOSTIC_CORE_H) $(TOPLEV_H) $(GIMPLE_TREE_H) \
+ $(GGC_H) gtype-gimple.h gt-gimple-gimple-lang.h
+gimple/parser.o: gimple/parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(CPPLIB_H) $(INPUT_H) $(DIAGNOSTIC_H) $(TREE_H) $(GIMPLE_H) \
+ $(TOPLEV_H) $(GIMPLE_PARSER_H)
diff --git a/gcc/gimple/config-lang.in b/gcc/gimple/config-lang.in
new file mode 100644
index 0000000..0ee83ab
--- /dev/null
+++ b/gcc/gimple/config-lang.in
@@ -0,0 +1,27 @@
+# Top level configure fragment for GIMPLE
+#
+# Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+language="gimple"
+compilers="gimple1\$(exeext)"
+stagestuff="gimple1\$(exeext)"
+
+gtfiles="\$(srcdir)/gimple/gimple-tree.h \$(srcdir)/gimple/gimple-lang.c"
+
+build_by_default=yes
diff --git a/gcc/gimple/gimple-lang.c b/gcc/gimple/gimple-lang.c
new file mode 100644
index 0000000..51ffb21
--- /dev/null
+++ b/gcc/gimple/gimple-lang.c
@@ -0,0 +1,1103 @@
+/* Language-dependent hooks for GIMPLE.
+
+ Copyright 2010 Free Software Foundation, Inc.
+ Contributed by Sandeep Soni and Diego Novillo
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "flags.h"
+#include "tm.h"
+#include "tree.h"
+#include "target.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "debug.h"
+#include "parser.h"
+#include "gimple.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "gimple-tree.h"
+
+static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_format_attribute (tree *, tree, tree, int, bool *);
+static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+
+/* Table of machine-independent attributes supported in GIMPLE. */
+const struct attribute_spec gimple_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "noreturn", 0, 0, true, false, false,
+ handle_noreturn_attribute },
+ /* The same comments as for noreturn attributes apply to const ones. */
+ { "const", 0, 0, true, false, false,
+ handle_const_attribute },
+ { "malloc", 0, 0, true, false, false,
+ handle_malloc_attribute },
+ { "pure", 0, 0, true, false, false,
+ handle_pure_attribute },
+ { "no vops", 0, 0, true, false, false,
+ handle_novops_attribute },
+ { "nonnull", 0, -1, false, true, true,
+ handle_nonnull_attribute },
+ { "nothrow", 0, 0, true, false, false,
+ handle_nothrow_attribute },
+ { "sentinel", 0, 1, false, true, true,
+ handle_sentinel_attribute },
+ { "type generic", 0, 0, false, true, true,
+ handle_type_generic_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
+/* Give the specifications for the format attributes, used by C and all
+ descendants. */
+
+const struct attribute_spec gimple_format_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "format", 3, 3, false, true, true,
+ handle_format_attribute },
+ { "format_arg", 1, 1, false, true, true,
+ handle_format_arg_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
+enum built_in_attribute
+{
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+ ATTR_LAST
+};
+
+static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
+
+/* Builtin types. */
+
+enum gimple_builtin_type
+{
+#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
+#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+ NAME,
+#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
+#include "builtin-types.def"
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_POINTER_TYPE
+ BT_LAST
+};
+
+typedef enum gimple_builtin_type builtin_type;
+
+static GTY(()) tree builtin_types[(int) BT_LAST + 1];
+
+static GTY(()) tree string_type_node;
+static GTY(()) tree const_string_type_node;
+static GTY(()) tree wint_type_node;
+static GTY(()) tree intmax_type_node;
+static GTY(()) tree uintmax_type_node;
+static GTY(()) tree signed_size_type_node;
+
+/* Flags needed to process builtins.def. */
+int flag_isoc94;
+int flag_isoc99;
+
+/* Attribute handlers. */
+
+/* Handle a "noreturn" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ tree type = TREE_TYPE (*node);
+
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_THIS_VOLATILE (*node) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (*node)
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type),
+ TYPE_READONLY (TREE_TYPE (type)), 1));
+ else
+ gcc_unreachable ();
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "const" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_const_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ tree type = TREE_TYPE (*node);
+
+ /* See FIXME comment on noreturn in c_common_attribute_table. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_READONLY (*node) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (*node)
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type), 1,
+ TREE_THIS_VOLATILE (TREE_TYPE (type))));
+ else
+ gcc_unreachable ();
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "malloc" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
+ DECL_IS_MALLOC (*node) = 1;
+ else
+ gcc_unreachable ();
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "pure" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_PURE_P (*node) = 1;
+ else
+ gcc_unreachable ();
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "no vops" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *ARG_UNUSED (no_add_attrs))
+{
+ gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ DECL_IS_NOVOPS (*node) = 1;
+ return NULL_TREE;
+}
+
+
+/* Helper for nonnull attribute handling; fetch the operand number
+ from the attribute argument list. */
+
+static bool
+get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
+{
+ /* Verify the arg number is a constant. */
+ if (TREE_CODE (arg_num_expr) != INTEGER_CST
+ || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+ return false;
+
+ *valp = TREE_INT_CST_LOW (arg_num_expr);
+ return true;
+}
+
+/* Handle the "nonnull" attribute. */
+
+static tree
+handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ tree type = *node;
+
+ /* If no arguments are specified, all pointer arguments should be
+ non-null. Verify a full prototype is given so that the arguments
+ will have the correct types when we actually check them later. */
+ if (!args)
+ {
+ gcc_assert (TYPE_ARG_TYPES (type));
+ return NULL_TREE;
+ }
+
+ /* Argument list specified. Verify that each argument number references
+ a pointer argument. */
+ for (; args; args = TREE_CHAIN (args))
+ {
+ tree argument;
+ unsigned HOST_WIDE_INT arg_num = 0, ck_num;
+
+ if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
+ gcc_unreachable ();
+
+ argument = TYPE_ARG_TYPES (type);
+ if (argument)
+ {
+ for (ck_num = 1; ; ck_num++)
+ {
+ if (!argument || ck_num == arg_num)
+ break;
+ argument = TREE_CHAIN (argument);
+ }
+
+ gcc_assert (argument
+ && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
+ }
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "nothrow" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_NOTHROW (*node) = 1;
+ else
+ gcc_unreachable ();
+
+ return NULL_TREE;
+}
+
+
+/* Handle a "sentinel" attribute. */
+
+static tree
+handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ tree params = TYPE_ARG_TYPES (*node);
+ gcc_assert (params);
+
+ while (TREE_CHAIN (params))
+ params = TREE_CHAIN (params);
+
+ gcc_assert (!VOID_TYPE_P (TREE_VALUE (params)));
+
+ if (args)
+ {
+ tree position = TREE_VALUE (args);
+ gcc_assert (TREE_CODE (position) == INTEGER_CST);
+ if (tree_int_cst_lt (position, integer_zero_node))
+ gcc_unreachable ();
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "type_generic" attribute. */
+
+static tree
+handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ tree params;
+
+ /* Ensure we have a function type. */
+ gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+ params = TYPE_ARG_TYPES (*node);
+ while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
+ params = TREE_CHAIN (params);
+
+ /* Ensure we have a variadic function. */
+ gcc_assert (!params);
+
+ return NULL_TREE;
+}
+
+/* Handle a "format" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+
+/* Handle a "format_arg" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+tree
+handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+
+/* Cribbed from c-common.c. */
+
+static void
+def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
+{
+ tree args = NULL, t;
+ va_list list;
+ int i;
+
+ va_start (list, n);
+ for (i = 0; i < n; ++i)
+ {
+ builtin_type a = (builtin_type) va_arg (list, int);
+ t = builtin_types[a];
+ if (t == error_mark_node)
+ goto egress;
+ args = tree_cons (NULL_TREE, t, args);
+ }
+ va_end (list);
+
+ args = nreverse (args);
+ if (!var)
+ args = chainon (args, void_list_node);
+
+ t = builtin_types[ret];
+ if (t == error_mark_node)
+ goto egress;
+ t = build_function_type (t, args);
+
+ egress:
+ builtin_types[def] = t;
+}
+
+/* Used to help initialize the builtin-types.def table. When a type of
+ the correct size doesn't exist, use error_mark_node instead of NULL.
+ The later results in segfaults even when a decl using the type doesn't
+ get invoked. */
+
+static tree
+builtin_type_for_size (int size, bool unsignedp)
+{
+ tree type = lang_hooks.types.type_for_size (size, unsignedp);
+ return type ? type : error_mark_node;
+}
+
+/* Support for DEF_BUILTIN. */
+
+static void
+def_builtin_1 (enum built_in_function fncode, const char *name,
+ enum built_in_class fnclass, tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p)
+{
+ tree decl;
+ const char *libname;
+
+ if (fntype == error_mark_node)
+ return;
+
+ libname = name + strlen ("__builtin_");
+ decl = add_builtin_function (name, fntype, fncode, fnclass,
+ (fallback_p ? libname : NULL),
+ fnattrs);
+
+ if (both_p
+ && !flag_no_builtin
+ && !(nonansi_p && flag_no_nonansi_builtin))
+ add_builtin_function (libname, libtype, fncode, fnclass,
+ NULL, fnattrs);
+
+ built_in_decls[(int) fncode] = decl;
+ if (implicit_p)
+ implicit_built_in_decls[(int) fncode] = decl;
+}
+
+
+/* Initialize the attribute table for all the supported builtins. */
+
+static void
+gimple_init_attributes (void)
+{
+ /* Fill in the built_in_attributes array. */
+#define DEF_ATTR_NULL_TREE(ENUM) \
+ built_in_attributes[(int) ENUM] = NULL_TREE;
+#define DEF_ATTR_INT(ENUM, VALUE) \
+ built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE);
+#define DEF_ATTR_IDENT(ENUM, STRING) \
+ built_in_attributes[(int) ENUM] = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
+ built_in_attributes[(int) ENUM] \
+ = tree_cons (built_in_attributes[(int) PURPOSE], \
+ built_in_attributes[(int) VALUE], \
+ built_in_attributes[(int) CHAIN]);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+}
+
+/* Create builtin types and functions. VA_LIST_REF_TYPE_NODE and
+ VA_LIST_ARG_TYPE_NODE are used in builtin-types.def. */
+
+static void
+gimple_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
+ tree va_list_arg_type_node ATTRIBUTE_UNUSED)
+{
+#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
+ builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 0, 1, ARG1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) \
+ def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) \
+ def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 1, 1, ARG1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_POINTER_TYPE(ENUM, TYPE) \
+ builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_POINTER_TYPE
+ builtin_types[(int) BT_LAST] = NULL_TREE;
+
+ gimple_init_attributes ();
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,\
+ NONANSI_P, ATTRS, IMPLICIT, COND) \
+ if (NAME && COND) \
+ def_builtin_1 (ENUM, NAME, CLASS, builtin_types[(int) TYPE], \
+ builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \
+ NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT);
+#include "builtins.def"
+#undef DEF_BUILTIN
+}
+
+static GTY(()) tree registered_builtin_types;
+
+/* A chain of builtin functions that we need to recognize. We will
+ assume that all other function names we see will be defined by the
+ user's program. */
+static GTY(()) tree registered_builtin_fndecls;
+
+/* Language hooks. */
+
+static unsigned int
+gimple_option_lang_mask (void)
+{
+ return CL_GIMPLE;
+}
+
+static void
+gimple_init_options (unsigned int decoded_options_count ATTRIBUTE_UNUSED,
+ struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
+{
+ /* By default, C99-like requirements for complex multiply and divide.
+ ??? Until the complex method is encoded in the IL this is the only
+ safe choice. This will pessimize Fortran code with GIMPLE unless
+ people specify a complex method manually or use -ffast-math. */
+ flag_complex_method = 2;
+}
+
+
+/* Return an integer type with PRECISION bits of precision,
+ that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
+
+static tree
+gimple_type_for_size (unsigned precision, int unsignedp)
+{
+ if (precision == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+
+ if (precision == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+
+ if (precision == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+
+ if (precision == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+ if (precision == TYPE_PRECISION (long_long_integer_type_node))
+ return unsignedp
+ ? long_long_unsigned_type_node
+ : long_long_integer_type_node;
+
+ if (precision <= TYPE_PRECISION (intQI_type_node))
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (precision <= TYPE_PRECISION (intHI_type_node))
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (precision <= TYPE_PRECISION (intSI_type_node))
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (precision <= TYPE_PRECISION (intDI_type_node))
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+
+ if (precision <= TYPE_PRECISION (intTI_type_node))
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+
+ return NULL_TREE;
+}
+
+
+/* Return a data type that has machine mode MODE.
+ If the mode is an integer,
+ then UNSIGNEDP selects between signed and unsigned types.
+ If the mode is a fixed-point mode,
+ then UNSIGNEDP selects between saturating and nonsaturating types. */
+
+static tree
+gimple_type_for_mode (enum machine_mode mode, int unsigned_p)
+{
+ tree t;
+
+ if (mode == TYPE_MODE (integer_type_node))
+ return unsigned_p ? unsigned_type_node : integer_type_node;
+
+ if (mode == TYPE_MODE (signed_char_type_node))
+ return unsigned_p ? unsigned_char_type_node : signed_char_type_node;
+
+ if (mode == TYPE_MODE (short_integer_type_node))
+ return unsigned_p ? short_unsigned_type_node : short_integer_type_node;
+
+ if (mode == TYPE_MODE (long_integer_type_node))
+ return unsigned_p ? long_unsigned_type_node : long_integer_type_node;
+
+ if (mode == TYPE_MODE (long_long_integer_type_node))
+ return unsigned_p ? long_long_unsigned_type_node : long_long_integer_type_node;
+
+ if (mode == QImode)
+ return unsigned_p ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (mode == HImode)
+ return unsigned_p ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (mode == SImode)
+ return unsigned_p ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (mode == DImode)
+ return unsigned_p ? unsigned_intDI_type_node : intDI_type_node;
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (mode == TYPE_MODE (intTI_type_node))
+ return unsigned_p ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+
+ if (mode == TYPE_MODE (float_type_node))
+ return float_type_node;
+
+ if (mode == TYPE_MODE (double_type_node))
+ return double_type_node;
+
+ if (mode == TYPE_MODE (long_double_type_node))
+ return long_double_type_node;
+
+ if (mode == TYPE_MODE (void_type_node))
+ return void_type_node;
+
+ if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
+ return (unsigned_p
+ ? make_unsigned_type (GET_MODE_PRECISION (mode))
+ : make_signed_type (GET_MODE_PRECISION (mode)));
+
+ if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
+ return (unsigned_p
+ ? make_unsigned_type (GET_MODE_PRECISION (mode))
+ : make_signed_type (GET_MODE_PRECISION (mode)));
+
+ if (COMPLEX_MODE_P (mode))
+ {
+ enum machine_mode inner_mode;
+ tree inner_type;
+
+ if (mode == TYPE_MODE (complex_float_type_node))
+ return complex_float_type_node;
+ if (mode == TYPE_MODE (complex_double_type_node))
+ return complex_double_type_node;
+ if (mode == TYPE_MODE (complex_long_double_type_node))
+ return complex_long_double_type_node;
+
+ if (mode == TYPE_MODE (complex_integer_type_node) && !unsigned_p)
+ return complex_integer_type_node;
+
+ inner_mode = GET_MODE_INNER (mode);
+ inner_type = gimple_type_for_mode (inner_mode, unsigned_p);
+ if (inner_type != NULL_TREE)
+ return build_complex_type (inner_type);
+ }
+ else if (VECTOR_MODE_P (mode))
+ {
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ tree inner_type = gimple_type_for_mode (inner_mode, unsigned_p);
+ if (inner_type != NULL_TREE)
+ return build_vector_type_for_mode (inner_type, mode);
+ }
+
+ if (mode == TYPE_MODE (dfloat32_type_node))
+ return dfloat32_type_node;
+ if (mode == TYPE_MODE (dfloat64_type_node))
+ return dfloat64_type_node;
+ if (mode == TYPE_MODE (dfloat128_type_node))
+ return dfloat128_type_node;
+
+ if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
+ {
+ if (mode == TYPE_MODE (short_fract_type_node))
+ return unsigned_p ? sat_short_fract_type_node : short_fract_type_node;
+ if (mode == TYPE_MODE (fract_type_node))
+ return unsigned_p ? sat_fract_type_node : fract_type_node;
+ if (mode == TYPE_MODE (long_fract_type_node))
+ return unsigned_p ? sat_long_fract_type_node : long_fract_type_node;
+ if (mode == TYPE_MODE (long_long_fract_type_node))
+ return unsigned_p ? sat_long_long_fract_type_node
+ : long_long_fract_type_node;
+
+ if (mode == TYPE_MODE (unsigned_short_fract_type_node))
+ return unsigned_p ? sat_unsigned_short_fract_type_node
+ : unsigned_short_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_fract_type_node))
+ return unsigned_p ? sat_unsigned_fract_type_node
+ : unsigned_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_long_fract_type_node))
+ return unsigned_p ? sat_unsigned_long_fract_type_node
+ : unsigned_long_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_long_long_fract_type_node))
+ return unsigned_p ? sat_unsigned_long_long_fract_type_node
+ : unsigned_long_long_fract_type_node;
+
+ if (mode == TYPE_MODE (short_accum_type_node))
+ return unsigned_p ? sat_short_accum_type_node : short_accum_type_node;
+ if (mode == TYPE_MODE (accum_type_node))
+ return unsigned_p ? sat_accum_type_node : accum_type_node;
+ if (mode == TYPE_MODE (long_accum_type_node))
+ return unsigned_p ? sat_long_accum_type_node : long_accum_type_node;
+ if (mode == TYPE_MODE (long_long_accum_type_node))
+ return unsigned_p ? sat_long_long_accum_type_node
+ : long_long_accum_type_node;
+
+ if (mode == TYPE_MODE (unsigned_short_accum_type_node))
+ return unsigned_p ? sat_unsigned_short_accum_type_node
+ : unsigned_short_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_accum_type_node))
+ return unsigned_p ? sat_unsigned_accum_type_node
+ : unsigned_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_long_accum_type_node))
+ return unsigned_p ? sat_unsigned_long_accum_type_node
+ : unsigned_long_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_long_long_accum_type_node))
+ return unsigned_p ? sat_unsigned_long_long_accum_type_node
+ : unsigned_long_long_accum_type_node;
+
+ if (mode == QQmode)
+ return unsigned_p ? sat_qq_type_node : qq_type_node;
+ if (mode == HQmode)
+ return unsigned_p ? sat_hq_type_node : hq_type_node;
+ if (mode == SQmode)
+ return unsigned_p ? sat_sq_type_node : sq_type_node;
+ if (mode == DQmode)
+ return unsigned_p ? sat_dq_type_node : dq_type_node;
+ if (mode == TQmode)
+ return unsigned_p ? sat_tq_type_node : tq_type_node;
+
+ if (mode == UQQmode)
+ return unsigned_p ? sat_uqq_type_node : uqq_type_node;
+ if (mode == UHQmode)
+ return unsigned_p ? sat_uhq_type_node : uhq_type_node;
+ if (mode == USQmode)
+ return unsigned_p ? sat_usq_type_node : usq_type_node;
+ if (mode == UDQmode)
+ return unsigned_p ? sat_udq_type_node : udq_type_node;
+ if (mode == UTQmode)
+ return unsigned_p ? sat_utq_type_node : utq_type_node;
+
+ if (mode == HAmode)
+ return unsigned_p ? sat_ha_type_node : ha_type_node;
+ if (mode == SAmode)
+ return unsigned_p ? sat_sa_type_node : sa_type_node;
+ if (mode == DAmode)
+ return unsigned_p ? sat_da_type_node : da_type_node;
+ if (mode == TAmode)
+ return unsigned_p ? sat_ta_type_node : ta_type_node;
+
+ if (mode == UHAmode)
+ return unsigned_p ? sat_uha_type_node : uha_type_node;
+ if (mode == USAmode)
+ return unsigned_p ? sat_usa_type_node : usa_type_node;
+ if (mode == UDAmode)
+ return unsigned_p ? sat_uda_type_node : uda_type_node;
+ if (mode == UTAmode)
+ return unsigned_p ? sat_uta_type_node : uta_type_node;
+ }
+
+ for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
+ if (TYPE_MODE (TREE_VALUE (t)) == mode)
+ return TREE_VALUE (t);
+
+ return NULL_TREE;
+}
+
+static int
+gimple_global_bindings_p (void)
+{
+ return cfun == NULL;
+}
+
+static void
+gimple_set_decl_assembler_name (tree decl)
+{
+ /* This is almost the same as lhd_set_decl_assembler_name, except that
+ we need to uniquify file-scope names, even if they are not
+ TREE_PUBLIC, to avoid conflicts between individual files. */
+ tree id;
+
+ if (TREE_PUBLIC (decl))
+ id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl));
+ else
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ char *label;
+
+ ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
+ id = get_identifier (label);
+ }
+
+ SET_DECL_ASSEMBLER_NAME (decl, id);
+}
+
+static tree
+gimple_pushdecl (tree t ATTRIBUTE_UNUSED)
+{
+ return NULL_TREE;
+}
+
+static tree
+gimple_getdecls (void)
+{
+ return registered_builtin_fndecls;
+}
+
+static tree
+gimple_builtin_function (tree decl)
+{
+ /* Record it. */
+ TREE_CHAIN (decl) = registered_builtin_fndecls;
+ registered_builtin_fndecls = decl;
+
+ return decl;
+}
+
+static void
+gimple_register_builtin_type (tree type, const char *name)
+{
+ tree decl;
+
+ decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier (name), type);
+ DECL_ARTIFICIAL (decl) = 1;
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = decl;
+
+ registered_builtin_types = tree_cons (0, type, registered_builtin_types);
+}
+
+/* Build nodes that would have be created by the C front-end; necessary
+ for including builtin-types.def and ultimately builtins.def. */
+
+static void
+gimple_build_c_type_nodes (void)
+{
+ gcc_assert (void_type_node);
+
+ void_list_node = build_tree_list (NULL_TREE, void_type_node);
+ string_type_node = build_pointer_type (char_type_node);
+ const_string_type_node
+ = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+ if (strcmp (SIZE_TYPE, "unsigned int") == 0)
+ {
+ intmax_type_node = integer_type_node;
+ uintmax_type_node = unsigned_type_node;
+ signed_size_type_node = integer_type_node;
+ }
+ else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
+ {
+ intmax_type_node = long_integer_type_node;
+ uintmax_type_node = long_unsigned_type_node;
+ signed_size_type_node = long_integer_type_node;
+ }
+ else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
+ {
+ intmax_type_node = long_long_integer_type_node;
+ uintmax_type_node = long_long_unsigned_type_node;
+ signed_size_type_node = long_long_integer_type_node;
+ }
+ else
+ gcc_unreachable ();
+
+ wint_type_node = unsigned_type_node;
+ pid_type_node = integer_type_node;
+}
+
+
+/* Perform GIMPLE-specific initialization. */
+
+static bool
+gimple_init (void)
+{
+ /* Initialize libcpp line maps for gcc_assert to work. */
+ linemap_add (line_table, LC_RENAME, 0, NULL, 0);
+ linemap_add (line_table, LC_RENAME, 0, NULL, 0);
+
+ /* Create the basic integer types. */
+ build_common_tree_nodes (flag_signed_char);
+
+ /* Share char_type_node with whatever would be the default for the target.
+ char_type_node will be used for internal types such as
+ va_list_type_node. */
+ /* ??? This breaks the more common case of consistent but non-standard
+ setting of flag_signed_char, so share according to flag_signed_char.
+ See PR42528. */
+ char_type_node
+ = flag_signed_char ? signed_char_type_node : unsigned_char_type_node;
+
+ /* Tell the middle end what type to use for the size of objects. */
+ if (strcmp (SIZE_TYPE, "unsigned int") == 0)
+ {
+ set_sizetype (unsigned_type_node);
+ size_type_node = unsigned_type_node;
+ }
+ else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
+ {
+ set_sizetype (long_unsigned_type_node);
+ size_type_node = long_unsigned_type_node;
+ }
+ else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
+ {
+ set_sizetype (long_long_unsigned_type_node);
+ size_type_node = long_long_unsigned_type_node;
+ }
+ else
+ gcc_unreachable ();
+
+ /* The global tree for the main identifier is filled in by
+ language-specific front-end initialization that is not run in the
+ GIMPLE front end. It appears that all languages that perform such
+ initialization currently do so in the same way, so we do it here. */
+ if (main_identifier_node == NULL_TREE)
+ main_identifier_node = get_identifier ("main");
+
+ /* In the C++ front-end, fileptr_type_node is defined as a variant
+ copy of of ptr_type_node, rather than ptr_node itself. The
+ distinction should only be relevant to the front-end, so we
+ always use the C definition here in gimple1. */
+ gcc_assert (fileptr_type_node == ptr_type_node);
+
+ ptrdiff_type_node = integer_type_node;
+
+ /* Create other basic types. */
+ build_common_tree_nodes_2 (/*short_double=*/false);
+ gimple_build_c_type_nodes ();
+ gcc_assert (va_list_type_node);
+
+ if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
+ {
+ tree x = build_pointer_type (TREE_TYPE (va_list_type_node));
+ gimple_define_builtins (x, x);
+ }
+ else
+ {
+ gimple_define_builtins (va_list_type_node,
+ build_reference_type (va_list_type_node));
+ }
+
+ targetm.init_builtins ();
+ build_common_builtin_nodes ();
+
+ return true;
+}
+
+/* Initialize tree structures required by the GIMPLE front end. */
+
+static void gimple_init_ts (void)
+{
+ tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
+}
+
+#undef LANG_HOOKS_NAME
+#define LANG_HOOKS_NAME "GNU GIMPLE"
+#undef LANG_HOOKS_OPTION_LANG_MASK
+#define LANG_HOOKS_OPTION_LANG_MASK gimple_option_lang_mask
+#undef LANG_HOOKS_INIT_OPTIONS
+#define LANG_HOOKS_INIT_OPTIONS gimple_init_options
+#undef LANG_HOOKS_GET_ALIAS_SET
+#define LANG_HOOKS_GET_ALIAS_SET gimple_get_alias_set
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE gimple_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE gimple_type_for_size
+#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
+#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME gimple_set_decl_assembler_name
+#undef LANG_HOOKS_GLOBAL_BINDINGS_P
+#define LANG_HOOKS_GLOBAL_BINDINGS_P gimple_global_bindings_p
+#undef LANG_HOOKS_PUSHDECL
+#define LANG_HOOKS_PUSHDECL gimple_pushdecl
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS gimple_getdecls
+#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
+#define LANG_HOOKS_REGISTER_BUILTIN_TYPE gimple_register_builtin_type
+#undef LANG_HOOKS_BUILTIN_FUNCTION
+#define LANG_HOOKS_BUILTIN_FUNCTION gimple_builtin_function
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT gimple_init
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE gimple_main
+#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
+#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION tree_rest_of_compilation
+#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
+#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P NULL
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE gimple_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE gimple_format_attribute_table
+
+#undef LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS gimple_init_ts
+
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+/* Language hooks that are not part of lang_hooks. */
+
+tree
+convert (tree type ATTRIBUTE_UNUSED, tree expr ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
+/* Tree walking support. */
+
+static enum gimple_tree_node_structure_enum
+gimple_tree_node_structure (union lang_tree_node *t ATTRIBUTE_UNUSED)
+{
+ return TS_GIMPLE_GENERIC;
+}
+
+#include "ggc.h"
+#include "gtype-gimple.h"
+#include "gt-gimple-gimple-lang.h"
diff --git a/gcc/gimple/gimple-tree.h b/gcc/gimple/gimple-tree.h
new file mode 100644
index 0000000..42b286a
--- /dev/null
+++ b/gcc/gimple/gimple-tree.h
@@ -0,0 +1,58 @@
+/* Definitions for GIMPLE parsing and type checking.
+
+ Copyright (C) 2010
+ Free Software Foundation, Inc.
+ Contributed by Diego Novillo.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GIMPLE_GIMPLE_TREE_H
+#define GIMPLE_GIMPLE_TREE_H
+
+struct GTY(()) lang_identifier
+{
+ struct tree_identifier base;
+};
+
+struct GTY(()) lang_decl
+{
+ int dummy; /* Added because ggc does not like empty structs. */
+};
+
+struct GTY(()) lang_type
+{
+ int dummy; /* Added because ggc does not like empty structs. */
+};
+
+struct GTY(()) language_function
+{
+ int dummy; /* Added because ggc does not like empty structs. */
+};
+
+enum gimple_tree_node_structure_enum {
+ TS_GIMPLE_GENERIC
+};
+
+union GTY((desc ("gimple_tree_node_structure (&%h)"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+ lang_tree_node
+{
+ union tree_node GTY ((tag ("TS_GIMPLE_GENERIC"),
+ desc ("gimple_tree_node_structure (&%h)"))) generic;
+};
+
+#endif /* GIMPLE_GIMPLE_TREE_H */
diff --git a/gcc/gimple/lang-specs.h b/gcc/gimple/lang-specs.h
new file mode 100644
index 0000000..de035ed
--- /dev/null
+++ b/gcc/gimple/lang-specs.h
@@ -0,0 +1,25 @@
+/* GIMPLE driver specs.
+
+ Copyright 2010 Free Software Foundation, Inc.
+ Contributed by Sandeep Soni and Diego Novillo.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* GIMPLE contributions to the "compilers" array in gcc.c. */
+
+ {"@gimple", "gimple1 %(cc1_options) %i %{!fsyntax-only:%(invoke_as)}",
+ /*cpp_spec=*/NULL, /*combinable=*/1, /*needs_preprocessing=*/1},
diff --git a/gcc/gimple/lang.opt b/gcc/gimple/lang.opt
new file mode 100644
index 0000000..a6b21b0
--- /dev/null
+++ b/gcc/gimple/lang.opt
@@ -0,0 +1,28 @@
+; Options for the GIMPLE front end.
+; Copyright (C) 2010 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3. If not see
+; <http://www.gnu.org/licenses/>.
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+Language
+GIMPLE
+
+
+; This comment is to ensure we retain the blank line above.
diff --git a/gcc/gimple/parser.c b/gcc/gimple/parser.c
new file mode 100644
index 0000000..510fedd
--- /dev/null
+++ b/gcc/gimple/parser.c
@@ -0,0 +1,491 @@
+/* GIMPLE parser.
+
+ Copyright 2010 Free Software Foundation, Inc.
+ Contributed by Sandeep Soni and Diego Novillo.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cpplib.h"
+#include "input.h"
+#include "diagnostic.h"
+#include "tree.h"
+#include "gimple.h"
+#include "toplev.h"
+#include "parser.h"
+
+/* Consumes a token if the EXPECTED_TOKEN_TYPE is exactly the one we
+ are looking for. The token is obtained by reading it from the reader P. */
+
+static const cpp_token *
+gimple_parse_expect_token (cpp_reader *p, enum cpp_ttype expected_token_type)
+{
+ const cpp_token *next_token;
+
+ next_token = cpp_peek_token (p, 0);
+
+ /* If the token type does not match then we must report an error,
+ otherwise consume the token. */
+
+ /* FIXME The error reported should be more precise to help
+ diagnostics similar to that reported by other front ends in
+ the same case. */
+
+ if (next_token->type != expected_token_type)
+ error ("expected token type %s instead of %s",
+ cpp_type2name (expected_token_type, 0),
+ cpp_type2name (next_token->type, 0));
+ else
+ next_token = cpp_get_token_with_location (p, &input_location);
+
+ return next_token;
+}
+
+
+/* Helper for gimple_parse_assign_stmt and gimple_parse_cond_stmt.
+ Peeks a token by reading from reader P and looks it up to match
+ against the tree codes. */
+
+static void
+gimple_parse_expect_subcode (cpp_reader *p)
+{
+ const cpp_token *next_token;
+ const char *text;
+ int i;
+
+ gimple_parse_expect_token (p, CPP_LESS);
+
+ /* Peeks a token and looks it up for a match. */
+
+ next_token = cpp_peek_token (p, 0);
+ text = (const char *) cpp_token_as_text (p, next_token);
+ for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
+ if (strcasecmp (text, tree_code_name[i]) == 0)
+ break;
+
+ /* If none of the tree codes match, then report an error. Otherwise
+ consume this token. */
+ if (i == LAST_AND_UNUSED_TREE_CODE)
+ error ("Expected token should be one of the tree codes");
+ else
+ next_token = cpp_get_token (p);
+
+ gimple_parse_expect_token (p, CPP_COMMA);
+
+ /* FIXME From this function we should return the tree code since it
+ can be used by the other helper functions to recognize precisely. */
+}
+
+/* Helper for gimple_parse_assign_stmt. The token read from reader P should
+ be the lhs of the tuple. */
+
+static void
+gimple_parse_expect_lhs (cpp_reader *p)
+{
+ const cpp_token *next_token;
+
+ /* Just before the name of the identifier we might get the symbol
+ of dereference too. If we do get it then consume that token, else
+ continue recognizing the name. */
+ next_token = cpp_peek_token (p, 0);
+ if (next_token->type == CPP_MULT)
+ next_token = cpp_get_token (p);
+
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_assign_stmt. The token read from reader P should
+ be the first operand in rhs of the tuple. */
+
+static void
+gimple_parse_expect_rhs1 (cpp_reader *p)
+{
+ const cpp_token *next_token;
+ next_token = cpp_peek_token (p, 0);
+
+ /* Currently there is duplication in the following blocks but there
+ would be more stuff added here as we go on. */
+
+ /* ??? Can there be more possibilities than these ? */
+ if (next_token->type == CPP_MULT)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_token (p, CPP_NAME);
+ }
+ else if (next_token->type == CPP_AND)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_token (p, CPP_NAME);
+ }
+ else if (next_token->type == CPP_NAME)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_NUMBER)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_STRING)
+ next_token = cpp_get_token (p);
+
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_assign_stmt. The token read from reader P should
+ be the second operand in rhs of the tuple. */
+
+static void
+gimple_parse_expect_rhs2 (cpp_reader *p)
+{
+ const cpp_token *next_token;
+ next_token = cpp_peek_token (p, 0);
+
+ /* ??? Can there be more possibilities than these ? */
+
+ if (next_token->type == CPP_NAME)
+ {
+ /* Handle a special case, this can be NULL too.
+
+ if (!strcasecmp ((const char *) cpp_token_as_text (p, next_token), "Null"));
+ {
+
+ } */
+
+ next_token = cpp_get_token (p);
+ }
+ else if (next_token->type == CPP_NUMBER)
+ next_token = cpp_get_token (p);
+
+ gimple_parse_expect_token (p, CPP_GREATER);
+}
+
+/* Parse a gimple_assign tuple that is read from the reader P. For now we
+ only recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_assign_stmt (cpp_reader *p)
+{
+ gimple_parse_expect_subcode (p);
+ gimple_parse_expect_lhs (p);
+ gimple_parse_expect_rhs1 (p);
+ gimple_parse_expect_rhs2 (p);
+}
+
+/* Helper for gimple_parse_cond_stmt. The token read from reader P should
+ be the first operand in the tuple. */
+static void
+gimple_parse_expect_op1 (cpp_reader *p)
+{
+ const cpp_token *next_token;
+ next_token = cpp_peek_token (p, 0);
+
+ if(next_token->type == CPP_NAME)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_NUMBER)
+ next_token = cpp_get_token (p);
+
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_cond_stmt. The token read from reader P should
+ be the second operand in the tuple. */
+
+static void
+gimple_parse_expect_op2 (cpp_reader *p)
+{
+ const cpp_token *next_token;
+ next_token = cpp_peek_token (p, 0);
+
+ if(next_token->type == CPP_NAME)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_NUMBER)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_STRING)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_AND)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_token (p, CPP_NAME);
+ }
+
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_cond_stmt. The token read from reader P should
+ be the true label in the tuple that means the label where the control
+ jumps if the condition evaluates to true. */
+
+static void
+gimple_parse_expect_true_label (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_GREATER);
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_cond_stmt. The token read from reader P should
+ be the false label in the tuple that means the label where the control
+ jumps if the condition evaluates to false. */
+
+static void
+gimple_parse_expect_false_label (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_RSHIFT);
+}
+
+/* Parse a gimple_cond tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_cond_stmt (cpp_reader *p)
+{
+ gimple_parse_expect_subcode (p);
+ gimple_parse_expect_op1 (p);
+ gimple_parse_expect_op2 (p);
+ gimple_parse_expect_true_label (p);
+ gimple_parse_expect_false_label (p);
+}
+
+/* Parse a gimple_goto tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_goto_stmt (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LSHIFT);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_RSHIFT);
+}
+
+/* Parse a gimple_label tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_label_stmt (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LSHIFT);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_RSHIFT);
+}
+
+/* Parse a gimple_switch tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_switch_stmt (cpp_reader *p)
+{
+ const cpp_token *next_token;
+
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_COMMA);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_COLON);
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+
+ for (;;)
+ {
+ next_token = cpp_peek_token (p, 0);
+
+ if (next_token->type == CPP_GREATER)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_token (p, CPP_COMMA);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_NUMBER);
+ gimple_parse_expect_token (p, CPP_COLON);
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ }
+ else if (next_token->type == CPP_RSHIFT)
+ {
+ next_token = cpp_get_token (p);
+ break;
+ }
+ else
+ error ("Incorrect use of the gimple_switch statement");
+ }
+}
+
+/* Helper for gimple_parse_call_stmt. The token read from reader P should
+ be the name of the function called. */
+
+static void
+gimple_parse_expect_function_name (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_COMMA);
+}
+
+/* Helper for gimple_parse_call_stmt. The token read from reader P should
+ be the identifier in which the value is returned. */
+
+static void
+gimple_parse_expect_return_var (cpp_reader *p)
+{
+ const cpp_token *next_token;
+
+ next_token = cpp_peek_token (p, 0);
+
+ if (next_token->type == CPP_NAME)
+ next_token = cpp_get_token (p);
+
+ /* There may be no variable in which the return value is collected.
+ In that case this field in the tuple will contain NULL. We need
+ to handle it too. */
+}
+
+/* Helper for gimple_parse_call_stmt. The token read from reader P should
+ be the argument in the function call. */
+
+static void
+gimple_parse_expect_argument (cpp_reader *p)
+{
+ const cpp_token *next_token;
+
+ next_token = cpp_peek_token (p, 0);
+
+ if (next_token->type == CPP_NUMBER)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_NAME)
+ next_token = cpp_get_token (p);
+ else if (next_token->type == CPP_MULT)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_token (p, CPP_NAME);
+ }
+ else
+ error ("Incorrect way to specify an argument");
+}
+
+/* Parse a gimple_call tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_call_stmt (cpp_reader *p)
+{
+ const cpp_token *next_token;
+
+ gimple_parse_expect_function_name (p);
+ gimple_parse_expect_return_var (p);
+
+ for (;;)
+ {
+ next_token = cpp_peek_token (p, 0);
+ if (next_token->type == CPP_GREATER)
+ {
+ next_token = cpp_get_token (p);
+ break;
+ }
+ else if (next_token->type == CPP_COMMA)
+ {
+ next_token = cpp_get_token (p);
+ gimple_parse_expect_argument (p);
+ }
+ }
+}
+
+/* Parse a gimple_return tuple that is read from the reader P. For now we only
+ recognize the tuple. Refer gimple.def for the format of this tuple. */
+
+static void
+gimple_parse_return_stmt (cpp_reader *p)
+{
+ gimple_parse_expect_token (p, CPP_LESS);
+ gimple_parse_expect_token (p, CPP_NAME);
+ gimple_parse_expect_token (p, CPP_GREATER);
+}
+
+/* The TOK read from the reader P is looked up for a match. Calls the
+ corresponding function to do the parsing for the match. */
+
+static void
+gimple_parse_stmt (cpp_reader *p, const cpp_token *tok)
+{
+ const char *text;
+ int i;
+ text = (const char *) cpp_token_as_text (p, tok);
+ for (i = GIMPLE_ERROR_MARK; i < LAST_AND_UNUSED_GIMPLE_CODE; i++)
+ if (strcasecmp (text, gimple_code_name[i]) == 0)
+ break;
+
+ if (i == LAST_AND_UNUSED_GIMPLE_CODE)
+ error ("Invalid gimple code used");
+ else
+ {
+ switch (i)
+ {
+ case GIMPLE_ASSIGN:
+ gimple_parse_assign_stmt (p);
+ break;
+ case GIMPLE_COND:
+ gimple_parse_cond_stmt (p);
+ break;
+ case GIMPLE_LABEL:
+ gimple_parse_label_stmt (p);
+ break;
+ case GIMPLE_GOTO:
+ gimple_parse_goto_stmt (p);
+ break;
+ case GIMPLE_SWITCH:
+ gimple_parse_switch_stmt (p);
+ break;
+ case GIMPLE_CALL:
+ gimple_parse_call_stmt (p);
+ break;
+ case GIMPLE_RETURN:
+ gimple_parse_return_stmt (p);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+/* Main entry point for the GIMPLE front end. */
+
+void
+gimple_main (int debug_p ATTRIBUTE_UNUSED)
+{
+ /* We invoke the parser here. */
+ cpp_reader *p;
+ const cpp_token *tok;
+ const char *input_file = "/tmp/gimple.txt";
+ const char *output_file;
+
+ struct line_maps *line_tab;
+ line_tab = ggc_alloc_cleared_line_maps ();
+ linemap_init (line_tab);
+ p = cpp_create_reader (CLK_GNUC99, ident_hash, line_tab);
+ output_file = cpp_read_main_file (p,input_file);
+ if (output_file)
+ {
+ tok = cpp_get_token (p);
+ while (tok->type != CPP_EOF)
+ {
+ gimple_parse_stmt (p, tok);
+ tok = cpp_get_token (p);
+ }
+ }
+ cpp_finish (p,NULL);
+ cpp_destroy (p);
+}
diff --git a/gcc/gimple/parser.h b/gcc/gimple/parser.h
new file mode 100644
index 0000000..36181d2
--- /dev/null
+++ b/gcc/gimple/parser.h
@@ -0,0 +1,28 @@
+/* GIMPLE parser declarations
+
+ Copyright 2010 Free Software Foundation, Inc.
+ Contributed by Sandeep Soni and Diego Novillo
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GIMPLE_PARSER_H
+#define GIMPLE_PARSER_H
+
+/* In parser.c */
+extern void gimple_main (int);
+
+#endif /* GIMPLE_PARSER_H */
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 388a46c..b03d7cc 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1133,7 +1133,7 @@ static void lto_init_ts (void)
}
#undef LANG_HOOKS_NAME
-#define LANG_HOOKS_NAME "GNU GIMPLE"
+#define LANG_HOOKS_NAME "GNU GIMPLE BC"
#undef LANG_HOOKS_OPTION_LANG_MASK
#define LANG_HOOKS_OPTION_LANG_MASK lto_option_lang_mask
#undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 40b56ba..e4ee214 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1992,434 +1992,6 @@ lto_eh_personality (void)
return lto_eh_personality_decl;
}
-/* Consumes a token if the EXPECTED_TOKEN_TYPE is exactly the one we
- are looking for. The token is obtained by reading it from the reader P. */
-
-static const cpp_token *
-gimple_parse_expect_token (cpp_reader *p, enum cpp_ttype expected_token_type)
-{
- const cpp_token *next_token;
-
- next_token = cpp_peek_token (p, 0);
-
- /* If the token type does not match then we must report an error,
- otherwise consume the token. */
-
- /* FIXME The error reported should be more precise to help
- diagnostics similar to that reported by other front ends in
- the same case. */
-
- if (next_token->type != expected_token_type)
- error ("expected token type %s instead of %s",
- cpp_type2name (expected_token_type, 0),
- cpp_type2name (next_token->type, 0));
- else
- next_token = cpp_get_token_with_location (p, &input_location);
-
- return next_token;
-}
-
-/* Helper for gimple_parse_assign_stmt and gimple_parse_cond_stmt.
- Peeks a token by reading from reader P and looks it up to match
- against the tree codes. */
-
-static void
-gimple_parse_expect_subcode (cpp_reader *p)
-{
- const cpp_token *next_token;
- const char *text;
- int i;
-
- gimple_parse_expect_token (p, CPP_LESS);
-
- /* Peeks a token and looks it up for a match. */
-
- next_token = cpp_peek_token (p, 0);
- text = (const char *) cpp_token_as_text (p, next_token);
- for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
- if (strcasecmp (text, tree_code_name[i]) == 0)
- break;
-
- /* If none of the tree codes match, then report an error. Otherwise
- consume this token. */
- if (i == LAST_AND_UNUSED_TREE_CODE)
- error ("Expected token should be one of the tree codes");
- else
- next_token = cpp_get_token (p);
-
- gimple_parse_expect_token (p, CPP_COMMA);
-
- /* FIXME From this function we should return the tree code since it
- can be used by the other helper functions to recognize precisely. */
-}
-
-/* Helper for gimple_parse_assign_stmt. The token read from reader P should
- be the lhs of the tuple. */
-
-static void
-gimple_parse_expect_lhs (cpp_reader *p)
-{
- const cpp_token *next_token;
-
- /* Just before the name of the identifier we might get the symbol
- of dereference too. If we do get it then consume that token, else
- continue recognizing the name. */
- next_token = cpp_peek_token (p, 0);
- if (next_token->type == CPP_MULT)
- next_token = cpp_get_token (p);
-
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_assign_stmt. The token read from reader P should
- be the first operand in rhs of the tuple. */
-
-static void
-gimple_parse_expect_rhs1 (cpp_reader *p)
-{
- const cpp_token *next_token;
- next_token = cpp_peek_token (p, 0);
-
- /* Currently there is duplication in the following blocks but there
- would be more stuff added here as we go on. */
-
- /* ??? Can there be more possibilities than these ? */
- if (next_token->type == CPP_MULT)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_token (p, CPP_NAME);
- }
- else if (next_token->type == CPP_AND)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_token (p, CPP_NAME);
- }
- else if (next_token->type == CPP_NAME)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_NUMBER)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_STRING)
- next_token = cpp_get_token (p);
-
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_assign_stmt. The token read from reader P should
- be the second operand in rhs of the tuple. */
-
-static void
-gimple_parse_expect_rhs2 (cpp_reader *p)
-{
- const cpp_token *next_token;
- next_token = cpp_peek_token (p, 0);
-
- /* ??? Can there be more possibilities than these ? */
-
- if (next_token->type == CPP_NAME)
- {
- /* Handle a special case, this can be NULL too.
-
- if (!strcasecmp ((const char *) cpp_token_as_text (p, next_token), "Null"));
- {
-
- } */
-
- next_token = cpp_get_token (p);
- }
- else if (next_token->type == CPP_NUMBER)
- next_token = cpp_get_token (p);
-
- gimple_parse_expect_token (p, CPP_GREATER);
-}
-
-/* Parse a gimple_assign tuple that is read from the reader P. For now we
- only recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_assign_stmt (cpp_reader *p)
-{
- gimple_parse_expect_subcode (p);
- gimple_parse_expect_lhs (p);
- gimple_parse_expect_rhs1 (p);
- gimple_parse_expect_rhs2 (p);
-}
-
-/* Helper for gimple_parse_cond_stmt. The token read from reader P should
- be the first operand in the tuple. */
-static void
-gimple_parse_expect_op1 (cpp_reader *p)
-{
- const cpp_token *next_token;
- next_token = cpp_peek_token (p, 0);
-
- if(next_token->type == CPP_NAME)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_NUMBER)
- next_token = cpp_get_token (p);
-
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_cond_stmt. The token read from reader P should
- be the second operand in the tuple. */
-
-static void
-gimple_parse_expect_op2 (cpp_reader *p)
-{
- const cpp_token *next_token;
- next_token = cpp_peek_token (p, 0);
-
- if(next_token->type == CPP_NAME)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_NUMBER)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_STRING)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_AND)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_token (p, CPP_NAME);
- }
-
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_cond_stmt. The token read from reader P should
- be the true label in the tuple that means the label where the control
- jumps if the condition evaluates to true. */
-
-static void
-gimple_parse_expect_true_label (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_GREATER);
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_cond_stmt. The token read from reader P should
- be the false label in the tuple that means the label where the control
- jumps if the condition evaluates to false. */
-
-static void
-gimple_parse_expect_false_label (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_RSHIFT);
-}
-
-/* Parse a gimple_cond tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_cond_stmt (cpp_reader *p)
-{
- gimple_parse_expect_subcode (p);
- gimple_parse_expect_op1 (p);
- gimple_parse_expect_op2 (p);
- gimple_parse_expect_true_label (p);
- gimple_parse_expect_false_label (p);
-}
-
-/* Parse a gimple_goto tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_goto_stmt (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LSHIFT);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_RSHIFT);
-}
-
-/* Parse a gimple_label tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_label_stmt (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LSHIFT);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_RSHIFT);
-}
-
-/* Parse a gimple_switch tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_switch_stmt (cpp_reader *p)
-{
- const cpp_token *next_token;
-
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_COMMA);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_COLON);
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
-
- for (;;)
- {
- next_token = cpp_peek_token (p, 0);
-
- if (next_token->type == CPP_GREATER)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_token (p, CPP_COMMA);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_NUMBER);
- gimple_parse_expect_token (p, CPP_COLON);
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- }
- else if (next_token->type == CPP_RSHIFT)
- {
- next_token = cpp_get_token (p);
- break;
- }
- else
- error ("Incorrect use of the gimple_switch statement");
- }
-}
-
-/* Helper for gimple_parse_call_stmt. The token read from reader P should
- be the name of the function called. */
-
-static void
-gimple_parse_expect_function_name (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_COMMA);
-}
-
-/* Helper for gimple_parse_call_stmt. The token read from reader P should
- be the identifier in which the value is returned. */
-
-static void
-gimple_parse_expect_return_var (cpp_reader *p)
-{
- const cpp_token *next_token;
-
- next_token = cpp_peek_token (p, 0);
-
- if (next_token->type == CPP_NAME)
- next_token = cpp_get_token (p);
-
- /* There may be no variable in which the return value is collected.
- In that case this field in the tuple will contain NULL. We need
- to handle it too. */
-}
-
-/* Helper for gimple_parse_call_stmt. The token read from reader P should
- be the argument in the function call. */
-
-static void
-gimple_parse_expect_argument (cpp_reader *p)
-{
- const cpp_token *next_token;
-
- next_token = cpp_peek_token (p, 0);
-
- if (next_token->type == CPP_NUMBER)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_NAME)
- next_token = cpp_get_token (p);
- else if (next_token->type == CPP_MULT)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_token (p, CPP_NAME);
- }
- else
- error ("Incorrect way to specify an argument");
-}
-
-/* Parse a gimple_call tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_call_stmt (cpp_reader *p)
-{
- const cpp_token *next_token;
-
- gimple_parse_expect_function_name (p);
- gimple_parse_expect_return_var (p);
-
- for (;;)
- {
- next_token = cpp_peek_token (p, 0);
- if (next_token->type == CPP_GREATER)
- {
- next_token = cpp_get_token (p);
- break;
- }
- else if (next_token->type == CPP_COMMA)
- {
- next_token = cpp_get_token (p);
- gimple_parse_expect_argument (p);
- }
- }
-}
-
-/* Parse a gimple_return tuple that is read from the reader P. For now we only
- recognize the tuple. Refer gimple.def for the format of this tuple. */
-
-static void
-gimple_parse_return_stmt (cpp_reader *p)
-{
- gimple_parse_expect_token (p, CPP_LESS);
- gimple_parse_expect_token (p, CPP_NAME);
- gimple_parse_expect_token (p, CPP_GREATER);
-}
-
-/* The TOK read from the reader P is looked up for a match. Calls the
- corresponding function to do the parsing for the match. */
-
-static void
-gimple_parse_stmt (cpp_reader *p, const cpp_token *tok)
-{
- const char *text;
- int i;
- text = (const char *) cpp_token_as_text (p, tok);
- for (i = GIMPLE_ERROR_MARK; i < LAST_AND_UNUSED_GIMPLE_CODE; i++)
- if (strcasecmp (text, gimple_code_name[i]) == 0)
- break;
-
- if (i == LAST_AND_UNUSED_GIMPLE_CODE)
- error ("Invalid gimple code used");
- else
- {
- switch (i)
- {
- case GIMPLE_ASSIGN:
- gimple_parse_assign_stmt (p);
- break;
- case GIMPLE_COND:
- gimple_parse_cond_stmt (p);
- break;
- case GIMPLE_LABEL:
- gimple_parse_label_stmt (p);
- break;
- case GIMPLE_GOTO:
- gimple_parse_goto_stmt (p);
- break;
- case GIMPLE_SWITCH:
- gimple_parse_switch_stmt (p);
- break;
- case GIMPLE_CALL:
- gimple_parse_call_stmt (p);
- break;
- case GIMPLE_RETURN:
- gimple_parse_return_stmt (p);
- break;
- default:
- break;
- }
- }
-}
/* Main entry point for the GIMPLE front end. This front end has
three main personalities:
@@ -2452,36 +2024,9 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
if (!seen_error ())
{
- if (flag_gimple_parser)
- {
- /* We invoke the parser here. */
- cpp_reader *p;
- const cpp_token *tok;
- const char *input_file = "/tmp/gimple.txt";
- const char *output_file;
-
- struct line_maps *line_tab;
- line_tab = ggc_alloc_cleared_line_maps ();
- linemap_init (line_tab);
- p = cpp_create_reader (CLK_GNUC99,ident_hash,line_tab);
- output_file = cpp_read_main_file (p,input_file);
- if (output_file)
- {
- tok = cpp_get_token (p);
- while (tok->type != CPP_EOF)
- {
- gimple_parse_stmt (p, tok);
- tok = cpp_get_token (p);
- }
- }
- cpp_finish (p,NULL);
- cpp_destroy (p);
- }
-
/* If WPA is enabled analyze the whole call graph and create an
optimization plan. Otherwise, read in all the function
bodies and continue with optimization. */
-
if (flag_wpa)
do_whole_program_analysis ();
else
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gimplefe] Skeleton GIMPLE front end
2010-08-13 15:34 [gimplefe] Skeleton GIMPLE front end Diego Novillo
@ 2010-08-13 15:35 ` Diego Novillo
2010-08-13 15:56 ` Diego Novillo
2010-08-23 9:46 ` Sandeep Soni
1 sibling, 1 reply; 4+ messages in thread
From: Diego Novillo @ 2010-08-13 15:35 UTC (permalink / raw)
To: gcc-patches, Sandeep Soni
On 10-08-13 11:31 , Diego Novillo wrote:
> Tested on x86_64. Committed.
Spoke too soon. The commit failed. My local svn tree is messed up.
I'll move to a new tree and commit from there.
Diego.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gimplefe] Skeleton GIMPLE front end
2010-08-13 15:35 ` Diego Novillo
@ 2010-08-13 15:56 ` Diego Novillo
0 siblings, 0 replies; 4+ messages in thread
From: Diego Novillo @ 2010-08-13 15:56 UTC (permalink / raw)
To: gcc-patches, Sandeep Soni
On 10-08-13 11:33 , Diego Novillo wrote:
> Spoke too soon. The commit failed. My local svn tree is messed up. I'll
> move to a new tree and commit from there.
OK, now committed at revision 163226.
Diego.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [gimplefe] Skeleton GIMPLE front end
2010-08-13 15:34 [gimplefe] Skeleton GIMPLE front end Diego Novillo
2010-08-13 15:35 ` Diego Novillo
@ 2010-08-23 9:46 ` Sandeep Soni
1 sibling, 0 replies; 4+ messages in thread
From: Sandeep Soni @ 2010-08-23 9:46 UTC (permalink / raw)
To: Diego Novillo; +Cc: gcc-patches
On Fri, Aug 13, 2010 at 9:01 PM, Diego Novillo <dnovillo@google.com> wrote:
> +union GTY((desc ("gimple_tree_node_structure (&%h)"),
> + chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> + lang_tree_node
> +{
> + union tree_node GTY ((tag ("TS_GIMPLE_GENERIC"),
> + desc ("gimple_tree_node_structure (&%h)"))) generic;
> +};
I am unsure that this works. It gave me a build error. Instead it should be:
> +union GTY((desc ("gimple_tree_node_structure (&%h)"),
> + chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> + lang_tree_node
> +{
> + union tree_node GTY ((tag ("TS_GIMPLE_GENERIC"),
> + desc ("tree_node_structure (&%h)"))) generic;
> +};
The build was successful by making that change from
gimple_tree_node_structure to tree_node_structure.
--
Cheers
Sandy
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-08-23 5:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-13 15:34 [gimplefe] Skeleton GIMPLE front end Diego Novillo
2010-08-13 15:35 ` Diego Novillo
2010-08-13 15:56 ` Diego Novillo
2010-08-23 9:46 ` Sandeep Soni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).