This patch is a small initial step toward using an interface to connect
the Go frontend to the gcc middle end.  This goal is to eventually
permit changing the gofrontend files so that they do not include any gcc
header files and do not call any gcc functions directly.  This first
step only does this for assignment statements.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


2011-04-03  Ian Lance Taylor  <i...@google.com>

        * go-gcc.cc: New file.
        * Make-lang.in (GO_OBJS): Add go/go-gcc.o.
        (go/go-gcc.o): New target.
        (go/go.o): Depend on go/gofrontend/backend.h.
        (go/statements.o): Likewise.


Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 171846)
+++ gcc/go/Make-lang.in	(working copy)
@@ -50,6 +50,7 @@ GO_OBJS = \
 	go/expressions.o \
 	go/go-backend.o \
 	go/go-dump.o \
+	go/go-gcc.o \
 	go/go-lang.o \
 	go/go.o \
 	go/gogo-tree.o \
@@ -235,6 +236,9 @@ go/go-lang.o: go/go-lang.c $(CONFIG_H) $
 
 GOINCLUDES = -I $(srcdir)/go -I $(srcdir)/go/gofrontend
 
+go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) go/gofrontend/backend.h
+	$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
+
 go/%.o: go/gofrontend/%.cc
 	$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
 
@@ -249,7 +253,7 @@ go/expressions.o: go/gofrontend/expressi
 	go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
 	$(GO_EXPRESSIONS_H)
 go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \
-	$(GO_PARSE_H) $(GO_GOGO_H)
+	$(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H)
 go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
 	go/gofrontend/go-dump.h
 go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
@@ -272,7 +276,7 @@ go/parse.o: go/gofrontend/parse.cc $(GO_
 go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
 	$(GIMPLE_H) convert.h tree-iterator.h $(TREE_FLOW_H) $(REAL_H) \
 	$(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
-	$(GO_STATEMENTS_H)
+	go/gofrontend/backend.h $(GO_STATEMENTS_H)
 go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
 	$(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
 	go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 0)
+++ gcc/go/go-gcc.cc	(revision 0)
@@ -0,0 +1,199 @@
+// go-gcc.cc -- Go frontend to gcc IR.
+// Copyright (C) 2011 Free Software Foundation, Inc.
+// Contributed by Ian Lance Taylor, Google.
+
+// 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 "go-system.h"
+
+// This has to be included outside of extern "C", so we have to
+// include it here before tree.h includes it later.
+#include <gmp.h>
+
+#ifndef ENABLE_BUILD_WITH_CXX
+extern "C"
+{
+#endif
+
+#include "tree.h"
+
+#ifndef ENABLE_BUILD_WITH_CXX
+}
+#endif
+
+#include "backend.h"
+
+// A class wrapping a tree.
+
+class Gcc_tree
+{
+ public:
+  Gcc_tree(tree t)
+    : t_(t)
+  { }
+
+  tree
+  get_tree()
+  { return this->t_; }
+
+ private:
+  tree t_;
+};
+
+// In gcc, types, expressions, and statements are all trees.
+class Btype : public Gcc_tree
+{
+ public:
+  Btype(tree t)
+    : Gcc_tree(t)
+  { }
+};
+
+class Bexpression : public Gcc_tree
+{
+ public:
+  Bexpression(tree t)
+    : Gcc_tree(t)
+  { }
+};
+
+class Bstatement : public Gcc_tree
+{
+ public:
+  Bstatement(tree t)
+    : Gcc_tree(t)
+  { }
+};
+
+// This file implements the interface between the Go frontend proper
+// and the gcc IR.  This implements specific instantiations of
+// abstract classes defined by the Go frontend proper.  The Go
+// frontend proper class methods of these classes to generate the
+// backend representation.
+
+class Gcc_backend : public Backend
+{
+ public:
+  // Types.
+
+  Btype*
+  error_type()
+  { gcc_unreachable(); }
+
+  Btype*
+  void_type()
+  { gcc_unreachable(); }
+
+  Btype*
+  bool_type()
+  { gcc_unreachable(); }
+
+  Btype*
+  integer_type(bool /* is_unsigned */, int /* bits */)
+  { gcc_unreachable(); }
+
+  Btype*
+  float_type(int /* bits */)
+  { gcc_unreachable(); }
+
+  Btype*
+  string_type()
+  { gcc_unreachable(); }
+
+  Btype*
+  function_type(const Function_type*, Btype* /* receiver */,
+		const Btypes* /* parameters */,
+		const Btypes* /* results */)
+  { gcc_unreachable(); }
+
+  Btype*
+  struct_type(const Struct_type*, const Btypes* /* field_types */)
+  { gcc_unreachable(); }
+
+  Btype*
+  array_type(const Btype* /* element_type */, const Bexpression* /* length */)
+  { gcc_unreachable(); }
+
+  Btype*
+  slice_type(const Btype* /* element_type */)
+  { gcc_unreachable(); }
+
+  Btype*
+  map_type(const Btype* /* key_type */, const Btype* /* value_type */,
+	   source_location)
+  { gcc_unreachable(); }
+
+  Btype*
+  channel_type(const Btype* /* element_type */)
+  { gcc_unreachable(); }
+
+  Btype*
+  interface_type(const Interface_type*, const Btypes* /* method_types */)
+  { gcc_unreachable(); }
+
+  // Statements.
+
+  // Create an assignment statement.
+  Bstatement*
+  assignment(Bexpression* lhs, Bexpression* rhs,
+	     source_location location);
+
+ private:
+  // Make a Bstatement from a tree.
+  Bstatement*
+  make_statement(tree t)
+  { return new Bstatement(t); }
+};
+
+// Assignment.
+
+Bstatement*
+Gcc_backend::assignment(Bexpression* lhs, Bexpression* rhs,
+			source_location location)
+{
+  return this->make_statement(fold_build2_loc(location, MODIFY_EXPR,
+					      void_type_node,
+					      lhs->get_tree(),
+					      rhs->get_tree()));
+}
+
+// The single backend.
+
+static Gcc_backend gcc_backend;
+
+// Return the backend generator.
+
+Backend*
+go_get_backend()
+{
+  return &gcc_backend;
+}
+
+// FIXME: Temporary functions while converting to the new backend
+// interface.
+
+Bexpression*
+tree_to_expr(tree t)
+{
+  return new Bexpression(t);
+}
+
+tree
+statement_to_tree(Bstatement* bs)
+{
+  return bs->get_tree();
+}
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 171846)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -19,8 +19,9 @@
 
 // Class Gogo.
 
-Gogo::Gogo(int int_type_size, int pointer_size)
-  : package_(NULL),
+Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
+  : backend_(backend),
+    package_(NULL),
     functions_(),
     globals_(new Bindings(NULL)),
     imports_(),
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 171846)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -37,6 +37,7 @@ class Methods;
 class Named_object;
 class Label;
 class Translate_context;
+class Backend;
 class Export;
 class Import;
 
@@ -102,7 +103,12 @@ class Gogo
  public:
   // Create the IR, passing in the sizes of the types "int" and
   // "uintptr" in bits.
-  Gogo(int int_type_size, int pointer_size);
+  Gogo(Backend* backend, int int_type_size, int pointer_size);
+
+  // Get the backend generator.
+  Backend*
+  backend()
+  { return this->backend_; }
 
   // Get the package name.
   const std::string&
@@ -647,6 +653,8 @@ class Gogo
   typedef Unordered_map_hash(const Type*, tree, Type_hash_identical,
 			     Type_identical) Type_descriptor_decls;
 
+  // The backend generator.
+  Backend* backend_;
   // The package we are compiling.
   Package* package_;
   // The list of currently open functions during parsing.
@@ -2451,16 +2459,16 @@ class Traverse
   Expressions_seen* expressions_seen_;
 };
 
-// When translating the gogo IR into trees, this is the context we
-// pass down the blocks and statements.
+// When translating the gogo IR into the backend data structure, this
+// is the context we pass down the blocks and statements.
 
 class Translate_context
 {
  public:
   Translate_context(Gogo* gogo, Named_object* function, Block* block,
 		    tree block_tree)
-    : gogo_(gogo), function_(function), block_(block), block_tree_(block_tree),
-      is_const_(false)
+    : gogo_(gogo), backend_(gogo->backend()), function_(function),
+      block_(block), block_tree_(block_tree), is_const_(false)
   { }
 
   // Accessors.
@@ -2469,6 +2477,10 @@ class Translate_context
   gogo()
   { return this->gogo_; }
 
+  Backend*
+  backend()
+  { return this->backend_; }
+
   Named_object*
   function()
   { return this->function_; }
@@ -2493,6 +2505,8 @@ class Translate_context
  private:
   // The IR for the entire compilation unit.
   Gogo* gogo_;
+  // The generator for the backend data structures.
+  Backend* backend_;
   // The function we are currently translating.
   Named_object* function_;
   // The block we are currently translating.
Index: gcc/go/gofrontend/go.cc
===================================================================
--- gcc/go/gofrontend/go.cc	(revision 171846)
+++ gcc/go/gofrontend/go.cc	(working copy)
@@ -10,6 +10,7 @@
 
 #include "lex.h"
 #include "parse.h"
+#include "backend.h"
 #include "gogo.h"
 
 // The unique prefix to use for exported symbols.  This is set during
@@ -27,7 +28,7 @@ void
 go_create_gogo(int int_type_size, int pointer_size)
 {
   gcc_assert(::gogo == NULL);
-  ::gogo = new Gogo(int_type_size, pointer_size);
+  ::gogo = new Gogo(go_get_backend(), int_type_size, pointer_size);
   if (!unique_prefix.empty())
     ::gogo->set_unique_prefix(unique_prefix);
 }
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 171846)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -29,6 +29,7 @@ extern "C"
 #include "types.h"
 #include "expressions.h"
 #include "gogo.h"
+#include "backend.h"
 #include "statements.h"
 
 // Class Statement.
@@ -560,8 +561,10 @@ Assignment_statement::do_get_tree(Transl
   if (rhs_tree == error_mark_node)
     return error_mark_node;
 
-  return fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
-			 lhs_tree, rhs_tree);
+  Bstatement* ret = context->backend()->assignment(tree_to_expr(lhs_tree),
+						   tree_to_expr(rhs_tree),
+						   this->location());
+  return statement_to_tree(ret);
 }
 
 // Make an assignment statement.
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 0)
+++ gcc/go/gofrontend/backend.h	(revision 0)
@@ -0,0 +1,119 @@
+// backend.h -- Go frontend interface to backend  -*- C++ -*-
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef GO_BACKEND_H
+#define GO_BACKEND_H
+
+class Function_type;
+class Struct_type;
+class Interface_type;
+
+// Pointers to these types are created by the backend, passed to the
+// frontend, and passed back to the backend.  The types must be
+// defined by the backend using these names.
+
+// The backend representation of a type.
+class Btype;
+
+// The backend represention of an expression.
+class Bexpression;
+
+// The backend representation of a statement.
+class Bstatement;
+
+// A list of backend types.
+typedef std::vector<Btype*> Btypes;
+
+// The backend interface.  This is a pure abstract class that a
+// specific backend will implement.
+
+class Backend
+{
+ public:
+  virtual ~Backend() { }
+
+  // Types.
+
+  // Produce an error type.  Actually the backend could probably just
+  // crash if this is called.
+  virtual Btype*
+  error_type() = 0;
+
+  // Get a void type.  This is used in (at least) two ways: 1) as the
+  // return type of a function with no result parameters; 2)
+  // unsafe.Pointer is represented as *void.
+  virtual Btype*
+  void_type() = 0;
+
+  // Get the unnamed boolean type.
+  virtual Btype*
+  bool_type() = 0;
+
+  // Get an unnamed integer type with the given signedness and number
+  // of bits.
+  virtual Btype*
+  integer_type(bool is_unsigned, int bits) = 0;
+
+  // Get an unnamed floating point type with the given number of bits.
+  virtual Btype*
+  float_type(int bits) = 0;
+
+  // Get the unnamed string type.
+  virtual Btype*
+  string_type() = 0;
+
+  // Get a function type.  The receiver, parameter, and results are
+  // generated from the types in the Function_type.  The Function_type
+  // is provided so that the names are available.
+  virtual Btype*
+  function_type(const Function_type*, Btype* receiver,
+		const Btypes* parameters,
+		const Btypes* results) = 0;
+
+  // Get a struct type.  The Struct_type is provided to get the field
+  // names.
+  virtual Btype*
+  struct_type(const Struct_type*, const Btypes* field_types) = 0;
+
+  // Get an array type.
+  virtual Btype*
+  array_type(const Btype* element_type, const Bexpression* length) = 0;
+
+  // Get a slice type.
+  virtual Btype*
+  slice_type(const Btype* element_type) = 0;
+
+  // Get a map type.
+  virtual Btype*
+  map_type(const Btype* key_type, const Btype* value_type, source_location) = 0;
+
+  // Get a channel type.
+  virtual Btype*
+  channel_type(const Btype* element_type) = 0;
+
+  // Get an interface type.  The Interface_type is provided to get the
+  // method names.
+  virtual Btype*
+  interface_type(const Interface_type*, const Btypes* method_types) = 0;
+
+  // Statements.
+
+  // Create an assignment statement.
+  virtual Bstatement*
+  assignment(Bexpression* lhs, Bexpression* rhs, source_location location) = 0;
+};
+
+// The backend interface has to define this function.
+
+extern Backend* go_get_backend();
+
+// FIXME: Temporary helper functions while converting to new backend
+// interface.
+
+extern Bexpression* tree_to_expr(tree);
+extern tree statement_to_tree(Bstatement*);
+
+#endif // !defined(GO_BACKEND_H)

Reply via email to