Patchwork [gimplefe] Skeleton GIMPLE front end

login
register
mail settings
Submitter Diego Novillo
Date Aug. 13, 2010, 3:31 p.m.
Message ID <20100813153126.GA9315@google.com>
Download mbox | patch
Permalink /patch/61698/
State New
Headers show

Comments

Diego Novillo - Aug. 13, 2010, 3:31 p.m.
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.
Diego Novillo - Aug. 13, 2010, 3:33 p.m.
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.
Diego Novillo - Aug. 13, 2010, 3:51 p.m.
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.
Sandeep Soni - Aug. 23, 2010, 5:32 a.m.
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.

Patch

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